import { LogicError } from '@serenity-js/core' ; import { ModuleLoader , TestRunnerAdapter } from '@serenity-js/core/lib/io' ; import { ExecutionIgnored , ImplementationPending , Outcome } from '@serenity-js/core/lib/model' ; import * as fs from 'fs' ; import * as path from 'path' ; import { MochaConfig } from './MochaConfig' ; import type Mocha = require ( 'mocha' ) ; desc Allows for programmatic execution of Mocha test scenarios,
 *  using  SerenityReporterForMocha to report progress.
 *
 *  implements serenity-js export class MochaAdapter implements TestRunnerAdapter { private mocha : Mocha ; private totalScenarios : number ; desc param { MochaConfig } config param { serenity-js constructor ( private readonly config , private readonly loader ) { } desc returns { Outcome | { Code : number } } successThreshold ( ) { return this . config . strict ? ExecutionIgnored : ImplementationPending ; } desc param { string [ ] } pathsToScenarios returns { Promise < void > } async load ( pathsToScenarios ) { const _Mocha = this . loader . require ( 'mocha' ) ; this . mocha = new _Mocha ( { ... this . config , reporter : require . resolve ( '../index' ) , } ) ; this . mocha . fullTrace ( ) ; this . mocha . files = pathsToScenarios ; this . mocha . suite . on ( 'pre-require' , ( context , file , mocha ) => { this . requireAny ( this . config . require ) ; } ) ; await this . mocha . loadFilesAsync ( ) ; const mochaRunner = new _Mocha . Runner ( this . mocha . suite , { delay : false , } ) ; if ( this . config . grep ) { mochaRunner . grep ( this . mocha . options . grep as RegExp , this . config . invert ) ; } this . totalScenarios = mochaRunner . total ; } desc throws returns { number } scenarioCount ( ) { if ( this . totalScenarios === undefined ) { throw new LogicError ( 'Make sure to call `load` before calling `scenarioCount`' ) ; } return this . totalScenarios ; } desc throws returns { Promise < void > } run ( ) { return new Promise ( ( resolve , reject ) => { if ( this . mocha === undefined ) { throw new LogicError ( 'Make sure to call `load` before calling `run`' ) ; } this . mocha . run ( numberOfFailures => resolve ( ) ) ; } ) ; } private requireAny ( filesOrModules ) { const requires = filesOrModules ? [ ] . concat ( filesOrModules ) . filter ( item => ! ! item ) : [ ] ; requires . forEach ( fileOrModule => { const required = fs . existsSync ( fileOrModule ) || fs . existsSync ( `${ fileOrModule }.js` ) ? path . resolve ( fileOrModule ) : fileOrModule ; require ( required ) ; } ) ; } }