|
35 | 35 | // a `beforeEach` or `it`. |
36 | 36 | const syncZone = ambientZone.fork(new SyncTestZoneSpec('jasmine.describe')); |
37 | 37 |
|
| 38 | + const symbol = Zone.__symbol__; |
| 39 | + |
38 | 40 | // This is the zone which will be used for running individual tests. |
39 | 41 | // It will be a proxy zone, so that the tests function can retroactively install |
40 | 42 | // different zones. |
|
45 | 47 | // - Because ProxyZone is parent fo `childZone` fakeAsync can retroactively add |
46 | 48 | // fakeAsync behavior to the childZone. |
47 | 49 | let testProxyZone: Zone = null; |
| 50 | + let testProxyZoneSpec: ZoneSpec = null; |
48 | 51 |
|
49 | 52 | // Monkey patch all of the jasmine DSL so that each function runs in appropriate zone. |
50 | 53 | const jasmineEnv: any = jasmine.getEnv(); |
|
56 | 59 | }); |
57 | 60 | ['it', 'xit', 'fit'].forEach((methodName) => { |
58 | 61 | let originalJasmineFn: Function = jasmineEnv[methodName]; |
59 | | - jasmineEnv[Zone.__symbol__(methodName)] = originalJasmineFn; |
| 62 | + jasmineEnv[symbol(methodName)] = originalJasmineFn; |
60 | 63 | jasmineEnv[methodName] = function( |
61 | 64 | description: string, specDefinitions: Function, timeout: number) { |
62 | 65 | arguments[1] = wrapTestInZone(specDefinitions); |
|
65 | 68 | }); |
66 | 69 | ['beforeEach', 'afterEach'].forEach((methodName) => { |
67 | 70 | let originalJasmineFn: Function = jasmineEnv[methodName]; |
68 | | - jasmineEnv[Zone.__symbol__(methodName)] = originalJasmineFn; |
| 71 | + jasmineEnv[symbol(methodName)] = originalJasmineFn; |
69 | 72 | jasmineEnv[methodName] = function(specDefinitions: Function, timeout: number) { |
70 | 73 | arguments[0] = wrapTestInZone(specDefinitions); |
71 | 74 | return originalJasmineFn.apply(this, arguments); |
72 | 75 | }; |
73 | 76 | }); |
| 77 | + const originalClockFn: Function = (jasmine as any)[symbol('clock')] = jasmine['clock']; |
| 78 | + (jasmine as any)['clock'] = function() { |
| 79 | + const clock = originalClockFn.apply(this, arguments); |
| 80 | + const originalTick = clock[symbol('tick')] = clock.tick; |
| 81 | + clock.tick = function() { |
| 82 | + const fakeAsyncZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); |
| 83 | + if (fakeAsyncZoneSpec) { |
| 84 | + return fakeAsyncZoneSpec.tick.apply(fakeAsyncZoneSpec, arguments); |
| 85 | + } |
| 86 | + return originalTick.apply(this, arguments); |
| 87 | + }; |
| 88 | + const originalMockDate = clock[symbol('mockDate')] = clock.mockDate; |
| 89 | + clock.mockDate = function() { |
| 90 | + const fakeAsyncZoneSpec = Zone.current.get('FakeAsyncTestZoneSpec'); |
| 91 | + if (fakeAsyncZoneSpec) { |
| 92 | + const dateTime = arguments[0]; |
| 93 | + return fakeAsyncZoneSpec.setCurrentRealTime.apply(fakeAsyncZoneSpec, dateTime && typeof dateTime.getTime === 'function' ? [dateTime.getTime()] : arguments); |
| 94 | + } |
| 95 | + return originalMockDate.apply(this, arguments); |
| 96 | + }; |
| 97 | + ['install', 'uninstall'].forEach(methodName => { |
| 98 | + const originalClockFn: Function = clock[symbol(methodName)] = clock[methodName]; |
| 99 | + clock[methodName] = function() { |
| 100 | + const FakeAsyncTestZoneSpec = (Zone as any)['FakeAsyncTestZoneSpec']; |
| 101 | + if (FakeAsyncTestZoneSpec) { |
| 102 | + (jasmine as any)[symbol('clockInstalled')] = 'install' === methodName; |
| 103 | + return; |
| 104 | + } |
| 105 | + return originalClockFn.apply(this, arguments); |
| 106 | + }; |
| 107 | + }); |
| 108 | + return clock; |
| 109 | + }; |
74 | 110 |
|
75 | 111 | /** |
76 | 112 | * Gets a function wrapping the body of a Jasmine `describe` block to execute in a |
|
82 | 118 | }; |
83 | 119 | } |
84 | 120 |
|
| 121 | + function runInTestZone(testBody: Function, done?: Function) { |
| 122 | + const isClockInstalled = !!(jasmine as any)[symbol('clockInstalled')]; |
| 123 | + let lastDelegate; |
| 124 | + if (isClockInstalled) { |
| 125 | + const FakeAsyncTestZoneSpec = (Zone as any)['FakeAsyncTestZoneSpec']; |
| 126 | + if (FakeAsyncTestZoneSpec) { |
| 127 | + const _fakeAsyncTestZoneSpec = new FakeAsyncTestZoneSpec(); |
| 128 | + lastDelegate = (testProxyZoneSpec as any).getDelegate(); |
| 129 | + (testProxyZoneSpec as any).setDelegate(_fakeAsyncTestZoneSpec); |
| 130 | + } |
| 131 | + } |
| 132 | + try { |
| 133 | + if (done) { |
| 134 | + return testProxyZone.run(testBody, this, [done]); |
| 135 | + } else { |
| 136 | + return testProxyZone.run(testBody, this); |
| 137 | + } |
| 138 | + } finally { |
| 139 | + if (isClockInstalled) { |
| 140 | + (testProxyZoneSpec as any).setDelegate(lastDelegate); |
| 141 | + } |
| 142 | + } |
| 143 | + } |
| 144 | + |
85 | 145 | /** |
86 | 146 | * Gets a function wrapping the body of a Jasmine `it/beforeEach/afterEach` block to |
87 | 147 | * execute in a ProxyZone zone. |
|
92 | 152 | // Note we have to make a function with correct number of arguments, otherwise jasmine will |
93 | 153 | // think that all functions are sync or async. |
94 | 154 | return testBody && (testBody.length ? function(done: Function) { |
95 | | - return testProxyZone.run(testBody, this, [done]); |
| 155 | + runInTestZone(testBody, done); |
96 | 156 | } : function() { |
97 | | - return testProxyZone.run(testBody, this); |
| 157 | + runInTestZone(testBody); |
98 | 158 | }); |
99 | 159 | } |
100 | 160 | interface QueueRunner { |
|
118 | 178 | attrs.onComplete = ((fn) => () => { |
119 | 179 | // All functions are done, clear the test zone. |
120 | 180 | testProxyZone = null; |
| 181 | + testProxyZoneSpec = null; |
121 | 182 | ambientZone.scheduleMicroTask('jasmine.onComplete', fn); |
122 | 183 | })(attrs.onComplete); |
123 | 184 | _super.call(this, attrs); |
124 | 185 | } |
125 | 186 | ZoneQueueRunner.prototype.execute = function() { |
126 | 187 | if (Zone.current !== ambientZone) throw new Error('Unexpected Zone: ' + Zone.current.name); |
127 | | - testProxyZone = ambientZone.fork(new ProxyZoneSpec()); |
| 188 | + testProxyZoneSpec = new ProxyZoneSpec(); |
| 189 | + testProxyZone = ambientZone.fork(testProxyZoneSpec); |
128 | 190 | if (!Zone.currentTask) { |
129 | 191 | // if we are not running in a task then if someone would register a |
130 | 192 | // element.addEventListener and then calling element.click() the |
|
0 commit comments