11'use strict' ;
22const EventEmitter = require ( 'events' ) ;
3+ const cloneDeep = require ( 'lodash.clonedeep' ) ;
34const Concurrent = require ( './concurrent' ) ;
45const Sequence = require ( './sequence' ) ;
56const Test = require ( './test' ) ;
67
8+ class ContextBind {
9+ constructor ( ref ) {
10+ this . ref = ref ;
11+ this . bound = false ;
12+ this . boundContext = { } ;
13+ }
14+
15+ get context ( ) {
16+ if ( ! this . bound ) {
17+ this . context = cloneDeep ( this . ref . context ) ;
18+ }
19+
20+ return this . boundContext ;
21+ }
22+
23+ set context ( context ) {
24+ this . bound = true ;
25+ this . boundContext = context ;
26+ }
27+ }
28+
29+ class Context {
30+ constructor ( ) {
31+ this . context = { } ;
32+ }
33+
34+ clone ( ) {
35+ return new ContextBind ( this ) ;
36+ }
37+ }
38+
739class TestCollection extends EventEmitter {
840 constructor ( options ) {
941 super ( ) ;
@@ -110,9 +142,9 @@ class TestCollection extends EventEmitter {
110142 this . emit ( 'test' , result ) ;
111143 }
112144
113- _buildHooks ( hooks , testTitle , context ) {
145+ _buildHooks ( hooks , testTitle , contextRef ) {
114146 return hooks . map ( hook => {
115- const test = this . _buildHook ( hook , testTitle , context ) ;
147+ const test = this . _buildHook ( hook , testTitle , contextRef ) ;
116148
117149 if ( hook . metadata . skipped || hook . metadata . todo ) {
118150 return this . _skippedTest ( test ) ;
@@ -129,10 +161,6 @@ class TestCollection extends EventEmitter {
129161 title += ` for ${ testTitle } ` ;
130162 }
131163
132- if ( ! contextRef ) {
133- contextRef = null ;
134- }
135-
136164 const test = new Test ( {
137165 contextRef,
138166 failWithoutAssertions : false ,
@@ -147,10 +175,6 @@ class TestCollection extends EventEmitter {
147175 }
148176
149177 _buildTest ( test , contextRef ) {
150- if ( ! contextRef ) {
151- contextRef = null ;
152- }
153-
154178 test = new Test ( {
155179 contextRef,
156180 failWithoutAssertions : this . failWithoutAssertions ,
@@ -164,26 +188,26 @@ class TestCollection extends EventEmitter {
164188 return test ;
165189 }
166190
167- _buildTestWithHooks ( test , context ) {
191+ _buildTestWithHooks ( test , contextRef ) {
168192 if ( test . metadata . skipped || test . metadata . todo ) {
169193 return new Sequence ( [ this . _skippedTest ( this . _buildTest ( test ) ) ] , true ) ;
170194 }
171195
172- const contextRef = context ? Object . create ( context ) : { context : { } } ;
196+ const context = contextRef . clone ( ) ;
173197
174- const beforeHooks = this . _buildHooks ( this . hooks . beforeEach , test . title , contextRef ) ;
175- const afterHooks = this . _buildHooks ( this . hooks . afterEach , test . title , contextRef ) ;
198+ const beforeHooks = this . _buildHooks ( this . hooks . beforeEach , test . title , context ) ;
199+ const afterHooks = this . _buildHooks ( this . hooks . afterEach , test . title , context ) ;
176200
177- let sequence = new Sequence ( [ ] . concat ( beforeHooks , this . _buildTest ( test , contextRef ) , afterHooks ) , true ) ;
201+ let sequence = new Sequence ( [ ] . concat ( beforeHooks , this . _buildTest ( test , context ) , afterHooks ) , true ) ;
178202 if ( this . hooks . afterEachAlways . length > 0 ) {
179- const afterAlwaysHooks = new Sequence ( this . _buildHooks ( this . hooks . afterEachAlways , test . title , contextRef ) ) ;
203+ const afterAlwaysHooks = new Sequence ( this . _buildHooks ( this . hooks . afterEachAlways , test . title , context ) ) ;
180204 sequence = new Sequence ( [ sequence , afterAlwaysHooks ] , false ) ;
181205 }
182206 return sequence ;
183207 }
184208
185- _buildTests ( tests , context ) {
186- return tests . map ( test => this . _buildTestWithHooks ( test , context ) ) ;
209+ _buildTests ( tests , contextRef ) {
210+ return tests . map ( test => this . _buildTestWithHooks ( test , contextRef ) ) ;
187211 }
188212
189213 _hasUnskippedTests ( ) {
@@ -194,26 +218,24 @@ class TestCollection extends EventEmitter {
194218 }
195219
196220 build ( ) {
197- const sequenceTests = context => {
198- const serialTests = new Sequence ( this . _buildTests ( this . tests . serial , context ) , this . bail ) ;
199- const concurrentTests = new Concurrent ( this . _buildTests ( this . tests . concurrent , context ) , this . bail ) ;
200- return new Sequence ( [ serialTests , concurrentTests ] ) ;
201- } ;
221+ const context = new Context ( ) ;
222+
223+ const serialTests = new Sequence ( this . _buildTests ( this . tests . serial , context ) , this . bail ) ;
224+ const concurrentTests = new Concurrent ( this . _buildTests ( this . tests . concurrent , context ) , this . bail ) ;
225+ const allTests = new Sequence ( [ serialTests , concurrentTests ] ) ;
202226
203227 let finalTests ;
204228 // Only run before and after hooks when there are unskipped tests
205229 if ( this . _hasUnskippedTests ( ) ) {
206- const context = { context : { } } ;
207-
208230 const beforeHooks = new Sequence ( this . _buildHooks ( this . hooks . before , null , context ) ) ;
209- const afterHooks = new Sequence ( this . _buildHooks ( this . hooks . after ) ) ;
210- finalTests = new Sequence ( [ beforeHooks , sequenceTests ( context ) , afterHooks ] , true ) ;
231+ const afterHooks = new Sequence ( this . _buildHooks ( this . hooks . after , null , context ) ) ;
232+ finalTests = new Sequence ( [ beforeHooks , allTests , afterHooks ] , true ) ;
211233 } else {
212- finalTests = new Sequence ( [ sequenceTests ( ) ] , true ) ;
234+ finalTests = new Sequence ( [ allTests ] , true ) ;
213235 }
214236
215237 if ( this . hooks . afterAlways . length > 0 ) {
216- const afterAlwaysHooks = new Sequence ( this . _buildHooks ( this . hooks . afterAlways ) ) ;
238+ const afterAlwaysHooks = new Sequence ( this . _buildHooks ( this . hooks . afterAlways , null , context ) ) ;
217239 finalTests = new Sequence ( [ finalTests , afterAlwaysHooks ] , false ) ;
218240 }
219241
0 commit comments