From ee04278cb856cc5ca1f906ff6f0713d6bf24b838 Mon Sep 17 00:00:00 2001 From: Dmitrii Sorin Date: Sun, 20 May 2018 10:22:33 +1000 Subject: [PATCH] Add multiple forgotten mocha API methods --- types/mocha/index.d.ts | 293 ++++++++++++++++++++++++++++++------- types/mocha/mocha-tests.ts | 34 +++-- 2 files changed, 259 insertions(+), 68 deletions(-) diff --git a/types/mocha/index.d.ts b/types/mocha/index.d.ts index 0e066791eb..2dd6bb2c21 100644 --- a/types/mocha/index.d.ts +++ b/types/mocha/index.d.ts @@ -5,10 +5,28 @@ // jt000 // Vadim Macagon // Andrew Bradley +// Dmitrii Sorin // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped // TypeScript Version: 2.1 -interface MochaSetupOptions { +/** + * 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. + * + * @see https://github.com/DefinitelyTyped/DefinitelyTyped/pull/25117#issuecomment-383404187 + */ +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; + } + + interface MochaSetupOptions { // milliseconds to wait before considering a test slow slow?: number; @@ -35,61 +53,67 @@ interface MochaSetupOptions { // require modules before running tests require?: string[]; -} -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; + asyncOnly?: boolean; + delay?: boolean; + files?: string[]; + forbidOnly?: boolean; + forbidPending?: boolean; + fullStackTrace?: boolean; + hasOnly?: boolean; + } -// Used with the --delay flag; see https://mochajs.org/#hooks -declare function run(): void; + 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; -type MochaDone = (error?: any) => void; + // Used with the --delay flag; see https://mochajs.org/#hooks + declare function run(): 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; + type MochaDone = (error?: any) => void; -interface ReporterConstructor { + 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 { + declare class Mocha { currentTest: Mocha.ITestDefinition; suite: Mocha.ISuite; + files: string[]; + options: MochaSetupOptions; - constructor(options?: { - grep?: RegExp; - ui?: string; - reporter?: string | ReporterConstructor; - timeout?: number; - reporterOptions?: any; - slow?: number; - bail?: boolean; - }); + 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; - /** Setup mocha with the given options. */ - setup(options: MochaSetupOptions): Mocha; bail(value?: boolean): Mocha; addFile(file: string): Mocha; /** Sets reporter by name, defaults to "spec". */ @@ -117,15 +141,22 @@ declare class Mocha { timeout(value: number): Mocha; slow(value: number): Mocha; enableTimeouts(value: boolean): Mocha; - asyncOnly(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; -} -// merge the Mocha class declaration with a module -declare namespace Mocha { + // internals exposed via exports.* + Runnable: Mocha.Runnable; + Context: Mocha.Context; + Runner: Mocha.Runner; + Suite: Mocha.Suite; + Hook: Mocha.Hook; + Test: Mocha.Test; + } + + // 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; @@ -136,6 +167,22 @@ declare namespace Mocha { 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; + } + interface ISuiteCallbackContext { timeout(ms: number | string): this; retries(n: number): this; @@ -157,7 +204,7 @@ declare namespace Mocha { } /** Partial interface for Mocha's `Runnable` class. */ - interface IRunnable { + interface IRunnable extends GenericEventEmitter { title: string; fn: Function; async: boolean; @@ -169,22 +216,49 @@ declare namespace Mocha { /** 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'; fullTitle(): string; } + interface IHook extends IRunnable { + ctx?: IContext; + parent?: ISuite; + type: 'hook'; + + error(err: Error): void; + } + interface IBeforeAndAfterContext extends IHookCallbackContext { currentTest: ITest; } @@ -201,12 +275,19 @@ declare namespace Mocha { } /** Partial interface for Mocha's `Runner` class. */ - interface IRunner { + interface IRunner extends GenericEventEmitter { + 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[]; @@ -231,6 +312,7 @@ declare namespace Mocha { namespace reporters { class Base { + runner: IRunner; stats: IStats; constructor(runner: IRunner); @@ -326,8 +408,115 @@ declare namespace Mocha { 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; -} -declare module "mocha" { + class Runnable extends GenericEventEmitter { + new(title: string, fn: () => any): IRunnable; + } + + class Context implements IContext { + constructor(); + + _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; + } + + 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; + } + + class Suite extends GenericEventEmitter implements ISuite { + constructor(title: string, parentContext: IContext); + + 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; + } + + class Hook extends Runnable implements IHook { + constructor(title: string, fn: () => any); + + async: boolean; + ctx?: IContext; + duration?: number; + fn: Function; + parent?: ISuite; + sync: boolean; + timedOut: boolean; + timeout(n: number | string): this; + title: string; + type: '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; + } + } + + declare module "mocha" { export = Mocha; -} + } diff --git a/types/mocha/mocha-tests.ts b/types/mocha/mocha-tests.ts index f2fa323f19..ec9b238d80 100644 --- a/types/mocha/mocha-tests.ts +++ b/types/mocha/mocha-tests.ts @@ -7,9 +7,12 @@ import { 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'; + // Warning!! // Don't refer node.d.ts!! // See #22510. @@ -454,55 +457,55 @@ function test_reporter_function() { } function test_setup_slow_option() { - mocha.setup({ slow: 25 }); + new Mocha({ slow: 25 }); } function test_setup_timeout_option() { - mocha.setup({ timeout: 25 }); + new Mocha({ timeout: 25 }); } function test_setup_globals_option() { - mocha.setup({ globals: ['mocha'] }); + new Mocha({ globals: ['mocha'] }); } function test_setup_ui_option() { - mocha.setup({ ui: 'bdd' }); + new Mocha({ ui: 'bdd' }); } function test_setup_reporter_string_option() { - mocha.setup({ reporter: 'html' }); + new Mocha({ reporter: 'html' }); } function test_setup_require_stringArray_option() { - mocha.setup({ require: ['ts-node/register'] }); + new Mocha({ require: ['ts-node/register'] }); } function test_setup_reporter_function_option() { - mocha.setup({ reporter: class { } }); + new Mocha({ reporter: class { } }); } function test_setup_bail_option() { - mocha.setup({ bail: false }); + new Mocha({ bail: false }); } function test_setup_ignore_leaks_option() { - mocha.setup({ ignoreLeaks: false }); + new Mocha({ ignoreLeaks: false }); } function test_setup_grep_string_option() { - mocha.setup({ grep: "describe" }); + new Mocha({ grep: "describe" }); } function test_setup_grep_regex_option() { - mocha.setup({ grep: new RegExp('describe') }); + new Mocha({ grep: new RegExp('describe') }); } function test_setup_grep_regex_literal_option() { - mocha.setup({ grep: /(expect|should)/i }); + new Mocha({ grep: /(expect|should)/i }); } function test_setup_all_options() { - mocha.setup({ + new Mocha({ slow: 25, timeout: 25, ui: 'bdd', @@ -524,8 +527,7 @@ function test_growl() { } function test_chaining() { - mocha - .setup({ slow: 25 }) + new Mocha({ slow: 25 }) .growl() .reporter('html') .reporter(class { });