From 64de40c96fadd0f199b019d931c310d35c2c579b Mon Sep 17 00:00:00 2001 From: Cyrus Date: Thu, 19 Jan 2017 17:33:50 -0800 Subject: [PATCH 1/5] feat(config): a 3rd option to run the tests by dynamically loading test scripts --- client/karma.js | 29 +++++-- client/updater.js | 6 ++ console.log | 10 +-- lib/config.js | 11 +++ lib/middleware/karma.js | 38 +++++--- static/client_with_context.html.html | 125 +++++++++++++++++++++++++++ test/client/karma.spec.js | 3 +- test/unit/web-server.spec.js | 9 +- 8 files changed, 207 insertions(+), 24 deletions(-) create mode 100644 static/client_with_context.html.html diff --git a/client/karma.js b/client/karma.js index 8bdd9fb07..30dfba7eb 100644 --- a/client/karma.js +++ b/client/karma.js @@ -49,12 +49,31 @@ var Karma = function (socket, iframe, opener, navigator, location) { var childWindow = null var navigateContextTo = function (url) { if (self.config.useIframe === false) { - // If there is a window already open, then close it - // DEV: In some environments (e.g. Electron), we don't have setter access for location - if (childWindow !== null && childWindow.closed !== true) { - childWindow.close() + // run in new window + if (self.config.runInParent === false) { + // If there is a window already open, then close it + // DEV: In some environments (e.g. Electron), we don't have setter access for location + if (childWindow !== null && childWindow.closed !== true) { + childWindow.close() + } + childWindow = opener(url) + // run context on parent element and dynamically loading scripts + } else if (url !== 'about:blank') { + var loadScript = function (idx) { + if (idx < window.__karma__.scriptUrls.length) { + var ele = document.createElement('script') + ele.src = window.__karma__.scriptUrls[idx] + ele.onload = function () { + loadScript(idx + 1) + } + document.body.appendChild(ele) + } else { + window.__karma__.loaded() + } + } + loadScript(0) } - childWindow = opener(url) + // run in iframe } else { iframe.src = url } diff --git a/client/updater.js b/client/updater.js index fa5e6383b..c5c0cf425 100644 --- a/client/updater.js +++ b/client/updater.js @@ -2,6 +2,9 @@ var VERSION = require('./constants').VERSION var StatusUpdater = function (socket, titleElement, bannerElement, browsersElement) { var updateBrowsersInfo = function (browsers) { + if (!browsersElement) { + return + } var items = [] var status for (var i = 0; i < browsers.length; i++) { @@ -13,6 +16,9 @@ var StatusUpdater = function (socket, titleElement, bannerElement, browsersEleme var updateBanner = function (status) { return function (param) { + if (!titleElement || !bannerElement) { + return + } var paramStatus = param ? status.replace('$', param) : status titleElement.innerHTML = 'Karma v' + VERSION + ' - ' + paramStatus bannerElement.className = status === 'connected' ? 'online' : 'offline' diff --git a/console.log b/console.log index 10d33cb21..029f6feb5 100644 --- a/console.log +++ b/console.log @@ -1,5 +1,5 @@ -PhantomJS 2.1.1 (Mac OS X 0.0.0) -PhantomJS 2.1.1 (Mac OS X 0.0.0) -PhantomJS 2.1.1 (Mac OS X 0.0.0) -PhantomJS 2.1.1 (Mac OS X 0.0.0) -PhantomJS 2.1.1 (Mac OS X 0.0.0) +PhantomJS 2.1.1 (Linux 0.0.0) +PhantomJS 2.1.1 (Linux 0.0.0) +PhantomJS 2.1.1 (Linux 0.0.0) +PhantomJS 2.1.1 (Linux 0.0.0) +PhantomJS 2.1.1 (Linux 0.0.0) diff --git a/lib/config.js b/lib/config.js index 089125bcf..dae77dd94 100644 --- a/lib/config.js +++ b/lib/config.js @@ -183,6 +183,16 @@ var normalizeConfig = function (config, configFilePath) { config.autoWatch = false } + if (config.runInParent) { + log.debug('useIframe set to false, because using runInParent') + config.useIframe = false + } + + if (!config.singleRun && !config.useIframe && config.runInParent) { + log.debug('singleRun set to true, because using runInParent') + config.singleRun = true + } + if (helper.isString(config.reporters)) { config.reporters = config.reporters.split(',') } @@ -316,6 +326,7 @@ var Config = function () { this.defaultClient = this.client = { args: [], useIframe: true, + useCurrentWindow: false, captureConsole: true, clearContext: true } diff --git a/lib/middleware/karma.js b/lib/middleware/karma.js index 7f8b591ab..ce988abc0 100644 --- a/lib/middleware/karma.js +++ b/lib/middleware/karma.js @@ -112,11 +112,16 @@ var createKarmaMiddleware = function ( // serve client.html if (requestUrl === '/') { - return serveStaticFile('/client.html', requestedRangeHeader, response, function (data) { - return data - .replace('\n%X_UA_COMPATIBLE%', getXUACompatibleMetaElement(request.url)) - .replace('%X_UA_COMPATIBLE_URL%', getXUACompatibleUrl(request.url)) - }) + // redirect client_with_context.html + if (!client.useIframe && client.runInParent) { + requestUrl = '/client_with_context.html' + } else { // serve client.html + return serveStaticFile('/client.html', requestedRangeHeader, response, function (data) { + return data + .replace('\n%X_UA_COMPATIBLE%', getXUACompatibleMetaElement(request.url)) + .replace('%X_UA_COMPATIBLE_URL%', getXUACompatibleUrl(request.url)) + }) + } } // serve karma.js, context.js, and debug.js @@ -139,7 +144,8 @@ var createKarmaMiddleware = function ( // or debug.html - execution context without channel to the server var isRequestingContextFile = requestUrl === '/context.html' var isRequestingDebugFile = requestUrl === '/debug.html' - if (isRequestingContextFile || isRequestingDebugFile) { + var isRequestingClientContextFile = requestUrl === '/client_with_context.html' + if (isRequestingContextFile || isRequestingDebugFile || isRequestingClientContextFile) { return filesPromise.then(function (files) { var fileServer var requestedFileUrl @@ -161,7 +167,10 @@ var createKarmaMiddleware = function ( fileServer(requestedFileUrl, requestedRangeHeader, response, function (data) { common.setNoCacheHeaders(response) - var scriptTags = files.included.map(function (file) { + var scriptTags = [] + var scriptUrls = [] + for (var i in files.included) { + var file = files.included[i] var filePath = file.path var fileExt = path.extname(filePath) @@ -173,12 +182,16 @@ var createKarmaMiddleware = function ( } } + scriptUrls.push(filePath) + if (fileExt === '.css') { - return util.format(LINK_TAG_CSS, filePath) + scriptTags.push(util.format(LINK_TAG_CSS, filePath)) + continue } if (fileExt === '.html') { - return util.format(LINK_TAG_HTML, filePath) + scriptTags.push(util.format(LINK_TAG_HTML, filePath)) + continue } // The script tag to be placed @@ -190,8 +203,8 @@ var createKarmaMiddleware = function ( } var crossOriginAttribute = includeCrossOriginAttribute ? CROSSORIGIN_ATTRIBUTE : '' - return util.format(SCRIPT_TAG, scriptType, filePath, crossOriginAttribute) - }) + scriptTags.push(util.format(SCRIPT_TAG, scriptType, filePath, crossOriginAttribute)) + } // TODO(vojta): don't compute if it's not in the template var mappings = files.served.map(function (file) { @@ -206,11 +219,14 @@ var createKarmaMiddleware = function ( var clientConfig = 'window.__karma__.config = ' + JSON.stringify(client) + ';\n' + var scriptUrlsJS = 'window.__karma__.scriptUrls = ' + JSON.stringify(scriptUrls) + ';\n' + mappings = 'window.__karma__.files = {\n' + mappings.join(',\n') + '\n};\n' return data .replace('%SCRIPTS%', scriptTags.join('\n')) .replace('%CLIENT_CONFIG%', clientConfig) + .replace('%SCRIPT_URL_ARRAY%', scriptUrlsJS) .replace('%MAPPINGS%', mappings) .replace('\n%X_UA_COMPATIBLE%', getXUACompatibleMetaElement(request.url)) }) diff --git a/static/client_with_context.html.html b/static/client_with_context.html.html new file mode 100644 index 000000000..e562bdee1 --- /dev/null +++ b/static/client_with_context.html.html @@ -0,0 +1,125 @@ + + + + + + + Karma + + + + + + + + + + + + + + + diff --git a/test/client/karma.spec.js b/test/client/karma.spec.js index 79c390150..85cb668c9 100644 --- a/test/client/karma.spec.js +++ b/test/client/karma.spec.js @@ -46,7 +46,8 @@ describe('Karma', function () { it('should open a new window when useIFrame is false', function () { var config = ck.config = { - useIframe: false + useIframe: false, + runInParent: false } socket.emit('execute', config) diff --git a/test/unit/web-server.spec.js b/test/unit/web-server.spec.js index 903d28402..42018d505 100644 --- a/test/unit/web-server.spec.js +++ b/test/unit/web-server.spec.js @@ -49,7 +49,11 @@ describe('web-server', () => { beforeMiddleware: ['beforeCustom'], middleware: ['custom'], middlewareResponse: 'hello middleware!', - mime: {'custom/custom': ['custom']} + mime: {'custom/custom': ['custom']}, + client: { + useIframe: true, + useSingleWindow: false + } } var injector = new di.Injector([{ @@ -213,7 +217,8 @@ describe('web-server', () => { emitter = new EventEmitter() var injector = new di.Injector([{ - config: ['value', {basePath: '/base/path', urlRoot: '/', protocol: 'https:', httpsServerOptions: credentials}], + config: ['value', {basePath: '/base/path', urlRoot: '/', protocol: 'https:', httpsServerOptions: credentials, + client: {useIframe: true, useSingleWindow: false}}], customFileHandlers: ['value', customFileHandlers], emitter: ['value', emitter], fileList: ['value', {files: {served: [], included: []}}], From cdc9ce1bad9a5be3769cf5dadaa66d9b729c645e Mon Sep 17 00:00:00 2001 From: Cyrus Date: Thu, 19 Jan 2017 17:41:45 -0800 Subject: [PATCH 2/5] feat(config): update flag name --- lib/config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/config.js b/lib/config.js index dae77dd94..c2cdb63b1 100644 --- a/lib/config.js +++ b/lib/config.js @@ -326,7 +326,7 @@ var Config = function () { this.defaultClient = this.client = { args: [], useIframe: true, - useCurrentWindow: false, + runInParent: false, captureConsole: true, clearContext: true } From 30afc61336024be7a269fdc3dbdd107494b40e53 Mon Sep 17 00:00:00 2001 From: Cyrus Date: Fri, 20 Jan 2017 17:06:10 -0800 Subject: [PATCH 3/5] feat(config): fix typo, add test --- console.log | 10 +-- docs/config/01-configuration-file.md | 8 +++ ...ext.html.html => client_with_context.html} | 0 test/e2e/runInParent.feature | 67 +++++++++++++++++++ 4 files changed, 80 insertions(+), 5 deletions(-) rename static/{client_with_context.html.html => client_with_context.html} (100%) create mode 100644 test/e2e/runInParent.feature diff --git a/console.log b/console.log index 029f6feb5..10d33cb21 100644 --- a/console.log +++ b/console.log @@ -1,5 +1,5 @@ -PhantomJS 2.1.1 (Linux 0.0.0) -PhantomJS 2.1.1 (Linux 0.0.0) -PhantomJS 2.1.1 (Linux 0.0.0) -PhantomJS 2.1.1 (Linux 0.0.0) -PhantomJS 2.1.1 (Linux 0.0.0) +PhantomJS 2.1.1 (Mac OS X 0.0.0) +PhantomJS 2.1.1 (Mac OS X 0.0.0) +PhantomJS 2.1.1 (Mac OS X 0.0.0) +PhantomJS 2.1.1 (Mac OS X 0.0.0) +PhantomJS 2.1.1 (Mac OS X 0.0.0) diff --git a/docs/config/01-configuration-file.md b/docs/config/01-configuration-file.md index 12641af02..0638400d6 100644 --- a/docs/config/01-configuration-file.md +++ b/docs/config/01-configuration-file.md @@ -224,6 +224,14 @@ How this value is used is up to your test adapter - you should check your adapte If true, Karma runs the tests inside an iFrame. If false, Karma runs the tests in a new window. Some tests may not run in an iFrame and may need a new window to run. +## client.runInParent +**Type:** Boolean + +**Default:** `false` + +**Description:** Run the tests on the same window as the client, without using iframe or a new window + +If true, Karma runs the tests inside the original window without using iframe. It will load the test scripts dynamically. ## client.captureConsole **Type:** Boolean diff --git a/static/client_with_context.html.html b/static/client_with_context.html similarity index 100% rename from static/client_with_context.html.html rename to static/client_with_context.html diff --git a/test/e2e/runInParent.feature b/test/e2e/runInParent.feature new file mode 100644 index 000000000..51c716695 --- /dev/null +++ b/test/e2e/runInParent.feature @@ -0,0 +1,67 @@ +Feature: runInParent option + In order to use Karma + As a person who wants to write great tests + I want Karma to run without iframe or opening new window + + Scenario: Execute a test in PhantomJS + Given a configuration with: + """ + files = ['basic/plus.js', 'basic/test.js']; + browsers = ['PhantomJS']; + plugins = [ + 'karma-jasmine', + 'karma-phantomjs-launcher' + ]; + client = { + useIframe: false, + runInParent: true + }; + """ + When I start Karma + Then it passes with: + """ + .. + PhantomJS + """ + @not-jenkins + Scenario: Execute a test in Chrome + Given a configuration with: + """ + files = ['basic/plus.js', 'basic/test.js'] + browsers = ['Chrome'] + plugins = [ + 'karma-jasmine', + 'karma-chrome-launcher' + ] + client = { + useIframe: false, + runInParent: true + } + """ + When I start Karma + Then it passes with: + """ + .. + Chrome + """ + + Scenario: Execute a test in Firefox + Given a configuration with: + """ + files = ['basic/plus.js', 'basic/test.js'] + browsers = ['Firefox'] + plugins = [ + 'karma-jasmine', + 'karma-firefox-launcher' + ] + client = { + useIframe: false, + runInParent: true + } + """ + When I start Karma + Then it passes with: + """ + .. + Firefox + """ From cde6777a8b019199e84f39a2b8bbecae64d09c59 Mon Sep 17 00:00:00 2001 From: Cyrus Date: Tue, 31 Jan 2017 16:54:11 -0800 Subject: [PATCH 4/5] feat(config): add customizable html --- console.log | 10 +++++----- docs/config/01-configuration-file.md | 8 ++++++++ lib/config.js | 3 +++ lib/middleware/karma.js | 7 ++++++- test/unit/config.spec.js | 4 +++- 5 files changed, 25 insertions(+), 7 deletions(-) diff --git a/console.log b/console.log index 10d33cb21..029f6feb5 100644 --- a/console.log +++ b/console.log @@ -1,5 +1,5 @@ -PhantomJS 2.1.1 (Mac OS X 0.0.0) -PhantomJS 2.1.1 (Mac OS X 0.0.0) -PhantomJS 2.1.1 (Mac OS X 0.0.0) -PhantomJS 2.1.1 (Mac OS X 0.0.0) -PhantomJS 2.1.1 (Mac OS X 0.0.0) +PhantomJS 2.1.1 (Linux 0.0.0) +PhantomJS 2.1.1 (Linux 0.0.0) +PhantomJS 2.1.1 (Linux 0.0.0) +PhantomJS 2.1.1 (Linux 0.0.0) +PhantomJS 2.1.1 (Linux 0.0.0) diff --git a/docs/config/01-configuration-file.md b/docs/config/01-configuration-file.md index 0638400d6..31a7ba99f 100644 --- a/docs/config/01-configuration-file.md +++ b/docs/config/01-configuration-file.md @@ -296,6 +296,14 @@ Disable this when you need to load external scripts that are served without the **Description:** If `null` (default), uses karma's own `debug.html` file. +## customClientContextFile +**Type:** string + +**Default:** `null` + +**Description:** If `null` (default), uses karma's own `client_with_context.html` file (which is used when client.runInParent set to true). + + ## customHeaders **Type:** Array diff --git a/lib/config.js b/lib/config.js index c2cdb63b1..69fc3db49 100644 --- a/lib/config.js +++ b/lib/config.js @@ -138,6 +138,7 @@ var normalizeConfig = function (config, configFilePath) { config.exclude = config.exclude.map(basePathResolve) config.customContextFile = config.customContextFile && basePathResolve(config.customContextFile) config.customDebugFile = config.customDebugFile && basePathResolve(config.customDebugFile) + config.customClientContextFile = config.customClientContextFile && basePathResolve(config.customClientContextFile) // normalize paths on windows config.basePath = helper.normalizeWinPath(config.basePath) @@ -145,6 +146,7 @@ var normalizeConfig = function (config, configFilePath) { config.exclude = config.exclude.map(helper.normalizeWinPath) config.customContextFile = helper.normalizeWinPath(config.customContextFile) config.customDebugFile = helper.normalizeWinPath(config.customDebugFile) + config.customClientContextFile = helper.normalizeWinPath(config.customClientContextFile) // normalize urlRoot config.urlRoot = normalizeUrlRoot(config.urlRoot) @@ -302,6 +304,7 @@ var Config = function () { } this.customContextFile = null this.customDebugFile = null + this.customClientContextFile = null this.exclude = [] this.logLevel = constant.LOG_INFO this.colors = true diff --git a/lib/middleware/karma.js b/lib/middleware/karma.js index ce988abc0..3392096bd 100644 --- a/lib/middleware/karma.js +++ b/lib/middleware/karma.js @@ -89,6 +89,7 @@ var createKarmaMiddleware = function ( var client = injector.get('config.client') var customContextFile = injector.get('config.customContextFile') var customDebugFile = injector.get('config.customDebugFile') + var customClientContextFile = injector.get('config.customClientContextFile') var jsVersion = injector.get('config.jsVersion') var includeCrossOriginAttribute = injector.get('config.crossOriginAttribute') @@ -149,7 +150,7 @@ var createKarmaMiddleware = function ( return filesPromise.then(function (files) { var fileServer var requestedFileUrl - log.debug('custom files', customContextFile, customDebugFile) + log.debug('custom files', customContextFile, customDebugFile, customClientContextFile) if (isRequestingContextFile && customContextFile) { log.debug('Serving customContextFile %s', customContextFile) fileServer = serveFile @@ -158,6 +159,10 @@ var createKarmaMiddleware = function ( log.debug('Serving customDebugFile %s', customDebugFile) fileServer = serveFile requestedFileUrl = customDebugFile + } else if (isRequestingClientContextFile && customClientContextFile) { + log.debug('Serving customClientContextFile %s', customClientContextFile) + fileServer = serveFile + requestedFileUrl = customClientContextFile } else { log.debug('Serving static request %s', requestUrl) fileServer = serveStaticFile diff --git a/test/unit/config.spec.js b/test/unit/config.spec.js index 4bcd91497..8caf7644c 100644 --- a/test/unit/config.spec.js +++ b/test/unit/config.spec.js @@ -302,7 +302,8 @@ describe('config', () => { basePath: '/base', files: ['a/*.js', {pattern: 'b.js', watched: false, included: false}, {pattern: 'c.js'}], customContextFile: 'context.html', - customDebugFile: 'debug.html' + customDebugFile: 'debug.html', + customClientContextFile: 'client_with_context.html' }) expect(config.files.length).to.equal(3) @@ -327,6 +328,7 @@ describe('config', () => { expect(config.customContextFile).to.equal(resolveWinPath('/base/context.html')) expect(config.customDebugFile).to.equal(resolveWinPath('/base/debug.html')) + expect(config.customClientContextFile).to.equal(resolveWinPath('/base/client_with_context.html')) }) it('should normalize preprocessors to an array', () => { From c968aa2508c7194e4d5694cab41c7929d9324d68 Mon Sep 17 00:00:00 2001 From: Cyrus Chan Date: Tue, 31 Jan 2017 16:58:34 -0800 Subject: [PATCH 5/5] Update console.log --- console.log | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/console.log b/console.log index 029f6feb5..10d33cb21 100644 --- a/console.log +++ b/console.log @@ -1,5 +1,5 @@ -PhantomJS 2.1.1 (Linux 0.0.0) -PhantomJS 2.1.1 (Linux 0.0.0) -PhantomJS 2.1.1 (Linux 0.0.0) -PhantomJS 2.1.1 (Linux 0.0.0) -PhantomJS 2.1.1 (Linux 0.0.0) +PhantomJS 2.1.1 (Mac OS X 0.0.0) +PhantomJS 2.1.1 (Mac OS X 0.0.0) +PhantomJS 2.1.1 (Mac OS X 0.0.0) +PhantomJS 2.1.1 (Mac OS X 0.0.0) +PhantomJS 2.1.1 (Mac OS X 0.0.0)