Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(server): .dom files include HTML tags in page. #3178

Merged
merged 1 commit into from
Oct 12, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions docs/config/02-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ Each pattern is either a simple string or an object with the following propertie
* `js`
* `dart`
* `module`
* `dom`
* **Description.** The type determines the mechanism for including the file. The `css` and `html` types
create `link` elements; the `js`, `dart`, and `module` elements create `script` elements. The `dom` type
includes the file content in the page, used, for example, to test components combinging HTML and JS.

### `watched`
* **Type.** Boolean
Expand All @@ -46,17 +50,17 @@ Each pattern is either a simple string or an object with the following propertie
* **Description.** Should the files be included in the browser using
`<script>` tag? Use `false` if you want to load them manually, eg.
using [Require.js](../plus/requirejs.html).

If a file is covered by multiple patterns with different `include` properties, the most specific pattern takes
precedence over the other.
The specificity of the pattern is defined as a six-tuple, where larger tuple implies lesser specificity:

The specificity of the pattern is defined as a six-tuple, where larger tuple implies lesser specificity:
*(n<sub>glob parts</sub>, n<sub>glob star</sub>, n<sub>star</sub>, n<sub>ext glob</sub>, n<sub>range</sub>, n<sub>optional</sub>)*.
Tuples are compared lexicographically.
The *n<sub>glob parts</sub>* is the number of patterns after the bracket sections are expanded. E.g. the
Tuples are compared lexicographically.

The *n<sub>glob parts</sub>* is the number of patterns after the bracket sections are expanded. E.g. the
the pattern *{0...9}* will yield *n<sub>glob parts</sub>=10*. The rest of the tuple is decided as the least
specific of each expanded pattern.
specific of each expanded pattern.

### `served`
* **Type.** Boolean
Expand Down
22 changes: 20 additions & 2 deletions lib/middleware/karma.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ const FILE_TYPES = [
'html',
'js',
'dart',
'module'
'module',
'dom'
]

function filePathToUrlPath (filePath, basePath, urlRoot, proxyPath) {
Expand Down Expand Up @@ -64,6 +65,7 @@ function createKarmaMiddleware (
filesPromise,
serveStaticFile,
serveFile,
readFilePromise,
injector,
basePath,
urlRoot,
Expand Down Expand Up @@ -133,8 +135,21 @@ function createKarmaMiddleware (
const isRequestingContextFile = requestUrl === '/context.html'
const isRequestingDebugFile = requestUrl === '/debug.html'
const isRequestingClientContextFile = requestUrl === '/client_with_context.html'
const includedContent = new Map() // file.path -> content
if (isRequestingContextFile || isRequestingDebugFile || isRequestingClientContextFile) {
return filesPromise.then(function (files) {
return filesPromise.then((files) => {
// Read any files.included that will be directly written into HTML before HTML is read.
const contentReads = []
for (const file of files.included) {
const fileType = file.type || path.extname(file.path).substring(1)
if (fileType === 'dom') {
contentReads.push(
readFilePromise(file.path).then((content) => includedContent.set(file.path, content))
)
}
}
return Promise.all(contentReads).then(() => files)
}).then(function (files) {
let fileServer
let requestedFileUrl
log.debug('custom files', customContextFile, customDebugFile, customClientContextFile)
Expand Down Expand Up @@ -181,6 +196,8 @@ function createKarmaMiddleware (

if (fileType === 'css') {
scriptTags.push(`<link type="text/css" href="${filePath}" rel="stylesheet">`)
} else if (fileType === 'dom') {
scriptTags.push(includedContent.get(file.path))
} else if (fileType === 'html') {
scriptTags.push(`<link href="${filePath}" rel="import">`)
} else {
Expand Down Expand Up @@ -224,6 +241,7 @@ createKarmaMiddleware.$inject = [
'filesPromise',
'serveStaticFile',
'serveFile',
'readFilePromise',
'injector',
'config.basePath',
'config.urlRoot',
Expand Down
2 changes: 2 additions & 0 deletions lib/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const plugin = require('./plugin')
const createServeFile = require('./web-server').createServeFile
const createServeStaticFile = require('./web-server').createServeStaticFile
const createFilesPromise = require('./web-server').createFilesPromise
const createReadFilePromise = require('./web-server').createReadFilePromise
const createWebServer = require('./web-server').createWebServer
const preprocessor = require('./preprocessor')
const Launcher = require('./launcher').Launcher
Expand Down Expand Up @@ -78,6 +79,7 @@ class Server extends KarmaEventEmitter {
serveFile: ['factory', createServeFile],
serveStaticFile: ['factory', createServeStaticFile],
filesPromise: ['factory', createFilesPromise],
readFilePromise: ['factory', createReadFilePromise],
socketServer: ['factory', createSocketIoServer],
executor: ['factory', Executor.factory],
// TODO(vojta): remove
Expand Down
23 changes: 21 additions & 2 deletions lib/web-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,25 @@ function createFilesPromise (emitter, fileList) {

return filesPromise
}
createFilesPromise.$inject = ['emitter', 'fileList']

// Bind the filesystem into the injectable file reader function
function createReadFilePromise () {
return (filepath) => {
return new Promise((resolve, reject) => {
fs.readFile(filepath, 'utf8', function (error, data) {
if (error) {
reject(new Error(`Cannot read ${filepath}, got: ${error}`))
} else if (!data) {
reject(new Error(`No content at ${filepath}`))
} else {
resolve(data.split('\n'))
}
})
})
}
}

createReadFilePromise.$inject = []

function createServeStaticFile (config) {
return common.createServeFile(fs, path.normalize(path.join(__dirname, '/../static')), config)
Expand Down Expand Up @@ -106,5 +124,6 @@ module.exports = {
createWebServer,
createServeFile,
createServeStaticFile,
createFilesPromise
createFilesPromise,
createReadFilePromise
}
48 changes: 48 additions & 0 deletions test/unit/middleware/karma.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const HttpRequestMock = mocks.http.ServerRequest

describe('middleware.karma', () => {
let serveFile
let readFilesDeferred
let filesDeferred
let nextSpy
let response
Expand Down Expand Up @@ -63,6 +64,7 @@ describe('middleware.karma', () => {
filesDeferred.promise,
serveFile,
null,
null,
injector,
'/base/path',
'/__karma__/',
Expand Down Expand Up @@ -119,10 +121,12 @@ describe('middleware.karma', () => {
})

it('should serve client.html', (done) => {
readFilesDeferred = helper.defer()
handler = createKarmaMiddleware(
null,
serveFile,
null,
readFilesDeferred.promise,
injector,
'/base',
'/'
Expand All @@ -138,10 +142,12 @@ describe('middleware.karma', () => {
})

it('should serve /?id=xxx', (done) => {
readFilesDeferred = helper.defer()
handler = createKarmaMiddleware(
null,
serveFile,
null,
readFilesDeferred.promise,
injector,
'/base',
'/'
Expand All @@ -157,10 +163,13 @@ describe('middleware.karma', () => {
})

it('should serve /?x-ua-compatible with replaced values', (done) => {
readFilesDeferred = helper.defer()

handler = createKarmaMiddleware(
null,
serveFile,
null,
readFilesDeferred.promise,
injector,
'/base',
'/'
Expand Down Expand Up @@ -268,6 +277,43 @@ describe('middleware.karma', () => {
callHandlerWith('/__karma__/context.html')
})

it('should serve context.html with included DOM content', (done) => {
const readFilePromise = (path) => {
const cases = {
'/some/abc/a.dom': 'a',
'/some/abc/b_test_dom.html': 'b',
'/some/abc/c': 'c',
'/some/abc/d_test_dom.html': 'd'
}
return Promise.resolve(cases[path] || '?unknown ' + path)
}

filesDeferred = helper.defer()
handler = createKarmaMiddleware(
filesDeferred.promise,
serveFile,
null,
readFilePromise,
injector,
'/base',
'/'
)

includedFiles([
new MockFile('/some/abc/a.dom', 'sha1'),
new MockFile('/some/abc/b_test_dom.html', 'sha2', 'dom'),
new MockFile('/some/abc/c', 'sha3', 'dom')
])

response.once('end', () => {
expect(nextSpy).not.to.have.been.called
expect(response).to.beServedAs(200, 'CONTEXT\na\nb\nc')
done()
})

callHandlerWith('/context.html')
})

it('should serve context.json with the correct paths for all files', (done) => {
includedFiles([
new MockFile('/some/abc/a.css', 'sha1'),
Expand Down Expand Up @@ -422,10 +468,12 @@ describe('middleware.karma', () => {

it('should update handle updated configs', (done) => {
let i = 0
readFilesDeferred = helper.defer()
handler = createKarmaMiddleware(
filesDeferred.promise,
serveFile,
null,
readFilesDeferred.promise,
{
get (val) {
if (val === 'config.client') {
Expand Down
4 changes: 3 additions & 1 deletion test/unit/web-server.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ describe('web-server', () => {
filesPromise: ['factory', m.createFilesPromise],
serveStaticFile: ['factory', m.createServeStaticFile],
serveFile: ['factory', m.createServeFile],
readFilePromise: ['factory', m.createReadFilePromise],
capturedBrowsers: ['value', null],
reporter: ['value', null],
executor: ['value', null],
Expand Down Expand Up @@ -232,7 +233,7 @@ describe('web-server', () => {
filesPromise: ['factory', m.createFilesPromise],
serveStaticFile: ['factory', m.createServeStaticFile],
serveFile: ['factory', m.createServeFile],

readFilePromise: ['factory', m.createReadFilePromise],
capturedBrowsers: ['value', null],
reporter: ['value', null],
executor: ['value', null],
Expand Down Expand Up @@ -277,6 +278,7 @@ describe('web-server', () => {
filesPromise: ['factory', m.createFilesPromise],
serveStaticFile: ['factory', m.createServeStaticFile],
serveFile: ['factory', m.createServeFile],
readFilePromise: ['factory', m.createReadFilePromise],
capturedBrowsers: ['value', null],
reporter: ['value', null],
executor: ['value', null],
Expand Down