|
9 | 9 | 'use strict'; |
10 | 10 | (() => { |
11 | 11 | const __extends = function(d: any, b: any) { |
12 | | - for (const p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; |
| 12 | + for (const p in b) |
| 13 | + if (b.hasOwnProperty(p)) d[p] = b[p]; |
13 | 14 | function __() { |
14 | 15 | this.constructor = d; |
15 | 16 | } |
16 | | - d.prototype = |
17 | | - b === null |
18 | | - ? Object.create(b) |
19 | | - : ((__.prototype = b.prototype), new (__ as any)()); |
| 17 | + d.prototype = b === null ? Object.create(b) : ((__.prototype = b.prototype), new (__ as any)()); |
20 | 18 | }; |
21 | | - const _global: any = typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global; |
| 19 | + const _global: any = |
| 20 | + typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global; |
22 | 21 | // Patch jasmine's describe/it/beforeEach/afterEach functions so test code always runs |
23 | 22 | // in a testZone (ProxyZone). (See: angular/zone.js#91 & angular/angular#10503) |
24 | 23 | if (!Zone) throw new Error('Missing: zone.js'); |
|
27 | 26 | throw new Error(`'jasmine' has already been patched with 'Zone'.`); |
28 | 27 | (jasmine as any)['__zone_patch__'] = true; |
29 | 28 |
|
30 | | - const SyncTestZoneSpec: { new (name: string): ZoneSpec } = (Zone as any)[ |
31 | | - 'SyncTestZoneSpec' |
32 | | - ]; |
33 | | - const ProxyZoneSpec: { new (): ZoneSpec } = (Zone as any)['ProxyZoneSpec']; |
| 29 | + const SyncTestZoneSpec: {new (name: string): ZoneSpec} = (Zone as any)['SyncTestZoneSpec']; |
| 30 | + const ProxyZoneSpec: {new (): ZoneSpec} = (Zone as any)['ProxyZoneSpec']; |
34 | 31 | if (!SyncTestZoneSpec) throw new Error('Missing: SyncTestZoneSpec'); |
35 | 32 | if (!ProxyZoneSpec) throw new Error('Missing: ProxyZoneSpec'); |
36 | 33 |
|
|
46 | 43 | const jasmineEnv: any = jasmine.getEnv(); |
47 | 44 | ['describe', 'xdescribe', 'fdescribe'].forEach(methodName => { |
48 | 45 | let originalJasmineFn: Function = jasmineEnv[methodName]; |
49 | | - jasmineEnv[methodName] = function( |
50 | | - description: string, |
51 | | - specDefinitions: Function |
52 | | - ) { |
53 | | - return originalJasmineFn.call( |
54 | | - this, |
55 | | - description, |
56 | | - wrapDescribeInZone(specDefinitions) |
57 | | - ); |
| 46 | + jasmineEnv[methodName] = function(description: string, specDefinitions: Function) { |
| 47 | + return originalJasmineFn.call(this, description, wrapDescribeInZone(specDefinitions)); |
58 | 48 | }; |
59 | 49 | }); |
60 | 50 | ['it', 'xit', 'fit'].forEach(methodName => { |
61 | 51 | let originalJasmineFn: Function = jasmineEnv[methodName]; |
62 | 52 | jasmineEnv[symbol(methodName)] = originalJasmineFn; |
63 | 53 | jasmineEnv[methodName] = function( |
64 | | - description: string, |
65 | | - specDefinitions: Function, |
66 | | - timeout: number |
67 | | - ) { |
| 54 | + description: string, specDefinitions: Function, timeout: number) { |
68 | 55 | arguments[1] = wrapTestInZone(specDefinitions); |
69 | 56 | return originalJasmineFn.apply(this, arguments); |
70 | 57 | }; |
71 | 58 | }); |
72 | 59 | ['beforeEach', 'afterEach'].forEach(methodName => { |
73 | 60 | let originalJasmineFn: Function = jasmineEnv[methodName]; |
74 | 61 | jasmineEnv[symbol(methodName)] = originalJasmineFn; |
75 | | - jasmineEnv[methodName] = function( |
76 | | - specDefinitions: Function, |
77 | | - timeout: number |
78 | | - ) { |
| 62 | + jasmineEnv[methodName] = function(specDefinitions: Function, timeout: number) { |
79 | 63 | arguments[0] = wrapTestInZone(specDefinitions); |
80 | 64 | return originalJasmineFn.apply(this, arguments); |
81 | 65 | }; |
82 | 66 | }); |
83 | | - const originalClockFn: Function = ((jasmine as any)[symbol('clock')] = |
84 | | - jasmine['clock']); |
| 67 | + const originalClockFn: Function = ((jasmine as any)[symbol('clock')] = jasmine['clock']); |
85 | 68 | (jasmine as any)['clock'] = function() { |
86 | 69 | const clock = originalClockFn.apply(this, arguments); |
87 | 70 | const originalTick = (clock[symbol('tick')] = clock.tick); |
|
98 | 81 | if (fakeAsyncZoneSpec) { |
99 | 82 | const dateTime = arguments[0]; |
100 | 83 | return fakeAsyncZoneSpec.setCurrentRealTime.apply( |
101 | | - fakeAsyncZoneSpec, |
102 | | - dateTime && typeof dateTime.getTime === 'function' |
103 | | - ? [dateTime.getTime()] |
104 | | - : arguments |
105 | | - ); |
| 84 | + fakeAsyncZoneSpec, |
| 85 | + dateTime && typeof dateTime.getTime === 'function' ? [dateTime.getTime()] : arguments); |
106 | 86 | } |
107 | 87 | return originalMockDate.apply(this, arguments); |
108 | 88 | }; |
109 | 89 | ['install', 'uninstall'].forEach(methodName => { |
110 | | - const originalClockFn: Function = (clock[symbol(methodName)] = |
111 | | - clock[methodName]); |
| 90 | + const originalClockFn: Function = (clock[symbol(methodName)] = clock[methodName]); |
112 | 91 | clock[methodName] = function() { |
113 | 92 | const FakeAsyncTestZoneSpec = (Zone as any)['FakeAsyncTestZoneSpec']; |
114 | 93 | if (FakeAsyncTestZoneSpec) { |
|
131 | 110 | }; |
132 | 111 | } |
133 | 112 |
|
134 | | - function runInTestZone( |
135 | | - testBody: Function, |
136 | | - queueRunner: any, |
137 | | - done?: Function |
138 | | - ) { |
| 113 | + function runInTestZone(testBody: Function, queueRunner: any, done?: Function) { |
139 | 114 | const isClockInstalled = !!(jasmine as any)[symbol('clockInstalled')]; |
140 | 115 | const testProxyZoneSpec = queueRunner.testProxyZoneSpec; |
141 | 116 | const testProxyZone = queueRunner.testProxyZone; |
|
170 | 145 | // The `done` callback is only passed through if the function expects at least one argument. |
171 | 146 | // Note we have to make a function with correct number of arguments, otherwise jasmine will |
172 | 147 | // think that all functions are sync or async. |
173 | | - return ( |
174 | | - testBody && |
175 | | - (testBody.length |
176 | | - ? function(done: Function) { |
177 | | - return runInTestZone(testBody, this.queueRunner, done); |
178 | | - } |
179 | | - : function() { |
180 | | - return runInTestZone(testBody, this.queueRunner); |
181 | | - }) |
182 | | - ); |
| 148 | + return (testBody && (testBody.length ? function(done: Function) { |
| 149 | + return runInTestZone(testBody, this.queueRunner, done); |
| 150 | + } : function() { |
| 151 | + return runInTestZone(testBody, this.queueRunner); |
| 152 | + })); |
183 | 153 | } |
184 | 154 | interface QueueRunner { |
185 | 155 | execute(): void; |
186 | 156 | } |
187 | 157 | interface QueueRunnerAttrs { |
188 | | - queueableFns: { fn: Function }[]; |
| 158 | + queueableFns: {fn: Function}[]; |
189 | 159 | onComplete: () => void; |
190 | 160 | clearStack: (fn: any) => void; |
191 | 161 | onException: (error: any) => void; |
192 | 162 | catchException: () => boolean; |
193 | 163 | userContext: any; |
194 | | - timeout: { setTimeout: Function; clearTimeout: Function }; |
| 164 | + timeout: {setTimeout: Function; clearTimeout: Function}; |
195 | 165 | fail: () => void; |
196 | 166 | } |
197 | 167 |
|
|
201 | 171 | (jasmine as any).QueueRunner = (function(_super) { |
202 | 172 | __extends(ZoneQueueRunner, _super); |
203 | 173 | function ZoneQueueRunner(attrs: { |
204 | | - onComplete: Function; |
205 | | - userContext?: any; |
206 | | - timeout?: { setTimeout: Function; clearTimeout: Function }; |
| 174 | + onComplete: Function; userContext?: any; |
| 175 | + timeout?: {setTimeout: Function; clearTimeout: Function}; |
| 176 | + onException?: (error: any) => void; |
207 | 177 | }) { |
208 | 178 | attrs.onComplete = (fn => () => { |
209 | 179 | // All functions are done, clear the test zone. |
|
221 | 191 | clearTimeout: nativeClearTimeout ? nativeClearTimeout : _global.clearTimeout |
222 | 192 | }; |
223 | 193 | } |
| 194 | + |
224 | 195 | // create a userContext to hold the queueRunner itself |
225 | 196 | // so we can access the testProxy in it/xit/beforeEach ... |
226 | 197 | if ((jasmine as any).UserContext) { |
|
234 | 205 | } |
235 | 206 | attrs.userContext.queueRunner = this; |
236 | 207 | } |
| 208 | + |
| 209 | + // patch attrs.onException |
| 210 | + const onException = attrs.onException; |
| 211 | + attrs.onException = function(error: any) { |
| 212 | + if (error && |
| 213 | + error.message === |
| 214 | + 'Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.') { |
| 215 | + // jasmine timeout, we can make the error message more |
| 216 | + // reasonable to tell what tasks are pending |
| 217 | + const proxyZoneSpec: any = this && this.testProxyZoneSpec; |
| 218 | + if (proxyZoneSpec) { |
| 219 | + const pendingTasksInfo = proxyZoneSpec.getAndClearPendingTasksInfo(); |
| 220 | + error.message += pendingTasksInfo; |
| 221 | + } |
| 222 | + } |
| 223 | + if (onException) { |
| 224 | + onException.call(this, error); |
| 225 | + } |
| 226 | + }; |
| 227 | + |
237 | 228 | _super.call(this, attrs); |
238 | 229 | } |
239 | 230 | ZoneQueueRunner.prototype.execute = function() { |
|
247 | 238 | zone = zone.parent; |
248 | 239 | } |
249 | 240 |
|
250 | | - if (!isChildOfAmbientZone) |
251 | | - throw new Error('Unexpected Zone: ' + Zone.current.name); |
| 241 | + if (!isChildOfAmbientZone) throw new Error('Unexpected Zone: ' + Zone.current.name); |
252 | 242 |
|
253 | 243 | // This is the zone which will be used for running individual tests. |
254 | 244 | // It will be a proxy zone, so that the tests function can retroactively install |
|
268 | 258 | // addEventListener callback would think that it is the top most task and would |
269 | 259 | // drain the microtask queue on element.click() which would be incorrect. |
270 | 260 | // For this reason we always force a task when running jasmine tests. |
271 | | - Zone.current.scheduleMicroTask('jasmine.execute().forceTask', () => |
272 | | - QueueRunner.prototype.execute.call(this) |
273 | | - ); |
| 261 | + Zone.current.scheduleMicroTask( |
| 262 | + 'jasmine.execute().forceTask', () => QueueRunner.prototype.execute.call(this)); |
274 | 263 | } else { |
275 | 264 | _super.prototype.execute.call(this); |
276 | 265 | } |
|
0 commit comments