Deployed the page to Github Pages.
This commit is contained in:
parent
1d79754e93
commit
2c89899458
62797 changed files with 6551425 additions and 15279 deletions
140
node_modules/karma/lib/launchers/base.js
generated
vendored
Normal file
140
node_modules/karma/lib/launchers/base.js
generated
vendored
Normal file
|
@ -0,0 +1,140 @@
|
|||
const KarmaEventEmitter = require('../events').EventEmitter
|
||||
const EventEmitter = require('events').EventEmitter
|
||||
|
||||
const log = require('../logger').create('launcher')
|
||||
const helper = require('../helper')
|
||||
|
||||
const BEING_CAPTURED = 'BEING_CAPTURED'
|
||||
const CAPTURED = 'CAPTURED'
|
||||
const BEING_KILLED = 'BEING_KILLED'
|
||||
const FINISHED = 'FINISHED'
|
||||
const RESTARTING = 'RESTARTING'
|
||||
const BEING_FORCE_KILLED = 'BEING_FORCE_KILLED'
|
||||
|
||||
/**
|
||||
* Base launcher that any custom launcher extends.
|
||||
*/
|
||||
function BaseLauncher (id, emitter) {
|
||||
if (this.start) {
|
||||
return
|
||||
}
|
||||
|
||||
// TODO(vojta): figure out how to do inheritance with DI
|
||||
Object.keys(EventEmitter.prototype).forEach(function (method) {
|
||||
this[method] = EventEmitter.prototype[method]
|
||||
}, this)
|
||||
|
||||
this.bind = KarmaEventEmitter.prototype.bind.bind(this)
|
||||
this.emitAsync = KarmaEventEmitter.prototype.emitAsync.bind(this)
|
||||
|
||||
this.id = id
|
||||
this._state = null
|
||||
Object.defineProperty(this, 'state', {
|
||||
get: () => {
|
||||
return this._state
|
||||
},
|
||||
set: (toState) => {
|
||||
log.debug(`${this._state} -> ${toState}`)
|
||||
this._state = toState
|
||||
}
|
||||
})
|
||||
|
||||
this.error = null
|
||||
|
||||
let killingPromise
|
||||
let previousUrl
|
||||
|
||||
this.start = function (url) {
|
||||
previousUrl = url
|
||||
|
||||
this.error = null
|
||||
this.state = BEING_CAPTURED
|
||||
this.emit('start', url + '?id=' + this.id + (helper.isDefined(this.displayName) ? '&displayName=' + encodeURIComponent(this.displayName) : ''))
|
||||
}
|
||||
|
||||
this.kill = function () {
|
||||
// Already killed, or being killed.
|
||||
if (killingPromise) {
|
||||
return killingPromise
|
||||
}
|
||||
|
||||
killingPromise = this.emitAsync('kill').then(() => {
|
||||
this.state = FINISHED
|
||||
})
|
||||
|
||||
this.state = BEING_KILLED
|
||||
|
||||
return killingPromise
|
||||
}
|
||||
|
||||
this.forceKill = function () {
|
||||
this.kill()
|
||||
this.state = BEING_FORCE_KILLED
|
||||
|
||||
return killingPromise
|
||||
}
|
||||
|
||||
this.restart = function () {
|
||||
if (this.state === BEING_FORCE_KILLED) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!killingPromise) {
|
||||
killingPromise = this.emitAsync('kill')
|
||||
}
|
||||
|
||||
killingPromise.then(() => {
|
||||
if (this.state === BEING_FORCE_KILLED) {
|
||||
this.state = FINISHED
|
||||
} else {
|
||||
killingPromise = null
|
||||
log.debug(`Restarting ${this.name}`)
|
||||
this.start(previousUrl)
|
||||
}
|
||||
})
|
||||
|
||||
this.state = RESTARTING
|
||||
}
|
||||
|
||||
this.markCaptured = function () {
|
||||
if (this.state === BEING_CAPTURED) {
|
||||
this.state = CAPTURED
|
||||
}
|
||||
}
|
||||
|
||||
this.isCaptured = function () {
|
||||
return this.state === CAPTURED
|
||||
}
|
||||
|
||||
this.toString = function () {
|
||||
return this.name
|
||||
}
|
||||
|
||||
this._done = function (error) {
|
||||
killingPromise = killingPromise || Promise.resolve()
|
||||
|
||||
this.error = this.error || error
|
||||
this.emit('done')
|
||||
|
||||
if (this.error && this.state !== BEING_FORCE_KILLED && this.state !== RESTARTING) {
|
||||
emitter.emit('browser_process_failure', this)
|
||||
}
|
||||
|
||||
this.state = FINISHED
|
||||
}
|
||||
|
||||
this.STATE_BEING_CAPTURED = BEING_CAPTURED
|
||||
this.STATE_CAPTURED = CAPTURED
|
||||
this.STATE_BEING_KILLED = BEING_KILLED
|
||||
this.STATE_FINISHED = FINISHED
|
||||
this.STATE_RESTARTING = RESTARTING
|
||||
this.STATE_BEING_FORCE_KILLED = BEING_FORCE_KILLED
|
||||
}
|
||||
|
||||
BaseLauncher.decoratorFactory = function (id, emitter) {
|
||||
return function (launcher) {
|
||||
BaseLauncher.call(launcher, id, emitter)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BaseLauncher
|
43
node_modules/karma/lib/launchers/capture_timeout.js
generated
vendored
Normal file
43
node_modules/karma/lib/launchers/capture_timeout.js
generated
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
const log = require('../logger').create('launcher')
|
||||
|
||||
/**
|
||||
* Kill browser if it does not capture in given `captureTimeout`.
|
||||
*/
|
||||
function CaptureTimeoutLauncher (timer, captureTimeout) {
|
||||
if (!captureTimeout) {
|
||||
return
|
||||
}
|
||||
|
||||
let pendingTimeoutId = null
|
||||
|
||||
this.on('start', () => {
|
||||
pendingTimeoutId = timer.setTimeout(() => {
|
||||
pendingTimeoutId = null
|
||||
if (this.state !== this.STATE_BEING_CAPTURED) {
|
||||
return
|
||||
}
|
||||
|
||||
log.warn(`${this.name} has not captured in ${captureTimeout} ms, killing.`)
|
||||
this.error = 'timeout'
|
||||
this.kill()
|
||||
}, captureTimeout)
|
||||
})
|
||||
|
||||
this.on('done', () => {
|
||||
if (pendingTimeoutId) {
|
||||
timer.clearTimeout(pendingTimeoutId)
|
||||
pendingTimeoutId = null
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
CaptureTimeoutLauncher.decoratorFactory = function (timer,
|
||||
/* config.captureTimeout */ captureTimeout) {
|
||||
return function (launcher) {
|
||||
CaptureTimeoutLauncher.call(launcher, timer, captureTimeout)
|
||||
}
|
||||
}
|
||||
|
||||
CaptureTimeoutLauncher.decoratorFactory.$inject = ['timer', 'config.captureTimeout']
|
||||
|
||||
module.exports = CaptureTimeoutLauncher
|
185
node_modules/karma/lib/launchers/process.js
generated
vendored
Normal file
185
node_modules/karma/lib/launchers/process.js
generated
vendored
Normal file
|
@ -0,0 +1,185 @@
|
|||
const path = require('path')
|
||||
const log = require('../logger').create('launcher')
|
||||
const env = process.env
|
||||
|
||||
function ProcessLauncher (spawn, tempDir, timer, processKillTimeout) {
|
||||
const self = this
|
||||
let onExitCallback
|
||||
const killTimeout = processKillTimeout || 2000
|
||||
// Will hold output from the spawned child process
|
||||
const streamedOutputs = {
|
||||
stdout: '',
|
||||
stderr: ''
|
||||
}
|
||||
|
||||
this._tempDir = tempDir.getPath(`/karma-${this.id.toString()}`)
|
||||
|
||||
this.on('start', function (url) {
|
||||
tempDir.create(self._tempDir)
|
||||
self._start(url)
|
||||
})
|
||||
|
||||
this.on('kill', function (done) {
|
||||
if (!self._process) {
|
||||
return process.nextTick(done)
|
||||
}
|
||||
|
||||
onExitCallback = done
|
||||
self._process.kill()
|
||||
self._killTimer = timer.setTimeout(self._onKillTimeout, killTimeout)
|
||||
})
|
||||
|
||||
this._start = function (url) {
|
||||
self._execCommand(self._getCommand(), self._getOptions(url))
|
||||
}
|
||||
|
||||
this._getCommand = function () {
|
||||
return env[self.ENV_CMD] || self.DEFAULT_CMD[process.platform]
|
||||
}
|
||||
|
||||
this._getOptions = function (url) {
|
||||
return [url]
|
||||
}
|
||||
|
||||
// Normalize the command, remove quotes (spawn does not like them).
|
||||
this._normalizeCommand = function (cmd) {
|
||||
if (cmd.charAt(0) === cmd.charAt(cmd.length - 1) && '\'`"'.includes(cmd.charAt(0))) {
|
||||
cmd = cmd.slice(1, -1)
|
||||
log.warn(`The path should not be quoted.\n Normalized the path to ${cmd}`)
|
||||
}
|
||||
|
||||
return path.normalize(cmd)
|
||||
}
|
||||
|
||||
this._onStdout = function (data) {
|
||||
streamedOutputs.stdout += data
|
||||
}
|
||||
|
||||
this._onStderr = function (data) {
|
||||
streamedOutputs.stderr += data
|
||||
}
|
||||
|
||||
this._execCommand = function (cmd, args) {
|
||||
if (!cmd) {
|
||||
log.error(`No binary for ${self.name} browser on your platform.\n Please, set "${self.ENV_CMD}" env variable.`)
|
||||
|
||||
// disable restarting
|
||||
self._retryLimit = -1
|
||||
|
||||
return self._clearTempDirAndReportDone('no binary')
|
||||
}
|
||||
|
||||
cmd = this._normalizeCommand(cmd)
|
||||
|
||||
log.debug(cmd + ' ' + args.join(' '))
|
||||
self._process = spawn(cmd, args)
|
||||
let errorOutput = ''
|
||||
|
||||
self._process.stdout.on('data', self._onStdout)
|
||||
|
||||
self._process.stderr.on('data', self._onStderr)
|
||||
|
||||
self._process.on('exit', function (code, signal) {
|
||||
self._onProcessExit(code, signal, errorOutput)
|
||||
})
|
||||
|
||||
self._process.on('error', function (err) {
|
||||
if (err.code === 'ENOENT') {
|
||||
self._retryLimit = -1
|
||||
errorOutput = `Can not find the binary ${cmd}\n\tPlease set env variable ${self.ENV_CMD}`
|
||||
} else if (err.code === 'EACCES') {
|
||||
self._retryLimit = -1
|
||||
errorOutput = `Permission denied accessing the binary ${cmd}\n\tMaybe it's a directory?`
|
||||
} else {
|
||||
errorOutput += err.toString()
|
||||
}
|
||||
self._onProcessExit(-1, null, errorOutput)
|
||||
})
|
||||
|
||||
self._process.stderr.on('data', function (errBuff) {
|
||||
errorOutput += errBuff.toString()
|
||||
})
|
||||
}
|
||||
|
||||
this._onProcessExit = function (code, signal, errorOutput) {
|
||||
if (!self._process) {
|
||||
// Both exit and error events trigger _onProcessExit(), but we only need one cleanup.
|
||||
return
|
||||
}
|
||||
log.debug(`Process ${self.name} exited with code ${code} and signal ${signal}`)
|
||||
|
||||
let error = null
|
||||
|
||||
if (self.state === self.STATE_BEING_CAPTURED) {
|
||||
log.error(`Cannot start ${self.name}\n\t${errorOutput}`)
|
||||
error = 'cannot start'
|
||||
}
|
||||
|
||||
if (self.state === self.STATE_CAPTURED) {
|
||||
log.error(`${self.name} crashed.\n\t${errorOutput}`)
|
||||
error = 'crashed'
|
||||
}
|
||||
|
||||
if (error) {
|
||||
log.error(`${self.name} stdout: ${streamedOutputs.stdout}`)
|
||||
log.error(`${self.name} stderr: ${streamedOutputs.stderr}`)
|
||||
}
|
||||
|
||||
self._process = null
|
||||
streamedOutputs.stdout = ''
|
||||
streamedOutputs.stderr = ''
|
||||
if (self._killTimer) {
|
||||
timer.clearTimeout(self._killTimer)
|
||||
self._killTimer = null
|
||||
}
|
||||
self._clearTempDirAndReportDone(error)
|
||||
}
|
||||
|
||||
this._clearTempDirAndReportDone = function (error) {
|
||||
tempDir.remove(self._tempDir, function () {
|
||||
self._done(error)
|
||||
if (onExitCallback) {
|
||||
onExitCallback()
|
||||
onExitCallback = null
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
this._onKillTimeout = function () {
|
||||
if (self.state !== self.STATE_BEING_KILLED && self.state !== self.STATE_BEING_FORCE_KILLED) {
|
||||
return
|
||||
}
|
||||
|
||||
log.warn(`${self.name} was not killed in ${killTimeout} ms, sending SIGKILL.`)
|
||||
self._process.kill('SIGKILL')
|
||||
|
||||
// NOTE: https://github.com/karma-runner/karma/pull/1184
|
||||
// NOTE: SIGKILL is just a signal. Processes should never ignore it, but they can.
|
||||
// If a process gets into a state where it doesn't respond in a reasonable amount of time
|
||||
// Karma should warn, and continue as though the kill succeeded.
|
||||
// This a certainly suboptimal, but it is better than having the test harness hang waiting
|
||||
// for a zombie child process to exit.
|
||||
self._killTimer = timer.setTimeout(function () {
|
||||
log.warn(`${self.name} was not killed by SIGKILL in ${killTimeout} ms, continuing.`)
|
||||
self._onProcessExit(-1, null, '')
|
||||
}, killTimeout)
|
||||
}
|
||||
}
|
||||
|
||||
ProcessLauncher.decoratorFactory = function (timer) {
|
||||
return function (launcher, processKillTimeout) {
|
||||
const spawn = require('child_process').spawn
|
||||
|
||||
function spawnWithoutOutput () {
|
||||
const proc = spawn.apply(null, arguments)
|
||||
proc.stdout.resume()
|
||||
proc.stderr.resume()
|
||||
|
||||
return proc
|
||||
}
|
||||
|
||||
ProcessLauncher.call(launcher, spawnWithoutOutput, require('../temp_dir'), timer, processKillTimeout)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ProcessLauncher
|
31
node_modules/karma/lib/launchers/retry.js
generated
vendored
Normal file
31
node_modules/karma/lib/launchers/retry.js
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
const log = require('../logger').create('launcher')
|
||||
|
||||
function RetryLauncher (retryLimit) {
|
||||
this._retryLimit = retryLimit
|
||||
|
||||
this.on('done', () => {
|
||||
if (!this.error) {
|
||||
return
|
||||
}
|
||||
|
||||
if (this._retryLimit > 0) {
|
||||
log.info(`Trying to start ${this.name} again (${retryLimit - this._retryLimit + 1}/${retryLimit}).`)
|
||||
this.restart()
|
||||
this._retryLimit--
|
||||
} else if (this._retryLimit === 0) {
|
||||
log.error(`${this.name} failed ${retryLimit} times (${this.error}). Giving up.`)
|
||||
} else {
|
||||
log.debug(`${this.name} failed (${this.error}). Not restarting.`)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
RetryLauncher.decoratorFactory = function (retryLimit) {
|
||||
return function (launcher) {
|
||||
RetryLauncher.call(launcher, retryLimit)
|
||||
}
|
||||
}
|
||||
|
||||
RetryLauncher.decoratorFactory.$inject = ['config.retryLimit']
|
||||
|
||||
module.exports = RetryLauncher
|
Loading…
Add table
Add a link
Reference in a new issue