;(function (window) {
// backwards compatible version of (Array|String).prototype.includes
var includes = function (collection, element, startIndex) {
if (!collection || !collection.length) {
return false
}
// strings support indexOf already
if (typeof collection === 'string') {
return collection.indexOf(element, startIndex) !== -1
}
if (Array.prototype.indexOf) {
return collection.indexOf(element, startIndex) !== -1
}
for (var i = startIndex || 0, len = collection.length; i < len; i++) {
if (collection[i] === element) {
return true
}
}
}
// Date.now polyfill for IE <= 8
if (!Date.now) {
Date.now = function () {
return +new Date()
}
}
var formatError = function (error) {
var stack = error.stack
var message = error.message
if (stack) {
if (message && !includes(stack, message)) {
stack = message + '\n' + stack
}
// remove mocha stack entries
return stack.replace(/\n.+\/mocha\/mocha\.js\?\w*:[\d:]+\)?(?=(\n|$))/g, '')
}
return message
}
var processAssertionError = function (error_) {
var error
if (window.Mocha && error_.hasOwnProperty('showDiff')) {
error = {
name: error_.name,
message: error_.message,
showDiff: error_.showDiff
}
if (error.showDiff) {
error.actual = window.Mocha.utils.stringify(error_.actual)
error.expected = window.Mocha.utils.stringify(error_.expected)
}
}
return error
}
// non-compliant version of Array::reduce.call (requires memo argument)
var arrayReduce = function (array, reducer, memo) {
for (var i = 0, len = array.length; i < len; i++) {
memo = reducer(memo, array[i])
}
return memo
}
var createMochaReporterNode = function () {
var mochaRunnerNode = document.createElement('div')
mochaRunnerNode.setAttribute('id', 'mocha')
document.body.appendChild(mochaRunnerNode)
}
var haveMochaConfig = function (karma) {
return karma.config && karma.config.mocha
}
var reportTestResult = function (karma, test) {
var skipped = test.pending === true
var result = {
id: '',
description: test.title,
suite: [],
success: test.state === 'passed',
skipped: skipped,
pending: skipped,
time: skipped ? 0 : test.duration,
log: test.$errors || [],
assertionErrors: test.$assertionErrors || [],
startTime: test.$startTime,
endTime: Date.now()
}
var pointer = test.parent
while (!pointer.root) {
result.suite.unshift(pointer.title)
pointer = pointer.parent
}
if (haveMochaConfig(karma) && karma.config.mocha.expose && karma.config.mocha.expose.forEach) {
result.mocha = {}
karma.config.mocha.expose.forEach(function (prop) {
if (test.hasOwnProperty(prop)) {
result.mocha[prop] = test[prop]
}
})
}
karma.result(result)
}
var createMochaReporterConstructor = function (tc, pathname) {
var isDebugPage = /debug.html$/.test(pathname)
// Set custom reporter on debug page
if (isDebugPage && haveMochaConfig(tc) && tc.config.mocha.reporter) {
createMochaReporterNode()
return tc.config.mocha.reporter
}
// TODO(vojta): error formatting
return function (runner) {
// runner events
// - start
// - end
// - suite
// - suite end
// - test
// - test end
// - pass
// - fail
// - pending
runner.on('start', function () {
tc.info({total: runner.total})
})
runner.on('end', function () {
tc.complete({
coverage: window.__coverage__
})
})
runner.on('test', function (test) {
test.$startTime = Date.now()
test.$errors = []
test.$assertionErrors = []
})
runner.on('pending', function (test) {
test.pending = true
})
runner.on('fail', function (test, error) {
var simpleError = formatError(error)
var assertionError = processAssertionError(error)
if (test.type === 'hook') {
test.$errors = isDebugPage ? [error] : [simpleError]
test.$assertionErrors = assertionError ? [assertionError] : []
reportTestResult(tc, test)
} else {
test.$errors.push(isDebugPage ? error : simpleError)
if (assertionError) test.$assertionErrors.push(assertionError)
}
})
runner.on('test end', function (test) {
reportTestResult(tc, test)
})
}
}
/* eslint-disable no-unused-vars */
var createMochaStartFn = function (mocha) {
/* eslint-enable no-unused-vars */
return function (config) {
var clientArguments
config = config || {}
clientArguments = config.args
if (clientArguments) {
if (Object.prototype.toString.call(clientArguments) === '[object Array]') {
arrayReduce(clientArguments, function (isGrepArg, arg) {
if (isGrepArg) {
mocha.grep(new RegExp(arg))
} else if (arg === '--grep') {
return true
} else {
var match = /--grep=(.*)/.exec(arg)
if (match) {
mocha.grep(new RegExp(match[1]))
}
}
return false
}, false)
}
/**
* TODO(maksimrv): remove when karma-grunt plugin will pass
* clientArguments how Array
*/
if (clientArguments.grep) {
mocha.grep(clientArguments.grep)
}
}
mocha.run()
}
}
// Default configuration
var mochaConfig = {
reporter: createMochaReporterConstructor(window.__karma__, window.location.pathname),
ui: 'bdd',
globals: ['__cov*']
}
// Pass options from client.mocha to mocha
/* eslint-disable no-unused-vars */
var createConfigObject = function (karma) {
/* eslint-enable no-unused-vars */
if (!karma.config || !karma.config.mocha) {
return mochaConfig
}
// Copy all properties to mochaConfig
for (var key in karma.config.mocha) {
// except for reporter, require, or expose
if (includes(['reporter', 'require', 'expose'], key)) {
continue
}
// and merge the globals if they exist.
if (key === 'globals') {
mochaConfig.globals = mochaConfig.globals.concat(karma.config.mocha[key])
continue
}
mochaConfig[key] = karma.config.mocha[key]
}
return mochaConfig
}
window.__karma__.start = createMochaStartFn(window.mocha)
window.mocha.setup(createConfigObject(window.__karma__))
})(window)