import { EventEmitter } from "events" ; import Hook from "./hook" ; import { assignNewMochaID , clamp , constants as utilsConstants , defineConstants , getMochaID , isString , } from "./utils" ; import milliseconds from "ms" ; import * as errors from "./errors" ; import Context from "./context" ; import Test from "./test" ; const { MOCHA_ID_PROP_NAME } = utilsConstants ; const constants = defineConstants ( { /**
     * Event emitted after a test file has been loaded Not emitted in browser.
     */ EVENT_FILE_POST_REQUIRE : "post-require" , /**
     * Event emitted before a test file has been loaded. In browser, this is emitted once an interface has been selected.
     */ EVENT_FILE_PRE_REQUIRE : "pre-require" , /**
     * Event emitted immediately after a test file has been loaded. Not emitted in browser.
     */ EVENT_FILE_REQUIRE : "require" , /**
     * Event emitted when `global.run()` is called (use with `delay` option)
     */ EVENT_ROOT_SUITE_RUN : "run" , /**
     * Namespace for collection of a `Suite`'s "after all" hooks
     */ HOOK_TYPE_AFTER_ALL : "afterAll" , /**
     * Namespace for collection of a `Suite`'s "after each" hooks
     */ HOOK_TYPE_AFTER_EACH : "afterEach" , /**
     * Namespace for collection of a `Suite`'s "before all" hooks
     */ HOOK_TYPE_BEFORE_ALL : "beforeAll" , /**
     * Namespace for collection of a `Suite`'s "before all" hooks
     */ HOOK_TYPE_BEFORE_EACH : "beforeEach" , /**
     * Emitted after an "after all" `Hook` has been added to a `Suite`. Deprecated
     */ EVENT_SUITE_ADD_HOOK_AFTER_ALL : "afterAll" , /**
     * Emitted after an "after each" `Hook` has been added to a `Suite` Deprecated
     */ EVENT_SUITE_ADD_HOOK_AFTER_EACH : "afterEach" , /**
     * Emitted after an "before all" `Hook` has been added to a `Suite` Deprecated
     */ EVENT_SUITE_ADD_HOOK_BEFORE_ALL : "beforeAll" , /**
     * Emitted after an "before each" `Hook` has been added to a `Suite` Deprecated
     */ EVENT_SUITE_ADD_HOOK_BEFORE_EACH : "beforeEach" , /**
     * Emitted after a child `Suite` has been added to a `Suite`. Deprecated
     */ EVENT_SUITE_ADD_SUITE : "suite" , /**
     * Emitted after a `Test` has been added to a `Suite`. Deprecated
     */ EVENT_SUITE_ADD_TEST : "test" , } ) ; class Suite extends EventEmitter { private _beforeEach ; private _beforeAll ; private _afterEach ; private _afterAll ; private _timeout ; private _slow ; private _bail ; private _retries ; private _onlyTests ; private _onlySuites ; ctx : Context ; suites : Suite [ ] ; tests : Test [ ] ; pending : boolean ; file ? : string | undefined ; root : boolean ; delayed : boolean ; parent : Suite | undefined ; title : string ; handle : string ; description : string ; tags : string [ ] ; public param { Suite } parent param { string } title return { Suite } static create = function ( parent , title ) { var suite = new Suite ( title , parent . ctx ) ; suite . parent = parent ; title = suite . fullTitle ( ) ; parent . addSuite ( suite ) ; return suite ; } ; public class extends EventEmitter see https param { string } title param { Context } parentContext param { boolean } isRoot constructor ( title , parentContext ? , isRoot ? ) { super ( ) ; if ( ! isString ( title ) ) { throw errors . createInvalidArgumentTypeError ( 'Suite argument "title" must be a string. Received type "' + typeof title + '"' , "title" , "string" ) ; } this . title = title ; function Context ( ) { } Context . prototype = parentContext ; this . ctx = new Context ( ) ; this . suites = [ ] ; this . tests = [ ] ; this . root = isRoot === true ; this . pending = false ; this . _retries = - 1 ; this . _beforeEach = [ ] ; this . _beforeAll = [ ] ; this . _afterEach = [ ] ; this . _afterAll = [ ] ; this . _timeout = 2000 ; this . _slow = 75 ; this . _bail = false ; this . _onlyTests = [ ] ; this . _onlySuites = [ ] ; assignNewMochaID ( this ) ; Object . defineProperty ( this , "id" , { get ( ) { return getMochaID ( this ) ; } , } ) ; this . reset ( ) ; } /**
     * Resets the state initially or for a next run.
     */ reset = function ( ) { this . delayed = false ; function doReset ( thingToReset ) { thingToReset . reset ( ) ; } this . suites . forEach ( doReset ) ; this . tests . forEach ( doReset ) ; this . _beforeEach . forEach ( doReset ) ; this . _afterEach . forEach ( doReset ) ; this . _beforeAll . forEach ( doReset ) ; this . _afterAll . forEach ( doReset ) ; } ; private return { Suite } clone = function ( ) { var suite = new Suite ( this . title ) ; suite . ctx = this . ctx ; suite . root = this . root ; suite . timeout ( this . timeout ( ) ) ; suite . retries ( this . retries ( ) ) ; suite . slow ( this . slow ( ) ) ; suite . bail ( this . bail ( ) ) ; return suite ; } ; private todo param { number | string } ms return { Suite | number } timeout = function ( ms ) { if ( ! arguments . length ) { return this . _timeout ; } if ( typeof ms === "string" ) { ms = milliseconds ( ms ) ; } var INT_MAX = Math . pow ( 2 , 31 ) - 1 ; var range = [ 0 , INT_MAX ] ; ms = clamp ( ms , range ) ; this . _timeout = parseInt ( ms , 10 ) ; return this ; } ; private param { number | string } n return { Suite | number } retries = function ( n ) { if ( ! arguments . length ) { return this . _retries ; } this . _retries = parseInt ( n , 10 ) || 0 ; return this ; } ; private param { number | string } ms return { Suite | number } slow = function ( ms ) { if ( ! arguments . length ) { return this . _slow ; } if ( typeof ms === "string" ) { ms = milliseconds ( ms ) ; } this . _slow = ms ; return this ; } ; private param { boolean } bail return { Suite | number } bail = function ( bail ) { if ( ! arguments . length ) { return this . _bail ; } this . _bail = bail ; return this ; } ; private isPending = function ( ) { return this . pending || ( this . parent && this . parent . isPending ( ) ) ; } ; private param { string } title param { Function } fn returns { Hook } _createHook = function ( title , fn ) { var hook = new Hook ( title , fn ) ; hook . parent = this ; hook . timeout ( this . timeout ( ) ) ; hook . retries ( this . retries ( ) ) ; hook . slow ( this . slow ( ) ) ; hook . ctx = this . ctx ; hook . file = this . file ; return hook ; } ; private param { string } title param { Function } fn return { Suite } beforeAll = function ( title , fn ? ) { if ( this . isPending ( ) ) { return this ; } if ( typeof title === "function" ) { fn = title ; title = fn . name ; } title = '"before all" hook' + ( title ? ": " + title : "" ) ; var hook = this . _createHook ( title , fn ) ; this . _beforeAll . push ( hook ) ; this . emit ( constants . EVENT_SUITE_ADD_HOOK_BEFORE_ALL , hook ) ; return this ; } ; private param { string } title param { Function } fn return { Suite } afterAll = function ( title , fn ? ) { if ( this . isPending ( ) ) { return this ; } if ( typeof title === "function" ) { fn = title ; title = fn . name ; } title = '"after all" hook' + ( title ? ": " + title : "" ) ; var hook = this . _createHook ( title , fn ) ; this . _afterAll . push ( hook ) ; this . emit ( constants . EVENT_SUITE_ADD_HOOK_AFTER_ALL , hook ) ; return this ; } ; private param { string } title param { Function } fn return { Suite } beforeEach = function ( title , fn ? ) { if ( this . isPending ( ) ) { return this ; } if ( typeof title === "function" ) { fn = title ; title = fn . name ; } title = '"before each" hook' + ( title ? ": " + title : "" ) ; var hook = this . _createHook ( title , fn ) ; this . _beforeEach . push ( hook ) ; this . emit ( constants . EVENT_SUITE_ADD_HOOK_BEFORE_EACH , hook ) ; return this ; } ; private param { string } title param { Function } fn return { Suite } afterEach = function ( title , fn ? ) { if ( this . isPending ( ) ) { return this ; } if ( typeof title === "function" ) { fn = title ; title = fn . name ; } title = '"after each" hook' + ( title ? ": " + title : "" ) ; var hook = this . _createHook ( title , fn ) ; this . _afterEach . push ( hook ) ; this . emit ( constants . EVENT_SUITE_ADD_HOOK_AFTER_EACH , hook ) ; return this ; } ; private param { Suite } suite return { Suite } addSuite = function ( suite ) { suite . parent = this ; suite . root = false ; suite . timeout ( this . timeout ( ) ) ; suite . retries ( this . retries ( ) ) ; suite . slow ( this . slow ( ) ) ; suite . bail ( this . bail ( ) ) ; this . suites . push ( suite ) ; this . emit ( constants . EVENT_SUITE_ADD_SUITE , suite ) ; return this ; } ; private param { Test } test return { Suite } addTest = function ( test ) { test . parent = this ; test . timeout ( this . timeout ( ) ) ; test . retries ( this . retries ( ) ) ; test . slow ( this . slow ( ) ) ; test . ctx = this . ctx ; this . tests . push ( test ) ; this . emit ( constants . EVENT_SUITE_ADD_TEST , test ) ; return this ; } ; memberof public return { string } fullTitle = function ( ) { return this . titlePath ( ) . join ( " " ) ; } ; memberof public return { string } titlePath = function ( ) { var result = [ ] ; if ( this . parent ) { result = result . concat ( this . parent . titlePath ( ) ) ; } if ( ! this . root ) { result . push ( this . title ) ; } return result ; } ; memberof public return { number } total = function ( ) { return ( this . suites . reduce ( function ( sum , suite ) { return sum + suite . total ( ) ; } , 0 ) + this . tests . length ) ; } ; private param { Function } fn return { Suite } eachTest = function ( fn ) { this . tests . forEach ( fn ) ; this . suites . forEach ( function ( suite ) { suite . eachTest ( fn ) ; } ) ; return this ; } ; private run = function run ( ) { if ( this . root ) { this . emit ( constants . EVENT_ROOT_SUITE_RUN ) ; } } ; private returns { Boolean } hasOnly = function hasOnly ( ) { return ( this . _onlyTests . length > 0 || this . _onlySuites . length > 0 || this . suites . some ( function ( suite ) { return suite . hasOnly ( ) ; } ) ) ; } ; private returns { Boolean } filterOnly = function filterOnly ( ) { if ( this . _onlyTests . length ) { this . tests = this . _onlyTests ; this . suites = [ ] ; } else { this . tests = [ ] ; this . _onlySuites . forEach ( function ( onlySuite ) { if ( onlySuite . hasOnly ( ) ) { onlySuite . filterOnly ( ) ; } } ) ; var onlySuites = this . _onlySuites ; this . suites = this . suites . filter ( function ( childSuite ) { return ( onlySuites . indexOf ( childSuite ) !== - 1 || childSuite . filterOnly ( ) ) ; } ) ; } return this . tests . length > 0 || this . suites . length > 0 ; } ; private param { Suite } suite appendOnlySuite = function ( suite ) { this . _onlySuites . push ( suite ) ; } ; private markOnly = function ( ) { this . parent && this . parent . appendOnlySuite ( this ) ; } ; private param { Test } test appendOnlyTest = function ( test ) { this . _onlyTests . push ( test ) ; } ; private getHooks = function getHooks ( name ) { return this [ "_" + name ] ; } ; /**
     * cleans all references from this suite and all child suites.
     */ dispose = function ( ) { this . suites . forEach ( function ( suite ) { suite . dispose ( ) ; } ) ; this . cleanReferences ( ) ; } ; private cleanReferences = function cleanReferences ( ) { function cleanArrReferences ( arr ) { for ( var i = 0 ; i < arr . length ; i ++ ) { delete arr [ i ] . fn ; } } if ( Array . isArray ( this . _beforeAll ) ) { cleanArrReferences ( this . _beforeAll ) ; } if ( Array . isArray ( this . _beforeEach ) ) { cleanArrReferences ( this . _beforeEach ) ; } if ( Array . isArray ( this . _afterAll ) ) { cleanArrReferences ( this . _afterAll ) ; } if ( Array . isArray ( this . _afterEach ) ) { cleanArrReferences ( this . _afterEach ) ; } for ( var i = 0 ; i < this . tests . length ; i ++ ) { delete this . tests [ i ] . fn ; } } ; private returns { Object } serialize = function serialize ( ) { return { _bail : this . _bail , $$fullTitle : this . fullTitle ( ) , $$isPending : Boolean ( this . isPending ( ) ) , root : this . root , title : this . title , [ MOCHA_ID_PROP_NAME ] : this . id , parent : this . parent ? { [ MOCHA_ID_PROP_NAME ] : this . parent . id } : null , } ; } ; static constants = constants ; } export { constants } ; export default Suite ;