// @flow import TestRunner from './runner/TestRunner'; import testRunnerReporter from './runner/testRunnerReporter'; export type MochaWebpackOptions = { cwd: string, webpackConfig: {}, bail: boolean, reporter: string | () => void, reporterOptions: {}, ui: string, fgrep?: string, grep?: string | RegExp, invert: boolean, ignoreLeaks: boolean, fullStackTrace: boolean, colors?: boolean, useInlineDiffs: boolean, timeout: number, retries?: number, slow: number, asyncOnly: boolean, delay: boolean, interactive: boolean, quiet: boolean, growl?: boolean, }; export default class MochaWebpack { /** * Files to run test against * * @private */ entries: Array<string> = []; /** * Files to include into the bundle * * @private */ includes: Array<string> = []; /** * Options * * @private */ options: MochaWebpackOptions = { cwd: process.cwd(), webpackConfig: {}, bail: false, reporter: 'spec', reporterOptions: {}, ui: 'bdd', invert: false, ignoreLeaks: true, fullStackTrace: false, useInlineDiffs: false, timeout: 2000, slow: 75, asyncOnly: false, delay: false, interactive: !!((process.stdout: any).isTTY), quiet: false, }; /** * Add file run test against * * @public * @param {string} file file or glob * @return {MochaWebpack} */ addEntry(file: string): MochaWebpack { this.entries = [ ...this.entries, file, ]; return this; } /** * Add file to include into the test bundle * * @public * @param {string} file absolute path to module * @return {MochaWebpack} */ addInclude(file: string): MochaWebpack { this.includes = [ ...this.includes, file, ]; return this; } /** * Sets the current working directory * * @public * @param {string} cwd absolute working directory path * @return {MochaWebpack} */ cwd(cwd: string): MochaWebpack { this.options = { ...this.options, cwd, }; return this; } /** * Sets the webpack config * * @public * @param {Object} config webpack config * @return {MochaWebpack} */ webpackConfig(config: {} = {}): MochaWebpack { this.options = { ...this.options, webpackConfig: config, }; return this; } /** * Enable or disable bailing on the first failure. * * @public * @param {boolean} [bail] * @return {MochaWebpack} */ bail(bail: boolean = false): MochaWebpack { this.options = { ...this.options, bail, }; return this; } /** * Set reporter to `reporter`, defaults to "spec". * * @param {string|Function} reporter name or constructor * @param {Object} reporterOptions optional options * @return {MochaWebpack} */ reporter(reporter: string | () => void, reporterOptions: {}): MochaWebpack { this.options = { ...this.options, reporter, reporterOptions, }; return this; } /** * Set test UI, defaults to "bdd". * * @public * @param {string} ui bdd/tdd * @return {MochaWebpack} */ ui(ui: string): MochaWebpack { this.options = { ...this.options, ui, }; return this; } /** * Only run tests containing <string> * * @public * @param {string} str * @return {MochaWebpack} */ fgrep(str: string): MochaWebpack { this.options = { ...this.options, fgrep: str, }; return this; } /** * Only run tests matching <pattern> * * @public * @param {string|RegExp} pattern * @return {MochaWebpack} */ grep(pattern: string | RegExp): MochaWebpack { this.options = { ...this.options, grep: pattern, }; return this; } /** * Invert `.grep()` matches. * * @public * @return {MochaWebpack} */ invert(): MochaWebpack { this.options = { ...this.options, invert: true, }; return this; } /** * Ignore global leaks. * * @public * @param {boolean} ignore * @return {MochaWebpack} */ ignoreLeaks(ignore: boolean): MochaWebpack { this.options = { ...this.options, ignoreLeaks: ignore, }; return this; } /** * Display long stack-trace on failing * * @public * @return {MochaWebpack} */ fullStackTrace(): MochaWebpack { this.options = { ...this.options, fullStackTrace: true, }; return this; } /** * Emit color output. * * @public * @param {boolean} colors * @return {MochaWebpack} */ useColors(colors: boolean): MochaWebpack { this.options = { ...this.options, colors, }; return this; } /** * Quiet informational messages. * * @public * @return {MochaWebpack} */ quiet(): MochaWebpack { this.options = { ...this.options, quiet: true, }; return this; } /** * Use inline diffs rather than +/-. * * @public * @param {boolean} inlineDiffs * @return {MochaWebpack} */ useInlineDiffs(inlineDiffs: boolean): MochaWebpack { this.options = { ...this.options, useInlineDiffs: inlineDiffs, }; return this; } /** * Set the timeout in milliseconds. Value of 0 disables timeouts * * @public * @param {number} timeout time in ms * @return {MochaWebpack} */ timeout(timeout: number): MochaWebpack { this.options = { ...this.options, timeout, }; return this; } /** * Set the number of times to retry failed tests. * * @public * @param {number} count retry times * @return {MochaWebpack} */ retries(count: number): MochaWebpack { this.options = { ...this.options, retries: count, }; return this; } /** * Set slowness threshold in milliseconds. * * @public * @param {number} threshold time in ms * @return {MochaWebpack} */ slow(threshold: number): MochaWebpack { this.options = { ...this.options, slow: threshold, }; return this; } /** * Makes all tests async (accepting a callback) * * @public * @return {MochaWebpack} */ asyncOnly(): MochaWebpack { this.options = { ...this.options, asyncOnly: true, }; return this; } /** * Delay root suite execution. * * @public * @return {MochaWebpack} */ delay(): MochaWebpack { this.options = { ...this.options, delay: true, }; return this; } /** * Force interactive mode (default enabled in terminal) * * @public * @param {boolean} interactive * @return {MochaWebpack} */ interactive(interactive: boolean): MochaWebpack { this.options = { ...this.options, interactive, }; return this; } /** * Enable growl notification support * * @public * @param {boolean} growl * @return {MochaWebpack} */ growl(): MochaWebpack { this.options = { ...this.options, growl: true, }; return this; } /** * Run tests * * @public * @return {Promise<number>} a Promise that gets resolved with the number of failed tests or rejected with build error */ async run(): Promise<number> { const runner = new TestRunner(this.entries, this.includes, this.options); testRunnerReporter({ eventEmitter: runner, interactive: this.options.interactive, quiet: this.options.quiet, cwd: this.options.cwd, }); return await runner.run(); } /** * Run tests and rerun them on changes * @public */ async watch(): Promise<void> { const runner = new TestRunner(this.entries, this.includes, this.options); testRunnerReporter({ eventEmitter: runner, interactive: this.options.interactive, quiet: this.options.quiet, cwd: this.options.cwd, }); await runner.watch(); } }