1
1
'use strict' ;
2
2
const EventEmitter = require ( 'events' ) ;
3
+ const clone = require ( 'lodash.clone' ) ;
3
4
const Concurrent = require ( './concurrent' ) ;
4
5
const Sequence = require ( './sequence' ) ;
5
6
const Test = require ( './test' ) ;
6
7
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
+
7
46
class TestCollection extends EventEmitter {
8
47
constructor ( options ) {
9
48
super ( ) ;
@@ -98,9 +137,9 @@ class TestCollection extends EventEmitter {
98
137
this . emit ( 'test' , result ) ;
99
138
}
100
139
101
- _buildHooks ( hooks , testTitle , context ) {
140
+ _buildHooks ( hooks , testTitle , contextRef ) {
102
141
return hooks . map ( hook => {
103
- const test = this . _buildHook ( hook , testTitle , context ) ;
142
+ const test = this . _buildHook ( hook , testTitle , contextRef ) ;
104
143
105
144
if ( hook . metadata . skipped || hook . metadata . todo ) {
106
145
return this . _skippedTest ( test ) ;
@@ -117,10 +156,6 @@ class TestCollection extends EventEmitter {
117
156
title += ` for ${ testTitle } ` ;
118
157
}
119
158
120
- if ( ! contextRef ) {
121
- contextRef = null ;
122
- }
123
-
124
159
const test = new Test ( {
125
160
contextRef,
126
161
failWithoutAssertions : false ,
@@ -135,10 +170,6 @@ class TestCollection extends EventEmitter {
135
170
}
136
171
137
172
_buildTest ( test , contextRef ) {
138
- if ( ! contextRef ) {
139
- contextRef = null ;
140
- }
141
-
142
173
test = new Test ( {
143
174
contextRef,
144
175
failWithoutAssertions : this . failWithoutAssertions ,
@@ -152,26 +183,26 @@ class TestCollection extends EventEmitter {
152
183
return test ;
153
184
}
154
185
155
- _buildTestWithHooks ( test ) {
186
+ _buildTestWithHooks ( test , contextRef ) {
156
187
if ( test . metadata . skipped || test . metadata . todo ) {
157
188
return new Sequence ( [ this . _skippedTest ( this . _buildTest ( test ) ) ] , true ) ;
158
189
}
159
190
160
- const context = { context : { } } ;
191
+ const copiedRef = contextRef . copy ( ) ;
161
192
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 ) ;
164
195
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 ) ;
166
197
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 ) ) ;
168
199
sequence = new Sequence ( [ sequence , afterAlwaysHooks ] , false ) ;
169
200
}
170
201
return sequence ;
171
202
}
172
203
173
- _buildTests ( tests ) {
174
- return tests . map ( test => this . _buildTestWithHooks ( test ) ) ;
204
+ _buildTests ( tests , contextRef ) {
205
+ return tests . map ( test => this . _buildTestWithHooks ( test , contextRef ) ) ;
175
206
}
176
207
177
208
_hasUnskippedTests ( ) {
@@ -182,22 +213,24 @@ class TestCollection extends EventEmitter {
182
213
}
183
214
184
215
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 ) ;
187
220
const allTests = new Sequence ( [ serialTests , concurrentTests ] ) ;
188
221
189
222
let finalTests ;
190
223
// Only run before and after hooks when there are unskipped tests
191
224
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 ) ) ;
194
227
finalTests = new Sequence ( [ beforeHooks , allTests , afterHooks ] , true ) ;
195
228
} else {
196
229
finalTests = new Sequence ( [ allTests ] , true ) ;
197
230
}
198
231
199
232
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 ) ) ;
201
234
finalTests = new Sequence ( [ finalTests , afterAlwaysHooks ] , false ) ;
202
235
}
203
236
0 commit comments