|
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