diff --git a/types/ember-mocha/ember-mocha-tests.ts b/types/ember-mocha/ember-mocha-tests.ts index 3516932eec..75d1154a87 100644 --- a/types/ember-mocha/ember-mocha-tests.ts +++ b/types/ember-mocha/ember-mocha-tests.ts @@ -3,7 +3,7 @@ import { setResolver, setupAcceptanceTest, setupComponentTest, setupModelTest, setupTest } from 'ember-mocha'; -import { context, describe, it, beforeEach, afterEach, before, after } from 'mocha'; +import { describe, it, beforeEach, afterEach, before, after } from 'mocha'; import chai = require('chai'); import Ember from "ember"; import hbs from 'htmlbars-inline-precompile'; diff --git a/types/ember-mocha/index.d.ts b/types/ember-mocha/index.d.ts index 1d24564e31..84510eee38 100644 --- a/types/ember-mocha/index.d.ts +++ b/types/ember-mocha/index.d.ts @@ -60,6 +60,5 @@ declare module 'ember-mocha' { declare module 'mocha' { // augment test callback context - interface ITestCallbackContext extends TestContext {} - interface IHookCallbackContext extends TestContext {} + interface Context extends TestContext {} } diff --git a/types/mocha/UNUSED_FILES.txt b/types/mocha/UNUSED_FILES.txt deleted file mode 100644 index 2c70329a00..0000000000 --- a/types/mocha/UNUSED_FILES.txt +++ /dev/null @@ -1,2 +0,0 @@ -mocha-node.d.ts -mocha-node-tests.ts \ No newline at end of file diff --git a/types/mocha/index.d.ts b/types/mocha/index.d.ts index 2dd6bb2c21..1ada77c0a4 100644 --- a/types/mocha/index.d.ts +++ b/types/mocha/index.d.ts @@ -9,261 +9,2146 @@ // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped // TypeScript Version: 2.1 +export = Mocha; +export as namespace Mocha; + /** - * Mocha is using node.js EventEmitter for its internal classes - * But when it's executed in the browser environment it bundles a 3rd party EventEmitter in its code - * Also node.js EventEmitter brings its globals which cannot be used in the browser environment. - * So it's unsafe to reference node EventEmitter here, that's why we have a generic interface for EventEmitter. + * Mocha API * - * @see https://github.com/DefinitelyTyped/DefinitelyTyped/pull/25117#issuecomment-383404187 + * @see https://mochajs.org/api/mocha */ -declare class GenericEventEmitter { - addListener(event: string, listener: (...args: any[]) => void): GenericEventEmitter; - on(event: string, listener: (...args: any[]) => void): GenericEventEmitter; - once(event: string, listener: (...args: any[]) => void): GenericEventEmitter; - removeListener(event: string, listener: (...args: any[]) => void): GenericEventEmitter; - removeAllListeners(event?: string): GenericEventEmitter; - emit(event: string, ...args: any[]): boolean; - } +declare class Mocha { + private _growl; + private _reporter; + private _ui; - interface MochaSetupOptions { - // milliseconds to wait before considering a test slow - slow?: number; + constructor(options?: Mocha.MochaOptions); - // timeout in milliseconds - timeout?: number; - - // ui name "bdd", "tdd", "exports" etc - ui?: Mocha.Interface; - - // array of accepted globals - globals?: any[]; - - // reporter instance (function or string), defaults to `mocha.reporters.Spec` - reporter?: string | ReporterConstructor; - - // bail on the first test failure - bail?: boolean; - - // ignore global leaks - ignoreLeaks?: boolean; - - // grep string or regexp to filter tests with - grep?: any; - - // require modules before running tests - require?: string[]; - - asyncOnly?: boolean; - delay?: boolean; - files?: string[]; - forbidOnly?: boolean; - forbidPending?: boolean; - fullStackTrace?: boolean; - hasOnly?: boolean; - } - - declare const mocha: Mocha; - declare const describe: Mocha.IContextDefinition; - declare const xdescribe: Mocha.IContextDefinition; - // alias for `describe` - declare const context: Mocha.IContextDefinition; - // alias for `describe` - declare const suite: Mocha.IContextDefinition; - declare const it: Mocha.ITestDefinition; - declare const xit: Mocha.ITestDefinition; - // alias for `it` - declare const test: Mocha.ITestDefinition; - declare const specify: Mocha.ITestDefinition; - - // Used with the --delay flag; see https://mochajs.org/#hooks - declare function run(): void; - - type MochaDone = (error?: any) => void; - - declare function setup(callback: (this: Mocha.IBeforeAndAfterContext, done: MochaDone) => PromiseLike | void): void; - declare function teardown(callback: (this: Mocha.IBeforeAndAfterContext, done: MochaDone) => PromiseLike | void): void; - declare function suiteSetup(callback: (this: Mocha.IHookCallbackContext, done: MochaDone) => PromiseLike | void): void; - declare function suiteTeardown(callback: (this: Mocha.IHookCallbackContext, done: MochaDone) => PromiseLike | void): void; - declare function before(callback: (this: Mocha.IHookCallbackContext, done: MochaDone) => PromiseLike | void): void; - declare function before(description: string, callback: (this: Mocha.IHookCallbackContext, done: MochaDone) => PromiseLike | void): void; - declare function after(callback: (this: Mocha.IHookCallbackContext, done: MochaDone) => PromiseLike | void): void; - declare function after(description: string, callback: (this: Mocha.IHookCallbackContext, done: MochaDone) => PromiseLike | void): void; - declare function beforeEach(callback: (this: Mocha.IBeforeAndAfterContext, done: MochaDone) => PromiseLike | void): void; - declare function beforeEach(description: string, callback: (this: Mocha.IBeforeAndAfterContext, done: MochaDone) => PromiseLike | void): void; - declare function afterEach(callback: (this: Mocha.IBeforeAndAfterContext, done: MochaDone) => PromiseLike | void): void; - declare function afterEach(description: string, callback: (this: Mocha.IBeforeAndAfterContext, done: MochaDone) => PromiseLike | void): void; - - interface ReporterConstructor { - new(runner: Mocha.IRunner, options: any): any; - } - - declare class Mocha { - currentTest: Mocha.ITestDefinition; - suite: Mocha.ISuite; + suite: Mocha.Suite; files: string[]; - options: MochaSetupOptions; + options: Mocha.MochaInstanceOptions; - constructor(options?: MochaSetupOptions); - - asyncOnly(): Mocha; - asyncOnly(value: boolean): Mocha; - delay(): Mocha; - forbidOnly(): Mocha; - forbidPending(): Mocha; - fullTrace(): Mocha; - /** Setup mocha with the given interface. */ - setup(interface: Mocha.Interface): Mocha; - bail(value?: boolean): Mocha; - addFile(file: string): Mocha; - /** Sets reporter by name, defaults to "spec". */ - reporter(name: string, reporterOptions?: any): Mocha; - /** Sets reporter constructor, defaults to mocha.reporters.Spec. */ - reporter(reporter: ReporterConstructor, reporterOptions?: any): Mocha; - ui(value: string): Mocha; - grep(value: string): Mocha; - grep(value: RegExp): Mocha; - invert(): Mocha; - ignoreLeaks(value: boolean): Mocha; - checkLeaks(): Mocha; /** - * Function to allow assertion libraries to throw errors directly into mocha. - * This is useful when running tests in a browser because window.onerror will - * only receive the 'message' attribute of the Error. + * Enable or disable bailing on the first failure. + * + * @see https://mochajs.org/api/mocha#bail */ - throwError(error: Error): void; - /** Enables growl support. */ - growl(): Mocha; - globals(value: string): Mocha; - globals(values: string[]): Mocha; - useColors(value: boolean): Mocha; - useInlineDiffs(value: boolean): Mocha; - timeout(value: number): Mocha; - slow(value: number): Mocha; - enableTimeouts(value: boolean): Mocha; - noHighlighting(value: boolean): Mocha; - /** Runs tests and invokes `onComplete()` when finished. */ - run(onComplete?: (failures: number) => void): Mocha.IRunner; - loadFiles(cb?: () => any): void; + bail(bail?: boolean): this; - // internals exposed via exports.* - Runnable: Mocha.Runnable; - Context: Mocha.Context; - Runner: Mocha.Runner; - Suite: Mocha.Suite; - Hook: Mocha.Hook; - Test: Mocha.Test; - } + /** + * Add test `file`. + * + * @see https://mochajs.org/api/mocha#addFile + */ + addFile(file: string): this; - // merge the Mocha class declaration with a module - declare namespace Mocha { - /** Third-party declarations that want to add new interfaces can contribute names here */ - interface InterfaceContributions { - bdd: any; - tdd: any; - qunit: any; - exports: any; + /** + * Set reporter to one of the built-in reporters. + * + * @see https://mochajs.org/api/mocha#reporter + */ + reporter(reporter: Mocha.Reporter, reporterOptions?: any): this; + + /** + * Set reporter to the provided constructor, one of the built-in reporters, or loads a reporter + * from a module path. Defaults to `"spec"`. + * + * @see https://mochajs.org/api/mocha#reporter + */ + reporter(reporter?: string | Mocha.ReporterConstructor, reporterOptions?: any): this; + + /** + * Set test UI to one of the built-in test interfaces. + * + * @see https://mochajs.org/api/mocha#ui + */ + ui(name: Mocha.Interface): this; + + /** + * Set test UI to one of the built-in test interfaces or loads a test interface from a module + * path. Defaults to `"bdd"`. + * + * @see https://mochajs.org/api/mocha#ui + */ + ui(name?: string): this; + + /** + * Escape string and add it to grep as a RegExp. + * + * @see https://mochajs.org/api/mocha#fgrep + */ + fgrep(str: string): this; + + /** + * Add regexp to grep, if `re` is a string it is escaped. + * + * @see https://mochajs.org/api/mocha#grep + */ + grep(re: string | RegExp): this; + + /** + * Invert `.grep()` matches. + * + * @see https://mochajs.org/api/mocha#invert + */ + invert(): this; + + /** + * Ignore global leaks. + * + * @see https://mochajs.org/api/mocha#ignoreLeaks + */ + ignoreLeaks(ignore: boolean): this; + + /** + * Enable global leak checking. + * + * @see https://mochajs.org/api/mocha#checkLeaks + */ + checkLeaks(): this; + + /** + * Display long stack-trace on failing + * + * @see https://mochajs.org/api/mocha#fullTrace + */ + fullTrace(): this; + + /** + * Enable growl support. + * + * @see https://mochajs.org/api/mocha#growl + */ + growl(): this; + + /** + * Ignore `globals` array or string. + * + * @see https://mochajs.org/api/mocha#globals + */ + globals(globals: string | ReadonlyArray): this; + + /** + * Emit color output. + * + * @see https://mochajs.org/api/mocha#useColors + */ + useColors(colors: boolean): this; + + /** + * Use inline diffs rather than +/-. + * + * @see https://mochajs.org/api/mocha#useInlineDiffs + */ + useInlineDiffs(inlineDiffs: boolean): this; + + /** + * Do not show diffs at all. + * + * @see https://mochajs.org/api/mocha#hideDiff + */ + hideDiff(hideDiff: boolean): this; + + /** + * Set the timeout in milliseconds. + * + * @see https://mochajs.org/api/mocha#timeout + */ + timeout(timeout: string | number): this; + + /** + * Set the number of times to retry failed tests. + * + * @see https://mochajs.org/api/mocha#retries + */ + retries(n: number): this; + + /** + * Set slowness threshold in milliseconds. + * + * @see https://mochajs.org/api/mocha#slow + */ + slow(slow: string | number): this; + + /** + * Enable timeouts. + * + * @see https://mochajs.org/api/mocha#enableTimeouts + */ + enableTimeouts(enabled?: boolean): this; + + /** + * Makes all tests async (accepting a callback) + * + * @see https://mochajs.org/api/mocha#asyncOnly. + */ + asyncOnly(): this; + + /** + * Disable syntax highlighting (in browser). + * + * @see https://mochajs.org/api/mocha#noHighlighting + */ + noHighlighting(): this; + + /** + * Enable uncaught errors to propagate (in browser). + * + * @see https://mochajs.org/api/mocha#allowUncaught + */ + allowUncaught(): boolean; + + /** + * Delay root suite execution. + * + * @see https://mochajs.org/api/mocha#delay + */ + delay(): boolean; + + /** + * Tests marked only fail the suite + * + * @see https://mochajs.org/api/mocha#forbidOnly + */ + forbidOnly(): boolean; + + /** + * Pending tests and tests marked skip fail the suite + * + * @see https://mochajs.org/api/mocha#forbidPending + */ + forbidPending(): boolean; + + /** + * Run tests and invoke `fn()` when complete. + * + * Note that `run` relies on Node's `require` to execute + * the test interface functions and will be subject to the + * cache - if the files are already in the `require` cache, + * they will effectively be skipped. Therefore, to run tests + * multiple times or to run tests in files that are already + * in the `require` cache, make sure to clear them from the + * cache first in whichever manner best suits your needs. + * + * @see https://mochajs.org/api/mocha#run + */ + run(fn?: (failures: number) => void): Mocha.Runner; + + /** + * Load registered files. + * + * @see https://mochajs.org/api/mocha#loadFiles + */ + protected loadFiles(fn?: () => void): void; +} + +declare namespace Mocha { + namespace utils { + /** + * Compute a slug from the given `str`. + * + * @see https://mochajs.org/api/module-utils.html#.slug + */ + function slug(str: string): string; + + /** + * Strip the function definition from `str`, and re-indent for pre whitespace. + * + * @see https://mochajs.org/api/module-utils.html#.clean + */ + function clean(str: string): string; + + /** + * Highlight the given string of `js`. + */ + function highlight(js: string): string; + + /** + * Takes some variable and asks `Object.prototype.toString()` what it thinks it is. + */ + function type(value: any): string; + + /** + * Stringify `value`. Different behavior depending on type of value: + * + * - If `value` is undefined or null, return `'[undefined]'` or `'[null]'`, respectively. + * - If `value` is not an object, function or array, return result of `value.toString()` wrapped in double-quotes. + * - If `value` is an *empty* object, function, or array, returns `'{}'`, `'[Function]'`, or `'[]'` respectively. + * - If `value` has properties, call canonicalize} on it, then return result of `JSON.stringify()` + * + * @see https://mochajs.org/api/module-utils.html#.stringify + */ + function stringify(value: any): string; + + /** + * Return a new Thing that has the keys in sorted order. Recursive. + * + * If the Thing... + * - has already been seen, return string `'[Circular]'` + * - is `undefined`, return string `'[undefined]'` + * - is `null`, return value `null` + * - is some other primitive, return the value + * - is not a primitive or an `Array`, `Object`, or `Function`, return the value of the Thing's `toString()` method + * - is a non-empty `Array`, `Object`, or `Function`, return the result of calling this function again. + * - is an empty `Array`, `Object`, or `Function`, returns `'[]'`, `'{}'`, or `'[Function]'` respectively. + * + * @see https://mochajs.org/api/module-utils.html#.canonicalize + */ + function canonicalize(value: any, stack: any[], typeHint: string): any; + + /** + * Lookup file names at the given `path`. + * + * @see https://mochajs.org/api/Mocha.utils.html#.exports.lookupFiles + */ + function lookupFiles(filepath: string, extensions?: string[], recursive?: boolean): string[]; + + /** + * Generate an undefined error with a message warning the user. + * + * @see https://mochajs.org/api/module-utils.html#.undefinedError + */ + function undefinedError(): Error; + + /** + * Generate an undefined error if `err` is not defined. + * + * @see https://mochajs.org/api/module-utils.html#.getError + */ + function getError(err: Error | undefined): Error; + + /** + * When invoking this function you get a filter function that get the Error.stack as an + * input, and return a prettify output. (i.e: strip Mocha and internal node functions from + * stack trace). + * + * @see https://mochajs.org/api/module-utils.html#.stackTraceFilter + */ + function stackTraceFilter(): (stack: string) => string; } - type Interface = keyof InterfaceContributions; - - interface IContext { - _runnable?: IRunnable; - test?: IRunnable; - - runnable(): IRunnable | undefined; - runnable(runnable: IRunnable): IContext; - timeout(): number; - timeout(timeout: number): IContext; - enableTimeouts(enableTimeouts: boolean): IContext; - slow(slow: number): IContext; - skip(): IContext; - retries(): number; - retries(retries: number): IContext; - inspect(): string; + namespace interfaces { + function bdd(suite: Suite): void; + function tdd(suite: Suite): void; + function qunit(suite: Suite): void; + function exports(suite: Suite): void; } - interface ISuiteCallbackContext { - timeout(ms: number | string): this; - retries(n: number): this; - slow(ms: number): this; + // #region Test interface augmentations + + interface HookFunction { + /** + * [bdd, qunit, tdd] Describe a "hook" to execute the given callback `fn`. The name of the + * function is used as the name of the hook. + * + * - _Only available when invoked via the mocha CLI._ + */ + (fn: Func): void; + + /** + * [bdd, qunit, tdd] Describe a "hook" to execute the given callback `fn`. The name of the + * function is used as the name of the hook. + * + * - _Only available when invoked via the mocha CLI._ + */ + (fn: AsyncFunc): void; + + /** + * [bdd, qunit, tdd] Describe a "hook" to execute the given `title` and callback `fn`. + * + * - _Only available when invoked via the mocha CLI._ + */ + (name: string, fn?: Func): void; + + /** + * [bdd, qunit, tdd] Describe a "hook" to execute the given `title` and callback `fn`. + * + * - _Only available when invoked via the mocha CLI._ + */ + (name: string, fn?: AsyncFunc): void; } - interface IHookCallbackContext { - skip(): this; - timeout(ms: number | string): this; - [index: string]: any; + interface SuiteFunction { + /** + * [bdd, tdd] Describe a "suite" with the given `title` and callback `fn` containing + * nested suites. + * + * - _Only available when invoked via the mocha CLI._ + */ + (title: string, fn: (this: Suite) => void): Suite; + + /** + * [qunit] Describe a "suite" with the given `title`. + * + * - _Only available when invoked via the mocha CLI._ + */ + (title: string): Suite; + + /** + * [bdd, tdd, qunit] Indicates this suite should be executed exclusively. + * + * - _Only available when invoked via the mocha CLI._ + */ + only: ExclusiveSuiteFunction; + + /** + * [bdd, tdd] Indicates this suite should not be executed. + * + * - _Only available when invoked via the mocha CLI._ + */ + skip: PendingSuiteFunction; } - interface ITestCallbackContext { - skip(): this; - timeout(ms: number | string): this; - retries(n: number): this; - slow(ms: number): this; - [index: string]: any; + interface ExclusiveSuiteFunction { + /** + * [bdd, tdd] Describe a "suite" with the given `title` and callback `fn` containing + * nested suites. Indicates this suite should be executed exclusively. + * + * - _Only available when invoked via the mocha CLI._ + */ + (title: string, fn: (this: Suite) => void): Suite; + + /** + * [qunit] Describe a "suite" with the given `title`. Indicates this suite should be executed + * exclusively. + * + * - _Only available when invoked via the mocha CLI._ + */ + (title: string): Suite; } - /** Partial interface for Mocha's `Runnable` class. */ - interface IRunnable extends GenericEventEmitter { + /** + * [bdd, tdd] Describe a "suite" with the given `title` and callback `fn` containing + * nested suites. Indicates this suite should not be executed. + * + * - _Only available when invoked via the mocha CLI._ + * + * @returns [bdd] `Suite` + * @returns [tdd] `void` + */ + type PendingSuiteFunction = (title: string, fn: (this: Suite) => void) => Suite | void; + + interface TestFunction { + /** + * Describe a specification or test-case with the given callback `fn` acting as a thunk. + * The name of the function is used as the name of the test. + * + * - _Only available when invoked via the mocha CLI._ + */ + (fn: Func): Test; + + /** + * Describe a specification or test-case with the given callback `fn` acting as a thunk. + * The name of the function is used as the name of the test. + * + * - _Only available when invoked via the mocha CLI._ + */ + (fn: AsyncFunc): Test; + + /** + * Describe a specification or test-case with the given `title` and callback `fn` acting + * as a thunk. + * + * - _Only available when invoked via the mocha CLI._ + */ + (title: string, fn?: Func): Test; + + /** + * Describe a specification or test-case with the given `title` and callback `fn` acting + * as a thunk. + * + * - _Only available when invoked via the mocha CLI._ + */ + (title: string, fn?: AsyncFunc): Test; + + /** + * Indicates this test should be executed exclusively. + * + * - _Only available when invoked via the mocha CLI._ + */ + only: ExclusiveTestFunction; + + /** + * Indicates this test should not be executed. + * + * - _Only available when invoked via the mocha CLI._ + */ + skip: PendingTestFunction; + + /** + * Number of attempts to retry. + * + * - _Only available when invoked via the mocha CLI._ + */ + retries(n: number): void; + } + + interface ExclusiveTestFunction { + /** + * [bdd, tdd, qunit] Describe a specification or test-case with the given callback `fn` + * acting as a thunk. The name of the function is used as the name of the test. Indicates + * this test should be executed exclusively. + * + * - _Only available when invoked via the mocha CLI._ + */ + (fn: Func): Test; + + /** + * [bdd, tdd, qunit] Describe a specification or test-case with the given callback `fn` + * acting as a thunk. The name of the function is used as the name of the test. Indicates + * this test should be executed exclusively. + * + * - _Only available when invoked via the mocha CLI._ + */ + (fn: AsyncFunc): Test; + + /** + * [bdd, tdd, qunit] Describe a specification or test-case with the given `title` and + * callback `fn` acting as a thunk. Indicates this test should be executed exclusively. + * + * - _Only available when invoked via the mocha CLI._ + */ + (title: string, fn?: Func): Test; + + /** + * [bdd, tdd, qunit] Describe a specification or test-case with the given `title` and + * callback `fn` acting as a thunk. Indicates this test should be executed exclusively. + * + * - _Only available when invoked via the mocha CLI._ + */ + (title: string, fn?: AsyncFunc): Test; + } + + interface PendingTestFunction { + /** + * [bdd, tdd, qunit] Describe a specification or test-case with the given callback `fn` + * acting as a thunk. The name of the function is used as the name of the test. Indicates + * this test should not be executed. + * + * - _Only available when invoked via the mocha CLI._ + */ + (fn: Func): Test; + + /** + * [bdd, tdd, qunit] Describe a specification or test-case with the given callback `fn` + * acting as a thunk. The name of the function is used as the name of the test. Indicates + * this test should not be executed. + * + * - _Only available when invoked via the mocha CLI._ + */ + (fn: AsyncFunc): Test; + + /** + * [bdd, tdd, qunit] Describe a specification or test-case with the given `title` and + * callback `fn` acting as a thunk. Indicates this test should not be executed. + * + * - _Only available when invoked via the mocha CLI._ + */ + (title: string, fn?: Func): Test; + + /** + * [bdd, tdd, qunit] Describe a specification or test-case with the given `title` and + * callback `fn` acting as a thunk. Indicates this test should not be executed. + * + * - _Only available when invoked via the mocha CLI._ + */ + (title: string, fn?: AsyncFunc): Test; + } + + /** + * Execute after each test case. + * + * - _Only available when invoked via the mocha CLI._ + * + * @see https://mochajs.org/api/global.html#afterEach + */ + let afterEach: HookFunction; + + /** + * Execute after running tests. + * + * - _Only available when invoked via the mocha CLI._ + * + * @see https://mochajs.org/api/global.html#after + */ + let after: HookFunction; + + /** + * Execute before each test case. + * + * - _Only available when invoked via the mocha CLI._ + * + * @see https://mochajs.org/api/global.html#beforeEach + */ + let beforeEach: HookFunction; + + /** + * Execute before running tests. + * + * - _Only available when invoked via the mocha CLI._ + * + * @see https://mochajs.org/api/global.html#before + */ + let before: HookFunction; + + /** + * Describe a "suite" containing nested suites and tests. + * + * - _Only available when invoked via the mocha CLI._ + */ + let describe: SuiteFunction; + + /** + * Describes a test case. + * + * - _Only available when invoked via the mocha CLI._ + */ + let it: TestFunction; + + /** + * Describes a pending test case. + * + * - _Only available when invoked via the mocha CLI._ + */ + let xit: PendingTestFunction; + + /** + * Execute before each test case. + * + * - _Only available when invoked via the mocha CLI._ + * + * @see https://mochajs.org/api/global.html#beforeEach + */ + let setup: HookFunction; + + /** + * Execute before running tests. + * + * - _Only available when invoked via the mocha CLI._ + * + * @see https://mochajs.org/api/global.html#before + */ + let suiteSetup: HookFunction; + + /** + * Execute after running tests. + * + * - _Only available when invoked via the mocha CLI._ + * + * @see https://mochajs.org/api/global.html#after + */ + let suiteTeardown: HookFunction; + + /** + * Describe a "suite" containing nested suites and tests. + * + * - _Only available when invoked via the mocha CLI._ + */ + let suite: SuiteFunction; + + /** + * Execute after each test case. + * + * - _Only available when invoked via the mocha CLI._ + * + * @see https://mochajs.org/api/global.html#afterEach + */ + let teardown: HookFunction; + + /** + * Describes a test case. + * + * - _Only available when invoked via the mocha CLI._ + */ + let test: TestFunction; + + /** + * Triggers root suite execution. + * + * - _Only available if flag --delay is passed into Mocha._ + * - _Only available when invoked via the mocha CLI._ + * + * @see https://mochajs.org/api/global.html#runWithSuite + */ + function run(): void; + + // #endregion Test interface augmentations + + namespace reporters { + /** + * Initialize a new `Base` reporter. + * + * All other reporters generally inherit from this reporter, providing stats such as test duration, + * number of tests passed / failed, etc. + * + * @see https://mochajs.org/api/Mocha.reporters.Base.html + */ + class Base { + constructor(runner: Runner, options?: MochaOptions); + /** @deprecated Use the overload that accepts `Mocha.Runner` instead. */ + constructor(runner: IRunner, options?: MochaOptions); + + /** + * Test run statistics + */ + stats: Stats; + + /** + * Test failures + */ + failures: Test[]; + + /** + * The configured runner + */ + runner: Runner; + + /** + * Output common epilogue used by many of the bundled reporters. + * + * @see https://mochajs.org/api/Mocha.reporters.Base.html#.Base#epilogue + */ + epilogue(): void; + + done?(failures: number, fn?: (failures: number) => void): void; + } + + namespace Base { + /** + * Enables coloring by default + * + * @see https://mochajs.org/api/module-base#.useColors + */ + let useColors: boolean; + + /** + * Inline diffs instead of +/- + * + * @see https://mochajs.org/api/module-base#.inlineDiffs + */ + let inlineDiffs: boolean; + + /** + * Default color map + * + * @see https://mochajs.org/api/module-base#.colors + */ + const colors: ColorMap; + + /** + * Default color map + * + * @see https://mochajs.org/api/module-base#.colors + */ + interface ColorMap { + // added by Base + pass: number; + fail: number; + "bright pass": number; + "bright fail": number; + "bright yellow": number; + pending: number; + suite: number; + "error title": number; + "error message": number; + "error stack": number; + checkmark: number; + fast: number; + medium: number; + slow: number; + green: number; + light: number; + "diff gutter": number; + "diff added": number; + "diff removed": number; + + // added by Progress + progress: number; + + // added by Landing + plane: number; + "plane crash": number; + runway: number; + + [key: string]: number; + } + + /** + * Default symbol map + * + * @see https://mochajs.org/api/module-base#.symbols + */ + const symbols: SymbolMap; + + /** + * Default symbol map + * + * @see https://mochajs.org/api/module-base#.symbols + */ + interface SymbolMap { + ok: string; + err: string; + dot: string; + comma: string; + bang: string; + [key: string]: string; + } + + /** + * Color `str` with the given `type` (from `colors`) + * + * @see https://mochajs.org/api/module-base#.color + */ + function color(type: string, str: string): string; + + /** + * Expose terminal window size + * + * @see https://mochajs.org/api/module-base#.window + */ + const window: { + width: number; + }; + + /** + * ANSI TTY control sequences common among reporters. + * + * @see https://mochajs.org/api/module-base#.cursor + */ + namespace cursor { + /** + * Hides the cursor + */ + function hide(): void; + + /** + * Shows the cursor + */ + function show(): void; + + /** + * Deletes the current line + */ + function deleteLine(): void; + + /** + * Moves to the beginning of the line + */ + function beginningOfLine(): void; + + /** + * Clears the line and moves to the beginning of the line. + */ + function CR(): void; + } + + /** + * Returns a diff between two strings with colored ANSI output. + * + * @see https://mochajs.org/api/module-base#.generateDiff + */ + function generateDiff(actual: string, expected: string): string; + + /** + * Output the given `failures` as a list. + * + * @see https://mochajs.org/api/Mocha.reporters.Base.html#.exports.list1 + */ + function list(failures: Test[]): void; + } + + /** + * Initialize a new `Dot` matrix test reporter. + * + * @see https://mochajs.org/api/Mocha.reporters.Dot.html + */ + class Dot extends Base { + } + + /** + * Initialize a new `Doc` reporter. + * + * @see https://mochajs.org/api/Mocha.reporters.Doc.html + */ + class Doc extends Base { + } + + /** + * Initialize a new `TAP` test reporter. + * + * @see https://mochajs.org/api/Mocha.reporters.TAP.html + */ + class TAP extends Base { + } + + /** + * Initialize a new `JSON` reporter + * + * @see https://mochajs.org/api/Mocha.reporters.JSON.html + */ + class JSON extends Base { + } + + /** + * Initialize a new `HTML` reporter. + * + * - _This reporter cannot be used on the console._ + * + * @see https://mochajs.org/api/Mocha.reporters.HTML.html + */ + class HTML extends Base { + /** + * Provide suite URL. + * + * @see https://mochajs.org/api/Mocha.reporters.HTML.html#suiteURL + */ + suiteURL(suite: Suite): string; + + /** + * Provide test URL. + * + * @see https://mochajs.org/api/Mocha.reporters.HTML.html#testURL + */ + testURL(test: Test): string; + + /** + * Adds code toggle functionality for the provided test's list element. + * + * @see https://mochajs.org/api/Mocha.reporters.HTML.html#addCodeToggle + */ + addCodeToggle(el: HTMLLIElement, contents: string): void; + } + + /** + * Initialize a new `List` test reporter. + * + * @see https://mochajs.org/api/Mocha.reporters.List.html + */ + class List extends Base { + } + + /** + * Initialize a new `Min` minimal test reporter (best used with --watch). + * + * @see https://mochajs.org/api/Mocha.reporters.Min.html + */ + class Min extends Base { + } + + /** + * Initialize a new `Spec` test reporter. + * + * @see https://mochajs.org/api/Mocha.reporters.Spec.html + */ + class Spec extends Base { + } + + /** + * Initialize a new `NyanCat` test reporter. + * + * @see https://mochajs.org/api/Mocha.reporters.Nyan.html + */ + class Nyan extends Base { + private colorIndex; + private numberOfLines; + private rainbowColors; + private scoreboardWidth; + private tick; + private trajectories; + private trajectoryWidthMax; + private draw; + private drawScoreboard; + private appendRainbow; + private drawRainbow; + private drawNyanCat; + private face; + private cursorUp; + private cursorDown; + private generateColors; + private rainbowify; + } + + /** + * Initialize a new `XUnit` test reporter. + * + * @see https://mochajs.org/api/Mocha.reporters.XUnit.html + */ + class XUnit extends Base { + constructor(runner: Runner, options?: XUnit.MochaOptions); + /** @deprecated Use the overload that accepts `Mocha.Runner` instead. */ + constructor(runner: IRunner, options?: XUnit.MochaOptions); + + /** + * Override done to close the stream (if it's a file). + * + * @see https://mochajs.org/api/Mocha.reporters.XUnit.html#done + */ + done(failures: number, fn: (failures: number) => void): void; + + /** + * Write out the given line. + * + * @see https://mochajs.org/api/Mocha.reporters.XUnit.html#write + */ + write(line: string): void; + + /** + * Output tag for the given `test.` + * + * @see https://mochajs.org/api/Mocha.reporters.XUnit.html#test + */ + test(test: Test): void; + } + + namespace XUnit { + interface MochaOptions extends Mocha.MochaOptions { + reporterOptions?: ReporterOptions; + } + + interface ReporterOptions { + output?: string; + suiteName?: string; + } + } + + /** + * Initialize a new `Markdown` test reporter. + * + * @see https://mochajs.org/api/Mocha.reporters.Markdown.html + */ + class Markdown extends Base { + } + + /** + * Initialize a new `Progress` bar test reporter. + * + * @see https://mochajs.org/api/Mocha.reporters.Progress.html + */ + class Progress extends Base { + constructor(runner: Runner, options?: Progress.MochaOptions); + /** @deprecated Use the overload that accepts `Mocha.Runner` instead. */ + constructor(runner: IRunner, options?: Progress.MochaOptions); + } + + namespace Progress { + interface MochaOptions extends Mocha.MochaOptions { + reporterOptions?: ReporterOptions; + } + + interface ReporterOptions { + open?: string; + complete?: string; + incomplete?: string; + close?: string; + verbose?: boolean; + } + } + + /** + * Initialize a new `Landing` reporter. + * + * @see https://mochajs.org/api/Mocha.reporters.Landing.html + */ + class Landing extends Base { + } + + /** + * Initialize a new `JSONStream` test reporter. + * + * @see https://mochajs.org/api/Mocha.reporters.JSONStream.html + */ + class JSONStream extends Base { + } + + // value-only aliases + const base: typeof Base; + const dot: typeof Dot; + const doc: typeof Doc; + const tap: typeof TAP; + const json: typeof JSON; + const html: typeof HTML; + const list: typeof List; + const spec: typeof Spec; + const nyan: typeof Nyan; + const xunit: typeof XUnit; + const markdown: typeof Markdown; + const progress: typeof Progress; + const landing: typeof Landing; + // NOTE: not possible to type this correctly: + // const "json-stream": typeof JSONStream; + } + + /** + * Initialize a new `Runnable` with the given `title` and callback `fn`. + * + * @see https://mochajs.org/api/Runnable.html + */ + class Runnable { + private _slow; + private _enableTimeouts; + private _retries; + private _currentRetry; + private _timeout; + private _timeoutError; + + constructor(title: string, fn?: Func | AsyncFunc); + title: string; - fn: Function; + fn: Func | AsyncFunc | undefined; + body: string; async: boolean; sync: boolean; timedOut: boolean; - timeout(n: number | string): this; - duration?: number; - } - - /** Partial interface for Mocha's `Suite` class. */ - interface ISuite { - ctx: IContext; - parent: ISuite; - root: boolean; - title: string; - suites: ISuite[]; - tests: ITest[]; - - _beforeEach: IHook[]; - _beforeAll: IHook[]; - _afterEach: IHook[]; - _afterAll: IHook[]; - - bail(): boolean; - bail(bail: boolean): ISuite; - fullTitle(): string; - retries(): number; - retries(retries: number): ISuite; - slow(): number; - slow(slow: number): ISuite; - timeout(): number; - timeout(timeout: number): ISuite; - } - - /** Partial interface for Mocha's `Test` class. */ - interface ITest extends IRunnable { - body?: string; - file?: string; - parent: ISuite; pending: boolean; - state: 'failed' | 'passed' | undefined; - type: 'test'; + duration?: number; + parent?: Suite; + state?: "failed" | "passed"; + timer?: any; + ctx?: Context; + callback?: Done; + allowUncaught?: boolean; + file?: string; + /** + * Get test timeout. + * + * @see https://mochajs.org/api/Runnable.html#timeout + */ + timeout(): number; + + /** + * Set test timeout. + * + * @see https://mochajs.org/api/Runnable.html#timeout + */ + timeout(ms: string | number): this; + + /** + * Get test slowness threshold. + * + * @see https://mochajs.org/api/Runnable.html#slow + */ + slow(): number; + + /** + * Set test slowness threshold. + * + * @see https://mochajs.org/api/Runnable.html#slow + */ + slow(ms: string | number): this; + + /** + * Get whether timeouts are enabled. + * + * @see https://mochajs.org/api/Runnable.html#enableTimeouts + */ + enableTimeouts(): boolean; + + /** + * Set whether timeouts are enabled. + * + * @see https://mochajs.org/api/Runnable.html#enableTimeouts + */ + enableTimeouts(enabled: boolean): this; + + /** + * Halt and mark as pending. + */ + skip(): never; + + /** + * Check if this runnable or its parent suite is marked as pending. + * + * @see https://mochajs.org/api/Runnable.html#isPending + */ + isPending(): boolean; + + /** + * Return `true` if this Runnable has failed. + */ + isFailed(): boolean; + + /** + * Return `true` if this Runnable has passed. + */ + isPassed(): boolean; + + /** + * Set or get number of retries. + * + * @see https://mochajs.org/api/Runnable.html#retries + */ + retries(): number; + + /** + * Set or get number of retries. + * + * @see https://mochajs.org/api/Runnable.html#retries + */ + retries(n: number): void; + + /** + * Set or get current retry + * + * @see https://mochajs.org/api/Runnable.html#currentRetry + */ + protected currentRetry(): number; + + /** + * Set or get current retry + * + * @see https://mochajs.org/api/Runnable.html#currentRetry + */ + protected currentRetry(n: number): void; + + /** + * Return the full title generated by recursively concatenating the parent's full title. + */ fullTitle(): string; + + /** + * Return the title path generated by concatenating the parent's title path with the title. + */ + titlePath(): string[]; + + /** + * Clear the timeout. + * + * @see https://mochajs.org/api/Runnable.html#clearTimeout + */ + clearTimeout(): void; + + /** + * Inspect the runnable void of private properties. + * + * @see https://mochajs.org/api/Runnable.html#inspect + */ + inspect(): string; + + /** + * Reset the timeout. + * + * @see https://mochajs.org/api/Runnable.html#resetTimeout + */ + resetTimeout(): void; + + /** + * Get a list of whitelisted globals for this test run. + * + * @see https://mochajs.org/api/Runnable.html#globals + */ + globals(): string[]; + + /** + * Set a list of whitelisted globals for this test run. + * + * @see https://mochajs.org/api/Runnable.html#globals + */ + globals(globals: ReadonlyArray): void; + + /** + * Run the test and invoke `fn(err)`. + * + * @see https://mochajs.org/api/Runnable.html#run + */ + run(fn: Done): void; } - interface IHook extends IRunnable { - ctx?: IContext; - parent?: ISuite; - type: 'hook'; + // #region Runnable "error" event + interface Runnable extends NodeJS.EventEmitter { + on(event: "error", listener: (error: any) => void): this; + once(event: "error", listener: (error: any) => void): this; + addListener(event: "error", listener: (error: any) => void): this; + removeListener(event: "error", listener: (error: any) => void): this; + prependListener(event: "error", listener: (error: any) => void): this; + prependOnceListener(event: "error", listener: (error: any) => void): this; + emit(name: "error", error: any): boolean; + } + // #endregion Runnable "error" event + // #region Runnable untyped events + interface Runnable extends NodeJS.EventEmitter { + on(event: string, listener: (...args: any[]) => void): this; + once(event: string, listener: (...args: any[]) => void): this; + addListener(event: string, listener: (...args: any[]) => void): this; + removeListener(event: string, listener: (...args: any[]) => void): this; + prependListener(event: string, listener: (...args: any[]) => void): this; + prependOnceListener(event: string, listener: (...args: any[]) => void): this; + emit(name: string, ...args: any[]): boolean; + } + // #endregion Runnable untyped events - error(err: Error): void; + /** + * Test context + * + * @see https://mochajs.org/api/module-Context.html#~Context + */ + class Context { + private _runnable; + + test?: Runnable; + currentTest?: Test; + + /** + * Get the context `Runnable`. + */ + runnable(): Runnable; + + /** + * Set the context `Runnable`. + */ + runnable(runnable: Runnable): this; + /** @deprecated Use the overload that accepts `Mocha.Runnable` instead. */ + runnable(runnable: IRunnable): this; + + /** + * Get test timeout. + */ + timeout(): number; + + /** + * Set test timeout. + */ + timeout(ms: string | number): this; + + /** + * Get whether timeouts are enabled. + */ + enableTimeouts(): boolean; + + /** + * Set whether timeouts are enabled. + */ + enableTimeouts(enabled: boolean): this; + + /** + * Get test slowness threshold. + */ + slow(): number; + + /** + * Set test slowness threshold. + */ + slow(ms: string | number): this; + + /** + * Mark a test as skipped. + */ + skip(): never; + + /** + * Get the number of allowed retries on failed tests. + */ + retries(): number; + + /** + * Set the number of allowed retries on failed tests. + */ + retries(n: number): this; + + [key: string]: any; } - interface IBeforeAndAfterContext extends IHookCallbackContext { - currentTest: ITest; + /** + * Initialize a `Runner` for the given `suite`. + * + * @see https://mochajs.org/api/Mocha.Runner.html + */ + class Runner { + private _globals; + private _abort; + private _delay; + private _defaultGrep; + private next; + private hookErr; + private prevGlobalsLength; + private nextSuite; + + constructor(suite: Suite, delay: boolean); + + /** @deprecated Use the overload that accepts `Mocha.Suite` instead. */ + constructor(suite: ISuite, delay: boolean); + + suite: Suite; + started: boolean; + total: number; + failures: number; + asyncOnly?: boolean; + allowUncaught?: boolean; + fullStackTrace?: boolean; + forbidOnly?: boolean; + forbidPending?: boolean; + ignoreLeaks?: boolean; + test?: Test; + currentRunnable?: Runnable; + stats?: Stats; // added by reporters + + /** + * Run tests with full titles matching `re`. Updates runner.total + * with number of tests matched. + * + * @see https://mochajs.org/api/Mocha.Runner.html#.Runner#grep + */ + grep(re: RegExp, invert: boolean): this; + + /** + * Returns the number of tests matching the grep search for the + * given suite. + * + * @see https://mochajs.org/api/Mocha.Runner.html#.Runner#grepTotal + */ + grepTotal(suite: Suite): number; + + /** @deprecated Use the overload that accepts `Mocha.Suite` instead. */ + grepTotal(suite: ISuite): number; + + /** + * Gets the allowed globals. + * + * @see https://mochajs.org/api/Mocha.Runner.html#.Runner#globals + */ + globals(): string[]; + + /** + * Allow the given `arr` of globals. + * + * @see https://mochajs.org/api/Mocha.Runner.html#.Runner#globals + */ + globals(arr: ReadonlyArray): this; + + /** + * Run the root suite and invoke `fn(failures)` on completion. + * + * @see https://mochajs.org/api/Mocha.Runner.html#.Runner#run + */ + run(fn?: (failures: number) => void): this; + + /** + * Cleanly abort execution. + * + * @see https://mochajs.org/api/Mocha.Runner.html#.Runner#abort + */ + abort(): this; + + /** + * Handle uncaught exceptions. + * + * @see https://mochajs.org/api/Mocha.Runner.html#uncaught + */ + uncaught(err: any): void; + + /** + * Wrapper for setImmediate, process.nextTick, or browser polyfill. + */ + protected static immediately(callback: Function): void; + + /** + * Return a list of global properties. + * + * @see https://mochajs.org/api/Mocha.Runner.html#globalProps + */ + protected globalProps(): string[]; + + /** + * Check for global variable leaks. + * + * @see https://mochajs.org/api/Mocha.Runner.html#checkGlobals + */ + protected checkGlobals(test: Test): void; + + /** + * Fail the given `test`. + * + * @see https://mochajs.org/api/Mocha.Runner.html#fail + */ + protected fail(test: Test, err: any): void; + + /** + * Fail the given `hook` with `err`. + * + * Hook failures work in the following pattern: + * - If bail, then exit + * - Failed `before` hook skips all tests in a suite and subsuites, + * but jumps to corresponding `after` hook + * - Failed `before each` hook skips remaining tests in a + * suite and jumps to corresponding `after each` hook, + * which is run only once + * - Failed `after` hook does not alter + * execution order + * - Failed `after each` hook skips remaining tests in a + * suite and subsuites, but executes other `after each` + * hooks + * + * @see https://mochajs.org/api/Mocha.Runner.html#failHook + */ + protected failHook(hook: Hook, err: any): void; + + /** + * Run hook `name` callbacks and then invoke `fn()`. + * + * @see https://mochajs.org/api/Mocha.Runner.html#hook + */ + protected hook(name: string, fn: () => void): void; + + /** + * Run hook `name` for the given array of `suites` + * in order, and callback `fn(err, errSuite)`. + * + * @see https://mochajs.org/api/Mocha.Runner.html#hooks + */ + protected hooks(name: string, suites: Suite[], fn: (err?: any, errSuite?: Suite) => void): void; + + /** + * Run hooks from the top level down. + * + * @see https://mochajs.org/api/Mocha.Runner.html#hookUp + */ + protected hookUp(name: string, fn: (err?: any, errSuite?: Suite) => void): void; + + /** + * Run hooks from the bottom up. + * + * @see https://mochajs.org/api/Mocha.Runner.html#hookDown + */ + protected hookDown(name: string, fn: (err?: any, errSuite?: Suite) => void): void; + + /** + * Return an array of parent Suites from closest to furthest. + * + * @see https://mochajs.org/api/Mocha.Runner.html#parents + */ + protected parents(): Suite[]; + + /** + * Run the current test and callback `fn(err)`. + * + * @see https://mochajs.org/api/Mocha.Runner.html#runTest + */ + protected runTest(fn: Done): any; + + /** + * Run tests in the given `suite` and invoke the callback `fn()` when complete. + * + * @see https://mochajs.org/api/Mocha.Runner.html#runTests + */ + protected runTests(suite: Suite, fn: (errSuite?: Suite) => void): void; + + /** + * Run the given `suite` and invoke the callback `fn()` when complete. + * + * @see https://mochajs.org/api/Mocha.Runner.html#runSuite + */ + protected runSuite(suite: Suite, fn: (errSuite?: Suite) => void): void; } - interface IStats { + // #region Runner "waiting" event + interface Runner { + on(event: "waiting", listener: (rootSuite: Suite) => void): this; + once(event: "waiting", listener: (rootSuite: Suite) => void): this; + addListener(event: "waiting", listener: (rootSuite: Suite) => void): this; + removeListener(event: "waiting", listener: (rootSuite: Suite) => void): this; + prependListener(event: "waiting", listener: (rootSuite: Suite) => void): this; + prependOnceListener(event: "waiting", listener: (rootSuite: Suite) => void): this; + emit(name: "waiting", rootSuite: Suite): boolean; + } + // #endregion Runner "waiting" event + // #region Runner "start" event + interface Runner extends NodeJS.EventEmitter { + on(event: "start", listener: () => void): this; + once(event: "start", listener: () => void): this; + addListener(event: "start", listener: () => void): this; + removeListener(event: "start", listener: () => void): this; + prependListener(event: "start", listener: () => void): this; + prependOnceListener(event: "start", listener: () => void): this; + emit(name: "start"): boolean; + } + // #endregion Runner "start" event + // #region Runner "end" event + interface Runner extends NodeJS.EventEmitter { + on(event: "end", listener: () => void): this; + once(event: "end", listener: () => void): this; + addListener(event: "end", listener: () => void): this; + removeListener(event: "end", listener: () => void): this; + prependListener(event: "end", listener: () => void): this; + prependOnceListener(event: "end", listener: () => void): this; + emit(name: "end"): boolean; + } + // #endregion Runner "end" event + // #region Runner "suite" event + interface Runner extends NodeJS.EventEmitter { + on(event: "suite", listener: (suite: Suite) => void): this; + once(event: "suite", listener: (suite: Suite) => void): this; + addListener(event: "suite", listener: (suite: Suite) => void): this; + removeListener(event: "suite", listener: (suite: Suite) => void): this; + prependListener(event: "suite", listener: (suite: Suite) => void): this; + prependOnceListener(event: "suite", listener: (suite: Suite) => void): this; + emit(name: "suite", suite: Suite): boolean; + } + // #endregion Runner "suite" event + // #region Runner "suite end" event + interface Runner extends NodeJS.EventEmitter { + on(event: "suite end", listener: (suite: Suite) => void): this; + once(event: "suite end", listener: (suite: Suite) => void): this; + addListener(event: "suite end", listener: (suite: Suite) => void): this; + removeListener(event: "suite end", listener: (suite: Suite) => void): this; + prependListener(event: "suite end", listener: (suite: Suite) => void): this; + prependOnceListener(event: "suite end", listener: (suite: Suite) => void): this; + emit(name: "suite end", suite: Suite): boolean; + } + // #endregion Runner "suite end" event + // #region Runner "test" event + interface Runner extends NodeJS.EventEmitter { + on(event: "test", listener: (test: Test) => void): this; + once(event: "test", listener: (test: Test) => void): this; + addListener(event: "test", listener: (test: Test) => void): this; + removeListener(event: "test", listener: (test: Test) => void): this; + prependListener(event: "test", listener: (test: Test) => void): this; + prependOnceListener(event: "test", listener: (test: Test) => void): this; + emit(name: "test", test: Test): boolean; + } + // #endregion Runner "test" event + // #region Runner "test end" event + interface Runner extends NodeJS.EventEmitter { + on(event: "test end", listener: (test: Test) => void): this; + once(event: "test end", listener: (test: Test) => void): this; + addListener(event: "test end", listener: (test: Test) => void): this; + removeListener(event: "test end", listener: (test: Test) => void): this; + prependListener(event: "test end", listener: (test: Test) => void): this; + prependOnceListener(event: "test end", listener: (test: Test) => void): this; + emit(name: "test end", test: Test): boolean; + } + // #endregion Runner "test end" event + // #region Runner "hook" event + interface Runner extends NodeJS.EventEmitter { + on(event: "hook", listener: (hook: Hook) => void): this; + once(event: "hook", listener: (hook: Hook) => void): this; + addListener(event: "hook", listener: (hook: Hook) => void): this; + removeListener(event: "hook", listener: (hook: Hook) => void): this; + prependListener(event: "hook", listener: (hook: Hook) => void): this; + prependOnceListener(event: "hook", listener: (hook: Hook) => void): this; + emit(name: "hook", hook: Hook): boolean; + } + // #endregion Runner "hook" event + // #region Runner "hook end" event + interface Runner extends NodeJS.EventEmitter { + on(event: "hook end", listener: (hook: Hook) => void): this; + once(event: "hook end", listener: (hook: Hook) => void): this; + addListener(event: "hook end", listener: (hook: Hook) => void): this; + removeListener(event: "hook end", listener: (hook: Hook) => void): this; + prependListener(event: "hook end", listener: (hook: Hook) => void): this; + prependOnceListener(event: "hook end", listener: (hook: Hook) => void): this; + emit(name: "hook end", hook: Hook): boolean; + } + // #endregion Runner "hook end" event + // #region Runner "pass" event + interface Runner extends NodeJS.EventEmitter { + on(event: "pass", listener: (test: Test) => void): this; + once(event: "pass", listener: (test: Test) => void): this; + addListener(event: "pass", listener: (test: Test) => void): this; + removeListener(event: "pass", listener: (test: Test) => void): this; + prependListener(event: "pass", listener: (test: Test) => void): this; + prependOnceListener(event: "pass", listener: (test: Test) => void): this; + emit(name: "pass", test: Test): boolean; + } + // #endregion Runner "pass" event + // #region Runner "fail" event + interface Runner extends NodeJS.EventEmitter { + on(event: "fail", listener: (test: Test, err: any) => void): this; + once(event: "fail", listener: (test: Test, err: any) => void): this; + addListener(event: "fail", listener: (test: Test, err: any) => void): this; + removeListener(event: "fail", listener: (test: Test, err: any) => void): this; + prependListener(event: "fail", listener: (test: Test, err: any) => void): this; + prependOnceListener(event: "fail", listener: (test: Test, err: any) => void): this; + emit(name: "fail", test: Test, err: any): boolean; + } + // #endregion Runner "fail" event + // #region Runner "pending" event + interface Runner extends NodeJS.EventEmitter { + on(event: "pending", listener: (test: Test) => void): this; + once(event: "pending", listener: (test: Test) => void): this; + addListener(event: "pending", listener: (test: Test) => void): this; + removeListener(event: "pending", listener: (test: Test) => void): this; + prependListener(event: "pending", listener: (test: Test) => void): this; + prependOnceListener(event: "pending", listener: (test: Test) => void): this; + emit(name: "pending", test: Test): boolean; + } + // #endregion Runner "pending" event + // #region Runner untyped events + interface Runner extends NodeJS.EventEmitter { + on(event: string, listener: (...args: any[]) => void): this; + once(event: string, listener: (...args: any[]) => void): this; + addListener(event: string, listener: (...args: any[]) => void): this; + removeListener(event: string, listener: (...args: any[]) => void): this; + prependListener(event: string, listener: (...args: any[]) => void): this; + prependOnceListener(event: string, listener: (...args: any[]) => void): this; + emit(name: string, ...args: any[]): boolean; + } + // #endregion Runner untyped events + + /** + * Initialize a new `Suite` with the given `title` and `ctx`. + * + * @see https://mochajs.org/api/Mocha.Suite.html + */ + class Suite { + private _beforeEach; + private _beforeAll; + private _afterEach; + private _afterAll; + private _timeout; + private _enableTimeouts; + private _slow; + private _bail; + private _retries; + private _onlyTests; + private _onlySuites; + + constructor(title: string, parentContext?: Context); + /** @deprecated Use the overload that accepts `Mocha.Context` instead. */ + constructor(title: string, parentContext?: IContext); + + ctx: Context; + suites: Suite[]; + tests: Test[]; + pending: boolean; + file?: string; + root: boolean; + delayed: boolean; + parent: Suite | undefined; + title: string; + + /** + * Create a new `Suite` with the given `title` and parent `Suite`. When a suite + * with the same title is already present, that suite is returned to provide + * nicer reporter and more flexible meta-testing. + * + * @see https://mochajs.org/api/mocha#.exports.create + */ + static create(parent: Suite, title: string): Suite; + /** @deprecated Use the overload that accepts `Mocha.Suite` instead. */ + static create(parent: ISuite, title: string): Suite; + + /** + * Return a clone of this `Suite`. + * + * @see https://mochajs.org/api/Mocha.Suite.html#clone + */ + clone(): Suite; + + /** + * Get timeout `ms`. + * + * @see https://mochajs.org/api/Mocha.Suite.html#timeout + */ + timeout(): number; + + /** + * Set timeout `ms` or short-hand such as "2s". + * + * @see https://mochajs.org/api/Mocha.Suite.html#timeout + */ + timeout(ms: string | number): this; + + /** + * Get number of times to retry a failed test. + * + * @see https://mochajs.org/api/Mocha.Suite.html#retries + */ + retries(): number; + + /** + * Set number of times to retry a failed test. + * + * @see https://mochajs.org/api/Mocha.Suite.html#retries + */ + retries(n: string | number): this; + + /** + * Get whether timeouts are enabled. + * + * @see https://mochajs.org/api/Mocha.Suite.html#enableTimeouts + */ + enableTimeouts(): boolean; + + /** + * Set whether timeouts are `enabled`. + * + * @see https://mochajs.org/api/Mocha.Suite.html#enableTimeouts + */ + enableTimeouts(enabled: boolean): this; + + /** + * Get slow `ms`. + * + * @see https://mochajs.org/api/Mocha.Suite.html#slow + */ + slow(): number; + + /** + * Set slow `ms` or short-hand such as "2s". + * + * @see https://mochajs.org/api/Mocha.Suite.html#slow + */ + slow(ms: string | number): this; + + /** + * Get whether to bail after first error. + * + * @see https://mochajs.org/api/Mocha.Suite.html#bail + */ + bail(): boolean; + + /** + * Set whether to bail after first error. + * + * @see https://mochajs.org/api/Mocha.Suite.html#bail + */ + bail(bail: boolean): this; + + /** + * Check if this suite or its parent suite is marked as pending. + * + * @see https://mochajs.org/api/Mocha.Suite.html#isPending + */ + isPending(): boolean; + + /** + * Run `fn(test[, done])` before running tests. + * + * @see https://mochajs.org/api/Mocha.Suite.html#beforeAll + */ + beforeAll(fn?: Func): this; + + /** + * Run `fn(test[, done])` before running tests. + * + * @see https://mochajs.org/api/Mocha.Suite.html#beforeAll + */ + beforeAll(fn?: AsyncFunc): this; + + /** + * Run `fn(test[, done])` before running tests. + * + * @see https://mochajs.org/api/Mocha.Suite.html#beforeAll + */ + beforeAll(title: string, fn?: Func): this; + + /** + * Run `fn(test[, done])` before running tests. + * + * @see https://mochajs.org/api/Mocha.Suite.html#beforeAll + */ + beforeAll(title: string, fn?: AsyncFunc): this; + + /** + * Run `fn(test[, done])` after running tests. + * + * @see https://mochajs.org/api/Mocha.Suite.html#afterAll + */ + afterAll(fn?: Func): this; + + /** + * Run `fn(test[, done])` after running tests. + * + * @see https://mochajs.org/api/Mocha.Suite.html#afterAll + */ + afterAll(fn?: AsyncFunc): this; + + /** + * Run `fn(test[, done])` after running tests. + * + * @see https://mochajs.org/api/Mocha.Suite.html#afterAll + */ + afterAll(title: string, fn?: Func): this; + + /** + * Run `fn(test[, done])` after running tests. + * + * @see https://mochajs.org/api/Mocha.Suite.html#afterAll + */ + afterAll(title: string, fn?: AsyncFunc): this; + + /** + * Run `fn(test[, done])` before each test case. + * + * @see https://mochajs.org/api/Mocha.Suite.html#beforeEach + */ + beforeEach(fn?: Func): this; + + /** + * Run `fn(test[, done])` before each test case. + * + * @see https://mochajs.org/api/Mocha.Suite.html#beforeEach + */ + beforeEach(fn?: AsyncFunc): this; + + /** + * Run `fn(test[, done])` before each test case. + * + * @see https://mochajs.org/api/Mocha.Suite.html#beforeEach + */ + beforeEach(title: string, fn?: Func): this; + + /** + * Run `fn(test[, done])` before each test case. + * + * @see https://mochajs.org/api/Mocha.Suite.html#beforeEach + */ + beforeEach(title: string, fn?: AsyncFunc): this; + + /** + * Run `fn(test[, done])` after each test case. + * + * @see https://mochajs.org/api/Mocha.Suite.html#afterEach + */ + afterEach(fn?: Func): this; + + /** + * Run `fn(test[, done])` after each test case. + * + * @see https://mochajs.org/api/Mocha.Suite.html#afterEach + */ + afterEach(fn?: AsyncFunc): this; + + /** + * Run `fn(test[, done])` after each test case. + * + * @see https://mochajs.org/api/Mocha.Suite.html#afterEach + */ + afterEach(title: string, fn?: Func): this; + + /** + * Run `fn(test[, done])` after each test case. + * + * @see https://mochajs.org/api/Mocha.Suite.html#afterEach + */ + afterEach(title: string, fn?: AsyncFunc): this; + + /** + * Add a test `suite`. + * + * @see https://mochajs.org/api/Mocha.Suite.html#addSuite + */ + addSuite(suite: Suite): this; + /** @deprecated Use the overload that accepts `Mocha.ISuite` instead. */ + addSuite(suite: ISuite): this; + + /** + * Add a `test` to this suite. + * + * @see https://mochajs.org/api/Mocha.Suite.html#addTest + */ + addTest(test: Test): this; + /** @deprecated Use the overload that accepts `Mocha.ITest` instead. */ + addTest(test: ITest): this; + + /** + * Return the full title generated by recursively concatenating the parent's + * full title. + * + * @see https://mochajs.org/api/Mocha.Suite.html#.Suite#fullTitle + */ + fullTitle(): string; + + /** + * Return the title path generated by recursively concatenating the parent's + * title path. + * + * @see https://mochajs.org/api/Mocha.Suite.html#.Suite#titlePath + */ + titlePath(): string[]; + + /** + * Return the total number of tests. + * + * @see https://mochajs.org/api/Mocha.Suite.html#.Suite#total + */ + total(): number; + + /** + * Iterates through each suite recursively to find all tests. Applies a + * function in the format `fn(test)`. + * + * @see https://mochajs.org/api/Mocha.Suite.html#eachTest + */ + eachTest(fn: (test: Test) => void): this; + + /** + * This will run the root suite if we happen to be running in delayed mode. + * + * @see https://mochajs.org/api/Mocha.Suite.html#run + */ + run(): void; + + /** + * Generic hook-creator. + */ + protected _createHook(title: string, fn?: Func | AsyncFunc): Hook; + } + + // #region Suite "beforeAll" event + interface Suite extends NodeJS.EventEmitter { + on(event: "beforeAll", listener: (hook: Hook) => void): this; + once(event: "beforeAll", listener: (hook: Hook) => void): this; + addListener(event: "beforeAll", listener: (hook: Hook) => void): this; + removeListener(event: "beforeAll", listener: (hook: Hook) => void): this; + prependListener(event: "beforeAll", listener: (hook: Hook) => void): this; + prependOnceListener(event: "beforeAll", listener: (hook: Hook) => void): this; + emit(name: "beforeAll", hook: Hook): boolean; + } + // #endregion Suite "beforeAll" event + // #region Suite "afterAll" event + interface Suite extends NodeJS.EventEmitter { + on(event: "afterAll", listener: (hook: Hook) => void): this; + once(event: "afterAll", listener: (hook: Hook) => void): this; + addListener(event: "afterAll", listener: (hook: Hook) => void): this; + removeListener(event: "afterAll", listener: (hook: Hook) => void): this; + prependListener(event: "afterAll", listener: (hook: Hook) => void): this; + prependOnceListener(event: "afterAll", listener: (hook: Hook) => void): this; + emit(name: "afterAll", hook: Hook): boolean; + } + // #endregion Suite "afterAll" event + // #region Suite "beforeEach" event + interface Suite extends NodeJS.EventEmitter { + on(event: "beforeEach", listener: (hook: Hook) => void): this; + once(event: "beforeEach", listener: (hook: Hook) => void): this; + addListener(event: "beforeEach", listener: (hook: Hook) => void): this; + removeListener(event: "beforeEach", listener: (hook: Hook) => void): this; + prependListener(event: "beforeEach", listener: (hook: Hook) => void): this; + prependOnceListener(event: "beforeEach", listener: (hook: Hook) => void): this; + emit(name: "beforeEach", hook: Hook): boolean; + } + // #endregion Suite "beforeEach" event + // #region Suite "afterEach" event + interface Suite extends NodeJS.EventEmitter { + on(event: "afterEach", listener: (hook: Hook) => void): this; + once(event: "afterEach", listener: (hook: Hook) => void): this; + addListener(event: "afterEach", listener: (hook: Hook) => void): this; + removeListener(event: "afterEach", listener: (hook: Hook) => void): this; + prependListener(event: "afterEach", listener: (hook: Hook) => void): this; + prependOnceListener(event: "afterEach", listener: (hook: Hook) => void): this; + emit(name: "afterEach", hook: Hook): boolean; + } + // #endregion Suite "afterEach" event + // #region Suite "suite" event + interface Suite extends NodeJS.EventEmitter { + on(event: "suite", listener: (suite: Suite) => void): this; + once(event: "suite", listener: (suite: Suite) => void): this; + addListener(event: "suite", listener: (suite: Suite) => void): this; + removeListener(event: "suite", listener: (suite: Suite) => void): this; + prependListener(event: "suite", listener: (suite: Suite) => void): this; + prependOnceListener(event: "suite", listener: (suite: Suite) => void): this; + emit(name: "suite", suite: Suite): boolean; + } + // #endregion Suite "suite" event + // #region Suite "test" event + interface Suite { + on(event: "test", listener: (test: Test) => void): this; + once(event: "test", listener: (test: Test) => void): this; + addListener(event: "test", listener: (test: Test) => void): this; + removeListener(event: "test", listener: (test: Test) => void): this; + prependListener(event: "test", listener: (test: Test) => void): this; + prependOnceListener(event: "test", listener: (test: Test) => void): this; + emit(name: "test", test: Test): boolean; + } + // #endregion Suite "test" event + // #region Suite "run" event + interface Suite extends NodeJS.EventEmitter { + on(event: "run", listener: () => void): this; + once(event: "run", listener: () => void): this; + addListener(event: "run", listener: () => void): this; + removeListener(event: "run", listener: () => void): this; + prependListener(event: "run", listener: () => void): this; + prependOnceListener(event: "run", listener: () => void): this; + emit(name: "run"): boolean; + } + // #endregion Suite "run" event + // #region Suite "pre-require" event + interface Suite extends NodeJS.EventEmitter { + on(event: "pre-require", listener: (context: MochaGlobals, file: string, mocha: Mocha) => void): this; + once(event: "pre-require", listener: (context: MochaGlobals, file: string, mocha: Mocha) => void): this; + addListener(event: "pre-require", listener: (context: MochaGlobals, file: string, mocha: Mocha) => void): this; + removeListener(event: "pre-require", listener: (context: MochaGlobals, file: string, mocha: Mocha) => void): this; + prependListener(event: "pre-require", listener: (context: MochaGlobals, file: string, mocha: Mocha) => void): this; + prependOnceListener(event: "pre-require", listener: (context: MochaGlobals, file: string, mocha: Mocha) => void): this; + emit(name: "pre-require", context: MochaGlobals, file: string, mocha: Mocha): boolean; + } + // #endregion Suite "pre-require" event + // #region Suite "require" event + interface Suite extends NodeJS.EventEmitter { + on(event: "require", listener: (module: any, file: string, mocha: Mocha) => void): this; + once(event: "require", listener: (module: any, file: string, mocha: Mocha) => void): this; + addListener(event: "require", listener: (module: any, file: string, mocha: Mocha) => void): this; + removeListener(event: "require", listener: (module: any, file: string, mocha: Mocha) => void): this; + prependListener(event: "require", listener: (module: any, file: string, mocha: Mocha) => void): this; + prependOnceListener(event: "require", listener: (module: any, file: string, mocha: Mocha) => void): this; + emit(name: "require", module: any, file: string, mocha: Mocha): boolean; + } + // #endregion Suite "require" event + // #region Suite "post-require" event + interface Suite extends NodeJS.EventEmitter { + on(event: "post-require", listener: (context: MochaGlobals, file: string, mocha: Mocha) => void): this; + once(event: "post-require", listener: (context: MochaGlobals, file: string, mocha: Mocha) => void): this; + addListener(event: "post-require", listener: (context: MochaGlobals, file: string, mocha: Mocha) => void): this; + removeListener(event: "post-require", listener: (context: MochaGlobals, file: string, mocha: Mocha) => void): this; + prependListener(event: "post-require", listener: (context: MochaGlobals, file: string, mocha: Mocha) => void): this; + prependOnceListener(event: "post-require", listener: (context: MochaGlobals, file: string, mocha: Mocha) => void): this; + emit(name: "post-require", context: MochaGlobals, file: string, mocha: Mocha): boolean; + } + // #endregion Suite "post-require" event + // #region Suite untyped events + interface Suite extends NodeJS.EventEmitter { + on(event: string, listener: (...args: any[]) => void): this; + once(event: string, listener: (...args: any[]) => void): this; + addListener(event: string, listener: (...args: any[]) => void): this; + removeListener(event: string, listener: (...args: any[]) => void): this; + prependListener(event: string, listener: (...args: any[]) => void): this; + prependOnceListener(event: string, listener: (...args: any[]) => void): this; + emit(name: string, ...args: any[]): boolean; + } + // #endregion Runner untyped events + + /** + * Initialize a new `Hook` with the given `title` and callback `fn` + * + * @see https://mochajs.org/api/Hook.html + */ + class Hook extends Runnable { + private _error; + + type: "hook"; + originalTitle?: string; // added by Runner + + /** + * Get the test `err`. + * + * @see https://mochajs.org/api/Hook.html#error + */ + error(): any; + + /** + * Set the test `err`. + * + * @see https://mochajs.org/api/Hook.html#error + */ + error(err: any): void; + } + + /** + * Initialize a new `Test` with the given `title` and callback `fn`. + * + * @see https://mochajs.org/api/Test.html + */ + class Test extends Runnable { + type: "test"; + speed?: "slow" | "medium" | "fast"; // added by reporters + err?: Error; // added by reporters + clone(): Test; + } + + /** + * Test statistics + */ + interface Stats { suites: number; tests: number; passes: number; @@ -271,252 +2156,701 @@ declare class GenericEventEmitter { failures: number; start?: Date; end?: Date; - duration?: Date; + duration?: number; } - /** Partial interface for Mocha's `Runner` class. */ - interface IRunner extends GenericEventEmitter { - asyncOnly?: boolean; - stats?: IStats; - started: boolean; - suite: ISuite; - total: number; - failures: number; - forbidOnly?: boolean; - forbidPending?: boolean; - fullStackTrace?: boolean; - hasOnly?: boolean; + type TestInterface = (suite: Suite) => void; + + interface ReporterConstructor { + new (runner: Runner, options: { reporterOptions?: any; }): reporters.Base; + } + + type Done = (err?: any) => void; + + /** + * Callback function used for tests and hooks. + */ + type Func = (this: Context, done: Done) => void; + + /** + * Async callback function used for tests and hooks. + */ + type AsyncFunc = (this: Context) => PromiseLike; + + /** + * Options to pass to Mocha. + */ + interface MochaOptions { + /** Test interfaces ("bdd", "tdd", "exports", etc.). */ + ui?: Interface; + + /** + * Reporter constructor, built-in reporter name, or reporter module path. Defaults to + * `"spec"`. + */ + reporter?: string | ReporterConstructor; + + /** Options to pass to the reporter. */ + reporterOptions?: any; + + /** Array of accepted globals. */ + globals?: string[]; + + /** timeout in milliseconds. */ + timeout?: number; + + enableTimeouts?: boolean; + + /** number of times to retry failed tests. */ + retries?: number; + + /** bail on the first test failure. */ + bail?: boolean; + + /** milliseconds to wait before considering a test slow. */ + slow?: number; + + /** ignore global leaks. */ ignoreLeaks?: boolean; - grep: (re: string, invert: boolean) => this; - grepTotal: (suite: ISuite) => number; - globals: (arr: ReadonlyArray) => this | string[]; - abort: () => this; - run: (fn?: (failures: number) => void) => this; + /** display the full stack trace on failure. */ + fullStackTrace?: boolean; + + /** string or regexp to filter tests with. */ + grep?: string | RegExp; + + /** Enable growl support. */ + growl?: boolean; + + /** Emit color output. */ + useColors?: boolean; + + /** Use inline diffs rather than +/-. */ + inlineDiffs?: boolean; + + /** Do not show diffs at all. */ + hideDiff?: boolean; + + asyncOnly?: boolean; + delay?: boolean; + forbidOnly?: boolean; + forbidPending?: boolean; + noHighlighting?: boolean; + allowUncaught?: boolean; } - interface IContextDefinition { - (description: string, callback: (this: ISuiteCallbackContext) => void): ISuite; - only(description: string, callback: (this: ISuiteCallbackContext) => void): ISuite; - skip(description: string, callback: (this: ISuiteCallbackContext) => void): void; - timeout(ms: number | string): void; + interface MochaInstanceOptions extends MochaOptions { + files?: string[]; } - interface ITestDefinition { - (expectation: string, callback?: (this: ITestCallbackContext, done: MochaDone) => PromiseLike | void): ITest; - only(expectation: string, callback?: (this: ITestCallbackContext, done: MochaDone) => PromiseLike | void): ITest; - skip(expectation: string, callback?: (this: ITestCallbackContext, done: MochaDone) => PromiseLike | void): void; - timeout(ms: number | string): void; - state: "failed" | "passed"; - } - - namespace reporters { - class Base { - runner: IRunner; - stats: IStats; - - constructor(runner: IRunner); - } - - class Doc extends Base { } - class Dot extends Base { } - class HTML extends Base { } - class HTMLCov extends Base { } - class JSON extends Base { } - class JSONCov extends Base { } - class JSONStream extends Base { } - class Landing extends Base { } - class List extends Base { } - class Markdown extends Base { } - class Min extends Base { } - class Nyan extends Base { } - class Progress extends Base { - /** - * @param options.open String used to indicate the start of the progress bar. - * @param options.complete String used to indicate a complete test on the progress bar. - * @param options.incomplete String used to indicate an incomplete test on the progress bar. - * @param options.close String used to indicate the end of the progress bar. - */ - constructor(runner: IRunner, options?: { - open?: string; - complete?: string; - incomplete?: string; - close?: string; - }); - } - class Spec extends Base { } - class TAP extends Base { } - class XUnit extends Base { - constructor(runner: IRunner, options?: any); - } - } - - /* - * All ambient functions are also available via require('mocha') when invoked via the mocha CLI - * See for details: https://mochajs.org/#require - */ - - /** Only available when invoked via the mocha CLI */ - const describe: IContextDefinition; - /** Only available when invoked via the mocha CLI */ - const xdescribe: IContextDefinition; /** - * alias for `describe` - * Only available when invoked via the mocha CLI + * Variables added to the global scope by Mocha when run in the CLI. */ - const context: IContextDefinition; - /** - * alias for `describe` - * Only available when invoked via the mocha CLI - */ - const suite: IContextDefinition; - /** Only available when invoked via the mocha CLI */ - const it: ITestDefinition; - /** Only available when invoked via the mocha CLI */ - const xit: ITestDefinition; - /** - * alias for `it` - * Only available when invoked via the mocha CLI - */ - const test: ITestDefinition; - /** - * Alias for `it` - * Only available when invoked via the mocha CLI - */ - const specify: ITestDefinition; - /** Only available when invoked via the mocha CLI */ - function setup(callback: (this: IBeforeAndAfterContext, done: MochaDone) => PromiseLike | void): void; - /** Only available when invoked via the mocha CLI */ - function teardown(callback: (this: IBeforeAndAfterContext, done: MochaDone) => PromiseLike | void): void; - /** Only available when invoked via the mocha CLI */ - function suiteSetup(callback: (this: IHookCallbackContext, done: MochaDone) => PromiseLike | void): void; - /** Only available when invoked via the mocha CLI */ - function suiteTeardown(callback: (this: IHookCallbackContext, done: MochaDone) => PromiseLike | void): void; - /** Only available when invoked via the mocha CLI */ - function before(callback: (this: IHookCallbackContext, done: MochaDone) => PromiseLike | void): void; - /** Only available when invoked via the mocha CLI */ - function before(description: string, callback: (this: IHookCallbackContext, done: MochaDone) => PromiseLike | void): void; - /** Only available when invoked via the mocha CLI */ - function after(callback: (this: IHookCallbackContext, done: MochaDone) => PromiseLike | void): void; - /** Only available when invoked via the mocha CLI */ - function after(description: string, callback: (this: IHookCallbackContext, done: MochaDone) => PromiseLike | void): void; - /** Only available when invoked via the mocha CLI */ - function beforeEach(callback: (this: IBeforeAndAfterContext, done: MochaDone) => PromiseLike | void): void; - /** Only available when invoked via the mocha CLI */ - function beforeEach(description: string, callback: (this: IBeforeAndAfterContext, done: MochaDone) => PromiseLike | void): void; - /** Only available when invoked via the mocha CLI */ - function afterEach(callback: (this: IBeforeAndAfterContext, done: MochaDone) => PromiseLike | void): void; - /** Only available when invoked via the mocha CLI */ - function afterEach(description: string, callback: (this: IBeforeAndAfterContext, done: MochaDone) => PromiseLike | void): void; + interface MochaGlobals { + /** + * Execute before running tests. + * + * - _Only available when invoked via the mocha CLI._ + * + * @see https://mochajs.org/api/global.html#before + */ + before: HookFunction; - class Runnable extends GenericEventEmitter { - new(title: string, fn: () => any): IRunnable; + /** + * Execute after running tests. + * + * - _Only available when invoked via the mocha CLI._ + * + * @see https://mochajs.org/api/global.html#after + */ + after: HookFunction; + + /** + * Execute before each test case. + * + * - _Only available when invoked via the mocha CLI._ + * + * @see https://mochajs.org/api/global.html#beforeEach + */ + beforeEach: HookFunction; + + /** + * Execute after each test case. + * + * - _Only available when invoked via the mocha CLI._ + * + * @see https://mochajs.org/api/global.html#afterEach + */ + afterEach: HookFunction; + + /** + * Describe a "suite" containing nested suites and tests. + * + * - _Only available when invoked via the mocha CLI._ + */ + describe: SuiteFunction; + + /** + * Describe a "suite" containing nested suites and tests. + * + * - _Only available when invoked via the mocha CLI._ + */ + context: SuiteFunction; + + /** + * Pending suite. + * + * - _Only available when invoked via the mocha CLI._ + */ + xdescribe: PendingSuiteFunction; + + /** + * Pending suite. + * + * - _Only available when invoked via the mocha CLI._ + */ + xcontext: PendingSuiteFunction; + + /** + * Describes a test case. + * + * - _Only available when invoked via the mocha CLI._ + */ + it: TestFunction; + + /** + * Describes a test case. + * + * - _Only available when invoked via the mocha CLI._ + */ + specify: TestFunction; + + /** + * Describes a pending test case. + * + * - _Only available when invoked via the mocha CLI._ + */ + xit: PendingTestFunction; + + /** + * Describes a pending test case. + * + * - _Only available when invoked via the mocha CLI._ + */ + xspecify: PendingTestFunction; + + /** + * Execute before running tests. + * + * - _Only available when invoked via the mocha CLI._ + * + * @see https://mochajs.org/api/global.html#before + */ + suiteSetup: HookFunction; + + /** + * Execute after running tests. + * + * - _Only available when invoked via the mocha CLI._ + * + * @see https://mochajs.org/api/global.html#after + */ + suiteTeardown: HookFunction; + + /** + * Execute before each test case. + * + * - _Only available when invoked via the mocha CLI._ + * + * @see https://mochajs.org/api/global.html#beforeEach + */ + setup: HookFunction; + + /** + * Execute after each test case. + * + * - _Only available when invoked via the mocha CLI._ + * + * @see https://mochajs.org/api/global.html#afterEach + */ + teardown: HookFunction; + + /** + * Describe a "suite" containing nested suites and tests. + * + * - _Only available when invoked via the mocha CLI._ + */ + suite: SuiteFunction; + + /** + * Describes a test case. + * + * - _Only available when invoked via the mocha CLI._ + */ + test: TestFunction; + + run: typeof run; } - class Context implements IContext { - constructor(); + /** + * Third-party declarations that want to add new entries to the `Reporter` union can + * contribute names here. + */ + interface ReporterContributions { + Base: never; + base: never; + Dot: never; + dot: never; + TAP: never; + tap: never; + JSON: never; + json: never; + HTML: never; + html: never; + List: never; + list: never; + Min: never; + min: never; + Spec: never; + spec: never; + Nyan: never; + nyan: never; + XUnit: never; + xunit: never; + Markdown: never; + markdown: never; + Progress: never; + progress: never; + Landing: never; + landing: never; + JSONStream: never; + "json-stream": never; + } - _runnable?: IRunnable; + type Reporter = keyof ReporterContributions; + + /** + * Third-party declarations that want to add new entries to the `Interface` union can + * contribute names here. + */ + interface InterfaceContributions { + bdd: never; + tdd: never; + qunit: never; + exports: never; + } + + type Interface = keyof InterfaceContributions; + + // #region Deprecations + + /** @deprecated use `Mocha.Context` instead. */ + interface IContext { test?: IRunnable; - runnable(): IRunnable | undefined; + /** @deprecated `.runnable()` returns `this` in `Mocha.Context`. */ runnable(runnable: IRunnable): IContext; timeout(): number; + /** @deprecated `.timeout()` returns `this` in `Mocha.Context`. */ timeout(timeout: number): IContext; + /** @deprecated `.enableTimeouts()` has additional overloads in `Mocha.Context`. */ + /** @deprecated `.enableTimeouts()` returns `this` in `Mocha.Context`. */ enableTimeouts(enableTimeouts: boolean): IContext; + /** @deprecated `.slow()` has additional overloads in `Mocha.Context`. */ + /** @deprecated `.slow()` returns `this` in `Mocha.Context`. */ slow(slow: number): IContext; + /** @deprecated `.skip()` returns `never` in `Mocha.Context`. */ skip(): IContext; retries(): number; + /** @deprecated `.retries()` returns `this` in `Mocha.Context`. */ retries(retries: number): IContext; - inspect(): string; } - class Runner extends GenericEventEmitter implements IRunner { - constructor(suite: ISuite, delay: boolean); - - asyncOnly?: boolean; - stats?: IStats; - started: boolean; - suite: ISuite; - total: number; - failures: number; - forbidOnly?: boolean; - forbidPending?: boolean; - fullStackTrace?: boolean; - hasOnly?: boolean; - ignoreLeaks?: boolean; - - grep: (re: string, invert: boolean) => this; - grepTotal: (suite: ISuite) => number; - globals: (arr: ReadonlyArray) => this | string[]; - abort: () => this; - run: (fn?: (failures: number) => void) => this; + /** @deprecated use `Mocha.Suite` instead. */ + interface ISuiteCallbackContext { + /** @deprecated `.timeout()` has additional overloads in `Mocha.Suite`. */ + timeout(ms: number | string): this; + /** @deprecated `.retries()` has additional overloads in `Mocha.Suite`. */ + retries(n: number): this; + /** @deprecated `.slow()` has additional overloads in `Mocha.Suite`. */ + slow(ms: number): this; } - class Suite extends GenericEventEmitter implements ISuite { - constructor(title: string, parentContext: IContext); + /** @deprecated use `Mocha.Context` instead. */ + interface IHookCallbackContext { + /** @deprecated `.skip()` returns `never` in `Mocha.Context`. */ + skip(): this; + /** @deprecated `.timeout()` has additional overloads in `Mocha.Context`. */ + timeout(ms: number | string): this; + [index: string]: any; + } + /** @deprecated use `Mocha.Context` instead. */ + interface ITestCallbackContext { + /** @deprecated `.skip()` returns `never` in `Mocha.Context`. */ + skip(): this; + /** @deprecated `.timeout()` has additional overloads in `Mocha.Context`. */ + timeout(ms: number | string): this; + /** @deprecated `.retries()` has additional overloads in `Mocha.Context`. */ + retries(n: number): this; + /** @deprecated `.slow()` has additional overloads in `Mocha.Context`. */ + slow(ms: number): this; + [index: string]: any; + } + + /** Partial interface for Mocha's `Runnable` class. */ + /** @deprecated use `Mocha.Runnable` instead. */ + interface IRunnable extends NodeJS.EventEmitter { + title: string; + /** @deprecated `.fn` has type `Func | AsyncFunc` in `Mocha.Runnable`. */ + fn: Function | undefined; + async: boolean; + sync: boolean; + timedOut: boolean; + /** @deprecated `.timeout()` has additional overloads in `Mocha.Runnable`. */ + timeout(n: number | string): this; + duration?: number; + } + + /** Partial interface for Mocha's `Suite` class. */ + /** @deprecated use `Mocha.Suite` instead. */ + interface ISuite { + /** @deprecated `.ctx` has type `Mocha.Context` in `Mocha.Suite`. */ ctx: IContext; - parent: ISuite; + /** @deprecated `.parent` has type `Mocha.Suite | undefined` in `Mocha.Suite`. */ + parent: ISuite | undefined; root: boolean; title: string; + /** @deprecated `.suites` has type `Mocha.Suite[]` in `Mocha.Suite`. */ suites: ISuite[]; + /** @deprecated `.tests` has type `Mocha.Test[]` in `Mocha.Suite`. */ tests: ITest[]; - _beforeEach: IHook[]; - _beforeAll: IHook[]; - _afterEach: IHook[]; - _afterAll: IHook[]; - bail(): boolean; + /** @deprecated `.bail()` returns `this` in `Mocha.Suite`. */ bail(bail: boolean): ISuite; fullTitle(): string; retries(): number; + /** @deprecated `.retries()` returns `this` in `Mocha.Suite`. */ retries(retries: number): ISuite; slow(): number; + /** @deprecated `.slow()` returns `this` in `Mocha.Suite`. */ slow(slow: number): ISuite; timeout(): number; + /** @deprecated `.timeout()` returns `this` in `Mocha.Suite`. */ timeout(timeout: number): ISuite; } - class Hook extends Runnable implements IHook { - constructor(title: string, fn: () => any); - - async: boolean; - ctx?: IContext; - duration?: number; - fn: Function; + /** Partial interface for Mocha's `Test` class. */ + /** @deprecated use `Mocha.Test` instead. */ + interface ITest extends IRunnable { + body?: string; + file?: string; + /** @deprecated `.parent` has type `Mocha.Suite | undefined` in `Mocha.Test`. */ parent?: ISuite; - sync: boolean; - timedOut: boolean; - timeout(n: number | string): this; - title: string; - type: 'hook'; + pending: boolean; + state?: 'failed' | 'passed'; + type: 'test'; + fullTitle(): string; + } + /** @deprecated use `Mocha.Hook` instead. */ + interface IHook extends IRunnable { + /** @deprecated `.ctx` has type `Mocha.Context` in `Mocha.Runnable`. */ + ctx?: IContext; + /** @deprecated `.parent` has type `Mocha.Suite` in `Mocha.Runnable`. */ + parent?: ISuite; + type: 'hook'; + /** @deprecated `.error()` has additional overloads in `Mocha.Hook`. */ error(err: Error): void; } - class Test extends Runnable implements ITest { - constructor(title: string, fn: () => any); - - async: boolean; - body?: string; - duration?: number; - file?: string; - fn: Function; - parent: ISuite; - pending: boolean; - state: 'failed' | 'passed' | undefined; - sync: boolean; - timedOut: boolean; - timeout(n: number | string): this; - title: string; - type: 'test'; - - fullTitle(): string; + /** @deprecated use `Mocha.Context` instead. */ + interface IBeforeAndAfterContext extends IHookCallbackContext { + /** @deprecated `.currentTest` has type `Mocha.Test` in `Mocha.Context`. */ + currentTest?: ITest; } - } - declare module "mocha" { - export = Mocha; - } + /** @deprecated use `Mocha.Stats` instead. */ + type IStats = Stats; + + /** Partial interface for Mocha's `Runner` class. */ + /** @deprecated use `Mocha.Runner` instead. */ + interface IRunner extends NodeJS.EventEmitter { + asyncOnly?: boolean; + stats?: IStats; + started: boolean; + /** @deprecated `.suite` has type `Mocha.Suite` in `Mocha.Runner`. */ + suite: ISuite; + total: number; + failures: number; + forbidOnly?: boolean; + forbidPending?: boolean; + fullStackTrace?: boolean; + ignoreLeaks?: boolean; + grep(re: RegExp, invert: boolean): this; + /** @deprecated Parameter `suite` has type `Mocha.Suite` in `Mocha.Runner`. */ + grepTotal(suite: ISuite): number; + /** @deprecated `.globals()` has different overloads in `Mocha.Runner`. */ + globals(arr: ReadonlyArray): this | string[]; + abort(): this; + run(fn?: (failures: number) => void): this; + } + + /** @deprecated use `Mocha.SuiteFunction` instead. */ + interface IContextDefinition { + /** @deprecated use `Mocha.SuiteFunction` instead. */ + (description: string, callback: (this: ISuiteCallbackContext) => void): ISuite; + /** @deprecated use `Mocha.SuiteFunction` instead. */ + only(description: string, callback: (this: ISuiteCallbackContext) => void): ISuite; + /** @deprecated use `Mocha.SuiteFunction` instead. */ + skip(description: string, callback: (this: ISuiteCallbackContext) => void): void; + } + + /** @deprecated use `Mocha.TestFunction` instead. */ + interface ITestDefinition { + /** @deprecated use `Mocha.TestFunction` instead. */ + /** @deprecated `Mocha.TestFunction` does not allow mixing `done` with a return type of `PromiseLike`. */ + (expectation: string, callback?: (this: ITestCallbackContext, done: MochaDone) => PromiseLike | void): ITest; + /** @deprecated use `Mocha.TestFunction` instead. */ + /** @deprecated `Mocha.TestFunction#only` does not allow mixing `done` with a return type of `PromiseLike`. */ + only(expectation: string, callback?: (this: ITestCallbackContext, done: MochaDone) => PromiseLike | void): ITest; + /** @deprecated use `Mocha.TestFunction` instead. */ + /** @deprecated `Mocha.TestFunction#skip` does not allow mixing `done` with a return type of `PromiseLike`. */ + skip(expectation: string, callback?: (this: ITestCallbackContext, done: MochaDone) => PromiseLike | void): void; + } + + // #endregion +} + +declare global { + // #region Test interface augmentations + + /** + * Triggers root suite execution. + * + * - _Only available if flag --delay is passed into Mocha._ + * - _Only available when invoked via the mocha CLI._ + * + * @see https://mochajs.org/api/global.html#runWithSuite + */ + function run(): void; + + /** + * Execute before running tests. + * + * - _Only available when invoked via the mocha CLI._ + * + * @see https://mochajs.org/api/global.html#before + */ + var before: Mocha.HookFunction; + + /** + * Execute before running tests. + * + * - _Only available when invoked via the mocha CLI._ + * + * @see https://mochajs.org/api/global.html#before + */ + var suiteSetup: Mocha.HookFunction; + + /** + * Execute after running tests. + * + * - _Only available when invoked via the mocha CLI._ + * + * @see https://mochajs.org/api/global.html#after + */ + var after: Mocha.HookFunction; + + /** + * Execute after running tests. + * + * - _Only available when invoked via the mocha CLI._ + * + * @see https://mochajs.org/api/global.html#after + */ + var suiteTeardown: Mocha.HookFunction; + + /** + * Execute before each test case. + * + * - _Only available when invoked via the mocha CLI._ + * + * @see https://mochajs.org/api/global.html#beforeEach + */ + var beforeEach: Mocha.HookFunction; + + /** + * Execute before each test case. + * + * - _Only available when invoked via the mocha CLI._ + * + * @see https://mochajs.org/api/global.html#beforeEach + */ + var setup: Mocha.HookFunction; + + /** + * Execute after each test case. + * + * - _Only available when invoked via the mocha CLI._ + * + * @see https://mochajs.org/api/global.html#afterEach + */ + var afterEach: Mocha.HookFunction; + + /** + * Execute after each test case. + * + * - _Only available when invoked via the mocha CLI._ + * + * @see https://mochajs.org/api/global.html#afterEach + */ + var teardown: Mocha.HookFunction; + + /** + * Describe a "suite" containing nested suites and tests. + * + * - _Only available when invoked via the mocha CLI._ + */ + var describe: Mocha.SuiteFunction; + + /** + * Describe a "suite" containing nested suites and tests. + * + * - _Only available when invoked via the mocha CLI._ + */ + var context: Mocha.SuiteFunction; + + /** + * Describe a "suite" containing nested suites and tests. + * + * - _Only available when invoked via the mocha CLI._ + */ + var suite: Mocha.SuiteFunction; + + /** + * Pending suite. + * + * - _Only available when invoked via the mocha CLI._ + */ + var xdescribe: Mocha.PendingSuiteFunction; + + /** + * Pending suite. + * + * - _Only available when invoked via the mocha CLI._ + */ + var xcontext: Mocha.PendingSuiteFunction; + + /** + * Describes a test case. + * + * - _Only available when invoked via the mocha CLI._ + */ + var it: Mocha.TestFunction; + + /** + * Describes a test case. + * + * - _Only available when invoked via the mocha CLI._ + */ + var specify: Mocha.TestFunction; + + /** + * Describes a test case. + * + * - _Only available when invoked via the mocha CLI._ + */ + var test: Mocha.TestFunction; + + /** + * Describes a pending test case. + * + * - _Only available when invoked via the mocha CLI._ + */ + var xit: Mocha.PendingTestFunction; + + /** + * Describes a pending test case. + * + * - _Only available when invoked via the mocha CLI._ + */ + var xspecify: Mocha.PendingTestFunction; + + // #endregion Test interface augmentations + + // #region Reporter augmentations + + // Forward declaration for `HTMLLIElement` from lib.dom.d.ts. + // Required by Mocha.reporters.HTML. + // NOTE: Mocha *must not* have a direct dependency on DOM types. + // tslint:disable-next-line no-empty-interface + interface HTMLLIElement { } + + // Augments the DOM `Window` object when lib.dom.d.ts is loaded. + // tslint:disable-next-line no-empty-interface + interface Window extends Mocha.MochaGlobals { } + + namespace NodeJS { + // Forward declaration for `NodeJS.EventEmitter` from node.d.ts. + // Required by Mocha.Runnable, Mocha.Runner, and Mocha.Suite. + // NOTE: Mocha *must not* have a direct dependency on @types/node. + // tslint:disable-next-line no-empty-interface + interface EventEmitter { } + + // Augments NodeJS's `global` object when node.d.ts is loaded + // tslint:disable-next-line no-empty-interface + interface Global extends Mocha.MochaGlobals { } + } + + // #endregion Reporter augmentations + + // #region Browser augmentations + + /** + * Mocha global. + * + * - _Only supported in the browser._ + */ + const mocha: BrowserMocha; + + interface BrowserMocha extends Mocha { + /** + * Function to allow assertion libraries to throw errors directly into mocha. + * This is useful when running tests in a browser because window.onerror will + * only receive the 'message' attribute of the Error. + * + * - _Only supported in the browser._ + */ + throwError(err: any): never; + + /** + * Setup mocha with the given settings options. + * + * - _Only supported in the browser._ + */ + setup(opts?: Mocha.Interface | MochaSetupOptions): this; + } + + /** + * Options to pass to `mocha.setup` in the browser. + */ + interface MochaSetupOptions extends Mocha.MochaOptions { + // TODO: This does not seem to be supported according to the source. Should it be removed? + require?: string[]; + fullTrace?: boolean; + } + + // #endregion Browser augmentations + + // #region Deprecations + + /** @deprecated use `Mocha.DoneCallback` instead. */ + type MochaDone = Mocha.Done; + + /** @deprecated use `Mocha.ReporterConstructor` instead. */ + type ReporterConstructor = Mocha.ReporterConstructor; + + // #endregion Deprecations +} diff --git a/types/mocha/lib/interfaces/common.d.ts b/types/mocha/lib/interfaces/common.d.ts new file mode 100644 index 0000000000..9756482354 --- /dev/null +++ b/types/mocha/lib/interfaces/common.d.ts @@ -0,0 +1,109 @@ +import Mocha = require("../../"); + +export = common; + +declare function common(suites: Mocha.Suite[], context: Mocha.MochaGlobals, mocha: Mocha): common.CommonFunctions; + +declare namespace common { + interface CommonFunctions { + /** + * This is only present if flag --delay is passed into Mocha. It triggers + * root suite execution. + */ + runWithSuite(suite: Mocha.Suite): () => void; + + /** + * Execute before running tests. + */ + before(fn?: Mocha.Func | Mocha.AsyncFunc): void; + + /** + * Execute before running tests. + */ + before(name: string, fn?: Mocha.Func | Mocha.AsyncFunc): void; + + /** + * Execute after running tests. + */ + after(fn?: Mocha.Func | Mocha.AsyncFunc): void; + + /** + * Execute after running tests. + */ + after(name: string, fn?: Mocha.Func | Mocha.AsyncFunc): void; + + /** + * Execute before each test case. + */ + beforeEach(fn?: Mocha.Func | Mocha.AsyncFunc): void; + + /** + * Execute before each test case. + */ + beforeEach(name: string, fn?: Mocha.Func | Mocha.AsyncFunc): void; + + /** + * Execute after each test case. + */ + afterEach(fn?: Mocha.Func | Mocha.AsyncFunc): void; + + /** + * Execute after each test case. + */ + afterEach(name: string, fn?: Mocha.Func | Mocha.AsyncFunc): void; + + suite: SuiteFunctions; + test: TestFunctions; + } + + interface CreateOptions { + /** Title of suite */ + title: string; + + /** Suite function */ + fn?: (this: Mocha.Suite) => void; + + /** Is suite pending? */ + pending?: boolean; + + /** Filepath where this Suite resides */ + file?: string; + + /** Is suite exclusive? */ + isOnly?: boolean; + } + + interface SuiteFunctions { + /** + * Create an exclusive Suite; convenience function + */ + only(opts: CreateOptions): Mocha.Suite; + + /** + * Create a Suite, but skip it; convenience function + */ + skip(opts: CreateOptions): Mocha.Suite; + + /** + * Creates a suite. + */ + create(opts: CreateOptions): Mocha.Suite; + } + + interface TestFunctions { + /** + * Exclusive test-case. + */ + only(mocha: Mocha, test: Mocha.Test): Mocha.Test; + + /** + * Pending test case. + */ + skip(title: string): void; + + /** + * Number of retry attempts + */ + retries(n: number): void; + } +} diff --git a/types/mocha/lib/ms.d.ts b/types/mocha/lib/ms.d.ts new file mode 100644 index 0000000000..3b89a55fc5 --- /dev/null +++ b/types/mocha/lib/ms.d.ts @@ -0,0 +1,17 @@ +export = milliseconds; + +/** + * Parse the given `str` and return milliseconds. + * + * @see {@link https://mochajs.org/api/module-milliseconds.html} + * @see {@link https://mochajs.org/api/module-milliseconds.html#~parse} + */ +declare function milliseconds(val: string): number; + +/** + * Format for `ms`. + * + * @see {@link https://mochajs.org/api/module-milliseconds.html} + * @see {@link https://mochajs.org/api/module-milliseconds.html#~format} + */ +declare function milliseconds(val: number): string; diff --git a/types/mocha/mocha-node-tests.ts b/types/mocha/mocha-node-tests.ts deleted file mode 100644 index e5cd80c8cf..0000000000 --- a/types/mocha/mocha-node-tests.ts +++ /dev/null @@ -1,37 +0,0 @@ - - -import MochaDef = require('mocha'); - -class CustomSpecReporter extends MochaDef.reporters.Spec { - constructor(runner: Mocha.IRunner) { - super(runner); - - runner.on('test', (test: Mocha.ITest) => { - console.log(test.parent.title + '/' + test.title); - }); - } -} - -class MyReporter extends MochaDef.reporters.Base { - passes: number = 0; - failures: number = 0; - - constructor(runner: Mocha.IRunner) { - super(runner); - - runner.on('pass', (test: Mocha.ITest) => { - this.passes++; - console.log('pass: %s', test.fullTitle()); - }); - - runner.on('fail', (test: Mocha.ITest, err: Error) => { - this.failures++; - console.log('fail: %s -- error: %s', test.fullTitle(), err.message); - }); - - runner.on('end', () => { - console.log('end: %d/%d', this.passes, this.passes + this.failures); - process.exit(this.failures); - }); - } -} diff --git a/types/mocha/mocha-node.d.ts b/types/mocha/mocha-node.d.ts deleted file mode 100644 index dcee001b54..0000000000 --- a/types/mocha/mocha-node.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -// Type definitions for mocha 2.2.5 -// Project: http://mochajs.org/ -// Definitions by: Vadim Macagon , vvakame -// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped - - -/// - -declare namespace Mocha { - interface IRunnable extends NodeJS.EventEmitter { - } - interface ISuite extends NodeJS.EventEmitter { - } - interface IRunner extends NodeJS.EventEmitter { - } -} diff --git a/types/mocha/mocha-tests.ts b/types/mocha/mocha-tests.ts index ec9b238d80..b80d7b415d 100644 --- a/types/mocha/mocha-tests.ts +++ b/types/mocha/mocha-tests.ts @@ -3,36 +3,36 @@ import { before as importedBefore, afterEach as importedAfterEach, beforeEach as importedBeforeEach, - context as importedContext, describe as importedDescribe, it as importedIt, - xdescribe as importedXdescribe, - xit as importedXit, + xit as importedXit } from 'mocha'; -// tslint:disable-next-line -import * as Mocha from 'mocha'; +import LocalMocha = require('mocha'); // Warning!! // Don't refer node.d.ts!! // See #22510. (): number => setTimeout(() => 0, 0); -let boolean: boolean; -let string: string; -let number: number; -let stringOrUndefined: string | undefined; -let dateOrUndefined: Date | undefined; -const resolved = Promise.resolve(); -const rejected = Promise.reject('some error'); +declare let number: number; +declare let boolean: boolean; +declare let string: string; +declare let stringOrUndefined: string | undefined; +declare let any: any; -// Use module augmentation to add a third-party interface +// Use module augmentation to add a third-party interface or reporter declare module 'mocha' { interface InterfaceContributions { - 'third-party-interface': any; + 'third-party-interface': never; + } + interface ReporterContributions { + 'third-party-reporter': never; } } -const i: Mocha.Interface = 'third-party-interface'; + +const thirdPartyInterface: Mocha.Interface = 'third-party-interface'; +const thirdPartyReporter: Mocha.Reporter = 'third-party-reporter'; // Lazy tests of compatibility between imported and global functions; should be identical const _after: typeof after = importedAfter; @@ -43,469 +43,786 @@ const _afterEach: typeof afterEach = importedAfterEach; const _afterEach2: typeof importedAfterEach = afterEach; const _beforeEach: typeof beforeEach = importedBeforeEach; const _beforeEach2: typeof importedBeforeEach = beforeEach; -const _context: typeof context = importedContext; -const _context2: typeof importedContext = context; const _describe: typeof describe = importedDescribe; const _describe2: typeof importedDescribe = describe; const _it: typeof it = importedIt; const _it2: typeof importedIt = it; -const _xdescribe: typeof xdescribe = importedXdescribe; -const _xdescribe2: typeof importedXdescribe = xdescribe; const _xit: typeof xit = importedXit; const _xit2: typeof importedXit = xit; -function test_describe() { - describe('something', () => { }); - - describe.only('something', () => { }); - - describe.skip('something', () => { }); - +function test_bdd_describe() { + // $ExpectType Suite describe('something', function() { - this.retries(3).slow(1000).timeout(2000).retries(3); + // $ExpectType Suite + this; + }); + + // $ExpectType Suite + describe.only('something', function() { + // $ExpectType Suite + this; + }); + + // $ExpectType void | Suite + describe.skip('something', function() { + // $ExpectType Suite + this; }); } -function test_context() { - context('some context', () => { }); +function test_bdd_context() { + // $ExpectType Suite + context('something', function() { + // $ExpectType Suite + this; + }); - context.only('some context', () => { }); + // $ExpectType Suite + context.only('something', function() { + // $ExpectType Suite + this; + }); - context.skip('some context', () => { }); - - context('some context', function() { - this.retries(3).slow(1000).timeout(2000).retries(3); + // $ExpectType void | Suite + context.skip('something', function() { + // $ExpectType Suite + this; }); } -function test_suite() { - suite('some context', () => { }); - - suite.only('some context', () => { }); - - suite.skip('some context', () => { }); - - suite('some context', function() { - this.retries(3).slow(1000).timeout(2000).retries(3); +function test_bdd_xdescribe() { + // $ExpectType void | Suite + xdescribe('something', function() { + // $ExpectType Suite + this; }); } -function test_it() { - it('does something', () => { }).timeout('2s'); - - it('does something', function() { this['sharedState'] = true; }); - - it('does something', (done) => { done(); }); - - it('does something', () => resolved); - it('does something', () => rejected); - - it.only('does something', () => { }); - - it.skip('does something', () => { }); - - it('does something', function() { - this.skip().retries(3).slow(1000).timeout(2000).skip(); +function test_bdd_xcontext() { + // $ExpectType void | Suite + xcontext('something', function() { + // $ExpectType Suite + this; }); } -function test_test() { - test('does something', () => { }); +function test_tdd_suite() { + // $ExpectType Suite + suite('something', function() { + // $ExpectType Suite + this; + }); - test('does something', function() { this['sharedState'] = true; }); + // $ExpectType Suite + suite.only('something', function() { + // $ExpectType Suite + this; + }); - test('does something', (done) => { done(); }); - - test('does something', () => resolved); - test('does something', () => rejected); - - test.only('does something', () => { }); - - test.skip('does something', () => { }); - - test('does something', function() { - this.skip().retries(3).slow(1000).timeout(2000).skip(); + // $ExpectType void | Suite + suite.skip('something', function() { + // $ExpectType Suite + this; }); } -function test_specify() { - specify('does something', () => { }); +function test_qunit_suite() { + // $ExpectType Suite + suite('some context'); - specify('does something', function() { this['sharedState'] = true; }); + // $ExpectType Suite + suite.only('some context'); +} - specify('does something', (done) => { done(); }); +function test_bdd_it() { + // $ExpectType Test + it(function doesSomething(done) { + // $ExpectType Done + done; - specify('does something', () => resolved); - specify('does something', () => rejected); + // $ExpectType Context + this; + }); - specify.only('does something', () => { }); + // $ExpectType Test + it(async function doesSomething() { + // $ExpectType Context + this; + }); - specify.skip('does something', () => { }); + // $ExpectType Test + it('does something', function(done) { + // $ExpectType Done + done; - specify('does something', function() { - this.skip().retries(3).slow(1000).timeout(2000).skip(); + // $ExpectType Context + this; + }); + + // $ExpectType Test + it('does something', async function() { + // $ExpectType Context + this; + }); + + // $ExpectType Test + it.only(function doesSomething(done) { + // $ExpectType Done + done; + + // $ExpectType Context + this; + }); + + // $ExpectType Test + it.only(async function doesSomething() { + // $ExpectType Context + this; + }); + + // $ExpectType Test + it.only('does something', function(done) { + // $ExpectType Done + done; + + // $ExpectType Context + this; + }); + + // $ExpectType Test + it.only('does something', async function() { + // $ExpectType Context + this; + }); + + // $ExpectType Test + it.skip(function doesSomething(done) { + // $ExpectType Done + done; + + // $ExpectType Context + this; + }); + + // $ExpectType Test + it.skip(async function doesSomething() { + // $ExpectType Context + this; + }); + + // $ExpectType Test + it.skip('does something', function(done) { + // $ExpectType Done + done; + + // $ExpectType Context + this; + }); + + // $ExpectType Test + it.skip('does something', async function() { + // $ExpectType Context + this; + }); + + // $ExpectType void + it.retries(number); +} + +function test_bdd_xit() { + // $ExpectType Test + xit(function doesSomething(done) { + // $ExpectType Done + done; + + // $ExpectType Context + this; + }); + + // $ExpectType Test + xit(async function doesSomething() { + // $ExpectType Context + this; + }); + + // $ExpectType Test + xit('does something', function(done) { + // $ExpectType Done + done; + + // $ExpectType Context + this; + }); + + // $ExpectType Test + xit('does something', async function() { + // $ExpectType Context + this; }); } -function test_before() { - before(() => { }); +function test_bdd_specify() { + // $ExpectType Test + specify(function doesSomething(done) { + // $ExpectType Done + done; - before(function() { this['sharedState'] = true; }); + // $ExpectType Context + this; + }); - before((done) => { done(); }); + // $ExpectType Test + specify(async function doesSomething() { + // $ExpectType Context + this; + }); - before(() => resolved); - before(() => rejected); + // $ExpectType Test + specify('does something', function(done) { + // $ExpectType Done + done; - before("my description", () => { }); + // $ExpectType Context + this; + }); - before("my description", done => { }); + // $ExpectType Test + specify('does something', async function() { + // $ExpectType Context + this; + }); - before("my description", () => resolved); + // $ExpectType Test + specify.only(function doesSomething(done) { + // $ExpectType Done + done; - before("my description", function() { - this.skip().timeout(2000).skip(); + // $ExpectType Context + this; + }); + + // $ExpectType Test + specify.only(async function doesSomething() { + // $ExpectType Context + this; + }); + + // $ExpectType Test + specify.only('does something', function(done) { + // $ExpectType Done + done; + + // $ExpectType Context + this; + }); + + // $ExpectType Test + specify.only('does something', async function() { + // $ExpectType Context + this; + }); + + // $ExpectType Test + specify.skip(function doesSomething(done) { + // $ExpectType Done + done; + + // $ExpectType Context + this; + }); + + // $ExpectType Test + specify.skip(async function doesSomething() { + // $ExpectType Context + this; + }); + + // $ExpectType Test + specify.skip('does something', function(done) { + // $ExpectType Done + done; + + // $ExpectType Context + this; + }); + + // $ExpectType Test + specify.skip('does something', async function() { + // $ExpectType Context + this; + }); + + // $ExpectType void + specify.retries(number); +} + +function test_bdd_xspecify() { + // $ExpectType Test + xspecify(function doesSomething(done) { + // $ExpectType Done + done; + + // $ExpectType Context + this; + }); + + // $ExpectType Test + xspecify(async function doesSomething() { + // $ExpectType Context + this; + }); + + // $ExpectType Test + xspecify('does something', function(done) { + // $ExpectType Done + done; + + // $ExpectType Context + this; + }); + + // $ExpectType Test + xspecify('does something', async function() { + // $ExpectType Context + this; }); } -function test_setup() { - setup(function() { - boolean = this.currentTest.async; - boolean = this.currentTest.pending; - boolean = this.currentTest.sync; - boolean = this.currentTest.timedOut; - string = this.currentTest.title; - string = this.currentTest.fullTitle(); - stringOrUndefined = this.currentTest.state; +function test_tdd_qunit_test() { + // $ExpectType Test + test(function doesSomething(done) { + // $ExpectType Done + done; + + // $ExpectType Context + this; }); - setup(function() { - this['sharedState'] = true; - boolean = this.currentTest.async; - boolean = this.currentTest.pending; - boolean = this.currentTest.sync; - boolean = this.currentTest.timedOut; - string = this.currentTest.title; - string = this.currentTest.fullTitle(); - stringOrUndefined = this.currentTest.state; + // $ExpectType Test + test(async function doesSomething() { + // $ExpectType Context + this; }); + // $ExpectType Test + test('does something', function(done) { + // $ExpectType Done + done; + + // $ExpectType Context + this; + }); + + // $ExpectType Test + test('does something', async function() { + // $ExpectType Context + this; + }); + + // $ExpectType Test + test.only(function doesSomething(done) { + // $ExpectType Done + done; + + // $ExpectType Context + this; + }); + + // $ExpectType Test + test.only(async function doesSomething() { + // $ExpectType Context + this; + }); + + // $ExpectType Test + test.only('does something', function(done) { + // $ExpectType Done + done; + + // $ExpectType Context + this; + }); + + // $ExpectType Test + test.only('does something', async function() { + // $ExpectType Context + this; + }); + + // $ExpectType Test + test.skip(function doesSomething(done) { + // $ExpectType Done + done; + + // $ExpectType Context + this; + }); + + // $ExpectType Test + test.skip(async function doesSomething() { + // $ExpectType Context + this; + }); + + // $ExpectType Test + test.skip('does something', function(done) { + // $ExpectType Done + done; + + // $ExpectType Context + this; + }); + + // $ExpectType Test + test.skip('does something', async function() { + // $ExpectType Context + this; + }); + + // $ExpectType void + test.retries(number); +} + +function test_bdd_qunit_before() { + before(function(done) { + // $ExpectType Done + done; + // $ExpectType Context + this; + }); + + before(async function() { + // $ExpectType Context + this; + }); + + before('description', function(done) { + // $ExpectType Done + done; + // $ExpectType Context + this; + }); + + before('description', async function() { + // $ExpectType Context + this; + }); +} + +function test_tdd_setup() { setup(function(done) { - done(); - boolean = this.currentTest.async; - boolean = this.currentTest.pending; - boolean = this.currentTest.sync; - boolean = this.currentTest.timedOut; - string = this.currentTest.title; - string = this.currentTest.fullTitle(); - stringOrUndefined = this.currentTest.state; + // $ExpectType Done + done; + // $ExpectType Context + this; }); - setup(function() { - boolean = this.currentTest.async; - boolean = this.currentTest.pending; - boolean = this.currentTest.sync; - boolean = this.currentTest.timedOut; - string = this.currentTest.title; - string = this.currentTest.fullTitle(); - stringOrUndefined = this.currentTest.state; - return resolved; + setup(async function() { + // $ExpectType Context + this; + }); + + setup('description', function(done) { + // $ExpectType Done + done; + // $ExpectType Context + this; + }); + + setup('description', async function() { + // $ExpectType Context + this; }); } -function test_after() { - after(() => { }); +function test_bdd_qunit_after() { + after(function(done) { + // $ExpectType Done + done; + // $ExpectType Context + this; + }); - after(function() { this['sharedState'] = true; }); + after(async function() { + // $ExpectType Context + this; + }); - after((done) => { done(); }); + after('description', function(done) { + // $ExpectType Done + done; + // $ExpectType Context + this; + }); - after(() => resolved); - - after("my description", () => { }); - - after("my description", done => { }); - - after("my description", () => resolved); + after('description', async function() { + // $ExpectType Context + this; + }); } -function test_teardown() { - teardown(function() { - boolean = this.currentTest.async; - boolean = this.currentTest.pending; - boolean = this.currentTest.sync; - boolean = this.currentTest.timedOut; - string = this.currentTest.title; - string = this.currentTest.fullTitle(); - stringOrUndefined = this.currentTest.state; - }); - - teardown(function() { - this['sharedState'] = true; - boolean = this.currentTest.async; - boolean = this.currentTest.pending; - boolean = this.currentTest.sync; - boolean = this.currentTest.timedOut; - string = this.currentTest.title; - string = this.currentTest.fullTitle(); - stringOrUndefined = this.currentTest.state; - }); - +function test_tdd_teardown() { teardown(function(done) { - done(); - boolean = this.currentTest.async; - boolean = this.currentTest.pending; - boolean = this.currentTest.sync; - boolean = this.currentTest.timedOut; - string = this.currentTest.title; - string = this.currentTest.fullTitle(); - stringOrUndefined = this.currentTest.state; + // $ExpectType Done + done; + // $ExpectType Context + this; }); - teardown(function() { - boolean = this.currentTest.async; - boolean = this.currentTest.pending; - boolean = this.currentTest.sync; - boolean = this.currentTest.timedOut; - string = this.currentTest.title; - string = this.currentTest.fullTitle(); - stringOrUndefined = this.currentTest.state; - return resolved; + teardown(async function() { + // $ExpectType Context + this; + }); + + teardown('description', function(done) { + // $ExpectType Done + done; + // $ExpectType Context + this; + }); + + teardown('description', async function() { + // $ExpectType Context + this; }); } -function test_beforeEach() { - beforeEach(function() { - boolean = this.currentTest.async; - boolean = this.currentTest.pending; - boolean = this.currentTest.sync; - boolean = this.currentTest.timedOut; - string = this.currentTest.title; - string = this.currentTest.fullTitle(); - stringOrUndefined = this.currentTest.state; - }); - - beforeEach(function() { - this['sharedState'] = true; - boolean = this.currentTest.async; - boolean = this.currentTest.pending; - boolean = this.currentTest.sync; - boolean = this.currentTest.timedOut; - string = this.currentTest.title; - string = this.currentTest.fullTitle(); - stringOrUndefined = this.currentTest.state; - }); - +function test_bdd_qunit_beforeEach() { beforeEach(function(done) { - done(); - boolean = this.currentTest.async; - boolean = this.currentTest.pending; - boolean = this.currentTest.sync; - boolean = this.currentTest.timedOut; - string = this.currentTest.title; - string = this.currentTest.fullTitle(); - stringOrUndefined = this.currentTest.state; + // $ExpectType Done + done; + // $ExpectType Context + this; }); - beforeEach(function() { - boolean = this.currentTest.async; - boolean = this.currentTest.pending; - boolean = this.currentTest.sync; - boolean = this.currentTest.timedOut; - string = this.currentTest.title; - string = this.currentTest.fullTitle(); - stringOrUndefined = this.currentTest.state; - return resolved; + beforeEach(async function() { + // $ExpectType Context + this; }); - beforeEach("my description", function() { - boolean = this.currentTest.async; - boolean = this.currentTest.pending; - boolean = this.currentTest.sync; - boolean = this.currentTest.timedOut; - string = this.currentTest.title; - string = this.currentTest.fullTitle(); - stringOrUndefined = this.currentTest.state; + beforeEach('description', function(done) { + // $ExpectType Done + done; + // $ExpectType Context + this; }); - beforeEach("my description", function(done) { - done(); - boolean = this.currentTest.async; - boolean = this.currentTest.pending; - boolean = this.currentTest.sync; - boolean = this.currentTest.timedOut; - string = this.currentTest.title; - string = this.currentTest.fullTitle(); - stringOrUndefined = this.currentTest.state; - }); - - beforeEach("my description", function() { - boolean = this.currentTest.async; - boolean = this.currentTest.pending; - boolean = this.currentTest.sync; - boolean = this.currentTest.timedOut; - string = this.currentTest.title; - string = this.currentTest.fullTitle(); - stringOrUndefined = this.currentTest.state; - return resolved; + beforeEach('description', async function() { + // $ExpectType Context + this; }); } -function test_suiteSetup() { - suiteSetup(() => { }); +function test_tdd_suiteSetup() { + suiteSetup(function(done) { + // $ExpectType Done + done; + // $ExpectType Context + this; + }); - suiteSetup(function() { this['sharedState'] = true; }); + suiteSetup(async function() { + // $ExpectType Context + this; + }); - suiteSetup((done) => { done(); }); + suiteSetup('description', function(done) { + // $ExpectType Done + done; + // $ExpectType Context + this; + }); - suiteSetup(() => resolved); + suiteSetup('description', async function() { + // $ExpectType Context + this; + }); } -function test_afterEach() { - afterEach(function() { - boolean = this.currentTest.async; - boolean = this.currentTest.pending; - boolean = this.currentTest.sync; - boolean = this.currentTest.timedOut; - string = this.currentTest.title; - string = this.currentTest.fullTitle(); - stringOrUndefined = this.currentTest.state; - }); - - afterEach(function() { - this['sharedState'] = true; - boolean = this.currentTest.async; - boolean = this.currentTest.pending; - boolean = this.currentTest.sync; - boolean = this.currentTest.timedOut; - string = this.currentTest.title; - string = this.currentTest.fullTitle(); - stringOrUndefined = this.currentTest.state; - }); - +function test_bdd_qunit_afterEach() { afterEach(function(done) { - done(); - boolean = this.currentTest.async; - boolean = this.currentTest.pending; - boolean = this.currentTest.sync; - boolean = this.currentTest.timedOut; - string = this.currentTest.title; - string = this.currentTest.fullTitle(); - stringOrUndefined = this.currentTest.state; + // $ExpectType Done + done; + // $ExpectType Context + this; }); - afterEach(function() { - boolean = this.currentTest.async; - boolean = this.currentTest.pending; - boolean = this.currentTest.sync; - boolean = this.currentTest.timedOut; - string = this.currentTest.title; - string = this.currentTest.fullTitle(); - stringOrUndefined = this.currentTest.state; - return resolved; + afterEach(async function() { + // $ExpectType Context + this; }); - afterEach("my description", function() { - boolean = this.currentTest.async; - boolean = this.currentTest.pending; - boolean = this.currentTest.sync; - boolean = this.currentTest.timedOut; - string = this.currentTest.title; - string = this.currentTest.fullTitle(); - stringOrUndefined = this.currentTest.state; + afterEach('description', function(done) { + // $ExpectType Done + done; + // $ExpectType Context + this; }); - afterEach("my description", function(done) { - done(); - boolean = this.currentTest.async; - boolean = this.currentTest.pending; - boolean = this.currentTest.sync; - boolean = this.currentTest.timedOut; - string = this.currentTest.title; - string = this.currentTest.fullTitle(); - stringOrUndefined = this.currentTest.state; - }); - - afterEach("my description", function() { - boolean = this.currentTest.async; - boolean = this.currentTest.pending; - boolean = this.currentTest.sync; - boolean = this.currentTest.timedOut; - string = this.currentTest.title; - string = this.currentTest.fullTitle(); - stringOrUndefined = this.currentTest.state; - return resolved; + afterEach('description', async function() { + // $ExpectType Context + this; }); } -function test_suiteTeardown() { - suiteTeardown(() => { }); +function test_tdd_suiteTeardown() { + suiteTeardown(function(done) { + // $ExpectType Done + done; + // $ExpectType Context + this; + }); - suiteTeardown(function() { this['sharedState'] = true; }); + suiteTeardown(async function() { + // $ExpectType Context + this; + }); - suiteTeardown((done) => { done(); }); + suiteTeardown('description', function(done) { + // $ExpectType Done + done; + // $ExpectType Context + this; + }); - suiteTeardown(() => resolved); + suiteTeardown('description', async function() { + // $ExpectType Context + this; + }); } -function test_reporter_string() { +function test_Context(ctx: LocalMocha.Context, runnable: LocalMocha.Runnable) { + // $ExpectType never + ctx.skip(); // throws + + // $ExpectType boolean + ctx.enableTimeouts(); + + // $ExpectType Context + ctx.enableTimeouts(boolean); + + // $ExpectType number + ctx.retries(); + + // $ExpectType Context + ctx.retries(number); + + // $ExpectType Runnable + ctx.runnable(); + + // $ExpectType Context + ctx.runnable(runnable); + + // $ExpectType number + ctx.slow(); + + // $ExpectType Context + ctx.slow(number); + + // $ExpectType number + ctx.timeout(); + + // $ExpectType Context + ctx.timeout(number); + + // $ExpectType Test | undefined + ctx.currentTest; + + // $ExpectType Runnable | undefined + ctx.test; + + ctx["extended"] = any; + + // $ExpectType any + ctx["extended"]; + + ctx.enableTimeouts(boolean) + .retries(number) + .runnable(runnable) + .slow(number) + .timeout(number) + .skip(); +} + +function test_reporter_string(localMocha: LocalMocha) { + // $ExpectType BrowserMocha mocha.reporter('html'); + + // $ExpectType Mocha + localMocha.reporter('html'); } -function test_reporter_function() { - mocha.reporter(class { }); +function test_reporter_function(localMocha: LocalMocha) { + // $ExpectType BrowserMocha + mocha.reporter(class extends LocalMocha.reporters.Base { }); + + // $ExpectType Mocha + localMocha.reporter(class extends LocalMocha.reporters.Base { }); } -function test_setup_slow_option() { - new Mocha({ slow: 25 }); +function test_browser_mocha_setup_slow_option() { + // $ExpectType BrowserMocha + mocha.setup({ slow: 25 }); } -function test_setup_timeout_option() { - new Mocha({ timeout: 25 }); +function test_browser_mocha_setup_timeout_option() { + // $ExpectType BrowserMocha + mocha.setup({ timeout: 25 }); } -function test_setup_globals_option() { - new Mocha({ globals: ['mocha'] }); +function test_browser_mocha_setup_globals_option() { + // $ExpectType BrowserMocha + mocha.setup({ globals: ['mocha'] }); } -function test_setup_ui_option() { - new Mocha({ ui: 'bdd' }); +function test_browser_mocha_setup_ui_option() { + // $ExpectType BrowserMocha + mocha.setup({ ui: 'bdd' }); } -function test_setup_reporter_string_option() { - new Mocha({ reporter: 'html' }); +function test_browser_mocha_setup_reporter_string_option() { + // $ExpectType BrowserMocha + mocha.setup({ reporter: 'html' }); } -function test_setup_require_stringArray_option() { - new Mocha({ require: ['ts-node/register'] }); +function test_browser_mocha_setup_require_stringArray_option() { + // $ExpectType BrowserMocha + mocha.setup({ require: ['ts-node/register'] }); } -function test_setup_reporter_function_option() { - new Mocha({ reporter: class { } }); +function test_browser_mocha_setup_reporter_function_option() { + // $ExpectType BrowserMocha + mocha.setup({ reporter: class extends LocalMocha.reporters.Base { } }); } -function test_setup_bail_option() { - new Mocha({ bail: false }); +function test_browser_mocha_setup_bail_option() { + // $ExpectType BrowserMocha + mocha.setup({ bail: false }); } -function test_setup_ignore_leaks_option() { - new Mocha({ ignoreLeaks: false }); +function test_browser_mocha_setup_ignore_leaks_option() { + // $ExpectType BrowserMocha + mocha.setup({ ignoreLeaks: false }); } -function test_setup_grep_string_option() { - new Mocha({ grep: "describe" }); +function test_browser_mocha_setup_grep_string_option() { + // $ExpectType BrowserMocha + mocha.setup({ grep: "describe" }); } -function test_setup_grep_regex_option() { - new Mocha({ grep: new RegExp('describe') }); +function test_browser_mocha_setup_grep_regex_option() { + // $ExpectType BrowserMocha + mocha.setup({ grep: new RegExp('describe') }); } -function test_setup_grep_regex_literal_option() { - new Mocha({ grep: /(expect|should)/i }); +function test_browser_mocha_setup_grep_regex_literal_option() { + // $ExpectType BrowserMocha + mocha.setup({ grep: /(expect|should)/i }); } -function test_setup_all_options() { - new Mocha({ +function test_browser_mocha_setup_all_options() { + // $ExpectType BrowserMocha + mocha.setup({ slow: 25, timeout: 25, ui: 'bdd', @@ -514,12 +831,97 @@ function test_setup_all_options() { bail: true, ignoreLeaks: true, grep: 'test', - require: ['ts-node/register'] + require: ['ts-node/register'] // TODO: It doesn't appear this is actually supported. Should it be removed? }); } -function test_run() { - mocha.run(() => {}); +function test_constructor_slow_option() { + // $ExpectType Mocha + new LocalMocha({ slow: 25 }); +} + +function test_constructor_timeout_option() { + // $ExpectType Mocha + new LocalMocha({ timeout: 25 }); +} + +function test_constructor_globals_option() { + // $ExpectType Mocha + new LocalMocha({ globals: ['mocha'] }); +} + +function test_constructor_ui_option() { + // $ExpectType Mocha + new LocalMocha({ ui: 'bdd' }); +} + +function test_constructor_reporter_string_option() { + // $ExpectType Mocha + new LocalMocha({ reporter: 'html' }); +} + +function test_constructor_reporter_function_option() { + // $ExpectType Mocha + new LocalMocha({ reporter: class extends LocalMocha.reporters.Base { } }); +} + +function test_constructor_bail_option() { + // $ExpectType Mocha + new LocalMocha({ bail: false }); +} + +function test_constructor_ignore_leaks_option() { + // $ExpectType Mocha + new LocalMocha({ ignoreLeaks: false }); +} + +function test_constructor_grep_string_option() { + // $ExpectType Mocha + new LocalMocha({ grep: "describe" }); +} + +function test_constructor_grep_regex_option() { + // $ExpectType Mocha + new LocalMocha({ grep: new RegExp('describe') }); +} + +function test_constructor_grep_regex_literal_option() { + // $ExpectType Mocha + new LocalMocha({ grep: /(expect|should)/i }); +} + +function test_constructor_all_options() { + // $ExpectType Mocha + new LocalMocha({ + slow: 25, + timeout: 25, + ui: 'bdd', + globals: ['mocha'], + reporter: 'html', + bail: true, + ignoreLeaks: true, + grep: 'test' + }); +} + +function test_run(localMocha: LocalMocha) { + // $ExpectType Runner + mocha.run(); + + // $ExpectType Runner + mocha.run((failures) => { + // $ExpectType number + failures; + }); + + // $ExpectType Runner + localMocha.run(); + + // $ExpectType Runner + localMocha.run((failures) => { + // $ExpectType number + failures; + }); } function test_growl() { @@ -527,24 +929,22 @@ function test_growl() { } function test_chaining() { - new Mocha({ slow: 25 }) + new LocalMocha({ slow: 25 }) .growl() .reporter('html') - .reporter(class { }); + .reporter(class extends LocalMocha.reporters.Base { }); } -import MochaDef = require('mocha'); - function test_require_constructor_empty() { - const instance = new MochaDef(); + const instance = new LocalMocha(); } function test_require_constructor_noOptions() { - const instance = new MochaDef({}); + const instance = new LocalMocha({}); } function test_require_constructor_allOptions() { - const instance = new MochaDef({ + const instance = new LocalMocha({ grep: /[a-z]*/, ui: 'tdd', reporter: 'dot', @@ -554,13 +954,13 @@ function test_require_constructor_allOptions() { } function test_require_fluentParams() { - const instance = new MochaDef(); + const instance = new LocalMocha(); instance.bail(true) .bail() .addFile('foo.js') - .reporter('bdd') - .ui('dot') + .reporter('dot') + .ui('bdd') .grep('[a-z]*') .grep(/[a-z]*/) .invert() @@ -574,60 +974,290 @@ function test_require_fluentParams() { .timeout(500) .slow(100) .enableTimeouts(true) - .asyncOnly(false) - .noHighlighting(true) + .asyncOnly() + .noHighlighting() .run(); } -function test_run_withOnComplete() { - const instance = new MochaDef(); - - instance.run((failures: number): void => { - console.log(failures); - }); -} - function test_throwError() { mocha.throwError(new Error("I'm an error!")); } -function test_mochaRunner_properties(runner: MochaDef.IRunner, suite: MochaDef.ISuite) { - runner = runner.abort(); +function test_mochaRunner_properties(runner: LocalMocha.Runner, suite: LocalMocha.Suite) { + // $Expecttype Runner + runner.abort(); - if (runner.stats !== undefined) { - number = runner.stats.failures; - number = runner.stats.passes; - number = runner.stats.pending; - number = runner.stats.suites; - number = runner.stats.tests; + // $ExpectType Suite + runner.suite; - dateOrUndefined = runner.stats.start; - dateOrUndefined = runner.stats.end; - dateOrUndefined = runner.stats.duration; - } + // $ExpectType boolean + runner.started; - const s: MochaDef.ISuite = runner.suite; - boolean = runner.started; - number = runner.total; - number = runner.failures; + // $ExpectType number + runner.total; - runner = runner.grep("regex", false); - number = runner.grepTotal(suite); + // $ExpectType number + runner.failures; - const globals: string[] | MochaDef.IRunner = runner.globals(["hello", "world"]); + // $ExpectType Runner + runner.grep(/regex/, false); - runner = runner.run(); - runner = runner.run((f: number) => {}); + // $ExpectType number + runner.grepTotal(suite); + + // $ExpectType string[] + runner.globals(); + + // $ExpectType Runner + runner.globals(["hello", "world"]); + + // $ExpectType Runner + runner.run(); + + // $ExpectType Runner + runner.run((failures) => { + // $ExpectType number + failures; + }); } -function test_base_reporter_properties(reporter: MochaDef.reporters.Base) { - number = reporter.stats.failures; - number = reporter.stats.passes; - number = reporter.stats.pending; - number = reporter.stats.suites; - number = reporter.stats.tests; +function test_base_reporter_properties(reporter: LocalMocha.reporters.Base) { + // $ExpectType number + reporter.stats.failures; - dateOrUndefined = reporter.stats.start; - dateOrUndefined = reporter.stats.end; - dateOrUndefined = reporter.stats.duration; + // $ExpectType number + reporter.stats.passes; + + // $ExpectType number + reporter.stats.pending; + + // $ExpectType number + reporter.stats.suites; + + // $ExpectType number + reporter.stats.tests; + + // $ExpectType Date | undefined + reporter.stats.start; + + // $ExpectType Date | undefined + reporter.stats.end; + + // $ExpectType number | undefined + reporter.stats.duration; +} + +function test_runner_events(runner: LocalMocha.Runner) { + // $ExpectType Runner + runner.on("start", () => {}); + + // $ExpectType Runner + runner.on("end", () => {}); + + // $ExpectType Runner + runner.on("suite", (suite) => { + // $ExpectType Suite + suite; + }); + + // $ExpectType Runner + runner.on("suite end", (suite) => { + // $ExpectType Suite + suite; + }); + + // $ExpectType Runner + runner.on("test", (test) => { + // $ExpectType Test + test; + }); + + // $ExpectType Runner + runner.on("test end", (test) => { + // $ExpectType Test + test; + }); + + // $ExpectType Runner + runner.on("hook", (hook) => { + // $ExpectType Hook + hook; + }); + + // $ExpectType Runner + runner.on("hook end", (hook) => { + // $ExpectType Hook + hook; + }); + + // $ExpectType Runner + runner.on("pass", (test) => { + // $ExpectType Test + test; + }); + + // $ExpectType Runner + runner.on("fail", (test, err) => { + // $ExpectType Test + test; + + // $ExpectType any + err; + }); + + // $ExpectType Runner + runner.on("pending", (test) => { + // $ExpectType Test + test; + }); +} + +function test_runnable_events(runnable: LocalMocha.Runnable) { + // $ExpectType Runnable + runnable.on("error", (error) => { + // $ExpectType any + error; + }); +} + +function test_suite_events(suite: LocalMocha.Suite) { + // $ExpectType Suite + suite.on("beforeAll", (hook) => { + // $ExpectType Hook + hook; + }); + + // $ExpectType Suite + suite.on("afterAll", (hook) => { + // $ExpectType Hook + hook; + }); + + // $ExpectType Suite + suite.on("beforeEach", (hook) => { + // $ExpectType Hook + hook; + }); + + // $ExpectType Suite + suite.on("afterEach", (hook) => { + // $ExpectType Hook + hook; + }); + + // $ExpectType Suite + suite.on("run", () => { }); + + // $ExpectType Suite + suite.on("pre-require", (context, file, mocha) => { + // $ExpectType MochaGlobals + context; + // $ExpectType string + file; + // $ExpectType Mocha + mocha; + }); + + // $ExpectType Suite + suite.on("require", (module, file, mocha) => { + // $ExpectType any + module; + // $ExpectType string + file; + // $ExpectType Mocha + mocha; + }); + + // $ExpectType Suite + suite.on("post-require", (context, file, mocha) => { + // $ExpectType MochaGlobals + context; + // $ExpectType string + file; + // $ExpectType Mocha + mocha; + }); +} + +function test_backcompat_Suite(suite: Mocha.Suite, iSuite: Mocha.ISuite, iSuiteContext: Mocha.ISuiteCallbackContext, iTest: Mocha.ITest, iContext: Mocha.IContext) { + iSuite = suite; + iSuiteContext = suite; + suite.addTest(iTest); + suite.addSuite(iSuite); + LocalMocha.Suite.create(iSuite, string); + new LocalMocha.Suite(string, iContext); +} + +function test_backcompat_Runner(runner: Mocha.Runner, iRunner: Mocha.IRunner, iSuite: Mocha.ISuite) { + iRunner = runner; + runner.grepTotal(iSuite); +} + +function test_backcompat_Runnable(runnable: Mocha.Runnable, iRunnable: Mocha.IRunnable) { + iRunnable = runnable; +} + +function test_backcompat_Test(test: Mocha.Test, iTest: Mocha.ITest) { + iTest = test; +} + +function test_backcompat_Hook(hook: Mocha.Hook, iHook: Mocha.IHook) { + iHook = hook; +} + +function test_backcompat_Context(context: Mocha.Context, iContext: Mocha.IContext, + iHookContext: Mocha.IHookCallbackContext, iBeforeAfterContext: Mocha.IBeforeAndAfterContext, + iTestContext: Mocha.ITestCallbackContext, iRunnable: Mocha.IRunnable) { + iContext = context; + iHookContext = context; + iBeforeAfterContext = context; + iTestContext = context; + context.runnable(iRunnable); +} + +function test_backcompat_Base(iRunner: Mocha.IRunner) { + new LocalMocha.reporters.Base(iRunner); +} + +function test_backcompat_XUnit(iRunner: Mocha.IRunner) { + new LocalMocha.reporters.XUnit(iRunner); +} + +function test_backcompat_Progress(iRunner: Mocha.IRunner) { + new LocalMocha.reporters.Progress(iRunner); +} + +import common = require("mocha/lib/interfaces/common"); + +function test_interfaces_common(suites: Mocha.Suite[], context: Mocha.MochaGlobals, localMocha: Mocha, + fn: Mocha.Func | Mocha.AsyncFunc, test: Mocha.Test) { + const funcs = common(suites, context, localMocha); + // $ExpectType CommonFunctions + funcs; + + funcs.before(fn); + funcs.before(string, fn); + funcs.beforeEach(fn); + funcs.beforeEach(string, fn); + funcs.after(fn); + funcs.after(string, fn); + funcs.afterEach(fn); + funcs.afterEach(string, fn); + + // $ExpectType Suite + funcs.suite.create({ title: string }); + funcs.suite.create({ title: string, file: string, fn: () => {}, pending: boolean, isOnly: boolean }); + + // $ExpectType Suite + funcs.suite.only({ title: string }); + funcs.suite.only({ title: string, file: string, fn: () => {}, pending: boolean, isOnly: boolean }); + + // $ExpectType Suite + funcs.suite.skip({ title: string }); + funcs.suite.skip({ title: string, file: string, fn: () => {}, pending: boolean, isOnly: boolean }); + + // $ExpectType Test + funcs.test.only(mocha, test); + funcs.test.skip(string); + funcs.test.retries(number); } diff --git a/types/mocha/tsconfig.json b/types/mocha/tsconfig.json index 6e88356fe4..f26091927f 100644 --- a/types/mocha/tsconfig.json +++ b/types/mocha/tsconfig.json @@ -19,6 +19,8 @@ }, "files": [ "index.d.ts", + "lib/ms.d.ts", + "lib/interfaces/common.d.ts", "mocha-tests.ts" ] } \ No newline at end of file