115 lines
3.9 KiB
JavaScript
115 lines
3.9 KiB
JavaScript
|
/**
|
||
|
* Runner middleware is responsible for communication with `karma run`.
|
||
|
*
|
||
|
* It basically triggers a test run and streams stdout back.
|
||
|
*/
|
||
|
|
||
|
const _ = require('lodash')
|
||
|
const path = require('path')
|
||
|
const helper = require('../helper')
|
||
|
const log = require('../logger').create()
|
||
|
const constant = require('../constants')
|
||
|
const json = require('body-parser').json()
|
||
|
|
||
|
// TODO(vojta): disable when single-run mode
|
||
|
function createRunnerMiddleware (emitter, fileList, capturedBrowsers, reporter, executor,
|
||
|
/* config.protocol */ protocol, /* config.hostname */ hostname, /* config.port */
|
||
|
port, /* config.urlRoot */ urlRoot, config) {
|
||
|
helper.saveOriginalArgs(config)
|
||
|
return function (request, response, next) {
|
||
|
if (request.url !== '/__run__' && request.url !== urlRoot + 'run') {
|
||
|
return next()
|
||
|
}
|
||
|
|
||
|
log.debug('Execution (fired by runner)')
|
||
|
response.writeHead(200)
|
||
|
|
||
|
if (!capturedBrowsers.length) {
|
||
|
const url = `${protocol}//${hostname}:${port}${urlRoot}`
|
||
|
return response.end(`No captured browser, open ${url}\n`)
|
||
|
}
|
||
|
|
||
|
json(request, response, function () {
|
||
|
if (!capturedBrowsers.areAllReady([])) {
|
||
|
response.write('Waiting for previous execution...\n')
|
||
|
}
|
||
|
|
||
|
const data = request.body
|
||
|
|
||
|
updateClientArgs(data)
|
||
|
handleRun(data)
|
||
|
refreshFileList(data).then(() => {
|
||
|
executor.schedule()
|
||
|
}).catch((error) => {
|
||
|
const errorMessage = `Error during refresh file list. ${error.stack || error}`
|
||
|
executor.scheduleError(errorMessage)
|
||
|
})
|
||
|
})
|
||
|
|
||
|
function updateClientArgs (data) {
|
||
|
helper.restoreOriginalArgs(config)
|
||
|
if (_.isEmpty(data.args)) {
|
||
|
log.debug('Ignoring empty client.args from run command')
|
||
|
} else if ((_.isArray(data.args) && _.isArray(config.client.args)) ||
|
||
|
(_.isPlainObject(data.args) && _.isPlainObject(config.client.args))) {
|
||
|
log.debug('Merging client.args with ', data.args)
|
||
|
config.client.args = _.merge(config.client.args, data.args)
|
||
|
} else {
|
||
|
log.warn('Replacing client.args with ', data.args, ' as their types do not match.')
|
||
|
config.client.args = data.args
|
||
|
}
|
||
|
}
|
||
|
|
||
|
async function refreshFileList (data) {
|
||
|
let fullRefresh = true
|
||
|
|
||
|
if (helper.isArray(data.changedFiles)) {
|
||
|
await Promise.all(data.changedFiles.map(async function (filepath) {
|
||
|
await fileList.changeFile(path.resolve(config.basePath, filepath))
|
||
|
fullRefresh = false
|
||
|
}))
|
||
|
}
|
||
|
|
||
|
if (helper.isArray(data.addedFiles)) {
|
||
|
await Promise.all(data.addedFiles.map(async function (filepath) {
|
||
|
await fileList.addFile(path.resolve(config.basePath, filepath))
|
||
|
fullRefresh = false
|
||
|
}))
|
||
|
}
|
||
|
|
||
|
if (helper.isArray(data.removedFiles)) {
|
||
|
await Promise.all(data.removedFiles.map(async function (filepath) {
|
||
|
await fileList.removeFile(path.resolve(config.basePath, filepath))
|
||
|
fullRefresh = false
|
||
|
}))
|
||
|
}
|
||
|
|
||
|
if (fullRefresh && data.refresh !== false) {
|
||
|
log.debug('Refreshing all the files / patterns')
|
||
|
await fileList.refresh()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function handleRun (data) {
|
||
|
emitter.once('run_start', function () {
|
||
|
const responseWrite = response.write.bind(response)
|
||
|
responseWrite.colors = data.colors
|
||
|
reporter.addAdapter(responseWrite)
|
||
|
|
||
|
// clean up, close runner response
|
||
|
emitter.once('run_complete', function (_browsers, results) {
|
||
|
reporter.removeAdapter(responseWrite)
|
||
|
const emptyTestSuite = (results.failed + results.success) === 0 ? 0 : 1
|
||
|
response.end(constant.EXIT_CODE + emptyTestSuite + results.exitCode)
|
||
|
})
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
createRunnerMiddleware.$inject = ['emitter', 'fileList', 'capturedBrowsers', 'reporter', 'executor',
|
||
|
'config.protocol', 'config.hostname', 'config.port', 'config.urlRoot', 'config']
|
||
|
|
||
|
// PUBLIC API
|
||
|
exports.create = createRunnerMiddleware
|