diff --git a/packages/wct-mocha/src/childrunner.ts b/packages/wct-mocha/src/childrunner.ts index 1dc603f32..589f6c90a 100644 --- a/packages/wct-mocha/src/childrunner.ts +++ b/packages/wct-mocha/src/childrunner.ts @@ -32,9 +32,9 @@ export default class ChildRunner { private container?: HTMLDivElement; private eventListenersToRemoveOnClean: EventListenerDescriptor[] = []; private iframe?: HTMLIFrameElement; - private onRunComplete: (error?: {}) => void; - private share: SharedState; - private state: 'initializing'|'loading'|'complete'; + private onRunComplete: ((error?: {}) => void)|null = null; + share: SharedState|null = null; + state: 'initializing'|'loading'|'complete'; private timeoutId?: number; private url: string; @@ -88,7 +88,7 @@ export default class ChildRunner { * @return {ChildRunner} The `ChildRunner` that was registered for this * window. */ - static current(): ChildRunner { + static current(): ChildRunner|null { return ChildRunner.get(window); } @@ -97,7 +97,7 @@ export default class ChildRunner { * @param {boolean} traversal Whether this is a traversal from a child window. * @return {ChildRunner} The `ChildRunner` that was registered for `target`. */ - static get(target: Window, traversal?: boolean): ChildRunner { + static get(target: Window, traversal?: boolean): ChildRunner|null { const childRunner = ChildRunner.byUrl[target.location.href]; if (childRunner) { return childRunner; @@ -154,7 +154,7 @@ export default class ChildRunner { () => this.loaded(new Error('Failed to load document ' + this.url)), iframe); this.addEventListener( - 'DOMContentLoaded', () => this.loaded(), iframe.contentWindow); + 'DOMContentLoaded', () => this.loaded(), iframe.contentWindow!); } /** @@ -165,15 +165,15 @@ export default class ChildRunner { loaded(error?: {}) { util.debug('ChildRunner#loaded', this.url, error); - if (this.iframe.contentWindow == null && error) { + if (!this.iframe || this.iframe.contentWindow == null && error) { this.signalRunComplete(error); this.done(); return; } // Not all targets have WCT loaded (compatiblity mode) - if (this.iframe.contentWindow.WCT) { - this.share = this.iframe.contentWindow.WCT.share; + if (this.iframe.contentWindow!.WCT) { + this.share = this.iframe.contentWindow!.WCT.share; } if (error) { @@ -215,7 +215,7 @@ export default class ChildRunner { setTimeout(() => { this.removeAllEventListeners(); - this.container.removeChild(this.iframe as Node); + this.container!.removeChild(this.iframe as Node); this.iframe = undefined; this.share = null; }, 0); diff --git a/packages/wct-mocha/src/clisocket.ts b/packages/wct-mocha/src/clisocket.ts index 6a6210d23..d88d1e84b 100644 --- a/packages/wct-mocha/src/clisocket.ts +++ b/packages/wct-mocha/src/clisocket.ts @@ -98,7 +98,7 @@ export default class CLISocket { * * @param {function(*, CLISocket)} done Node-style callback. */ - static init(done: (error?: {}, socket?: CLISocket) => void) { + static init(done: (error?: {}|null|undefined, socket?: CLISocket) => void) { const browserId = util.getParam('cli_browser_id'); if (!browserId) { return done(); @@ -108,7 +108,7 @@ export default class CLISocket { return done(); } - util.loadScript(SOCKETIO_LIBRARY, (error: {}) => { + util.loadScript(SOCKETIO_LIBRARY, (error: {}|undefined|null) => { if (error) { return done(error); } @@ -139,7 +139,7 @@ export default class CLISocket { * @return {!Array.} The titles of the runnable and its parents. */ function getTitles(runnable: Mocha.IRunnable) { - const titles = []; + const titles: string[] = []; while (runnable && !runnable.root && runnable.title) { titles.unshift(runnable.title); runnable = runnable.parent as {} as Mocha.IRunnable; diff --git a/packages/wct-mocha/src/config.ts b/packages/wct-mocha/src/config.ts index e867e8a96..0667fc969 100644 --- a/packages/wct-mocha/src/config.ts +++ b/packages/wct-mocha/src/config.ts @@ -76,7 +76,7 @@ export function setup(options: Partial) { const wctMochaJsRoot = util.scriptPrefix('wct-mocha.js'); const browserJsRoot = util.scriptPrefix('browser.js'); const scriptName = wctMochaJsRoot ? 'wct-mocha.js' : 'browser.js'; - const root = wctMochaJsRoot || browserJsRoot; + const root = (wctMochaJsRoot || browserJsRoot)!; _config.root = util.basePath(root.substr(0, root.length - 1)); if (!_config.root) { throw new Error( @@ -93,11 +93,13 @@ export function get(key: K): Config[K] { return _config[key]; } -export function deepMerge(target: Partial, source: Partial) { - Object.keys(source).forEach((key) => { - if (target[key] !== null && typeof target[key] === 'object' && - !Array.isArray(target[key])) { - deepMerge(target[key], source[key]); +export function deepMerge(target: V, source: V) { + Object.keys(source).forEach((untypedKey) => { + const key = untypedKey as keyof typeof source; + const targetValue = target[key]; + if (targetValue != null && typeof targetValue === 'object' && + !Array.isArray(targetValue)) { + deepMerge(targetValue, source[key]); } else { target[key] = source[key]; } diff --git a/packages/wct-mocha/src/environment.ts b/packages/wct-mocha/src/environment.ts index 757e29d03..8a6a4d029 100644 --- a/packages/wct-mocha/src/environment.ts +++ b/packages/wct-mocha/src/environment.ts @@ -30,7 +30,7 @@ export function loadSync() { scripts.push(a11ySuiteScriptPath); } scripts.forEach((path) => { - const url = util.expandUrl(path, config.get('root')); + const url = util.expandUrl(path, config.get('root')!); util.debug('Loading environment script:', url); // Synchronous load. document.write(``); @@ -38,7 +38,7 @@ export function loadSync() { util.debug('Environment scripts loaded'); const imports = config.get('environmentImports'); imports.forEach((path) => { - const url = util.expandUrl(path, config.get('root')); + const url = util.expandUrl(path, config.get('root')!); util.debug('Loading environment import:', url); // Synchronous load. document.write(``); diff --git a/packages/wct-mocha/src/environment/helpers.ts b/packages/wct-mocha/src/environment/helpers.ts index 6962b87f4..be9c7a13f 100644 --- a/packages/wct-mocha/src/environment/helpers.ts +++ b/packages/wct-mocha/src/environment/helpers.ts @@ -132,7 +132,7 @@ export function flush(callback: () => void) { } else if (window.WebComponents && window.WebComponents.flush) { scope = window.WebComponents; } - if (scope) { + if (scope && scope.flush) { scope.flush(); } diff --git a/packages/wct-mocha/src/index.ts b/packages/wct-mocha/src/index.ts index d632fd8a3..65245fab7 100644 --- a/packages/wct-mocha/src/index.ts +++ b/packages/wct-mocha/src/index.ts @@ -58,7 +58,7 @@ export function initialize(initConfig?: config.Config) { // Until then, we get to rely on it to expose parent runners to their // children. _ChildRunner: ChildRunner, - _reporter: undefined as MultiReporter, // assigned below + _reporter: undefined! as MultiReporter, // assigned below _config: config._config, // Public API diff --git a/packages/wct-mocha/src/mocha/extend.ts b/packages/wct-mocha/src/mocha/extend.ts index d775cf15c..f25ce11b5 100644 --- a/packages/wct-mocha/src/mocha/extend.ts +++ b/packages/wct-mocha/src/mocha/extend.ts @@ -28,7 +28,10 @@ export function extendInterfaces( interfaceExtensions.push(() => { const Mocha = window.Mocha; // For all Mocha interfaces (probably just TDD and BDD): - Object.keys(Mocha.interfaces).forEach((interfaceName: 'tdd'|'bdd') => { + Object.keys(Mocha.interfaces).forEach((interfaceName: string) => { + if (interfaceName !== 'tdd' && interfaceName !== 'bdd') { + return; + } // This is the original callback that defines the interface (TDD or // BDD): const originalInterface = Mocha.interfaces[interfaceName]; @@ -44,16 +47,22 @@ export function extendInterfaces( originalInterface.apply(this, arguments); // Register a listener so that we can further extend the base // interface: - suite.on('pre-require', (context: {}, _file: string, _mocha: {}) => { - // Capture a bound reference to the teardown function as a - // convenience: - const teardown = context[teardownProperty].bind(context); - // Add our new helper to the testing context. The helper is - // generated by a factory method that receives the context, - // the teardown function and the interface name and returns - // the new method to be added to that context: - context[helperName] = helperFactory(context, teardown, interfaceName); - }); + suite.on( + 'pre-require', + (context: {teardown: Function, afterEach: Function}, + _file: string, + _mocha: {}) => { + // Capture a bound reference to the teardown function as a + // convenience: + const teardown = context[teardownProperty].bind(context); + // Add our new helper to the testing context. The helper is + // generated by a factory method that receives the context, + // the teardown function and the interface name and returns + // the new method to be added to that context: + // tslint:disable-next-line:no-any + (context as any)[helperName] = + helperFactory(context, teardown, interfaceName); + }); }; }); }); diff --git a/packages/wct-mocha/src/reporters.ts b/packages/wct-mocha/src/reporters.ts index b9284507b..4cab60c34 100644 --- a/packages/wct-mocha/src/reporters.ts +++ b/packages/wct-mocha/src/reporters.ts @@ -24,10 +24,10 @@ export let jsSuites: Array = []; * @return {!Array. logIndent + l).join('\n'); if (CAN_STYLE_LOG) { - console.log('%c' + text, STYLES[style] || STYLES.plain); + console.log('%c' + text, getStyle(style)); } else { console.log(text); } @@ -45,7 +52,7 @@ function log(text: string, style?: keyof typeof STYLES) { function logGroup(text: string, style?: keyof typeof STYLES) { if (CAN_STYLE_GROUP) { - console.group('%c' + text, STYLES[style] || STYLES.plain); + console.group('%c' + text, getStyle(style)); } else if (console.group) { console.group(text); } else { diff --git a/packages/wct-mocha/src/reporters/html.ts b/packages/wct-mocha/src/reporters/html.ts index 97df6595f..4b8652335 100644 --- a/packages/wct-mocha/src/reporters/html.ts +++ b/packages/wct-mocha/src/reporters/html.ts @@ -14,12 +14,12 @@ * * @param {!Mocha.Runner} runner The runner that is being reported on. */ -export default function HTML(runner: Mocha.IRunner) { +export default function HTML(this: Mocha.IRunner, runner: Mocha.IRunner) { const output = document.createElement('div'); output.id = 'mocha'; document.body.appendChild(output); - runner.on('suite', function(_test: {}) { + runner.on('suite', function(this: Mocha.IRunner, _test: {}) { this.total = runner.total; }.bind(this)); @@ -67,4 +67,4 @@ style.textContent = ` color: #555 !important; } `; -document.head.appendChild(style); +document.head!.appendChild(style); diff --git a/packages/wct-mocha/src/reporters/multi.ts b/packages/wct-mocha/src/reporters/multi.ts index 5f20fe3b1..ad8c7c02e 100644 --- a/packages/wct-mocha/src/reporters/multi.ts +++ b/packages/wct-mocha/src/reporters/multi.ts @@ -48,16 +48,16 @@ export interface ReporterFactory { } interface ExtendedTest extends Mocha.ITest { - err: {}; + err: {}|undefined; } /** * A Mocha-like reporter that combines the output of multiple Mocha suites. */ export default class MultiReporter implements Reporter { - private readonly reporters: ReadonlyArray; - private readonly parent: MultiReporter|undefined; - private readonly basePath: string; + readonly reporters: ReadonlyArray; + readonly parent: MultiReporter|undefined|null; + readonly basePath: string; total: number; private currentRunner: null|Mocha.IRunner; /** Arguments that would be called on emit(). */ @@ -73,7 +73,7 @@ export default class MultiReporter implements Reporter { */ constructor( numSuites: number, reporters: ReporterFactory[], - parent: MultiReporter|undefined) { + parent: MultiReporter|undefined|null) { this.reporters = reporters.map((reporter) => { return new reporter(this); }); @@ -92,12 +92,10 @@ export default class MultiReporter implements Reporter { } /** - * @param location The location this reporter represents. * @return A reporter-like "class" for each child suite * that should be passed to `mocha.run`. */ - childReporter(location: Location|string): ReporterFactory { - const name = this.suiteTitle(location); + childReporter(): ReporterFactory { // The reporter is used as a constructor, so we can't depend on `this` being // properly bound. const self = this; diff --git a/packages/wct-mocha/src/reporters/title.ts b/packages/wct-mocha/src/reporters/title.ts index f94f2f645..276f9294d 100644 --- a/packages/wct-mocha/src/reporters/title.ts +++ b/packages/wct-mocha/src/reporters/title.ts @@ -20,7 +20,6 @@ const ARC_WIDTH = 6; * @param {!Mocha.Runner} runner The runner that is being reported on. */ export default class Title { - runner: Mocha.Runner; constructor(runner: Mocha.IRunner) { Mocha.reporters.Base.call(this, runner); @@ -46,7 +45,7 @@ export default class Title { updateFavicon() { const canvas = document.createElement('canvas'); canvas.height = canvas.width = 32; - const context = canvas.getContext('2d'); + const context = canvas.getContext('2d')!; const passing = this.stats.passes; const pending = this.stats.pending; @@ -61,9 +60,9 @@ export default class Title { /** Sets the current favicon by URL. */ setFavicon(url: string) { - const current = document.head.querySelector('link[rel="icon"]'); + const current = document.head!.querySelector('link[rel="icon"]'); if (current) { - document.head.removeChild(current as Node); + document.head!.removeChild(current as Node); } const link = document.createElement('link'); @@ -71,7 +70,7 @@ export default class Title { link.type = 'image/x-icon'; link.href = url; link.setAttribute('sizes', '32x32'); - document.head.appendChild(link); + document.head!.appendChild(link); } } diff --git a/packages/wct-mocha/src/stacktrace/formatting.ts b/packages/wct-mocha/src/stacktrace/formatting.ts index 75b5838a4..bd09a3506 100644 --- a/packages/wct-mocha/src/stacktrace/formatting.ts +++ b/packages/wct-mocha/src/stacktrace/formatting.ts @@ -15,27 +15,26 @@ export type FormattingFunction = (text: string) => string; export interface FormattingOptions { showColumns?: boolean; // Methods are aligned up to this much padding. - maxMethodPadding?: number; + maxMethodPadding: number; // A string to prefix each line with. - indent?: string; + indent: string; // A string to show for stack lines that are missing a method. - methodPlaceholder?: string; + methodPlaceholder: string; // A list of Strings/RegExps that will be stripped from `location` values // on each line (via `String#replace`). - locationStrip?: (string|RegExp)[]; + locationStrip: (string|RegExp)[]; // A list of Strings/RegExps that indicate that a line is *not* important, // and should be styled as such. - unimportantLocation?: Array; + unimportantLocation: Array; // A filter function to completely remove lines - filter?: (line: ParsedLine) => boolean; + filter: (line: ParsedLine) => boolean; // styles are functions that take a string and return // that string when styled. - styles?: { - method?: FormattingFunction; - location?: FormattingFunction; - line?: FormattingFunction; - column?: FormattingFunction; - unimportant?: FormattingFunction; + styles: { + method: FormattingFunction; location: FormattingFunction; + line: FormattingFunction; + column: FormattingFunction; + unimportant: FormattingFunction; }; } @@ -56,14 +55,15 @@ export const defaults: FormattingOptions = { }; export function pretty( - stackOrParsed: string|ParsedLine[], options?: FormattingOptions): string { - options = mergeDefaults(options || {}, defaults); - let lines = + stackOrParsed: string|Array, + maybeOptions?: Partial): string { + const options = mergeDefaults(maybeOptions || {}, defaults); + const linesAndNulls = Array.isArray(stackOrParsed) ? stackOrParsed : parse(stackOrParsed); - lines = clean(lines, options); + const lines = clean(linesAndNulls, options); const padSize = methodPadding(lines, options); - const parts = lines.map((line: ParsedLine) => { + const parts = lines.map((line) => { const method = line.method || options.methodPlaceholder; const pad = options.indent + padding(padSize - method.length); const locationBits = [ @@ -84,10 +84,11 @@ export function pretty( return parts.join('\n'); } -function clean(lines: ParsedLine[], options: FormattingOptions): ParsedLine[] { - const result = []; +function clean( + lines: Array, options: FormattingOptions): ParsedLine[] { + const result: ParsedLine[] = []; for (let i = 0, line; line = lines[i]; i++) { - if (options.filter(line)) { + if (options.filter && options.filter(line)) { continue; } line.location = cleanLocation(line.location, options); @@ -104,24 +105,27 @@ function passthrough(text: string): string { return text; } -function mergeDefaults( - options: FormattingOptions, defaults: FormattingOptions) { +function mergeDefaults(options: Partial, defaults: V): V { const result = Object.create(defaults); - Object.keys(options).forEach((key) => { + Object.keys(options).forEach((untypedKey) => { + const key = untypedKey as keyof typeof options; let value = options[key]; if (typeof value === 'object' && !Array.isArray(value)) { - value = mergeDefaults(value, defaults[key]); + value = + mergeDefaults(value as typeof defaults[typeof key], defaults[key]); } result[key] = value; }); return result; } -function methodPadding(lines: ParsedLine[], options: FormattingOptions) { - let size = options.methodPlaceholder.length; +function methodPadding( + lines: Array, options: FormattingOptions) { + let size = (options.methodPlaceholder || '').length; for (let i = 0, line; line = lines[i]; i++) { - size = - Math.min(options.maxMethodPadding, Math.max(size, line.method.length)); + size = Math.min( + options.maxMethodPadding || Infinity, + Math.max(size, line.method.length)); } return size; } diff --git a/packages/wct-mocha/src/stacktrace/normalization.ts b/packages/wct-mocha/src/stacktrace/normalization.ts index 811041629..8673b6fc5 100644 --- a/packages/wct-mocha/src/stacktrace/normalization.ts +++ b/packages/wct-mocha/src/stacktrace/normalization.ts @@ -21,13 +21,14 @@ export type ErrorLikeThing = Error&{ }; export function normalize( - error: ErrorLikeThing, prettyOptions: FormattingOptions): ErrorLikeThing { + error: ErrorLikeThing, + prettyOptions: Partial): ErrorLikeThing { if (error.parsedStack) { return error; } const message = error.message || error.description || error || ''; - let parsedStack: ParsedLine[] = []; + let parsedStack: Array = []; try { parsedStack = parse(error.stack || error.toString()); } catch (error) { @@ -38,8 +39,8 @@ export function normalize( parsedStack.push({ method: '', location: error.fileName, - line: error.lineNumber, - column: error.columnNumber, + line: error.lineNumber || -1, + column: error.columnNumber || -1, }); } diff --git a/packages/wct-mocha/src/stacktrace/parsing.ts b/packages/wct-mocha/src/stacktrace/parsing.ts index 64321453e..e75bed43f 100644 --- a/packages/wct-mocha/src/stacktrace/parsing.ts +++ b/packages/wct-mocha/src/stacktrace/parsing.ts @@ -42,7 +42,7 @@ export function parse(stack: string) { // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/Stack const GECKO_LINE = /^(?:([^@]*)@)?(.*?):(\d+)(?::(\d+))?$/; -export function parseGeckoLine(line: string): ParsedLine { +export function parseGeckoLine(line: string): ParsedLine|null { const match = line.match(GECKO_LINE); if (!match) { return null; @@ -60,7 +60,7 @@ const V8_OUTER1 = /^\s*(eval )?at (.*) \((.*)\)$/; const V8_OUTER2 = /^\s*at()() (\S+)$/; const V8_INNER = /^\(?([^\(]+):(\d+):(\d+)\)?$/; -export function parseV8Line(line: string): ParsedLine { +export function parseV8Line(line: string): ParsedLine|null { const outer = line.match(V8_OUTER1) || line.match(V8_OUTER2); if (!outer) { return null; @@ -83,7 +83,7 @@ export function parseV8Line(line: string): ParsedLine { const STACKY_LINE = /^\s*(.+) at (.+):(\d+):(\d+)$/; -export function parseStackyLine(line: string): ParsedLine { +export function parseStackyLine(line: string): ParsedLine|null { const match = line.match(STACKY_LINE); if (!match) { return null; diff --git a/packages/wct-mocha/src/suites.ts b/packages/wct-mocha/src/suites.ts index b61445c92..41a893119 100644 --- a/packages/wct-mocha/src/suites.ts +++ b/packages/wct-mocha/src/suites.ts @@ -47,7 +47,7 @@ export function loadSuites(files: string[]) { export function activeChildSuites(): string[] { let subsuites = htmlSuites; if (GREP) { - const cleanSubsuites = []; + const cleanSubsuites: string[] = []; for (let i = 0, subsuite; subsuite = subsuites[i]; i++) { if (GREP.indexOf(util.cleanLocation(subsuite)) !== -1) { cleanSubsuites.push(subsuite); @@ -62,7 +62,7 @@ export function activeChildSuites(): string[] { * Loads all `.js` sources requested by the current suite. */ export function loadJsSuites( - _reporter: MultiReporter, done: (error: Error) => void) { + _reporter: MultiReporter, done: (error: {}|undefined) => void) { util.debug('loadJsSuites', jsSuites); // We only support `.js` dependencies for now. @@ -77,7 +77,7 @@ export function runSuites( done: (error?: {}) => void) { util.debug('runSuites'); - const suiteRunners: Array<(next: () => void) => void> = [ + const suiteRunners: Array = [ // Run the local tests (if any) first, not stopping on error; _runMocha.bind(null, reporter), ]; @@ -120,10 +120,9 @@ function _runMocha(reporter: MultiReporter, done: () => void, waited: boolean) { const mocha = window.mocha; const Mocha = window.Mocha; - mocha.reporter( - reporter.childReporter(window.location) as {} as Mocha.Reporter); + mocha.reporter(reporter.childReporter() as {} as Mocha.Reporter); mocha.suite.title = reporter.suiteTitle(window.location); - mocha.grep(GREP); + mocha.grep(GREP!); // We can't use `mocha.run` because it bashes over grep, invert, and friends. // See https://github.com/visionmedia/mocha/blob/master/support/tail.js#L137 @@ -139,7 +138,7 @@ function _runMocha(reporter: MultiReporter, done: () => void, waited: boolean) { // // TODO(nevir): Can we expand support to other browsers? if (navigator.userAgent.match(/chrome/i)) { - window.onerror = null; + window.onerror = null!; window.addEventListener('error', (event) => { if (!event.error) { return; @@ -154,7 +153,7 @@ function _runMocha(reporter: MultiReporter, done: () => void, waited: boolean) { runner.uncaught(event.error); }); } else { - window.onerror = null; + window.onerror = null!; window.addEventListener('error', (event) => { if (window.uncaughtErrorFilter && window.uncaughtErrorFilter(event)) { event.preventDefault(); diff --git a/packages/wct-mocha/src/util.ts b/packages/wct-mocha/src/util.ts index f88173d6b..cc447a264 100644 --- a/packages/wct-mocha/src/util.ts +++ b/packages/wct-mocha/src/util.ts @@ -57,7 +57,7 @@ export function loadScript(path: string, done: (error?: {}) => void) { script.onload = done.bind(null, null); script.onerror = done.bind(null, 'Failed to load script ' + script.src); } - document.head.appendChild(script); + document.head!.appendChild(script); } /** @@ -72,7 +72,7 @@ export function loadStyle(path: string, done?: () => void) { link.onload = done.bind(null, null); link.onerror = done.bind(null, 'Failed to load stylesheet ' + link.href); } - document.head.appendChild(link); + document.head!.appendChild(link); } /** @@ -94,7 +94,7 @@ export function debug(...var_args: unknown[]) { * @return {{base: string, params: string}} */ export function parseUrl(url: string) { - const parts = url.match(/^(.*?)(?:\?(.*))?$/); + const parts = url.match(/^(.*?)(?:\?(.*))?$/)!; return { base: parts[1], params: getParams(parts[2] || ''), @@ -204,7 +204,7 @@ function getPathName(location: Location|string): string { } export function basePath(location: Location|string) { - return getPathName(location).match(/^.*\//)[0]; + return getPathName(location).match(/^.*\//)![0]; } export function relativeLocation(location: Location|string, basePath: string) { @@ -236,9 +236,11 @@ export type Runner = (f: Function) => void; * @param {?function(*)} done Callback that should be triggered once all runners * have completed, or encountered an error. */ -export function parallel(runners: Runner[], done: (error?: {}) => void): void; export function parallel( - runners: Runner[], limit: number, done: (error?: {}) => void): void; + runners: Runner[], done: (error?: {}|undefined) => void): void; +export function parallel( + runners: Runner[], limit: number, done: (error?: {}|undefined) => void): + void; export function parallel( runners: Runner[], maybeLimit: number|((error?: {}) => void), @@ -251,7 +253,7 @@ export function parallel( limit = maybeLimit; } if (!runners.length) { - return done(); + return done && done(); } let called = false; @@ -268,7 +270,7 @@ export function parallel( if (error || numDone >= total) { called = true; - done(error); + done && done(error); } else { runOne(); } @@ -282,7 +284,7 @@ export function parallel( return; } numActive = numActive + 1; - runners.shift()(runnerDone); + runners.shift()!(runnerDone); } runners.forEach(runOne); } diff --git a/tools.code-workspace b/tools.code-workspace index 634b8cef6..330f08475 100644 --- a/tools.code-workspace +++ b/tools.code-workspace @@ -42,6 +42,9 @@ { "path": "packages/wct-local" }, + { + "path": "packages/wct-mocha" + }, { "path": "packages/web-component-tester" },