@@ -72,6 +72,11 @@ function isTestFailure(testResult) {
72
72
return testResult === TestResult . Failed || testResult === TestResult . TimedOut || testResult === TestResult . Crashed ;
73
73
}
74
74
75
+ function createHook ( callback , name ) {
76
+ const location = getCallerLocation ( __filename ) ;
77
+ return { name, body : callback , location } ;
78
+ }
79
+
75
80
class Test {
76
81
constructor ( suite , name , callback , location ) {
77
82
this . _suite = suite ;
@@ -83,6 +88,7 @@ class Test {
83
88
this . _location = location ;
84
89
this . _timeout = INFINITE_TIMEOUT ;
85
90
this . _repeat = 1 ;
91
+ this . _hooks = [ ] ;
86
92
87
93
// Test results. TODO: make these private.
88
94
this . result = null ;
@@ -100,6 +106,7 @@ class Test {
100
106
test . _timeout = this . _timeout ;
101
107
test . _mode = this . _mode ;
102
108
test . _expectation = this . _expectation ;
109
+ test . _hooks = this . _hooks . slice ( ) ;
103
110
return test ;
104
111
}
105
112
@@ -155,6 +162,18 @@ class Test {
155
162
setRepeat ( repeat ) {
156
163
this . _repeat = repeat ;
157
164
}
165
+
166
+ before ( callback ) {
167
+ this . _hooks . push ( createHook ( callback , 'before' ) ) ;
168
+ }
169
+
170
+ after ( callback ) {
171
+ this . _hooks . push ( createHook ( callback , 'after' ) ) ;
172
+ }
173
+
174
+ hooks ( name ) {
175
+ return this . _hooks . filter ( hook => ! name || hook . name === name ) ;
176
+ }
158
177
}
159
178
160
179
class Suite {
@@ -166,12 +185,7 @@ class Suite {
166
185
this . _expectation = TestExpectation . Ok ;
167
186
this . _location = location ;
168
187
this . _repeat = 1 ;
169
-
170
- // TODO: make these private.
171
- this . beforeAll = null ;
172
- this . beforeEach = null ;
173
- this . afterAll = null ;
174
- this . afterEach = null ;
188
+ this . _hooks = [ ] ;
175
189
176
190
this . Modes = { ...TestMode } ;
177
191
this . Expectations = { ...TestExpectation } ;
@@ -225,6 +239,26 @@ class Suite {
225
239
setRepeat ( repeat ) {
226
240
this . _repeat = repeat ;
227
241
}
242
+
243
+ beforeEach ( callback ) {
244
+ this . _hooks . push ( createHook ( callback , 'beforeEach' ) ) ;
245
+ }
246
+
247
+ afterEach ( callback ) {
248
+ this . _hooks . push ( createHook ( callback , 'afterEach' ) ) ;
249
+ }
250
+
251
+ beforeAll ( callback ) {
252
+ this . _hooks . push ( createHook ( callback , 'beforeAll' ) ) ;
253
+ }
254
+
255
+ afterAll ( callback ) {
256
+ this . _hooks . push ( createHook ( callback , 'afterAll' ) ) ;
257
+ }
258
+
259
+ hooks ( name ) {
260
+ return this . _hooks . filter ( hook => ! name || hook . name === name ) ;
261
+ }
228
262
}
229
263
230
264
class Result {
@@ -330,16 +364,20 @@ class TestWorker {
330
364
if ( this . _markTerminated ( test ) )
331
365
return ;
332
366
const suite = this . _suiteStack . pop ( ) ;
333
- if ( ! await this . _runHook ( test , suite , 'afterAll' ) )
334
- return ;
367
+ for ( const hook of suite . hooks ( 'afterAll' ) ) {
368
+ if ( ! await this . _runHook ( test , hook , suite . fullName ( ) ) )
369
+ return ;
370
+ }
335
371
}
336
372
while ( this . _suiteStack . length < suiteStack . length ) {
337
373
if ( this . _markTerminated ( test ) )
338
374
return ;
339
375
const suite = suiteStack [ this . _suiteStack . length ] ;
340
376
this . _suiteStack . push ( suite ) ;
341
- if ( ! await this . _runHook ( test , suite , 'beforeAll' ) )
342
- return ;
377
+ for ( const hook of suite . hooks ( 'beforeAll' ) ) {
378
+ if ( ! await this . _runHook ( test , hook , suite . fullName ( ) ) )
379
+ return ;
380
+ }
343
381
}
344
382
345
383
if ( this . _markTerminated ( test ) )
@@ -349,8 +387,12 @@ class TestWorker {
349
387
// no matter what happens.
350
388
351
389
await this . _testPass . _willStartTest ( this , test ) ;
352
- for ( let i = 0 ; i < this . _suiteStack . length ; i ++ )
353
- await this . _runHook ( test , this . _suiteStack [ i ] , 'beforeEach' ) ;
390
+ for ( const suite of this . _suiteStack ) {
391
+ for ( const hook of suite . hooks ( 'beforeEach' ) )
392
+ await this . _runHook ( test , hook , suite . fullName ( ) , true ) ;
393
+ }
394
+ for ( const hook of test . hooks ( 'before' ) )
395
+ await this . _runHook ( test , hook , test . fullName ( ) , true ) ;
354
396
355
397
if ( ! test . error && ! this . _markTerminated ( test ) ) {
356
398
await this . _testPass . _willStartTestBody ( this , test ) ;
@@ -371,19 +413,19 @@ class TestWorker {
371
413
await this . _testPass . _didFinishTestBody ( this , test ) ;
372
414
}
373
415
374
- for ( let i = this . _suiteStack . length - 1 ; i >= 0 ; i -- )
375
- await this . _runHook ( test , this . _suiteStack [ i ] , 'afterEach' ) ;
416
+ for ( const hook of test . hooks ( 'after' ) )
417
+ await this . _runHook ( test , hook , test . fullName ( ) , true ) ;
418
+ for ( const suite of this . _suiteStack . slice ( ) . reverse ( ) ) {
419
+ for ( const hook of suite . hooks ( 'afterEach' ) )
420
+ await this . _runHook ( test , hook , suite . fullName ( ) , true ) ;
421
+ }
376
422
await this . _testPass . _didFinishTest ( this , test ) ;
377
423
}
378
424
379
- async _runHook ( test , suite , hookName ) {
380
- const hook = suite [ hookName ] ;
381
- if ( ! hook )
382
- return true ;
383
-
384
- await this . _testPass . _willStartHook ( this , suite , hook . location , hookName ) ;
425
+ async _runHook ( test , hook , fullName , passTest = false ) {
426
+ await this . _testPass . _willStartHook ( this , hook , fullName ) ;
385
427
const timeout = this . _testPass . _runner . _timeout ;
386
- const { promise, terminate } = runUserCallback ( hook . body , timeout , [ this . _state , test ] ) ;
428
+ const { promise, terminate } = runUserCallback ( hook . body , timeout , passTest ? [ this . _state , test ] : [ this . _state ] ) ;
387
429
this . _runningHookTerminate = terminate ;
388
430
let error = await promise ;
389
431
this . _runningHookTerminate = null ;
@@ -396,7 +438,7 @@ class TestWorker {
396
438
}
397
439
let message ;
398
440
if ( error === TimeoutError ) {
399
- message = `${ locationString } - Timeout Exceeded ${ timeout } ms while running "${ hookName } " in suite "${ suite . fullName ( ) } "` ;
441
+ message = `${ locationString } - Timeout Exceeded ${ timeout } ms while running "${ hook . name } " in "${ fullName } "` ;
400
442
error = null ;
401
443
} else if ( error === TerminatedError ) {
402
444
// Do not report termination details - it's just noise.
@@ -405,21 +447,22 @@ class TestWorker {
405
447
} else {
406
448
if ( error . stack )
407
449
await this . _testPass . _runner . _sourceMapSupport . rewriteStackTraceWithSourceMaps ( error ) ;
408
- message = `${ locationString } - FAILED while running "${ hookName } " in suite "${ suite . fullName ( ) } ": ` ;
450
+ message = `${ locationString } - FAILED while running "${ hook . name } " in suite "${ fullName } ": ` ;
409
451
}
410
- await this . _testPass . _didFailHook ( this , suite , hook . location , hookName , message , error ) ;
452
+ await this . _testPass . _didFailHook ( this , hook , fullName , message , error ) ;
411
453
test . error = error ;
412
454
return false ;
413
455
}
414
456
415
- await this . _testPass . _didCompleteHook ( this , suite , hook . location , hookName ) ;
457
+ await this . _testPass . _didCompleteHook ( this , hook , fullName ) ;
416
458
return true ;
417
459
}
418
460
419
461
async shutdown ( ) {
420
462
while ( this . _suiteStack . length > 0 ) {
421
463
const suite = this . _suiteStack . pop ( ) ;
422
- await this . _runHook ( { } , suite , 'afterAll' ) ;
464
+ for ( const hook of suite . hooks ( 'afterAll' ) )
465
+ await this . _runHook ( { } , hook , suite . fullName ( ) ) ;
423
466
}
424
467
}
425
468
}
@@ -542,19 +585,19 @@ class TestPass {
542
585
debug ( 'testrunner:test' ) ( `[${ worker . _workerId } ] ${ test . result . toUpperCase ( ) } "${ test . fullName ( ) } " (${ test . location ( ) . fileName + ':' + test . location ( ) . lineNumber } )` ) ;
543
586
}
544
587
545
- async _willStartHook ( worker , suite , location , hookName ) {
546
- debug ( 'testrunner:hook' ) ( `[${ worker . _workerId } ] "${ hookName } " started for "${ suite . fullName ( ) } " (${ location . fileName + ':' + location . lineNumber } )` ) ;
588
+ async _willStartHook ( worker , hook , fullName ) {
589
+ debug ( 'testrunner:hook' ) ( `[${ worker . _workerId } ] "${ hook . name } " started for "${ fullName } " (${ hook . location . fileName + ':' + hook . location . lineNumber } )` ) ;
547
590
}
548
591
549
- async _didFailHook ( worker , suite , location , hookName , message , error ) {
550
- debug ( 'testrunner:hook' ) ( `[${ worker . _workerId } ] "${ hookName } " FAILED for "${ suite . fullName ( ) } " (${ location . fileName + ':' + location . lineNumber } )` ) ;
592
+ async _didFailHook ( worker , hook , fullName , message , error ) {
593
+ debug ( 'testrunner:hook' ) ( `[${ worker . _workerId } ] "${ hook . name } " FAILED for "${ fullName } " (${ hook . location . fileName + ':' + hook . location . lineNumber } )` ) ;
551
594
if ( message )
552
595
this . _result . addError ( message , error , worker ) ;
553
596
this . _result . setResult ( TestResult . Crashed , message ) ;
554
597
}
555
598
556
- async _didCompleteHook ( worker , suite , location , hookName ) {
557
- debug ( 'testrunner:hook' ) ( `[${ worker . _workerId } ] "${ hookName } " OK for "${ suite . fullName ( ) } " (${ location . fileName + ':' + location . lineNumber } )` ) ;
599
+ async _didCompleteHook ( worker , hook , fullName ) {
600
+ debug ( 'testrunner:hook' ) ( `[${ worker . _workerId } ] "${ hook . name } " OK for "${ fullName } " (${ hook . location . fileName + ':' + hook . location . lineNumber } )` ) ;
558
601
}
559
602
}
560
603
@@ -593,10 +636,10 @@ class TestRunner extends EventEmitter {
593
636
594
637
this . _debuggerLogBreakpointLines = new Multimap ( ) ;
595
638
596
- this . beforeAll = this . _addHook . bind ( this , ' beforeAll' ) ;
597
- this . beforeEach = this . _addHook . bind ( this , ' beforeEach' ) ;
598
- this . afterAll = this . _addHook . bind ( this , ' afterAll' ) ;
599
- this . afterEach = this . _addHook . bind ( this , ' afterEach' ) ;
639
+ this . beforeAll = ( callback ) => this . _currentSuite . beforeAll ( callback ) ;
640
+ this . beforeEach = ( callback ) => this . _currentSuite . beforeEach ( callback ) ;
641
+ this . afterAll = ( callback ) => this . _currentSuite . afterAll ( callback ) ;
642
+ this . afterEach = ( callback ) => this . _currentSuite . afterEach ( callback ) ;
600
643
601
644
this . describe = this . _suiteBuilder ( [ ] ) ;
602
645
this . it = this . _testBuilder ( [ ] ) ;
@@ -694,12 +737,6 @@ class TestRunner extends EventEmitter {
694
737
this . describe . skip ( true ) ( '' , module . xdescribe , ...args ) ;
695
738
}
696
739
697
- _addHook ( hookName , callback ) {
698
- assert ( this . _currentSuite [ hookName ] === null , `Only one ${ hookName } hook available per suite` ) ;
699
- const location = getCallerLocation ( __filename ) ;
700
- this . _currentSuite [ hookName ] = { body : callback , location } ;
701
- }
702
-
703
740
async run ( options = { } ) {
704
741
const { totalTimeout = 0 } = options ;
705
742
let session = this . _debuggerLogBreakpointLines . size ? await setLogBreakpoints ( this . _debuggerLogBreakpointLines ) : null ;
0 commit comments