Skip to content

Commit

Permalink
feat: add an option to run the tests by dynamically loading test scri…
Browse files Browse the repository at this point in the history
…pts without iframe
  • Loading branch information
chan1cyrus2 authored and dignifiedquire committed Feb 19, 2017
1 parent eb407ab commit aa42c41
Show file tree
Hide file tree
Showing 10 changed files with 297 additions and 21 deletions.
29 changes: 24 additions & 5 deletions client/karma.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down
6 changes: 6 additions & 0 deletions client/updater.js
Original file line number Diff line number Diff line change
Expand Up @@ -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++) {
Expand All @@ -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'
Expand Down
16 changes: 16 additions & 0 deletions docs/config/01-configuration-file.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,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
Expand Down Expand Up @@ -289,6 +297,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

Expand Down
14 changes: 14 additions & 0 deletions lib/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,13 +138,15 @@ 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)
config.files = config.files.map(createPatternMapper(helper.normalizeWinPath))
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)
Expand Down Expand Up @@ -183,6 +185,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(',')
}
Expand Down Expand Up @@ -296,6 +308,7 @@ var Config = function () {
}
this.customContextFile = null
this.customDebugFile = null
this.customClientContextFile = null
this.exclude = []
this.logLevel = constant.LOG_INFO
this.colors = true
Expand All @@ -320,6 +333,7 @@ var Config = function () {
this.defaultClient = this.client = {
args: [],
useIframe: true,
runInParent: false,
captureConsole: true,
clearContext: true
}
Expand Down
45 changes: 33 additions & 12 deletions lib/middleware/karma.js
Original file line number Diff line number Diff line change
Expand Up @@ -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')

Expand All @@ -112,11 +113,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
Expand All @@ -139,11 +145,12 @@ 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
log.debug('custom files', customContextFile, customDebugFile)
log.debug('custom files', customContextFile, customDebugFile, customClientContextFile)
if (isRequestingContextFile && customContextFile) {
log.debug('Serving customContextFile %s', customContextFile)
fileServer = serveFile
Expand All @@ -152,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
Expand All @@ -161,7 +172,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)

Expand All @@ -173,12 +187,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
Expand All @@ -190,8 +208,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) {
Expand All @@ -206,11 +224,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))
})
Expand Down
125 changes: 125 additions & 0 deletions static/client_with_context.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@

<!DOCTYPE html>
<!--
This is the combined client and execution context.
Is used for single-shot tests.
-->
<html>
<head>

<title>Karma</title>
<link href="favicon.ico" rel="icon" type="image/x-icon">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
<style type="text/css">
iframe {
height: 100%;
width: 100%;
border: 0;
}

html, body {
height: 100%;
padding: 0;
margin: 0;

font-family: sans-serif;
}

.offline {
background: #DDD;
}

.online {
background: #6C4;
}

.idle {
}

.executing {
background: #F99;
}

#banner {
padding: 5px 10px;
}

h1 {
font-size: 1.8em;
margin: 0;
padding: 0;
}

ul {
margin: 0;
padding: 0;

list-style: none;
}

li {
padding: 5px 12px;
}

.btn-debug {
float: right;
}

.offline .btn-debug {
display: none;
}

.btn-debug {
-moz-box-shadow:inset 0px 1px 0px 0px #ffffff;
-webkit-box-shadow:inset 0px 1px 0px 0px #ffffff;
box-shadow:inset 0px 1px 0px 0px #ffffff;
background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #ffffff), color-stop(1, #f6f6f6) );
background:-moz-linear-gradient( center top, #ffffff 5%, #f6f6f6 100% );
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#f6f6f6');
background-color:#ffffff;
-moz-border-radius:6px;
-webkit-border-radius:6px;
border-radius:6px;
border:1px solid #dcdcdc;
display:inline-block;
color:#666666;
font-family:arial;
font-size:15px;
font-weight:bold;
padding:6px 24px;
text-decoration:none;
text-shadow:1px 1px 0px #ffffff;
}

.btn-debug:hover {
background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #f6f6f6), color-stop(1, #ffffff) );
background:-moz-linear-gradient( center top, #f6f6f6 5%, #ffffff 100% );
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#f6f6f6', endColorstr='#ffffff');
background-color:#f6f6f6;
}
</style>
</head>
<body>
<div id="banner" class="offline">
<h1 id="title">Karma - starting</h1>
</div>
<script src="socket.io/socket.io.js"></script>
<script src="karma.js"></script>
<script src="context.js"></script>
<!-- The scripts need to be at the end of body, so that some test running frameworks
(Angular Scenario, for example) need the body to be loaded so that it can insert its magic
into it. If it is before body, then it fails to find the body and crashes and burns in an epic
manner. -->
<script type="text/javascript">
// sets window.__karma__ and overrides console and error handling
%CLIENT_CONFIG%
window.__karma__.setupContext(window);

// All served files with the latest timestamps
%MAPPINGS%
%SCRIPT_URL_ARRAY%
</script>
<!-- Dynamically replaced with <script> tags -->
</body>
</html>
3 changes: 2 additions & 1 deletion test/client/karma.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading

0 comments on commit aa42c41

Please sign in to comment.