11'use strict' ;
22const EventEmitter = require ( 'events' ) ;
3+ const clone = require ( 'lodash.clone' ) ;
34const Concurrent = require ( './concurrent' ) ;
45const Sequence = require ( './sequence' ) ;
56const Test = require ( './test' ) ;
67
8+ class ContextRef {
9+ constructor ( ) {
10+ this . value = { } ;
11+ }
12+
13+ get ( ) {
14+ return this . value ;
15+ }
16+
17+ set ( newValue ) {
18+ this . value = newValue ;
19+ }
20+
21+ copy ( ) {
22+ return new LateBinding ( this ) ; // eslint-disable-line no-use-before-define
23+ }
24+ }
25+
26+ class LateBinding extends ContextRef {
27+ constructor ( ref ) {
28+ super ( ) ;
29+ this . ref = ref ;
30+ this . bound = false ;
31+ }
32+
33+ get ( ) {
34+ if ( ! this . bound ) {
35+ this . set ( clone ( this . ref . get ( ) ) ) ;
36+ }
37+ return super . get ( ) ;
38+ }
39+
40+ set ( newValue ) {
41+ this . bound = true ;
42+ super . set ( newValue ) ;
43+ }
44+ }
45+
746class TestCollection extends EventEmitter {
847 constructor ( options ) {
948 super ( ) ;
@@ -98,9 +137,9 @@ class TestCollection extends EventEmitter {
98137 this . emit ( 'test' , result ) ;
99138 }
100139
101- _buildHooks ( hooks , testTitle , context ) {
140+ _buildHooks ( hooks , testTitle , contextRef ) {
102141 return hooks . map ( hook => {
103- const test = this . _buildHook ( hook , testTitle , context ) ;
142+ const test = this . _buildHook ( hook , testTitle , contextRef ) ;
104143
105144 if ( hook . metadata . skipped || hook . metadata . todo ) {
106145 return this . _skippedTest ( test ) ;
@@ -117,10 +156,6 @@ class TestCollection extends EventEmitter {
117156 title += ` for ${ testTitle } ` ;
118157 }
119158
120- if ( ! contextRef ) {
121- contextRef = null ;
122- }
123-
124159 const test = new Test ( {
125160 contextRef,
126161 failWithoutAssertions : false ,
@@ -135,10 +170,6 @@ class TestCollection extends EventEmitter {
135170 }
136171
137172 _buildTest ( test , contextRef ) {
138- if ( ! contextRef ) {
139- contextRef = null ;
140- }
141-
142173 test = new Test ( {
143174 contextRef,
144175 failWithoutAssertions : this . failWithoutAssertions ,
@@ -152,26 +183,26 @@ class TestCollection extends EventEmitter {
152183 return test ;
153184 }
154185
155- _buildTestWithHooks ( test ) {
186+ _buildTestWithHooks ( test , contextRef ) {
156187 if ( test . metadata . skipped || test . metadata . todo ) {
157188 return new Sequence ( [ this . _skippedTest ( this . _buildTest ( test ) ) ] , true ) ;
158189 }
159190
160- const context = { context : { } } ;
191+ const copiedRef = contextRef . copy ( ) ;
161192
162- const beforeHooks = this . _buildHooks ( this . hooks . beforeEach , test . title , context ) ;
163- const afterHooks = this . _buildHooks ( this . hooks . afterEach , test . title , context ) ;
193+ const beforeHooks = this . _buildHooks ( this . hooks . beforeEach , test . title , copiedRef ) ;
194+ const afterHooks = this . _buildHooks ( this . hooks . afterEach , test . title , copiedRef ) ;
164195
165- let sequence = new Sequence ( [ ] . concat ( beforeHooks , this . _buildTest ( test , context ) , afterHooks ) , true ) ;
196+ let sequence = new Sequence ( [ ] . concat ( beforeHooks , this . _buildTest ( test , copiedRef ) , afterHooks ) , true ) ;
166197 if ( this . hooks . afterEachAlways . length > 0 ) {
167- const afterAlwaysHooks = new Sequence ( this . _buildHooks ( this . hooks . afterEachAlways , test . title , context ) ) ;
198+ const afterAlwaysHooks = new Sequence ( this . _buildHooks ( this . hooks . afterEachAlways , test . title , copiedRef ) ) ;
168199 sequence = new Sequence ( [ sequence , afterAlwaysHooks ] , false ) ;
169200 }
170201 return sequence ;
171202 }
172203
173- _buildTests ( tests ) {
174- return tests . map ( test => this . _buildTestWithHooks ( test ) ) ;
204+ _buildTests ( tests , contextRef ) {
205+ return tests . map ( test => this . _buildTestWithHooks ( test , contextRef ) ) ;
175206 }
176207
177208 _hasUnskippedTests ( ) {
@@ -182,22 +213,24 @@ class TestCollection extends EventEmitter {
182213 }
183214
184215 build ( ) {
185- const serialTests = new Sequence ( this . _buildTests ( this . tests . serial ) , this . bail ) ;
186- const concurrentTests = new Concurrent ( this . _buildTests ( this . tests . concurrent ) , this . bail ) ;
216+ const contextRef = new ContextRef ( ) ;
217+
218+ const serialTests = new Sequence ( this . _buildTests ( this . tests . serial , contextRef ) , this . bail ) ;
219+ const concurrentTests = new Concurrent ( this . _buildTests ( this . tests . concurrent , contextRef ) , this . bail ) ;
187220 const allTests = new Sequence ( [ serialTests , concurrentTests ] ) ;
188221
189222 let finalTests ;
190223 // Only run before and after hooks when there are unskipped tests
191224 if ( this . _hasUnskippedTests ( ) ) {
192- const beforeHooks = new Sequence ( this . _buildHooks ( this . hooks . before ) ) ;
193- const afterHooks = new Sequence ( this . _buildHooks ( this . hooks . after ) ) ;
225+ const beforeHooks = new Sequence ( this . _buildHooks ( this . hooks . before , null , contextRef ) ) ;
226+ const afterHooks = new Sequence ( this . _buildHooks ( this . hooks . after , null , contextRef ) ) ;
194227 finalTests = new Sequence ( [ beforeHooks , allTests , afterHooks ] , true ) ;
195228 } else {
196229 finalTests = new Sequence ( [ allTests ] , true ) ;
197230 }
198231
199232 if ( this . hooks . afterAlways . length > 0 ) {
200- const afterAlwaysHooks = new Sequence ( this . _buildHooks ( this . hooks . afterAlways ) ) ;
233+ const afterAlwaysHooks = new Sequence ( this . _buildHooks ( this . hooks . afterAlways , null , contextRef ) ) ;
201234 finalTests = new Sequence ( [ finalTests , afterAlwaysHooks ] , false ) ;
202235 }
203236
0 commit comments