mocha-typescript
Advanced tools
Comparing version 1.1.14 to 1.1.15
#!/usr/bin/env node | ||
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const chalk_1 = require("chalk"); | ||
const spawn = require("cross-spawn"); | ||
const readline = require("readline"); | ||
const chalk = require("chalk"); | ||
const yargs = require("yargs"); | ||
const cross_spawn_1 = require("cross-spawn"); | ||
var argv = yargs | ||
const argv = yargs | ||
.options({ | ||
"p": { | ||
p: { | ||
alias: "project", | ||
@@ -15,5 +15,5 @@ demand: false, | ||
describe: "Path to tsconfig file or directory containing tsconfig, passed to `tsc -p <value>`.", | ||
type: "string" | ||
type: "string", | ||
}, | ||
"t": { | ||
t: { | ||
alias: "tsc", | ||
@@ -23,5 +23,5 @@ demand: false, | ||
describe: "Path to executable tsc, by default points to typescript installed as dev dependency. Set to 'tsc' for global tsc installation.", | ||
type: "string" | ||
type: "string", | ||
}, | ||
"o": { | ||
o: { | ||
alias: "opts", | ||
@@ -31,5 +31,5 @@ demand: false, | ||
describe: "Path to mocha.opts file containing additional mocha configuration.", | ||
type: "string" | ||
type: "string", | ||
}, | ||
"m": { | ||
m: { | ||
alias: "mocha", | ||
@@ -39,5 +39,5 @@ demand: false, | ||
describe: "Path to executable mocha, by default points to mocha installed as dev dependency.", | ||
type: "string" | ||
type: "string", | ||
}, | ||
"g": { | ||
g: { | ||
alias: "grep", | ||
@@ -47,5 +47,5 @@ demand: false, | ||
describe: "Passed down to mocha: only run tests matching <pattern>", | ||
type: "string" | ||
type: "string", | ||
}, | ||
"f": { | ||
f: { | ||
alias: "fgrep", | ||
@@ -55,4 +55,4 @@ demand: false, | ||
describe: "Passed down to mocha: only run tests containing <string>", | ||
type: "string" | ||
} | ||
type: "string", | ||
}, | ||
}) | ||
@@ -62,9 +62,9 @@ .help("h") | ||
.argv; | ||
var stdl = readline.createInterface({ input: process.stdin, }); | ||
stdl.on("line", line => { | ||
const stdl = readline.createInterface({ input: process.stdin }); | ||
stdl.on("line", (line) => { | ||
// TODO: handle "g <pattern>" or "f <pattern>" to run mocha with pattern | ||
// Ctrl + R may restart mocha test run? | ||
}); | ||
var mochap = null; | ||
var errors = 0; | ||
let mochap = null; | ||
let errors = 0; | ||
function compilationStarted() { | ||
@@ -83,23 +83,23 @@ if (mochap) { | ||
if (errors) { | ||
console.log(chalk.red("TS errors!")); | ||
console.log(chalk_1.default.red("TS errors!")); | ||
return; | ||
} | ||
else { | ||
console.log(chalk.gray("Run mocha.")); | ||
console.log(chalk_1.default.gray("Run mocha.")); | ||
} | ||
var mocha_options = ["--opts", argv.opts, "--colors"].concat(argv._); | ||
const mochaOptions = ["--opts", argv.opts, "--colors"].concat(argv._); | ||
if (argv.g) { | ||
mocha_options.push("-g"); | ||
mocha_options.push(argv.g); | ||
mochaOptions.push("-g"); | ||
mochaOptions.push(argv.g); | ||
} | ||
if (argv.f) { | ||
mocha_options.push("-f"); | ||
mocha_options.push(argv.f); | ||
mochaOptions.push("-f"); | ||
mochaOptions.push(argv.f); | ||
} | ||
mochap = cross_spawn_1.spawn(argv.mocha, mocha_options); | ||
let source = mochap; | ||
mochap.on("close", code => { | ||
mochap = spawn(argv.mocha, mochaOptions); | ||
const source = mochap; | ||
mochap.on("close", (code) => { | ||
if (source === mochap) { | ||
if (code) { | ||
console.log(chalk.red("Exited with " + code)); | ||
console.log(chalk_1.default.red("Exited with " + code)); | ||
} | ||
@@ -111,3 +111,3 @@ else { | ||
}); | ||
mochap.stdout.on("data", chunk => { | ||
mochap.stdout.on("data", (chunk) => { | ||
// Ensure old processes won't interfere tsc, .pipe here may be good enough. | ||
@@ -118,3 +118,3 @@ if (source === mochap) { | ||
}); | ||
mochap.stderr.on("data", chunk => { | ||
mochap.stderr.on("data", (chunk) => { | ||
// Ensure old processes won't interfere tsc, .pipe here may be good enough. | ||
@@ -126,6 +126,6 @@ if (source === mochap) { | ||
} | ||
var tscp = cross_spawn_1.spawn(argv.tsc, ["-p", argv.project, "-w"]); | ||
var tscl = readline.createInterface({ input: tscp.stdout }); | ||
tscl.on("line", line => { | ||
if (line.indexOf("Compilation complete.") >= 0) { | ||
const tscp = spawn(argv.tsc, ["-p", argv.project, "-w"]); | ||
const tscl = readline.createInterface({ input: tscp.stdout }); | ||
tscl.on("line", (line) => { | ||
if (line.indexOf("Compilation complete.") >= 0 || line.indexOf("Found ") >= 0) { | ||
console.log(line); | ||
@@ -132,0 +132,0 @@ compilationComplete(); |
@@ -5,5 +5,11 @@ declare namespace Mocha { | ||
} | ||
export interface Test { | ||
<T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>): TypedPropertyDescriptor<T> | void; | ||
} | ||
export interface ISuite { | ||
<TFunction extends Function>(target: TFunction): TFunction | void; | ||
} | ||
export interface Suite { | ||
<TFunction extends Function>(target: TFunction): TFunction | void; | ||
} | ||
} | ||
@@ -10,0 +16,0 @@ |
253
index.js
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const Mocha = require("mocha"); | ||
const Common = require("mocha/lib/interfaces/common"); | ||
const Test = require("mocha/lib/test"); | ||
const Common = require("mocha/lib/interfaces/common"); | ||
const globalTestFunctions = { | ||
@@ -11,18 +12,21 @@ get describe() { return global.describe; }, | ||
get beforeEach() { return global.beforeEach; }, | ||
get afterEach() { return global.afterEach; } | ||
get afterEach() { return global.afterEach; }, | ||
}; | ||
// key => Symbol("mocha-typescript:" + key) | ||
let nodeSymbol = key => "__mts_" + key; | ||
let testNameSymbol = nodeSymbol("test"); | ||
let slowSymbol = nodeSymbol("slow"); | ||
let timeoutSymbol = nodeSymbol("timout"); | ||
let retriesSymbol = nodeSymbol("retries"); | ||
let onlySymbol = nodeSymbol("only"); | ||
let pendingSumbol = nodeSymbol("pending"); | ||
let skipSymbol = nodeSymbol("skip"); | ||
let traitsSymbol = nodeSymbol("traits"); | ||
let isTraitSymbol = nodeSymbol("isTrait"); | ||
let contextSymbol = nodeSymbol("context"); | ||
let handled = nodeSymbol("handled"); | ||
const noname = cb => cb; | ||
const nodeSymbol = (key) => "__mts_" + key; | ||
const suiteSymbol = nodeSymbol("suite"); | ||
const testNameSymbol = nodeSymbol("test"); | ||
const parametersSymbol = nodeSymbol("parametersSymbol"); | ||
const nameForParametersSymbol = nodeSymbol("nameForParameters"); | ||
const slowSymbol = nodeSymbol("slow"); | ||
const timeoutSymbol = nodeSymbol("timout"); | ||
const retriesSymbol = nodeSymbol("retries"); | ||
const onlySymbol = nodeSymbol("only"); | ||
const pendingSymbol = nodeSymbol("pending"); | ||
const skipSymbol = nodeSymbol("skip"); | ||
const traitsSymbol = nodeSymbol("traits"); | ||
const isTraitSymbol = nodeSymbol("isTrait"); | ||
const contextSymbol = nodeSymbol("context"); | ||
const handled = nodeSymbol("handled"); | ||
const noname = (cb) => cb; | ||
function applyDecorators(mocha, ctorOrProto, method, instance) { | ||
@@ -34,8 +38,8 @@ const timeoutValue = method[timeoutSymbol]; | ||
const slowValue = method[slowSymbol]; | ||
if (mocha['slow'] && typeof slowValue === "number") { | ||
mocha['slow'](slowValue); | ||
if (mocha.slow && typeof slowValue === "number") { | ||
mocha.slow(slowValue); | ||
} | ||
const retriesValue = method[retriesSymbol]; | ||
if (mocha['retries'] && typeof retriesValue === "number") { | ||
mocha['retries'](retriesValue); | ||
if (mocha.retries && typeof retriesValue === "number") { | ||
mocha.retries(retriesValue); | ||
} | ||
@@ -50,3 +54,3 @@ const contextProperty = ctorOrProto[contextSymbol]; | ||
if (traits) { | ||
traits.forEach(trait => { | ||
traits.forEach((trait) => { | ||
trait.call(context, context, instance, method); | ||
@@ -59,3 +63,3 @@ }); | ||
if (traits) { | ||
traits.forEach(trait => { | ||
traits.forEach((trait) => { | ||
trait.call(context, context, target); | ||
@@ -98,3 +102,3 @@ }); | ||
} | ||
let prototype = target.prototype; | ||
const prototype = target.prototype; | ||
let beforeEachFunction; | ||
@@ -154,48 +158,83 @@ if (prototype.before) { | ||
context.afterEach(afterEachFunction); | ||
function runTests(prototype) { | ||
Object.getOwnPropertyNames(prototype).forEach(key => { | ||
try { | ||
let method = prototype[key]; | ||
if (method === target) { | ||
return; | ||
} | ||
let testName = method[testNameSymbol]; | ||
let shouldSkip = method[skipSymbol]; | ||
let shouldOnly = method[onlySymbol]; | ||
let shouldPending = method[pendingSumbol]; | ||
let testFunc = (shouldSkip && context.it.skip) | ||
|| (shouldOnly && context.it.only) | ||
|| context.it; | ||
if (testName || shouldOnly || shouldPending || shouldSkip) { | ||
testName = testName || method.name; | ||
if (shouldPending && !shouldSkip && !shouldOnly) { | ||
function runTest(prototype, method) { | ||
const testName = method[testNameSymbol] || method.name; | ||
const shouldSkip = method[skipSymbol]; | ||
const shouldOnly = method[onlySymbol]; | ||
const shouldPending = method[pendingSymbol]; | ||
const parameters = method[parametersSymbol]; | ||
if (testName || shouldOnly || shouldPending || shouldSkip) { | ||
if (shouldPending && !shouldSkip && !shouldOnly) { | ||
context.it.skip(testName); | ||
} | ||
else if (parameters) { | ||
const nameForParameters = method[nameForParametersSymbol]; | ||
parameters.forEach((parameterOptions, i) => { | ||
const { mark, name, params } = parameterOptions; | ||
let parametersTestName = `${testName}_${i}`; | ||
if (name) { | ||
parametersTestName = name; | ||
} | ||
else if (nameForParameters) { | ||
parametersTestName = nameForParameters(params); | ||
} | ||
const shouldSkipParam = shouldSkip || (mark === 1 /* skip */); | ||
const shouldOnlyParam = shouldOnly || (mark === 2 /* only */); | ||
const shouldPendingParam = shouldPending || (mark === 3 /* pending */); | ||
if (shouldPendingParam && !shouldSkipParam && !shouldOnlyParam) { | ||
context.it.skip(testName); | ||
} | ||
else if (method.length > 0) { | ||
testFunc(testName, noname(function (done) { | ||
applyDecorators(this, prototype, method, instance); | ||
applyTestTraits(this, instance, method); | ||
return method.call(instance, done); | ||
})); | ||
} | ||
else { | ||
testFunc(testName, noname(function () { | ||
applyDecorators(this, prototype, method, instance); | ||
applyTestTraits(this, instance, method); | ||
return method.call(instance); | ||
})); | ||
const testFunc = (shouldSkipParam && context.it.skip) | ||
|| (shouldOnlyParam && context.it.only) | ||
|| context.it; | ||
applyTestFunc(testFunc, parametersTestName, method, [params], method.length <= 1); | ||
} | ||
} | ||
}); | ||
} | ||
catch (e) { | ||
// console.log(e); | ||
else { | ||
const testFunc = (shouldSkip && context.it.skip) | ||
|| (shouldOnly && context.it.only) | ||
|| context.it; | ||
applyTestFunc(testFunc, testName, method, [], method.length === 0); | ||
} | ||
}); | ||
} | ||
} | ||
// run all tests along the inheritance chain | ||
function applyTestFunc(testFunc, testName, method, callArgs, sync = true) { | ||
if (sync) { | ||
testFunc(testName, noname(function () { | ||
applyDecorators(this, prototype, method, instance); | ||
applyTestTraits(this, instance, method); | ||
return method.call(instance, ...callArgs); | ||
})); | ||
} | ||
else { | ||
testFunc(testName, noname(function (done) { | ||
applyDecorators(this, prototype, method, instance); | ||
applyTestTraits(this, instance, method); | ||
return method.call(instance, ...callArgs, done); | ||
})); | ||
} | ||
} | ||
// collect all tests along the inheritance chain, allow overrides | ||
const collectedTests = {}; | ||
let currentPrototype = prototype; | ||
while (currentPrototype !== Object.prototype) { | ||
runTests(currentPrototype); | ||
Object.getOwnPropertyNames(currentPrototype).forEach((key) => { | ||
if (typeof prototype[key] === "function") { | ||
const method = prototype[key]; | ||
if (method[testNameSymbol] && !collectedTests[key]) { | ||
collectedTests[key] = [prototype, method]; | ||
} | ||
} | ||
}); | ||
currentPrototype = Object.getPrototypeOf(currentPrototype); | ||
if (currentPrototype !== Object.prototype && currentPrototype.constructor[suiteSymbol]) { | ||
throw new Error("deriving from other suites is bad practice and thus prohibited"); | ||
} | ||
} | ||
// run all collected tests | ||
for (const key in collectedTests) { | ||
const value = collectedTests[key]; | ||
runTest(value[0], value[1]); | ||
} | ||
}; | ||
@@ -205,3 +244,3 @@ } | ||
return function () { | ||
if (arguments.length == 2 && typeof arguments[0] === "string" && typeof arguments[1] === "function" && !arguments[1][isTraitSymbol]) { | ||
if (arguments.length === 2 && typeof arguments[0] === "string" && typeof arguments[1] === "function" && !arguments[1][isTraitSymbol]) { | ||
return overloads.suite.apply(this, arguments); | ||
@@ -226,2 +265,3 @@ } | ||
suiteCtor(ctor) { | ||
ctor[suiteSymbol] = true; | ||
suiteFunc(ctor)(ctor.name, suiteClassCallback(ctor, context)); | ||
@@ -231,2 +271,3 @@ }, | ||
return function (ctor) { | ||
ctor[suiteSymbol] = true; | ||
ctor[traitsSymbol] = traits; | ||
@@ -238,6 +279,7 @@ suiteFunc(ctor)(ctor.name, suiteClassCallback(ctor, context)); | ||
return function (ctor) { | ||
ctor[suiteSymbol] = true; | ||
ctor[traitsSymbol] = traits; | ||
suiteFunc(ctor)(name, suiteClassCallback(ctor, context)); | ||
}; | ||
} | ||
}, | ||
}); | ||
@@ -248,5 +290,5 @@ } | ||
if (ctor) { | ||
let shouldSkip = ctor[skipSymbol]; | ||
let shouldOnly = ctor[onlySymbol]; | ||
let shouldPending = ctor[pendingSumbol]; | ||
const shouldSkip = ctor[skipSymbol]; | ||
const shouldOnly = ctor[onlySymbol]; | ||
const shouldPending = ctor[pendingSymbol]; | ||
return (shouldSkip && context.describe.skip) | ||
@@ -266,9 +308,41 @@ || (shouldOnly && context.describe.only) | ||
only: makeSuiteFunction(() => context.describe.only, context), | ||
pending: makeSuiteFunction(() => context.describe.skip, context) | ||
pending: makeSuiteFunction(() => context.describe.skip, context), | ||
}); | ||
} | ||
exports.suite = makeSuiteObject(globalTestFunctions); | ||
var Mark; | ||
(function (Mark) { | ||
Mark[Mark["test"] = 0] = "test"; | ||
Mark[Mark["skip"] = 1] = "skip"; | ||
Mark[Mark["only"] = 2] = "only"; | ||
Mark[Mark["pending"] = 3] = "pending"; | ||
})(Mark || (Mark = {})); | ||
function makeParamsFunction(mark) { | ||
return (params, name) => { | ||
return (target, propertyKey) => { | ||
target[propertyKey][testNameSymbol] = propertyKey ? propertyKey.toString() : ""; | ||
target[propertyKey][parametersSymbol] = target[propertyKey][parametersSymbol] || []; | ||
target[propertyKey][parametersSymbol].push({ mark, name, params }); | ||
}; | ||
}; | ||
} | ||
function makeParamsNameFunction() { | ||
return (nameForParameters) => { | ||
return (target, propertyKey) => { | ||
target[propertyKey][nameForParametersSymbol] = nameForParameters; | ||
}; | ||
}; | ||
} | ||
function makeParamsObject(context) { | ||
return Object.assign(makeParamsFunction(0 /* test */), { | ||
skip: makeParamsFunction(1 /* skip */), | ||
only: makeParamsFunction(2 /* only */), | ||
pending: makeParamsFunction(3 /* pending */), | ||
naming: makeParamsNameFunction(), | ||
}); | ||
} | ||
exports.params = makeParamsObject(globalTestFunctions); | ||
function testOverload(overloads) { | ||
return function () { | ||
if (arguments.length == 2 && typeof arguments[0] === "string" && typeof arguments[1] === "function" && !arguments[1][isTraitSymbol]) { | ||
if (arguments.length === 2 && typeof arguments[0] === "string" && typeof arguments[1] === "function" && !arguments[1][isTraitSymbol]) { | ||
return overloads.test.apply(this, arguments); | ||
@@ -294,3 +368,5 @@ } | ||
target[propertyKey][testNameSymbol] = propertyKey ? propertyKey.toString() : ""; | ||
mark && (target[propertyKey][mark] = true); | ||
if (mark) { | ||
target[propertyKey][mark] = true; | ||
} | ||
}, | ||
@@ -301,3 +377,5 @@ testDecorator(...traits) { | ||
target[propertyKey][traitsSymbol] = traits; | ||
mark && (target[propertyKey][mark] = true); | ||
if (mark) { | ||
target[propertyKey][mark] = true; | ||
} | ||
}; | ||
@@ -309,5 +387,7 @@ }, | ||
target[propertyKey][traitsSymbol] = traits; | ||
mark && (target[propertyKey][mark] = true); | ||
if (mark) { | ||
target[propertyKey][mark] = true; | ||
} | ||
}; | ||
} | ||
}, | ||
}); | ||
@@ -319,3 +399,3 @@ } | ||
only: makeTestFunction(() => context.it.only, onlySymbol), | ||
pending: makeTestFunction(() => context.it.skip, pendingSumbol) | ||
pending: makeTestFunction(() => context.it.skip, pendingSymbol), | ||
}); | ||
@@ -459,6 +539,6 @@ } | ||
if (arguments.length === 1) { | ||
target[pendingSumbol] = true; | ||
target[pendingSymbol] = true; | ||
} | ||
else { | ||
target[propertyKey][pendingSumbol] = true; | ||
target[propertyKey][pendingSymbol] = true; | ||
} | ||
@@ -507,5 +587,5 @@ } | ||
function tsdd(suite) { | ||
var suites = [suite]; | ||
suite.on('pre-require', function (context, file, mocha) { | ||
var common = Common(suites, context, mocha); | ||
const suites = [suite]; | ||
suite.on("pre-require", function (context, file, mocha) { | ||
const common = Common(suites, context, mocha); | ||
context.before = common.before; | ||
@@ -519,5 +599,5 @@ context.after = common.after; | ||
return common.suite.create({ | ||
title: title, | ||
file: file, | ||
fn: fn | ||
title, | ||
file, | ||
fn, | ||
}); | ||
@@ -527,5 +607,5 @@ }; | ||
return common.suite.skip({ | ||
title: title, | ||
file: file, | ||
fn: fn | ||
title, | ||
file, | ||
fn, | ||
}); | ||
@@ -535,13 +615,13 @@ }; | ||
return common.suite.only({ | ||
title: title, | ||
file: file, | ||
fn: fn | ||
title, | ||
file, | ||
fn, | ||
}); | ||
}; | ||
context.it = context.specify = function (title, fn) { | ||
var suite = suites[0]; | ||
const suite = suites[0]; | ||
if (suite.isPending()) { | ||
fn = null; | ||
} | ||
var test = new Test(title, fn); | ||
const test = new Test(title, fn); | ||
test.file = file; | ||
@@ -561,2 +641,3 @@ suite.addTest(test); | ||
context.suite = makeSuiteObject(context); | ||
context.params = makeParamsObject(context); | ||
context.test = makeTestObject(context); | ||
@@ -570,4 +651,4 @@ context.test.retries = common.test.retries; | ||
} | ||
; | ||
module.exports = Object.assign(tsdd, exports); | ||
Mocha.interfaces["mocha-typescript"] = tsdd; | ||
//# sourceMappingURL=index.js.map |
984
index.ts
import * as Mocha from "mocha"; | ||
import * as Common from "mocha/lib/interfaces/common"; | ||
import * as Suite from "mocha/lib/suite"; | ||
import * as Test from "mocha/lib/test"; | ||
import * as Common from "mocha/lib/interfaces/common"; | ||
interface TestFunctions { | ||
it: { | ||
(name: string, fn: Function): void, | ||
only(name: string, fn: Function): void; | ||
skip(name: string, fn?: Function): void; | ||
}, | ||
describe: { | ||
(name: string, fn: Function): void, | ||
only(name: string, fn: Function): void; | ||
skip(name: string, fn?: Function): void; | ||
}, | ||
before: any, | ||
after: any, | ||
beforeEach: any, | ||
afterEach: any | ||
it: { | ||
(name: string, fn: Function): void, | ||
only(name: string, fn: Function): void; | ||
skip(name: string, fn?: Function): void; | ||
}; | ||
describe: { | ||
(name: string, fn: Function): void, | ||
only(name: string, fn: Function): void; | ||
skip(name: string, fn?: Function): void; | ||
}; | ||
before: any; | ||
after: any; | ||
beforeEach: any; | ||
afterEach: any; | ||
} | ||
const globalTestFunctions: TestFunctions = { | ||
get describe() { return (<any>global).describe; }, | ||
get it() { return (<any>global).it; }, | ||
get before() { return (<any>global).before; }, | ||
get after() { return (<any>global).after; }, | ||
get beforeEach() { return (<any>global).beforeEach; }, | ||
get afterEach() { return (<any>global).afterEach; } | ||
get describe() { return (global as any).describe; }, | ||
get it() { return (global as any).it; }, | ||
get before() { return (global as any).before; }, | ||
get after() { return (global as any).after; }, | ||
get beforeEach() { return (global as any).beforeEach; }, | ||
get afterEach() { return (global as any).afterEach; }, | ||
}; | ||
// key => Symbol("mocha-typescript:" + key) | ||
let nodeSymbol = key => "__mts_" + key; | ||
const nodeSymbol = (key) => "__mts_" + key; | ||
let testNameSymbol = nodeSymbol("test"); | ||
let slowSymbol = nodeSymbol("slow"); | ||
let timeoutSymbol = nodeSymbol("timout"); | ||
let retriesSymbol = nodeSymbol("retries"); | ||
let onlySymbol = nodeSymbol("only"); | ||
let pendingSumbol = nodeSymbol("pending"); | ||
let skipSymbol = nodeSymbol("skip"); | ||
let traitsSymbol = nodeSymbol("traits"); | ||
let isTraitSymbol = nodeSymbol("isTrait"); | ||
let contextSymbol = nodeSymbol("context"); | ||
let handled = nodeSymbol("handled"); | ||
const suiteSymbol = nodeSymbol("suite"); | ||
const testNameSymbol = nodeSymbol("test"); | ||
const parametersSymbol = nodeSymbol("parametersSymbol"); | ||
const nameForParametersSymbol = nodeSymbol("nameForParameters"); | ||
const slowSymbol = nodeSymbol("slow"); | ||
const timeoutSymbol = nodeSymbol("timout"); | ||
const retriesSymbol = nodeSymbol("retries"); | ||
const onlySymbol = nodeSymbol("only"); | ||
const pendingSymbol = nodeSymbol("pending"); | ||
const skipSymbol = nodeSymbol("skip"); | ||
const traitsSymbol = nodeSymbol("traits"); | ||
const isTraitSymbol = nodeSymbol("isTrait"); | ||
const contextSymbol = nodeSymbol("context"); | ||
const handled = nodeSymbol("handled"); | ||
interface MochaDone { | ||
(error?: any): any; | ||
} | ||
type MochaDone = (error?: any) => any; | ||
interface SuiteCtor { | ||
prototype: SuiteProto; | ||
before?: (done?: MochaDone) => void; | ||
after?: (done?: MochaDone) => void; | ||
new(); | ||
prototype: SuiteProto; | ||
before?: (done?: MochaDone) => void; | ||
after?: (done?: MochaDone) => void; | ||
new(); | ||
} | ||
interface SuiteProto { | ||
before?: (done?: MochaDone) => void; | ||
after?: (done?: MochaDone) => void; | ||
before?: (done?: MochaDone) => void; | ||
after?: (done?: MochaDone) => void; | ||
[key: string]: any; | ||
} | ||
export interface SuiteTrait { | ||
(this: Mocha.ISuiteCallbackContext, ctx: Mocha.ISuiteCallbackContext, ctor: SuiteCtor): void; | ||
} | ||
export interface TestTrait { | ||
(this: Mocha.ITestCallbackContext, ctx: Mocha.ITestCallbackContext, instance: SuiteProto, method: Function): void; | ||
} | ||
export type SuiteTrait = (this: Mocha.ISuiteCallbackContext, ctx: Mocha.ISuiteCallbackContext, ctor: SuiteCtor) => void; | ||
export type TestTrait = (this: Mocha.ITestCallbackContext, ctx: Mocha.ITestCallbackContext, instance: SuiteProto, method: Function) => void; | ||
const noname = cb => cb; | ||
const noname = (cb) => cb; | ||
function applyDecorators(mocha: Mocha.IHookCallbackContext, ctorOrProto, method, instance) { | ||
const timeoutValue = method[timeoutSymbol]; | ||
if (typeof timeoutValue === "number") { | ||
mocha.timeout(timeoutValue); | ||
} | ||
const slowValue = method[slowSymbol]; | ||
if (mocha['slow'] && typeof slowValue === "number") { | ||
mocha['slow'](slowValue); | ||
} | ||
const retriesValue = method[retriesSymbol]; | ||
if (mocha['retries'] && typeof retriesValue === "number") { | ||
mocha['retries'](retriesValue); | ||
} | ||
const contextProperty = ctorOrProto[contextSymbol]; | ||
if (contextProperty) { | ||
instance[contextProperty] = mocha; | ||
} | ||
const timeoutValue = method[timeoutSymbol]; | ||
if (typeof timeoutValue === "number") { | ||
mocha.timeout(timeoutValue); | ||
} | ||
const slowValue = method[slowSymbol]; | ||
if (mocha.slow && typeof slowValue === "number") { | ||
mocha.slow(slowValue); | ||
} | ||
const retriesValue = method[retriesSymbol]; | ||
if (mocha.retries && typeof retriesValue === "number") { | ||
mocha.retries(retriesValue); | ||
} | ||
const contextProperty = ctorOrProto[contextSymbol]; | ||
if (contextProperty) { | ||
instance[contextProperty] = mocha; | ||
} | ||
} | ||
function applyTestTraits(context: Mocha.ITestCallbackContext, instance: SuiteProto, method: Function) { | ||
const traits: TestTrait[] = method[traitsSymbol]; | ||
if (traits) { | ||
traits.forEach(trait => { | ||
trait.call(context, context, instance, method); | ||
}); | ||
} | ||
const traits: TestTrait[] = method[traitsSymbol]; | ||
if (traits) { | ||
traits.forEach((trait) => { | ||
trait.call(context, context, instance, method); | ||
}); | ||
} | ||
} | ||
function applySuiteTraits(context: Mocha.ISuiteCallbackContext, target: SuiteCtor) { | ||
const traits: SuiteTrait[] = target[traitsSymbol]; | ||
if (traits) { | ||
traits.forEach(trait => { | ||
trait.call(context, context, target); | ||
}); | ||
} | ||
const traits: SuiteTrait[] = target[traitsSymbol]; | ||
if (traits) { | ||
traits.forEach((trait) => { | ||
trait.call(context, context, target); | ||
}); | ||
} | ||
} | ||
function suiteClassCallback(target: SuiteCtor, context: TestFunctions) { | ||
return function () { | ||
applySuiteTraits(this, target); | ||
applyDecorators(this, target, target, target); | ||
let instance; | ||
if (target.before) { | ||
if (target.before.length > 0) { | ||
context.before(function (done) { | ||
applyDecorators(this, target, target.before, target); | ||
return target.before(done); | ||
}); | ||
} else { | ||
context.before(function () { | ||
applyDecorators(this, target, target.before, target); | ||
return target.before(); | ||
}); | ||
} | ||
} | ||
if (target.after) { | ||
if (target.after.length > 0) { | ||
context.after(function (done) { | ||
applyDecorators(this, target, target.after, target); | ||
return target.after(done); | ||
}); | ||
} else { | ||
context.after(function () { | ||
applyDecorators(this, target, target.after, target); | ||
return target.after(); | ||
}); | ||
} | ||
} | ||
let prototype = target.prototype; | ||
let beforeEachFunction: { (): any } | { (done: Function): any }; | ||
if (prototype.before) { | ||
if (prototype.before.length > 0) { | ||
beforeEachFunction = noname(function (this: Mocha.IHookCallbackContext, done: Function) { | ||
instance = new target(); | ||
applyDecorators(this, prototype, prototype.before, instance); | ||
return prototype.before.call(instance, done); | ||
}); | ||
} else { | ||
beforeEachFunction = noname(function (this: Mocha.IHookCallbackContext) { | ||
instance = new target(); | ||
applyDecorators(this, prototype, prototype.before, instance); | ||
return prototype.before.call(instance); | ||
}); | ||
} | ||
} else { | ||
beforeEachFunction = noname(function (this: Mocha.IHookCallbackContext) { | ||
instance = new target(); | ||
}); | ||
} | ||
context.beforeEach(beforeEachFunction); | ||
return function() { | ||
applySuiteTraits(this, target); | ||
applyDecorators(this, target, target, target); | ||
let instance; | ||
if (target.before) { | ||
if (target.before.length > 0) { | ||
context.before(function(done) { | ||
applyDecorators(this, target, target.before, target); | ||
return target.before(done); | ||
}); | ||
} else { | ||
context.before(function() { | ||
applyDecorators(this, target, target.before, target); | ||
return target.before(); | ||
}); | ||
} | ||
} | ||
if (target.after) { | ||
if (target.after.length > 0) { | ||
context.after(function(done) { | ||
applyDecorators(this, target, target.after, target); | ||
return target.after(done); | ||
}); | ||
} else { | ||
context.after(function() { | ||
applyDecorators(this, target, target.after, target); | ||
return target.after(); | ||
}); | ||
} | ||
} | ||
const prototype = target.prototype; | ||
let beforeEachFunction: (() => any) | ((done: Function) => any); | ||
if (prototype.before) { | ||
if (prototype.before.length > 0) { | ||
beforeEachFunction = noname(function(this: Mocha.IHookCallbackContext, done: Function) { | ||
instance = new target(); | ||
applyDecorators(this, prototype, prototype.before, instance); | ||
return prototype.before.call(instance, done); | ||
}); | ||
} else { | ||
beforeEachFunction = noname(function(this: Mocha.IHookCallbackContext) { | ||
instance = new target(); | ||
applyDecorators(this, prototype, prototype.before, instance); | ||
return prototype.before.call(instance); | ||
}); | ||
} | ||
} else { | ||
beforeEachFunction = noname(function(this: Mocha.IHookCallbackContext) { | ||
instance = new target(); | ||
}); | ||
} | ||
context.beforeEach(beforeEachFunction); | ||
let afterEachFunction: { (): any } | { (done: Function): any }; | ||
if (prototype.after) { | ||
if (prototype.after.length > 0) { | ||
afterEachFunction = noname(function (this: Mocha.IHookCallbackContext, done) { | ||
try { | ||
applyDecorators(this, prototype, prototype.after, instance); | ||
return prototype.after.call(instance, done); | ||
} finally { | ||
instance = undefined; | ||
} | ||
}); | ||
} else { | ||
afterEachFunction = noname(function (this: Mocha.IHookCallbackContext) { | ||
try { | ||
applyDecorators(this, prototype, prototype.after, instance); | ||
return prototype.after.call(instance); | ||
} finally { | ||
instance = undefined; | ||
} | ||
}); | ||
} | ||
} else { | ||
afterEachFunction = noname(function (this: Mocha.IHookCallbackContext) { | ||
instance = undefined; | ||
}); | ||
} | ||
context.afterEach(afterEachFunction); | ||
let afterEachFunction: (() => any) | ((done: Function) => any); | ||
if (prototype.after) { | ||
if (prototype.after.length > 0) { | ||
afterEachFunction = noname(function(this: Mocha.IHookCallbackContext, done) { | ||
try { | ||
applyDecorators(this, prototype, prototype.after, instance); | ||
return prototype.after.call(instance, done); | ||
} finally { | ||
instance = undefined; | ||
} | ||
}); | ||
} else { | ||
afterEachFunction = noname(function(this: Mocha.IHookCallbackContext) { | ||
try { | ||
applyDecorators(this, prototype, prototype.after, instance); | ||
return prototype.after.call(instance); | ||
} finally { | ||
instance = undefined; | ||
} | ||
}); | ||
} | ||
} else { | ||
afterEachFunction = noname(function(this: Mocha.IHookCallbackContext) { | ||
instance = undefined; | ||
}); | ||
} | ||
context.afterEach(afterEachFunction); | ||
function runTests(prototype: any) { | ||
(<any>Object).getOwnPropertyNames(prototype).forEach(key => { | ||
try { | ||
let method = <Function>prototype[key]; | ||
if (method === target) { | ||
return; | ||
} | ||
function runTest(prototype: any, method: Function) { | ||
const testName = method[testNameSymbol] || (method as any).name; | ||
const shouldSkip = method[skipSymbol]; | ||
const shouldOnly = method[onlySymbol]; | ||
const shouldPending = method[pendingSymbol]; | ||
const parameters = method[parametersSymbol] as TestParams[]; | ||
let testName = method[testNameSymbol]; | ||
let shouldSkip = method[skipSymbol]; | ||
let shouldOnly = method[onlySymbol]; | ||
let shouldPending = method[pendingSumbol]; | ||
if (testName || shouldOnly || shouldPending || shouldSkip) { | ||
if (shouldPending && !shouldSkip && !shouldOnly) { | ||
context.it.skip(testName); | ||
} else if (parameters) { | ||
const nameForParameters = method[nameForParametersSymbol]; | ||
parameters.forEach((parameterOptions, i) => { | ||
const { mark, name, params } = parameterOptions; | ||
let testFunc = (shouldSkip && context.it.skip) | ||
|| (shouldOnly && context.it.only) | ||
|| context.it; | ||
let parametersTestName = `${testName}_${i}`; | ||
if (name) { | ||
parametersTestName = name; | ||
} else if (nameForParameters) { | ||
parametersTestName = nameForParameters(params); | ||
} | ||
if (testName || shouldOnly || shouldPending || shouldSkip) { | ||
testName = testName || (<any>method).name; | ||
if (shouldPending && !shouldSkip && !shouldOnly) { | ||
context.it.skip(testName); | ||
} else if (method.length > 0) { | ||
testFunc(testName, noname(function(this: Mocha.ITestCallbackContext, done) { | ||
applyDecorators(this, prototype, method, instance); | ||
applyTestTraits(this, instance, method); | ||
return method.call(instance, done); | ||
})); | ||
const shouldSkipParam = shouldSkip || (mark === Mark.skip); | ||
const shouldOnlyParam = shouldOnly || (mark === Mark.only); | ||
const shouldPendingParam = shouldPending || (mark === Mark.pending); | ||
if (shouldPendingParam && !shouldSkipParam && !shouldOnlyParam) { | ||
context.it.skip(testName); | ||
} else { | ||
const testFunc = (shouldSkipParam && context.it.skip) | ||
|| (shouldOnlyParam && context.it.only) | ||
|| context.it; | ||
applyTestFunc(testFunc, parametersTestName, method, [params], method.length <= 1); | ||
} | ||
}); | ||
} else { | ||
const testFunc = (shouldSkip && context.it.skip) | ||
|| (shouldOnly && context.it.only) | ||
|| context.it; | ||
applyTestFunc(testFunc, testName, method, [], method.length === 0); | ||
} | ||
} | ||
} | ||
function applyTestFunc(testFunc: Function, testName: string, | ||
method: Function, callArgs: any[], | ||
sync: boolean = true) { | ||
if (sync) { | ||
testFunc(testName, noname(function(this: Mocha.ITestCallbackContext) { | ||
applyDecorators(this, prototype, method, instance); | ||
applyTestTraits(this, instance, method); | ||
return method.call(instance, ...callArgs); | ||
})); | ||
} else { | ||
testFunc(testName, noname(function(this: Mocha.ITestCallbackContext) { | ||
applyDecorators(this, prototype, method, instance); | ||
applyTestTraits(this, instance, method); | ||
return method.call(instance); | ||
})); | ||
testFunc(testName, noname(function(this: Mocha.ITestCallbackContext, done) { | ||
applyDecorators(this, prototype, method, instance); | ||
applyTestTraits(this, instance, method); | ||
return method.call(instance, ...callArgs, done); | ||
})); | ||
} | ||
} | ||
} catch (e) { | ||
// console.log(e); | ||
} | ||
}); | ||
} | ||
// run all tests along the inheritance chain | ||
let currentPrototype = prototype; | ||
while (currentPrototype !== Object.prototype) { | ||
runTests(currentPrototype); | ||
currentPrototype = (<any>Object).getPrototypeOf(currentPrototype); | ||
} | ||
} | ||
// collect all tests along the inheritance chain, allow overrides | ||
const collectedTests: { [key: string]: any[] } = {}; | ||
let currentPrototype = prototype; | ||
while (currentPrototype !== Object.prototype) { | ||
Object.getOwnPropertyNames(currentPrototype).forEach((key) => { | ||
if (typeof prototype[key] === "function") { | ||
const method = prototype[key]; | ||
if (method[testNameSymbol] && !collectedTests[key]) { | ||
collectedTests[key] = [prototype, method]; | ||
} | ||
} | ||
}); | ||
currentPrototype = (Object as any).getPrototypeOf(currentPrototype); | ||
if (currentPrototype !== Object.prototype && currentPrototype.constructor[suiteSymbol]) { | ||
throw new Error("deriving from other suites is bad practice and thus prohibited"); | ||
} | ||
} | ||
// run all collected tests | ||
for (const key in collectedTests) { | ||
const value = collectedTests[key]; | ||
runTest(value[0], value[1]); | ||
} | ||
}; | ||
} | ||
function suiteOverload(overloads: { | ||
suite(name: string, fn: Function): any; | ||
suiteCtor(ctor: SuiteCtor): void; | ||
suiteDecorator(... traits: SuiteTrait[]): ClassDecorator; | ||
suiteDecoratorNamed(name: string, ... traits: SuiteTrait[]): ClassDecorator; | ||
suite(name: string, fn: Function): any; | ||
suiteCtor(ctor: SuiteCtor): void; | ||
suiteDecorator(...traits: SuiteTrait[]): ClassDecorator; | ||
suiteDecoratorNamed(name: string, ...traits: SuiteTrait[]): ClassDecorator; | ||
}) { | ||
return function() { | ||
if (arguments.length == 2 && typeof arguments[0] === "string" && typeof arguments[1] === "function" && !arguments[1][isTraitSymbol]) { | ||
return overloads.suite.apply(this, arguments); | ||
} else if (arguments.length === 1 && typeof arguments[0] === "function" && !arguments[0][isTraitSymbol]) { | ||
overloads.suiteCtor.apply(this, arguments); | ||
} else if (arguments.length >= 1 && typeof arguments[0] === "string") { | ||
return overloads.suiteDecoratorNamed.apply(this, arguments); | ||
} else { | ||
return overloads.suiteDecorator.apply(this, arguments); | ||
} | ||
} | ||
return function() { | ||
if (arguments.length === 2 && typeof arguments[0] === "string" && typeof arguments[1] === "function" && !arguments[1][isTraitSymbol]) { | ||
return overloads.suite.apply(this, arguments); | ||
} else if (arguments.length === 1 && typeof arguments[0] === "function" && !arguments[0][isTraitSymbol]) { | ||
overloads.suiteCtor.apply(this, arguments); | ||
} else if (arguments.length >= 1 && typeof arguments[0] === "string") { | ||
return overloads.suiteDecoratorNamed.apply(this, arguments); | ||
} else { | ||
return overloads.suiteDecorator.apply(this, arguments); | ||
} | ||
}; | ||
} | ||
function makeSuiteFunction(suiteFunc: (ctor?: SuiteCtor) => Function, context: TestFunctions) { | ||
return suiteOverload({ | ||
suite(name: string, fn: Function): any { | ||
return suiteFunc()(name, fn); | ||
}, | ||
suiteCtor(ctor: SuiteCtor): void { | ||
suiteFunc(ctor)(ctor.name, suiteClassCallback(ctor, context)); | ||
}, | ||
suiteDecorator(... traits: SuiteTrait[]): ClassDecorator { | ||
return function<TFunction extends Function>(ctor: TFunction): void { | ||
ctor[traitsSymbol] = traits; | ||
suiteFunc(<any>ctor)(ctor.name, suiteClassCallback(<any>ctor, context)); | ||
} | ||
}, | ||
suiteDecoratorNamed(name: string, ... traits: SuiteTrait[]): ClassDecorator { | ||
return function<TFunction extends Function>(ctor: TFunction): void { | ||
ctor[traitsSymbol] = traits; | ||
suiteFunc(<any>ctor)(name, suiteClassCallback(<any>ctor, context)); | ||
} | ||
} | ||
}); | ||
return suiteOverload({ | ||
suite(name: string, fn: Function): any { | ||
return suiteFunc()(name, fn); | ||
}, | ||
suiteCtor(ctor: SuiteCtor): void { | ||
ctor[suiteSymbol] = true; | ||
suiteFunc(ctor)(ctor.name, suiteClassCallback(ctor, context)); | ||
}, | ||
suiteDecorator(...traits: SuiteTrait[]): ClassDecorator { | ||
return function <TFunction extends Function>(ctor: TFunction): void { | ||
ctor[suiteSymbol] = true; | ||
ctor[traitsSymbol] = traits; | ||
suiteFunc(ctor as any)(ctor.name, suiteClassCallback(ctor as any, context)); | ||
}; | ||
}, | ||
suiteDecoratorNamed(name: string, ...traits: SuiteTrait[]): ClassDecorator { | ||
return function <TFunction extends Function>(ctor: TFunction): void { | ||
ctor[suiteSymbol] = true; | ||
ctor[traitsSymbol] = traits; | ||
suiteFunc(ctor as any)(name, suiteClassCallback(ctor as any, context)); | ||
}; | ||
}, | ||
}); | ||
} | ||
function suiteFuncCheckingDecorators(context: TestFunctions) { | ||
return function(ctor?: SuiteCtor) { | ||
if (ctor) { | ||
let shouldSkip = ctor[skipSymbol]; | ||
let shouldOnly = ctor[onlySymbol]; | ||
let shouldPending = ctor[pendingSumbol]; | ||
return (shouldSkip && context.describe.skip) | ||
|| (shouldOnly && context.describe.only) | ||
|| (shouldPending && context.describe.skip) | ||
|| context.describe; | ||
} else { | ||
return context.describe; | ||
} | ||
} | ||
return function(ctor?: SuiteCtor) { | ||
if (ctor) { | ||
const shouldSkip = ctor[skipSymbol]; | ||
const shouldOnly = ctor[onlySymbol]; | ||
const shouldPending = ctor[pendingSymbol]; | ||
return (shouldSkip && context.describe.skip) | ||
|| (shouldOnly && context.describe.only) | ||
|| (shouldPending && context.describe.skip) | ||
|| context.describe; | ||
} else { | ||
return context.describe; | ||
} | ||
}; | ||
} | ||
function makeSuiteObject(context: TestFunctions): Suite { | ||
return Object.assign(makeSuiteFunction(suiteFuncCheckingDecorators(context), context), { | ||
skip: makeSuiteFunction(() => context.describe.skip, context), | ||
only: makeSuiteFunction(() => context.describe.only, context), | ||
pending: makeSuiteFunction(() => context.describe.skip, context) | ||
}); | ||
return Object.assign(makeSuiteFunction(suiteFuncCheckingDecorators(context), context), { | ||
skip: makeSuiteFunction(() => context.describe.skip, context), | ||
only: makeSuiteFunction(() => context.describe.only, context), | ||
pending: makeSuiteFunction(() => context.describe.skip, context), | ||
}); | ||
} | ||
export const suite = makeSuiteObject(globalTestFunctions); | ||
const enum Mark { test, skip, only, pending } | ||
interface TestParams { | ||
mark: Mark; | ||
name?: string; | ||
params: any; | ||
} | ||
function makeParamsFunction(mark: Mark) { | ||
return (params: any, name?: string) => { | ||
return (target: Object, propertyKey: string) => { | ||
target[propertyKey][testNameSymbol] = propertyKey ? propertyKey.toString() : ""; | ||
target[propertyKey][parametersSymbol] = target[propertyKey][parametersSymbol] || []; | ||
target[propertyKey][parametersSymbol].push({ mark, name, params } as TestParams); | ||
}; | ||
}; | ||
} | ||
function makeParamsNameFunction() { | ||
return (nameForParameters: (parameters: any) => string) => { | ||
return (target: Object, propertyKey: string) => { | ||
target[propertyKey][nameForParametersSymbol] = nameForParameters; | ||
}; | ||
}; | ||
} | ||
function makeParamsObject(context: TestFunctions) { | ||
return Object.assign(makeParamsFunction(Mark.test), { | ||
skip: makeParamsFunction(Mark.skip), | ||
only: makeParamsFunction(Mark.only), | ||
pending: makeParamsFunction(Mark.pending), | ||
naming: makeParamsNameFunction(), | ||
}); | ||
} | ||
export const params = makeParamsObject(globalTestFunctions); | ||
function testOverload(overloads: { | ||
test(name: string, fn: Function); | ||
testProperty(target: Object, propertyKey: string | symbol, descriptor?: PropertyDescriptor): void; | ||
testDecorator(... traits: TestTrait[]): PropertyDecorator & MethodDecorator; | ||
testDecoratorNamed(name: string, ... traits: TestTrait[]): PropertyDecorator & MethodDecorator; | ||
test(name: string, fn: Function); | ||
testProperty(target: Object, propertyKey: string | symbol, descriptor?: PropertyDescriptor): void; | ||
testDecorator(...traits: TestTrait[]): PropertyDecorator & MethodDecorator; | ||
testDecoratorNamed(name: string, ...traits: TestTrait[]): PropertyDecorator & MethodDecorator; | ||
}) { | ||
return function() { | ||
if (arguments.length == 2 && typeof arguments[0] === "string" && typeof arguments[1] === "function" && !arguments[1][isTraitSymbol]) { | ||
return overloads.test.apply(this, arguments); | ||
} else if (arguments.length >= 2 && typeof arguments[0] !== "string" && typeof arguments[0] !== "function") { | ||
overloads.testProperty.apply(this, arguments); | ||
} else if (arguments.length >= 1 && typeof arguments[0] === "string") { | ||
return overloads.testDecoratorNamed.apply(this, arguments); | ||
} else { | ||
return overloads.testDecorator.apply(this, arguments); | ||
} | ||
} | ||
return function() { | ||
if (arguments.length === 2 && typeof arguments[0] === "string" && typeof arguments[1] === "function" && !arguments[1][isTraitSymbol]) { | ||
return overloads.test.apply(this, arguments); | ||
} else if (arguments.length >= 2 && typeof arguments[0] !== "string" && typeof arguments[0] !== "function") { | ||
overloads.testProperty.apply(this, arguments); | ||
} else if (arguments.length >= 1 && typeof arguments[0] === "string") { | ||
return overloads.testDecoratorNamed.apply(this, arguments); | ||
} else { | ||
return overloads.testDecorator.apply(this, arguments); | ||
} | ||
}; | ||
} | ||
function makeTestFunction(testFunc: () => Function, mark: null | string | symbol) { | ||
return testOverload({ | ||
test(name: string, fn: Function) { | ||
testFunc()(name, fn); | ||
}, | ||
testProperty(target: Object, propertyKey: string | symbol, descriptor?: PropertyDescriptor): void { | ||
target[propertyKey][testNameSymbol] = propertyKey ? propertyKey.toString() : ""; | ||
mark && (target[propertyKey][mark] = true); | ||
}, | ||
testDecorator(... traits: TestTrait[]): PropertyDecorator & MethodDecorator { | ||
return function(target: Object, propertyKey: string | symbol, descriptor?: PropertyDescriptor): void { | ||
target[propertyKey][testNameSymbol] = propertyKey ? propertyKey.toString() : ""; | ||
target[propertyKey][traitsSymbol] = traits; | ||
mark && (target[propertyKey][mark] = true); | ||
} | ||
}, | ||
testDecoratorNamed(name: string, ... traits: TestTrait[]): PropertyDecorator & MethodDecorator { | ||
return function(target: Object, propertyKey: string | symbol, descriptor?: PropertyDescriptor): void { | ||
target[propertyKey][testNameSymbol] = name; | ||
target[propertyKey][traitsSymbol] = traits; | ||
mark && (target[propertyKey][mark] = true); | ||
} | ||
} | ||
}); | ||
return testOverload({ | ||
test(name: string, fn: Function) { | ||
testFunc()(name, fn); | ||
}, | ||
testProperty(target: Object, propertyKey: string | symbol, descriptor?: PropertyDescriptor): void { | ||
target[propertyKey][testNameSymbol] = propertyKey ? propertyKey.toString() : ""; | ||
if (mark) { | ||
target[propertyKey][mark] = true; | ||
} | ||
}, | ||
testDecorator(...traits: TestTrait[]): PropertyDecorator & MethodDecorator { | ||
return function(target: Object, propertyKey: string | symbol, descriptor?: PropertyDescriptor): void { | ||
target[propertyKey][testNameSymbol] = propertyKey ? propertyKey.toString() : ""; | ||
target[propertyKey][traitsSymbol] = traits; | ||
if (mark) { | ||
target[propertyKey][mark] = true; | ||
} | ||
}; | ||
}, | ||
testDecoratorNamed(name: string, ...traits: TestTrait[]): PropertyDecorator & MethodDecorator { | ||
return function(target: Object, propertyKey: string | symbol, descriptor?: PropertyDescriptor): void { | ||
target[propertyKey][testNameSymbol] = name; | ||
target[propertyKey][traitsSymbol] = traits; | ||
if (mark) { | ||
target[propertyKey][mark] = true; | ||
} | ||
}; | ||
}, | ||
}); | ||
} | ||
function makeTestObject(context: TestFunctions): Test { | ||
return Object.assign(makeTestFunction(() => context.it, null), { | ||
skip: makeTestFunction(() => context.it.skip, skipSymbol), | ||
only: makeTestFunction(() => context.it.only, onlySymbol), | ||
pending: makeTestFunction(() => context.it.skip, pendingSumbol) | ||
}); | ||
return Object.assign(makeTestFunction(() => context.it, null), { | ||
skip: makeTestFunction(() => context.it.skip, skipSymbol), | ||
only: makeTestFunction(() => context.it.only, onlySymbol), | ||
pending: makeTestFunction(() => context.it.skip, pendingSymbol), | ||
}); | ||
} | ||
@@ -359,4 +447,4 @@ export const test = makeTestObject(globalTestFunctions); | ||
export function trait<T extends SuiteTrait | TestTrait>(arg: T): T { | ||
arg[isTraitSymbol] = true; | ||
return arg; | ||
arg[isTraitSymbol] = true; | ||
return arg; | ||
} | ||
@@ -369,28 +457,28 @@ | ||
export function slow(time: number): PropertyDecorator & ClassDecorator & SuiteTrait & TestTrait { | ||
return trait(function() { | ||
if (arguments.length === 1) { | ||
const target = arguments[0]; | ||
target[slowSymbol] = time; | ||
} else if (arguments.length === 2 && typeof arguments[1] === "string" || typeof arguments[1] === "symbol") { | ||
const target = arguments[0]; | ||
const property = arguments[1]; | ||
target[property][slowSymbol] = time; | ||
} else if (arguments.length === 2) { | ||
const context: Mocha.ISuiteCallbackContext = arguments[0]; | ||
const ctor = arguments[1]; | ||
context.slow(time); | ||
} else if (arguments.length === 3) { | ||
if (typeof arguments[2] === "function") { | ||
const context: Mocha.ITestCallbackContext = arguments[0]; | ||
const instance = arguments[1]; | ||
const method = arguments[2]; | ||
context.slow(time); | ||
} else if (typeof arguments[1] === "string" || typeof arguments[1] === "symbol") { | ||
const proto: Mocha.ITestCallbackContext = arguments[0]; | ||
const prop = arguments[1]; | ||
const descriptor = arguments[2]; | ||
proto[prop][slowSymbol] = time; | ||
} | ||
} | ||
}); | ||
return trait(function() { | ||
if (arguments.length === 1) { | ||
const target = arguments[0]; | ||
target[slowSymbol] = time; | ||
} else if (arguments.length === 2 && typeof arguments[1] === "string" || typeof arguments[1] === "symbol") { | ||
const target = arguments[0]; | ||
const property = arguments[1]; | ||
target[property][slowSymbol] = time; | ||
} else if (arguments.length === 2) { | ||
const context: Mocha.ISuiteCallbackContext = arguments[0]; | ||
const ctor = arguments[1]; | ||
context.slow(time); | ||
} else if (arguments.length === 3) { | ||
if (typeof arguments[2] === "function") { | ||
const context: Mocha.ITestCallbackContext = arguments[0]; | ||
const instance = arguments[1]; | ||
const method = arguments[2]; | ||
context.slow(time); | ||
} else if (typeof arguments[1] === "string" || typeof arguments[1] === "symbol") { | ||
const proto: Mocha.ITestCallbackContext = arguments[0]; | ||
const prop = arguments[1]; | ||
const descriptor = arguments[2]; | ||
proto[prop][slowSymbol] = time; | ||
} | ||
} | ||
}); | ||
} | ||
@@ -403,28 +491,28 @@ | ||
export function timeout(time: number): MethodDecorator & PropertyDecorator & ClassDecorator & SuiteTrait & TestTrait { | ||
return trait(function() { | ||
if (arguments.length === 1) { | ||
const target = arguments[0]; | ||
target[timeoutSymbol] = time; | ||
} else if (arguments.length === 2 && typeof arguments[1] === "string" || typeof arguments[1] === "symbol") { | ||
const target = arguments[0]; | ||
const property = arguments[1]; | ||
target[property][timeoutSymbol] = time; | ||
} else if (arguments.length === 2) { | ||
const context: Mocha.ISuiteCallbackContext = arguments[0]; | ||
const ctor = arguments[1]; | ||
context.timeout(time); | ||
} else if (arguments.length === 3) { | ||
if (typeof arguments[2] === "function") { | ||
const context: Mocha.ITestCallbackContext = arguments[0]; | ||
const instance = arguments[1]; | ||
const method = arguments[2]; | ||
context.timeout(time); | ||
} else if (typeof arguments[1] === "string" || typeof arguments[1] === "symbol") { | ||
const proto: Mocha.ITestCallbackContext = arguments[0]; | ||
const prop = arguments[1]; | ||
const descriptor = arguments[2]; | ||
proto[prop][timeoutSymbol] = time; | ||
} | ||
} | ||
}); | ||
return trait(function() { | ||
if (arguments.length === 1) { | ||
const target = arguments[0]; | ||
target[timeoutSymbol] = time; | ||
} else if (arguments.length === 2 && typeof arguments[1] === "string" || typeof arguments[1] === "symbol") { | ||
const target = arguments[0]; | ||
const property = arguments[1]; | ||
target[property][timeoutSymbol] = time; | ||
} else if (arguments.length === 2) { | ||
const context: Mocha.ISuiteCallbackContext = arguments[0]; | ||
const ctor = arguments[1]; | ||
context.timeout(time); | ||
} else if (arguments.length === 3) { | ||
if (typeof arguments[2] === "function") { | ||
const context: Mocha.ITestCallbackContext = arguments[0]; | ||
const instance = arguments[1]; | ||
const method = arguments[2]; | ||
context.timeout(time); | ||
} else if (typeof arguments[1] === "string" || typeof arguments[1] === "symbol") { | ||
const proto: Mocha.ITestCallbackContext = arguments[0]; | ||
const prop = arguments[1]; | ||
const descriptor = arguments[2]; | ||
proto[prop][timeoutSymbol] = time; | ||
} | ||
} | ||
}); | ||
} | ||
@@ -437,28 +525,28 @@ | ||
export function retries(count: number): MethodDecorator & PropertyDecorator & ClassDecorator & SuiteTrait & TestTrait { | ||
return trait(function() { | ||
if (arguments.length === 1) { | ||
const target = arguments[0]; | ||
target[retriesSymbol] = count; | ||
} else if (arguments.length === 2 && typeof arguments[1] === "string" || typeof arguments[1] === "symbol") { | ||
const target = arguments[0]; | ||
const property = arguments[1]; | ||
target[property][retriesSymbol] = count; | ||
} else if (arguments.length === 2) { | ||
const context: Mocha.ISuiteCallbackContext = arguments[0]; | ||
const ctor = arguments[1]; | ||
context.retries(count); | ||
} else if (arguments.length === 3) { | ||
if (typeof arguments[2] === "function") { | ||
const context: Mocha.ITestCallbackContext = arguments[0]; | ||
const instance = arguments[1]; | ||
const method = arguments[2]; | ||
context.retries(count); | ||
} else if (typeof arguments[1] === "string" || typeof arguments[1] === "symbol") { | ||
const proto: Mocha.ITestCallbackContext = arguments[0]; | ||
const prop = arguments[1]; | ||
const descriptor = arguments[2]; | ||
proto[prop][retriesSymbol] = count; | ||
} | ||
} | ||
}); | ||
return trait(function() { | ||
if (arguments.length === 1) { | ||
const target = arguments[0]; | ||
target[retriesSymbol] = count; | ||
} else if (arguments.length === 2 && typeof arguments[1] === "string" || typeof arguments[1] === "symbol") { | ||
const target = arguments[0]; | ||
const property = arguments[1]; | ||
target[property][retriesSymbol] = count; | ||
} else if (arguments.length === 2) { | ||
const context: Mocha.ISuiteCallbackContext = arguments[0]; | ||
const ctor = arguments[1]; | ||
context.retries(count); | ||
} else if (arguments.length === 3) { | ||
if (typeof arguments[2] === "function") { | ||
const context: Mocha.ITestCallbackContext = arguments[0]; | ||
const instance = arguments[1]; | ||
const method = arguments[2]; | ||
context.retries(count); | ||
} else if (typeof arguments[1] === "string" || typeof arguments[1] === "symbol") { | ||
const proto: Mocha.ITestCallbackContext = arguments[0]; | ||
const prop = arguments[1]; | ||
const descriptor = arguments[2]; | ||
proto[prop][retriesSymbol] = count; | ||
} | ||
} | ||
}); | ||
} | ||
@@ -485,7 +573,7 @@ | ||
export function pending<TFunction extends Function>(target: Object | TFunction, propertyKey?: string | symbol): void { | ||
if (arguments.length === 1) { | ||
target[pendingSumbol] = true; | ||
} else { | ||
target[propertyKey][pendingSumbol] = true; | ||
} | ||
if (arguments.length === 1) { | ||
target[pendingSymbol] = true; | ||
} else { | ||
target[propertyKey][pendingSymbol] = true; | ||
} | ||
} | ||
@@ -499,7 +587,7 @@ | ||
export function only<TFunction extends Function>(target: Object, propertyKey?: string | symbol): void { | ||
if (arguments.length === 1) { | ||
target[onlySymbol] = true; | ||
} else { | ||
target[propertyKey][onlySymbol] = true; | ||
} | ||
if (arguments.length === 1) { | ||
target[onlySymbol] = true; | ||
} else { | ||
target[propertyKey][onlySymbol] = true; | ||
} | ||
} | ||
@@ -513,7 +601,7 @@ | ||
export function skip<TFunction extends Function>(target: Object | TFunction, propertyKey?: string | symbol): void { | ||
if (arguments.length === 1) { | ||
target[onlySymbol] = true; | ||
} else { | ||
target[propertyKey][skipSymbol] = true; | ||
} | ||
if (arguments.length === 1) { | ||
target[onlySymbol] = true; | ||
} else { | ||
target[propertyKey][skipSymbol] = true; | ||
} | ||
} | ||
@@ -525,3 +613,3 @@ | ||
export function context(target: Object, propertyKey: string | symbol): void { | ||
target[contextSymbol] = propertyKey; | ||
target[contextSymbol] = propertyKey; | ||
} | ||
@@ -534,66 +622,68 @@ | ||
function tsdd(suite) { | ||
var suites = [suite]; | ||
const suites = [suite]; | ||
suite.on('pre-require', function (context, file, mocha) { | ||
var common = Common(suites, context, mocha); | ||
suite.on("pre-require", function(context, file, mocha) { | ||
const common = Common(suites, context, mocha); | ||
context.before = common.before; | ||
context.after = common.after; | ||
context.beforeEach = common.beforeEach; | ||
context.afterEach = common.afterEach; | ||
context.run = mocha.options.delay && common.runWithSuite(suite); | ||
context.before = common.before; | ||
context.after = common.after; | ||
context.beforeEach = common.beforeEach; | ||
context.afterEach = common.afterEach; | ||
context.run = mocha.options.delay && common.runWithSuite(suite); | ||
// Copy of bdd | ||
context.describe = context.context = function (title, fn) { | ||
return common.suite.create({ | ||
title: title, | ||
file: file, | ||
fn: fn | ||
}); | ||
}; | ||
context.xdescribe = context.xcontext = context.describe.skip = function (title, fn) { | ||
return common.suite.skip({ | ||
title: title, | ||
file: file, | ||
fn: fn | ||
}); | ||
}; | ||
context.describe.only = function (title, fn) { | ||
return common.suite.only({ | ||
title: title, | ||
file: file, | ||
fn: fn | ||
}); | ||
}; | ||
context.it = context.specify = function (title, fn) { | ||
var suite = suites[0]; | ||
if (suite.isPending()) { | ||
fn = null; | ||
} | ||
var test = new Test(title, fn); | ||
test.file = file; | ||
suite.addTest(test); | ||
return test; | ||
}; | ||
context.it.only = function (title, fn) { | ||
return common.test.only(mocha, context.it(title, fn)); | ||
}; | ||
context.xit = context.xspecify = context.it.skip = function (title) { | ||
context.it(title); | ||
}; | ||
context.it.retries = function (n) { | ||
context.retries(n); | ||
}; | ||
// Copy of bdd | ||
context.describe = context.context = function(title, fn) { | ||
return common.suite.create({ | ||
title, | ||
file, | ||
fn, | ||
}); | ||
}; | ||
context.xdescribe = context.xcontext = context.describe.skip = function(title, fn) { | ||
return common.suite.skip({ | ||
title, | ||
file, | ||
fn, | ||
}); | ||
}; | ||
context.describe.only = function(title, fn) { | ||
return common.suite.only({ | ||
title, | ||
file, | ||
fn, | ||
}); | ||
}; | ||
context.it = context.specify = function(title, fn) { | ||
const suite = suites[0]; | ||
if (suite.isPending()) { | ||
fn = null; | ||
} | ||
const test = new Test(title, fn); | ||
test.file = file; | ||
suite.addTest(test); | ||
return test; | ||
}; | ||
context.it.only = function(title, fn) { | ||
return common.test.only(mocha, context.it(title, fn)); | ||
}; | ||
context.xit = context.xspecify = context.it.skip = function(title) { | ||
context.it(title); | ||
}; | ||
context.it.retries = function(n) { | ||
context.retries(n); | ||
}; | ||
context.suite = makeSuiteObject(context); | ||
context.test = makeTestObject(context); | ||
context.suite = makeSuiteObject(context); | ||
context.params = makeParamsObject(context); | ||
context.test = makeTestObject(context); | ||
context.test.retries = common.test.retries; | ||
context.test.retries = common.test.retries; | ||
context.timeout = timeout; | ||
context.slow = slow; | ||
context.retries = retries; | ||
context.skipOnError = skipOnError; | ||
}); | ||
}; | ||
context.timeout = timeout; | ||
context.slow = slow; | ||
context.retries = retries; | ||
context.skipOnError = skipOnError; | ||
}); | ||
} | ||
module.exports = Object.assign(tsdd, exports); | ||
(Mocha as any).interfaces["mocha-typescript"] = tsdd; |
{ | ||
"name": "mocha-typescript", | ||
"version": "1.1.14", | ||
"version": "1.1.15", | ||
"description": "TypeScript decorators based wrapper over mocha's interface", | ||
@@ -16,24 +16,31 @@ "main": "index.js", | ||
"pretest": "tsc", | ||
"test": "mocha test.js --opts mocha.opts", | ||
"prepare": "tsc" | ||
"test": "mocha test.js --opts mocha.opts && tslint --project .", | ||
"prepare": "tsc", | ||
"tslint-fix": "tslint --fix --project .", | ||
"tslint": "tslint --project ." | ||
}, | ||
"author": "Panayot Cankov", | ||
"contributors": [ | ||
{ | ||
"name": "silkentrance", | ||
"url": "https://github.com/silkentrance" | ||
} | ||
], | ||
"license": "Apache-2.0", | ||
"dependencies": { | ||
"@types/mocha": "*", | ||
"chalk": "^1.1.3", | ||
"cross-spawn": "^5.1.0", | ||
"yargs": "^6.5.0" | ||
"@types/mocha": "^5.2.0", | ||
"chalk": "^2.4.1", | ||
"cross-spawn": "^6.0.5", | ||
"yargs": "^11.0.0" | ||
}, | ||
"devDependencies": { | ||
"@types/chai": "^3.4.35", | ||
"@types/mocha": "^5.0.0", | ||
"@types/node": "^7.0.60", | ||
"assert": "^1.3.0", | ||
"better-assert": "^1.0.2", | ||
"chai": "^3.5.0", | ||
"mocha": "^4.0.1", | ||
"rimraf": "^2.6.1", | ||
"source-map-support": "^0.4.15", | ||
"typescript": "^2.4.1" | ||
"@types/chai": "^4.1.3", | ||
"@types/node": "^10.1.4", | ||
"@types/cross-spawn": "^6.0.0", | ||
"chai": "^4.1.2", | ||
"mocha": "^5.2.0", | ||
"rimraf": "^2.6.2", | ||
"source-map-support": "^0.5.6", | ||
"tslint": "^5.10.0", | ||
"typescript": "^2.9.1" | ||
}, | ||
@@ -40,0 +47,0 @@ "files": [ |
@@ -30,2 +30,3 @@ Writing mocha tests with style - OOP style: | ||
- [Test Inheritance](#test-inheritance) | ||
- [Overriding Tests](#overriding-tests) | ||
- [Inheritance and Both Synchronous and Asynchronous Before and After Actions](#inheritance-and-both-synchronous-and-asynchronous-before-and-after-actions) | ||
@@ -339,7 +340,32 @@ - [Generated Suites and Tests](#generated-suites-and-tests) | ||
One can also inherit from another concrete test class or suite, but keep in mind that that the tests declared by that suite will | ||
be run multiple times and not just in the context of the concrete test classes, see the example provided in `tests/ts/suite.inheritance.suite.ts`. | ||
Note: You can override test methods inherited from a base class and then call `super()` in order to run the assertions implemented by the super class. | ||
Important: One should not override test methods inherited from a base class and then call `super()` as this will run the tests from the base class twice. | ||
Best practice: You must not inherit from other classes that have been decorated with the ``suite`` decorator. Doing so will result in an exception. Use abstract base classes instead. | ||
### Overriding Tests | ||
Sometimes you might want to override tests inherited from a given base class. You can do this by redeclaring the same test method in your sub class, e.g. | ||
``` TypeScript | ||
export abstract class AbstractTestBase { | ||
@test 'test that will be overridden by sub classes'() { | ||
chai.assert.fail('sub classes must override this'); | ||
} | ||
} | ||
export class ConcreteTest extends AbstractTestBase { | ||
@test 'test that will be overridden by sub classes'() { | ||
chai.assertTrue(somethingTruthy); | ||
} | ||
} | ||
``` | ||
You may now either implement the test or simply just skip it. | ||
Given that ``skip`` actually marks the test as pending, this might not be what you want for your test reports. In that case, you could just override the test with an empty body. | ||
Which, of course, is considered to be a bad practice, yet sometimes it will become a necessity when testing class hierarchies. So the best practice is to actually | ||
provide an assertion for that test. | ||
### Inheritance and Both Synchronous and Asynchronous Before and After Actions | ||
@@ -346,0 +372,0 @@ As for both static and instance `before()` and `after()` actions, one must make sure that the hooks from the parent class are called, see the |
Sorry, the diff of this file is not supported yet
Floating dependency
QualityPackage has a dependency with a floating version range. This can cause issues if the dependency publishes a new major version.
Found 1 instance in 1 package
116796
9
1520
0
546
+ Added@types/mocha@5.2.7(transitive)
+ Addedansi-regex@3.0.1(transitive)
+ Addedansi-styles@3.2.1(transitive)
+ Addedcamelcase@4.1.0(transitive)
+ Addedchalk@2.4.2(transitive)
+ Addedcliui@4.1.0(transitive)
+ Addedcolor-convert@1.9.3(transitive)
+ Addedcolor-name@1.1.3(transitive)
+ Addedcross-spawn@6.0.5(transitive)
+ Addedend-of-stream@1.4.4(transitive)
+ Addedexeca@1.0.0(transitive)
+ Addedfind-up@2.1.0(transitive)
+ Addedget-stream@4.1.0(transitive)
+ Addedhas-flag@3.0.0(transitive)
+ Addedinvert-kv@2.0.0(transitive)
+ Addedis-fullwidth-code-point@2.0.0(transitive)
+ Addedis-stream@1.1.0(transitive)
+ Addedlcid@2.0.0(transitive)
+ Addedlocate-path@2.0.0(transitive)
+ Addedmap-age-cleaner@0.1.3(transitive)
+ Addedmem@4.3.0(transitive)
+ Addedmimic-fn@2.1.0(transitive)
+ Addednice-try@1.0.5(transitive)
+ Addednpm-run-path@2.0.2(transitive)
+ Addedonce@1.4.0(transitive)
+ Addedos-locale@3.1.0(transitive)
+ Addedp-defer@1.0.0(transitive)
+ Addedp-finally@1.0.0(transitive)
+ Addedp-is-promise@2.1.0(transitive)
+ Addedp-limit@1.3.0(transitive)
+ Addedp-locate@2.0.0(transitive)
+ Addedp-try@1.0.0(transitive)
+ Addedpath-exists@3.0.0(transitive)
+ Addedpath-key@2.0.1(transitive)
+ Addedpump@3.0.0(transitive)
+ Addedsignal-exit@3.0.7(transitive)
+ Addedstring-width@2.1.1(transitive)
+ Addedstrip-ansi@4.0.0(transitive)
+ Addedstrip-eof@1.0.0(transitive)
+ Addedsupports-color@5.5.0(transitive)
+ Addedwhich-module@2.0.1(transitive)
+ Addedwrappy@1.0.2(transitive)
+ Addedyargs@11.1.1(transitive)
+ Addedyargs-parser@9.0.2(transitive)
- Removed@types/mocha@10.0.6(transitive)
- Removedansi-styles@2.2.1(transitive)
- Removedcamelcase@3.0.0(transitive)
- Removedchalk@1.1.3(transitive)
- Removedcliui@3.2.0(transitive)
- Removedcross-spawn@5.1.0(transitive)
- Removederror-ex@1.3.2(transitive)
- Removedfind-up@1.1.2(transitive)
- Removedfunction-bind@1.1.2(transitive)
- Removedgraceful-fs@4.2.11(transitive)
- Removedhas-ansi@2.0.0(transitive)
- Removedhasown@2.0.2(transitive)
- Removedhosted-git-info@2.8.9(transitive)
- Removedinvert-kv@1.0.0(transitive)
- Removedis-arrayish@0.2.1(transitive)
- Removedis-core-module@2.13.1(transitive)
- Removedis-utf8@0.2.1(transitive)
- Removedlcid@1.0.0(transitive)
- Removedload-json-file@1.1.0(transitive)
- Removedlru-cache@4.1.5(transitive)
- Removednormalize-package-data@2.5.0(transitive)
- Removedos-locale@1.4.0(transitive)
- Removedparse-json@2.2.0(transitive)
- Removedpath-exists@2.1.0(transitive)
- Removedpath-parse@1.0.7(transitive)
- Removedpath-type@1.1.0(transitive)
- Removedpify@2.3.0(transitive)
- Removedpinkie@2.0.4(transitive)
- Removedpinkie-promise@2.0.1(transitive)
- Removedpseudomap@1.0.2(transitive)
- Removedread-pkg@1.1.0(transitive)
- Removedread-pkg-up@1.0.1(transitive)
- Removedresolve@1.22.8(transitive)
- Removedspdx-correct@3.2.0(transitive)
- Removedspdx-exceptions@2.5.0(transitive)
- Removedspdx-expression-parse@3.0.1(transitive)
- Removedspdx-license-ids@3.0.18(transitive)
- Removedstrip-bom@2.0.0(transitive)
- Removedsupports-color@2.0.0(transitive)
- Removedsupports-preserve-symlinks-flag@1.0.0(transitive)
- Removedvalidate-npm-package-license@3.0.4(transitive)
- Removedwhich-module@1.0.0(transitive)
- Removedyallist@2.1.2(transitive)
- Removedyargs@6.6.0(transitive)
- Removedyargs-parser@4.2.1(transitive)
Updated@types/mocha@^5.2.0
Updatedchalk@^2.4.1
Updatedcross-spawn@^6.0.5
Updatedyargs@^11.0.0