123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- /**
- * 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
|