1+ /**
2+ * Patch Jest's describe/test/beforeEach/afterEach functions so test code
3+ * always runs in a testZone (ProxyZone).
4+ */
5+
6+ if ( Zone === undefined ) {
7+ throw new Error ( 'Missing: Zone (zone.js)' ) ;
8+ }
9+ if ( jest === undefined ) {
10+ throw new Error (
11+ 'Missing: jest.\n' +
12+ 'This patch must be included in a script called with ' +
13+ '`setupTestFrameworkScriptFile` in Jest config.'
14+ ) ;
15+ }
16+ if ( jest [ '__zone_patch__' ] === true ) {
17+ throw new Error ( "'jest' has already been patched with 'Zone'." ) ;
18+ }
19+
20+ jest [ '__zone_patch__' ] = true ;
21+ const SyncTestZoneSpec = Zone [ 'SyncTestZoneSpec' ] ;
22+ const ProxyZoneSpec = Zone [ 'ProxyZoneSpec' ] ;
23+
24+ if ( SyncTestZoneSpec === undefined ) {
25+ throw new Error ( 'Missing: SyncTestZoneSpec (zone.js/dist/sync-test)' ) ;
26+ }
27+ if ( ProxyZoneSpec === undefined ) {
28+ throw new Error ( 'Missing: ProxyZoneSpec (zone.js/dist/proxy.js)' ) ;
29+ }
30+
31+ const env = global ;
32+ const ambientZone = Zone . current ;
33+
34+ // Create a synchronous-only zone in which to run `describe` blocks in order to
35+ // raise an error if any asynchronous operations are attempted
36+ // inside of a `describe` but outside of a `beforeEach` or `it`.
37+ const syncZone = ambientZone . fork ( new SyncTestZoneSpec ( 'jest.describe' ) ) ;
38+ function wrapDescribeInZone ( describeBody ) {
39+ return function ( ) {
40+ return syncZone . run ( describeBody , null , arguments ) ;
41+ } ;
42+ }
43+
44+ // Create a proxy zone in which to run `test` blocks so that the tests function
45+ // can retroactively install different zones.
46+ const testProxyZone = ambientZone . fork ( new ProxyZoneSpec ( ) ) ;
47+ function wrapTestInZone ( testBody ) {
48+ if ( testBody === undefined ) {
49+ return ;
50+ }
51+ return testBody . length === 0
52+ ? ( ) => testProxyZone . run ( testBody , null )
53+ : done => testProxyZone . run ( testBody , null , [ done ] ) ;
54+ }
55+
56+ const bindDescribe = originalJestFn =>
57+ function ( ) {
58+ const eachArguments = arguments ;
59+ return function ( description , specDefinitions , timeout ) {
60+ arguments [ 1 ] = wrapDescribeInZone ( specDefinitions ) ;
61+ return originalJestFn . apply ( this , eachArguments ) . apply ( this , arguments ) ;
62+ } ;
63+ } ;
64+
65+ [ 'xdescribe' , 'fdescribe' , 'describe' ] . forEach ( methodName => {
66+ const originaljestFn = env [ methodName ] ;
67+ env [ methodName ] = function ( description , specDefinitions , timeout ) {
68+ arguments [ 1 ] = wrapDescribeInZone ( specDefinitions ) ;
69+ return originaljestFn . apply ( this , arguments ) ;
70+ } ;
71+ env [ methodName ] . each = bindDescribe ( originaljestFn . each ) ;
72+ if ( methodName === 'describe' ) {
73+ env [ methodName ] . only = env [ 'fdescribe' ] ;
74+ env [ methodName ] . skip = env [ 'xdescribe' ] ;
75+ env [ methodName ] . only . each = bindDescribe ( originaljestFn . only . each ) ;
76+ env [ methodName ] . skip . each = bindDescribe ( originaljestFn . skip . each ) ;
77+ }
78+ } ) ;
79+
80+ [ 'xit' , 'fit' , 'xtest' , 'test' , 'it' ] . forEach ( methodName => {
81+ const originaljestFn = env [ methodName ] ;
82+ env [ methodName ] = function ( description , specDefinitions , timeout ) {
83+ arguments [ 1 ] = wrapTestInZone ( specDefinitions ) ;
84+ return originaljestFn . apply ( this , arguments ) ;
85+ } ;
86+ // The revised method will be populated to the final each method, so we only declare the method that in the new globals
87+ env [ methodName ] . each = originaljestFn . each ;
88+
89+ if ( methodName === 'test' || methodName === 'it' ) {
90+ env [ methodName ] . only = env [ 'fit' ] ;
91+ env [ methodName ] . only . each = originaljestFn . only . each ;
92+
93+ env [ methodName ] . skip = env [ 'xit' ] ;
94+ env [ methodName ] . skip . each = originaljestFn . skip . each ;
95+
96+ env [ methodName ] . todo = function ( description ) {
97+ return originaljestFn . todo . apply ( this , arguments ) ;
98+ } ;
99+ }
100+ } ) ;
101+
102+ [ 'beforeEach' , 'afterEach' , 'beforeAll' , 'afterAll' ] . forEach ( methodName => {
103+ const originaljestFn = env [ methodName ] ;
104+ env [ methodName ] = function ( specDefinitions , timeout ) {
105+ arguments [ 0 ] = wrapTestInZone ( specDefinitions ) ;
106+ return originaljestFn . apply ( this , arguments ) ;
107+ } ;
108+ } ) ;
0 commit comments