UNPKG

107 kBJavaScriptView Raw
1/**
2 * @license Angular v13.0.2
3 * (c) 2010-2021 Google LLC. https://angular.io/
4 * License: MIT
5 */
6
7import * as i0 from '@angular/core';
8import { getDebugNode, RendererFactory2, ɵstringify, ɵReflectionCapabilities, Directive, Component, Pipe, NgModule, ɵgetInjectableDef, resolveForwardRef, ɵNG_COMP_DEF, ɵRender3NgModuleRef, ApplicationInitStatus, LOCALE_ID, ɵDEFAULT_LOCALE_ID, ɵsetLocaleId, ɵRender3ComponentFactory, ɵcompileComponent, ɵNG_DIR_DEF, ɵcompileDirective, ɵNG_PIPE_DEF, ɵcompilePipe, ɵNG_MOD_DEF, ɵtransitiveScopesFor, ɵpatchComponentDefWithScope, ɵNG_INJ_DEF, ɵcompileNgModuleDefs, NgZone, Compiler, COMPILER_OPTIONS, ɵNgModuleFactory, ModuleWithComponentFactories, InjectionToken, Injector, InjectFlags, ɵresetCompiledComponents, ɵflushModuleScopingQueueAsMuchAsPossible, Injectable, ɵclearOverrides, ɵoverrideComponentView, ɵINJECTOR_SCOPE, Optional, SkipSelf, ɵoverrideProvider, ɵivyEnabled } from '@angular/core';
9import { __decorate } from 'tslib';
10import { ResourceLoader } from '@angular/compiler';
11
12/**
13 * @license
14 * Copyright Google LLC All Rights Reserved.
15 *
16 * Use of this source code is governed by an MIT-style license that can be
17 * found in the LICENSE file at https://angular.io/license
18 */
19/**
20 * Wraps a test function in an asynchronous test zone. The test will automatically
21 * complete when all asynchronous calls within this zone are done. Can be used
22 * to wrap an {@link inject} call.
23 *
24 * Example:
25 *
26 * ```
27 * it('...', waitForAsync(inject([AClass], (object) => {
28 * object.doSomething.then(() => {
29 * expect(...);
30 * })
31 * });
32 * ```
33 *
34 * @publicApi
35 */
36function waitForAsync(fn) {
37 const _Zone = typeof Zone !== 'undefined' ? Zone : null;
38 if (!_Zone) {
39 return function () {
40 return Promise.reject('Zone is needed for the waitForAsync() test helper but could not be found. ' +
41 'Please make sure that your environment includes zone.js');
42 };
43 }
44 const asyncTest = _Zone && _Zone[_Zone.__symbol__('asyncTest')];
45 if (typeof asyncTest === 'function') {
46 return asyncTest(fn);
47 }
48 return function () {
49 return Promise.reject('zone-testing.js is needed for the async() test helper but could not be found. ' +
50 'Please make sure that your environment includes zone.js/testing');
51 };
52}
53/**
54 * @deprecated use `waitForAsync()`, (expected removal in v12)
55 * @see {@link waitForAsync}
56 * @publicApi
57 * */
58function async(fn) {
59 return waitForAsync(fn);
60}
61
62/**
63 * @license
64 * Copyright Google LLC All Rights Reserved.
65 *
66 * Use of this source code is governed by an MIT-style license that can be
67 * found in the LICENSE file at https://angular.io/license
68 */
69/**
70 * Fixture for debugging and testing a component.
71 *
72 * @publicApi
73 */
74class ComponentFixture {
75 constructor(componentRef, ngZone, _autoDetect) {
76 this.componentRef = componentRef;
77 this.ngZone = ngZone;
78 this._autoDetect = _autoDetect;
79 this._isStable = true;
80 this._isDestroyed = false;
81 this._resolve = null;
82 this._promise = null;
83 this._onUnstableSubscription = null;
84 this._onStableSubscription = null;
85 this._onMicrotaskEmptySubscription = null;
86 this._onErrorSubscription = null;
87 this.changeDetectorRef = componentRef.changeDetectorRef;
88 this.elementRef = componentRef.location;
89 this.debugElement = getDebugNode(this.elementRef.nativeElement);
90 this.componentInstance = componentRef.instance;
91 this.nativeElement = this.elementRef.nativeElement;
92 this.componentRef = componentRef;
93 this.ngZone = ngZone;
94 if (ngZone) {
95 // Create subscriptions outside the NgZone so that the callbacks run oustide
96 // of NgZone.
97 ngZone.runOutsideAngular(() => {
98 this._onUnstableSubscription = ngZone.onUnstable.subscribe({
99 next: () => {
100 this._isStable = false;
101 }
102 });
103 this._onMicrotaskEmptySubscription = ngZone.onMicrotaskEmpty.subscribe({
104 next: () => {
105 if (this._autoDetect) {
106 // Do a change detection run with checkNoChanges set to true to check
107 // there are no changes on the second run.
108 this.detectChanges(true);
109 }
110 }
111 });
112 this._onStableSubscription = ngZone.onStable.subscribe({
113 next: () => {
114 this._isStable = true;
115 // Check whether there is a pending whenStable() completer to resolve.
116 if (this._promise !== null) {
117 // If so check whether there are no pending macrotasks before resolving.
118 // Do this check in the next tick so that ngZone gets a chance to update the state of
119 // pending macrotasks.
120 scheduleMicroTask(() => {
121 if (!ngZone.hasPendingMacrotasks) {
122 if (this._promise !== null) {
123 this._resolve(true);
124 this._resolve = null;
125 this._promise = null;
126 }
127 }
128 });
129 }
130 }
131 });
132 this._onErrorSubscription = ngZone.onError.subscribe({
133 next: (error) => {
134 throw error;
135 }
136 });
137 });
138 }
139 }
140 _tick(checkNoChanges) {
141 this.changeDetectorRef.detectChanges();
142 if (checkNoChanges) {
143 this.checkNoChanges();
144 }
145 }
146 /**
147 * Trigger a change detection cycle for the component.
148 */
149 detectChanges(checkNoChanges = true) {
150 if (this.ngZone != null) {
151 // Run the change detection inside the NgZone so that any async tasks as part of the change
152 // detection are captured by the zone and can be waited for in isStable.
153 this.ngZone.run(() => {
154 this._tick(checkNoChanges);
155 });
156 }
157 else {
158 // Running without zone. Just do the change detection.
159 this._tick(checkNoChanges);
160 }
161 }
162 /**
163 * Do a change detection run to make sure there were no changes.
164 */
165 checkNoChanges() {
166 this.changeDetectorRef.checkNoChanges();
167 }
168 /**
169 * Set whether the fixture should autodetect changes.
170 *
171 * Also runs detectChanges once so that any existing change is detected.
172 */
173 autoDetectChanges(autoDetect = true) {
174 if (this.ngZone == null) {
175 throw new Error('Cannot call autoDetectChanges when ComponentFixtureNoNgZone is set');
176 }
177 this._autoDetect = autoDetect;
178 this.detectChanges();
179 }
180 /**
181 * Return whether the fixture is currently stable or has async tasks that have not been completed
182 * yet.
183 */
184 isStable() {
185 return this._isStable && !this.ngZone.hasPendingMacrotasks;
186 }
187 /**
188 * Get a promise that resolves when the fixture is stable.
189 *
190 * This can be used to resume testing after events have triggered asynchronous activity or
191 * asynchronous change detection.
192 */
193 whenStable() {
194 if (this.isStable()) {
195 return Promise.resolve(false);
196 }
197 else if (this._promise !== null) {
198 return this._promise;
199 }
200 else {
201 this._promise = new Promise(res => {
202 this._resolve = res;
203 });
204 return this._promise;
205 }
206 }
207 _getRenderer() {
208 if (this._renderer === undefined) {
209 this._renderer = this.componentRef.injector.get(RendererFactory2, null);
210 }
211 return this._renderer;
212 }
213 /**
214 * Get a promise that resolves when the ui state is stable following animations.
215 */
216 whenRenderingDone() {
217 const renderer = this._getRenderer();
218 if (renderer && renderer.whenRenderingDone) {
219 return renderer.whenRenderingDone();
220 }
221 return this.whenStable();
222 }
223 /**
224 * Trigger component destruction.
225 */
226 destroy() {
227 if (!this._isDestroyed) {
228 this.componentRef.destroy();
229 if (this._onUnstableSubscription != null) {
230 this._onUnstableSubscription.unsubscribe();
231 this._onUnstableSubscription = null;
232 }
233 if (this._onStableSubscription != null) {
234 this._onStableSubscription.unsubscribe();
235 this._onStableSubscription = null;
236 }
237 if (this._onMicrotaskEmptySubscription != null) {
238 this._onMicrotaskEmptySubscription.unsubscribe();
239 this._onMicrotaskEmptySubscription = null;
240 }
241 if (this._onErrorSubscription != null) {
242 this._onErrorSubscription.unsubscribe();
243 this._onErrorSubscription = null;
244 }
245 this._isDestroyed = true;
246 }
247 }
248}
249function scheduleMicroTask(fn) {
250 Zone.current.scheduleMicroTask('scheduleMicrotask', fn);
251}
252
253/**
254 * @license
255 * Copyright Google LLC All Rights Reserved.
256 *
257 * Use of this source code is governed by an MIT-style license that can be
258 * found in the LICENSE file at https://angular.io/license
259 */
260const _Zone = typeof Zone !== 'undefined' ? Zone : null;
261const fakeAsyncTestModule = _Zone && _Zone[_Zone.__symbol__('fakeAsyncTest')];
262const fakeAsyncTestModuleNotLoadedErrorMessage = `zone-testing.js is needed for the fakeAsync() test helper but could not be found.
263 Please make sure that your environment includes zone.js/testing`;
264/**
265 * Clears out the shared fake async zone for a test.
266 * To be called in a global `beforeEach`.
267 *
268 * @publicApi
269 */
270function resetFakeAsyncZone() {
271 if (fakeAsyncTestModule) {
272 return fakeAsyncTestModule.resetFakeAsyncZone();
273 }
274 throw new Error(fakeAsyncTestModuleNotLoadedErrorMessage);
275}
276/**
277 * Wraps a function to be executed in the `fakeAsync` zone:
278 * - Microtasks are manually executed by calling `flushMicrotasks()`.
279 * - Timers are synchronous; `tick()` simulates the asynchronous passage of time.
280 *
281 * If there are any pending timers at the end of the function, an exception is thrown.
282 *
283 * Can be used to wrap `inject()` calls.
284 *
285 * @param fn The function that you want to wrap in the `fakeAysnc` zone.
286 *
287 * @usageNotes
288 * ### Example
289 *
290 * {@example core/testing/ts/fake_async.ts region='basic'}
291 *
292 *
293 * @returns The function wrapped to be executed in the `fakeAsync` zone.
294 * Any arguments passed when calling this returned function will be passed through to the `fn`
295 * function in the parameters when it is called.
296 *
297 * @publicApi
298 */
299function fakeAsync(fn) {
300 if (fakeAsyncTestModule) {
301 return fakeAsyncTestModule.fakeAsync(fn);
302 }
303 throw new Error(fakeAsyncTestModuleNotLoadedErrorMessage);
304}
305/**
306 * Simulates the asynchronous passage of time for the timers in the `fakeAsync` zone.
307 *
308 * The microtasks queue is drained at the very start of this function and after any timer callback
309 * has been executed.
310 *
311 * @param millis The number of milliseconds to advance the virtual timer.
312 * @param tickOptions The options to pass to the `tick()` function.
313 *
314 * @usageNotes
315 *
316 * The `tick()` option is a flag called `processNewMacroTasksSynchronously`,
317 * which determines whether or not to invoke new macroTasks.
318 *
319 * If you provide a `tickOptions` object, but do not specify a
320 * `processNewMacroTasksSynchronously` property (`tick(100, {})`),
321 * then `processNewMacroTasksSynchronously` defaults to true.
322 *
323 * If you omit the `tickOptions` parameter (`tick(100))`), then
324 * `tickOptions` defaults to `{processNewMacroTasksSynchronously: true}`.
325 *
326 * ### Example
327 *
328 * {@example core/testing/ts/fake_async.ts region='basic'}
329 *
330 * The following example includes a nested timeout (new macroTask), and
331 * the `tickOptions` parameter is allowed to default. In this case,
332 * `processNewMacroTasksSynchronously` defaults to true, and the nested
333 * function is executed on each tick.
334 *
335 * ```
336 * it ('test with nested setTimeout', fakeAsync(() => {
337 * let nestedTimeoutInvoked = false;
338 * function funcWithNestedTimeout() {
339 * setTimeout(() => {
340 * nestedTimeoutInvoked = true;
341 * });
342 * };
343 * setTimeout(funcWithNestedTimeout);
344 * tick();
345 * expect(nestedTimeoutInvoked).toBe(true);
346 * }));
347 * ```
348 *
349 * In the following case, `processNewMacroTasksSynchronously` is explicitly
350 * set to false, so the nested timeout function is not invoked.
351 *
352 * ```
353 * it ('test with nested setTimeout', fakeAsync(() => {
354 * let nestedTimeoutInvoked = false;
355 * function funcWithNestedTimeout() {
356 * setTimeout(() => {
357 * nestedTimeoutInvoked = true;
358 * });
359 * };
360 * setTimeout(funcWithNestedTimeout);
361 * tick(0, {processNewMacroTasksSynchronously: false});
362 * expect(nestedTimeoutInvoked).toBe(false);
363 * }));
364 * ```
365 *
366 *
367 * @publicApi
368 */
369function tick(millis = 0, tickOptions = {
370 processNewMacroTasksSynchronously: true
371}) {
372 if (fakeAsyncTestModule) {
373 return fakeAsyncTestModule.tick(millis, tickOptions);
374 }
375 throw new Error(fakeAsyncTestModuleNotLoadedErrorMessage);
376}
377/**
378 * Simulates the asynchronous passage of time for the timers in the `fakeAsync` zone by
379 * draining the macrotask queue until it is empty.
380 *
381 * @param maxTurns The maximum number of times the scheduler attempts to clear its queue before
382 * throwing an error.
383 * @returns The simulated time elapsed, in milliseconds.
384 *
385 * @publicApi
386 */
387function flush(maxTurns) {
388 if (fakeAsyncTestModule) {
389 return fakeAsyncTestModule.flush(maxTurns);
390 }
391 throw new Error(fakeAsyncTestModuleNotLoadedErrorMessage);
392}
393/**
394 * Discard all remaining periodic tasks.
395 *
396 * @publicApi
397 */
398function discardPeriodicTasks() {
399 if (fakeAsyncTestModule) {
400 return fakeAsyncTestModule.discardPeriodicTasks();
401 }
402 throw new Error(fakeAsyncTestModuleNotLoadedErrorMessage);
403}
404/**
405 * Flush any pending microtasks.
406 *
407 * @publicApi
408 */
409function flushMicrotasks() {
410 if (fakeAsyncTestModule) {
411 return fakeAsyncTestModule.flushMicrotasks();
412 }
413 throw new Error(fakeAsyncTestModuleNotLoadedErrorMessage);
414}
415
416/**
417 * @license
418 * Copyright Google LLC All Rights Reserved.
419 *
420 * Use of this source code is governed by an MIT-style license that can be
421 * found in the LICENSE file at https://angular.io/license
422 */
423/**
424 * Used to resolve resource URLs on `@Component` when used with JIT compilation.
425 *
426 * Example:
427 * ```
428 * @Component({
429 * selector: 'my-comp',
430 * templateUrl: 'my-comp.html', // This requires asynchronous resolution
431 * })
432 * class MyComponent{
433 * }
434 *
435 * // Calling `renderComponent` will fail because `renderComponent` is a synchronous process
436 * // and `MyComponent`'s `@Component.templateUrl` needs to be resolved asynchronously.
437 *
438 * // Calling `resolveComponentResources()` will resolve `@Component.templateUrl` into
439 * // `@Component.template`, which allows `renderComponent` to proceed in a synchronous manner.
440 *
441 * // Use browser's `fetch()` function as the default resource resolution strategy.
442 * resolveComponentResources(fetch).then(() => {
443 * // After resolution all URLs have been converted into `template` strings.
444 * renderComponent(MyComponent);
445 * });
446 *
447 * ```
448 *
449 * NOTE: In AOT the resolution happens during compilation, and so there should be no need
450 * to call this method outside JIT mode.
451 *
452 * @param resourceResolver a function which is responsible for returning a `Promise` to the
453 * contents of the resolved URL. Browser's `fetch()` method is a good default implementation.
454 */
455function resolveComponentResources(resourceResolver) {
456 // Store all promises which are fetching the resources.
457 const componentResolved = [];
458 // Cache so that we don't fetch the same resource more than once.
459 const urlMap = new Map();
460 function cachedResourceResolve(url) {
461 let promise = urlMap.get(url);
462 if (!promise) {
463 const resp = resourceResolver(url);
464 urlMap.set(url, promise = resp.then(unwrapResponse));
465 }
466 return promise;
467 }
468 componentResourceResolutionQueue.forEach((component, type) => {
469 const promises = [];
470 if (component.templateUrl) {
471 promises.push(cachedResourceResolve(component.templateUrl).then((template) => {
472 component.template = template;
473 }));
474 }
475 const styleUrls = component.styleUrls;
476 const styles = component.styles || (component.styles = []);
477 const styleOffset = component.styles.length;
478 styleUrls && styleUrls.forEach((styleUrl, index) => {
479 styles.push(''); // pre-allocate array.
480 promises.push(cachedResourceResolve(styleUrl).then((style) => {
481 styles[styleOffset + index] = style;
482 styleUrls.splice(styleUrls.indexOf(styleUrl), 1);
483 if (styleUrls.length == 0) {
484 component.styleUrls = undefined;
485 }
486 }));
487 });
488 const fullyResolved = Promise.all(promises).then(() => componentDefResolved(type));
489 componentResolved.push(fullyResolved);
490 });
491 clearResolutionOfComponentResourcesQueue();
492 return Promise.all(componentResolved).then(() => undefined);
493}
494let componentResourceResolutionQueue = new Map();
495// Track when existing ɵcmp for a Type is waiting on resources.
496const componentDefPendingResolution = new Set();
497function maybeQueueResolutionOfComponentResources(type, metadata) {
498 if (componentNeedsResolution(metadata)) {
499 componentResourceResolutionQueue.set(type, metadata);
500 componentDefPendingResolution.add(type);
501 }
502}
503function isComponentDefPendingResolution(type) {
504 return componentDefPendingResolution.has(type);
505}
506function componentNeedsResolution(component) {
507 return !!((component.templateUrl && !component.hasOwnProperty('template')) ||
508 component.styleUrls && component.styleUrls.length);
509}
510function clearResolutionOfComponentResourcesQueue() {
511 const old = componentResourceResolutionQueue;
512 componentResourceResolutionQueue = new Map();
513 return old;
514}
515function restoreComponentResolutionQueue(queue) {
516 componentDefPendingResolution.clear();
517 queue.forEach((_, type) => componentDefPendingResolution.add(type));
518 componentResourceResolutionQueue = queue;
519}
520function isComponentResourceResolutionQueueEmpty() {
521 return componentResourceResolutionQueue.size === 0;
522}
523function unwrapResponse(response) {
524 return typeof response == 'string' ? response : response.text();
525}
526function componentDefResolved(type) {
527 componentDefPendingResolution.delete(type);
528}
529
530/**
531 * @license
532 * Copyright Google LLC All Rights Reserved.
533 *
534 * Use of this source code is governed by an MIT-style license that can be
535 * found in the LICENSE file at https://angular.io/license
536 */
537let _nextReferenceId = 0;
538class MetadataOverrider {
539 constructor() {
540 this._references = new Map();
541 }
542 /**
543 * Creates a new instance for the given metadata class
544 * based on an old instance and overrides.
545 */
546 overrideMetadata(metadataClass, oldMetadata, override) {
547 const props = {};
548 if (oldMetadata) {
549 _valueProps(oldMetadata).forEach((prop) => props[prop] = oldMetadata[prop]);
550 }
551 if (override.set) {
552 if (override.remove || override.add) {
553 throw new Error(`Cannot set and add/remove ${ɵstringify(metadataClass)} at the same time!`);
554 }
555 setMetadata(props, override.set);
556 }
557 if (override.remove) {
558 removeMetadata(props, override.remove, this._references);
559 }
560 if (override.add) {
561 addMetadata(props, override.add);
562 }
563 return new metadataClass(props);
564 }
565}
566function removeMetadata(metadata, remove, references) {
567 const removeObjects = new Set();
568 for (const prop in remove) {
569 const removeValue = remove[prop];
570 if (Array.isArray(removeValue)) {
571 removeValue.forEach((value) => {
572 removeObjects.add(_propHashKey(prop, value, references));
573 });
574 }
575 else {
576 removeObjects.add(_propHashKey(prop, removeValue, references));
577 }
578 }
579 for (const prop in metadata) {
580 const propValue = metadata[prop];
581 if (Array.isArray(propValue)) {
582 metadata[prop] = propValue.filter((value) => !removeObjects.has(_propHashKey(prop, value, references)));
583 }
584 else {
585 if (removeObjects.has(_propHashKey(prop, propValue, references))) {
586 metadata[prop] = undefined;
587 }
588 }
589 }
590}
591function addMetadata(metadata, add) {
592 for (const prop in add) {
593 const addValue = add[prop];
594 const propValue = metadata[prop];
595 if (propValue != null && Array.isArray(propValue)) {
596 metadata[prop] = propValue.concat(addValue);
597 }
598 else {
599 metadata[prop] = addValue;
600 }
601 }
602}
603function setMetadata(metadata, set) {
604 for (const prop in set) {
605 metadata[prop] = set[prop];
606 }
607}
608function _propHashKey(propName, propValue, references) {
609 const replacer = (key, value) => {
610 if (typeof value === 'function') {
611 value = _serializeReference(value, references);
612 }
613 return value;
614 };
615 return `${propName}:${JSON.stringify(propValue, replacer)}`;
616}
617function _serializeReference(ref, references) {
618 let id = references.get(ref);
619 if (!id) {
620 id = `${ɵstringify(ref)}${_nextReferenceId++}`;
621 references.set(ref, id);
622 }
623 return id;
624}
625function _valueProps(obj) {
626 const props = [];
627 // regular public props
628 Object.keys(obj).forEach((prop) => {
629 if (!prop.startsWith('_')) {
630 props.push(prop);
631 }
632 });
633 // getters
634 let proto = obj;
635 while (proto = Object.getPrototypeOf(proto)) {
636 Object.keys(proto).forEach((protoProp) => {
637 const desc = Object.getOwnPropertyDescriptor(proto, protoProp);
638 if (!protoProp.startsWith('_') && desc && 'get' in desc) {
639 props.push(protoProp);
640 }
641 });
642 }
643 return props;
644}
645
646/**
647 * @license
648 * Copyright Google LLC All Rights Reserved.
649 *
650 * Use of this source code is governed by an MIT-style license that can be
651 * found in the LICENSE file at https://angular.io/license
652 */
653const reflection = new ɵReflectionCapabilities();
654/**
655 * Allows to override ivy metadata for tests (via the `TestBed`).
656 */
657class OverrideResolver {
658 constructor() {
659 this.overrides = new Map();
660 this.resolved = new Map();
661 }
662 addOverride(type, override) {
663 const overrides = this.overrides.get(type) || [];
664 overrides.push(override);
665 this.overrides.set(type, overrides);
666 this.resolved.delete(type);
667 }
668 setOverrides(overrides) {
669 this.overrides.clear();
670 overrides.forEach(([type, override]) => {
671 this.addOverride(type, override);
672 });
673 }
674 getAnnotation(type) {
675 const annotations = reflection.annotations(type);
676 // Try to find the nearest known Type annotation and make sure that this annotation is an
677 // instance of the type we are looking for, so we can use it for resolution. Note: there might
678 // be multiple known annotations found due to the fact that Components can extend Directives (so
679 // both Directive and Component annotations would be present), so we always check if the known
680 // annotation has the right type.
681 for (let i = annotations.length - 1; i >= 0; i--) {
682 const annotation = annotations[i];
683 const isKnownType = annotation instanceof Directive || annotation instanceof Component ||
684 annotation instanceof Pipe || annotation instanceof NgModule;
685 if (isKnownType) {
686 return annotation instanceof this.type ? annotation : null;
687 }
688 }
689 return null;
690 }
691 resolve(type) {
692 let resolved = this.resolved.get(type) || null;
693 if (!resolved) {
694 resolved = this.getAnnotation(type);
695 if (resolved) {
696 const overrides = this.overrides.get(type);
697 if (overrides) {
698 const overrider = new MetadataOverrider();
699 overrides.forEach(override => {
700 resolved = overrider.overrideMetadata(this.type, resolved, override);
701 });
702 }
703 }
704 this.resolved.set(type, resolved);
705 }
706 return resolved;
707 }
708}
709class DirectiveResolver extends OverrideResolver {
710 get type() {
711 return Directive;
712 }
713}
714class ComponentResolver extends OverrideResolver {
715 get type() {
716 return Component;
717 }
718}
719class PipeResolver extends OverrideResolver {
720 get type() {
721 return Pipe;
722 }
723}
724class NgModuleResolver extends OverrideResolver {
725 get type() {
726 return NgModule;
727 }
728}
729
730/**
731 * @license
732 * Copyright Google LLC All Rights Reserved.
733 *
734 * Use of this source code is governed by an MIT-style license that can be
735 * found in the LICENSE file at https://angular.io/license
736 */
737var TestingModuleOverride;
738(function (TestingModuleOverride) {
739 TestingModuleOverride[TestingModuleOverride["DECLARATION"] = 0] = "DECLARATION";
740 TestingModuleOverride[TestingModuleOverride["OVERRIDE_TEMPLATE"] = 1] = "OVERRIDE_TEMPLATE";
741})(TestingModuleOverride || (TestingModuleOverride = {}));
742function isTestingModuleOverride(value) {
743 return value === TestingModuleOverride.DECLARATION ||
744 value === TestingModuleOverride.OVERRIDE_TEMPLATE;
745}
746class R3TestBedCompiler {
747 constructor(platform, additionalModuleTypes) {
748 this.platform = platform;
749 this.additionalModuleTypes = additionalModuleTypes;
750 this.originalComponentResolutionQueue = null;
751 // Testing module configuration
752 this.declarations = [];
753 this.imports = [];
754 this.providers = [];
755 this.schemas = [];
756 // Queues of components/directives/pipes that should be recompiled.
757 this.pendingComponents = new Set();
758 this.pendingDirectives = new Set();
759 this.pendingPipes = new Set();
760 // Keep track of all components and directives, so we can patch Providers onto defs later.
761 this.seenComponents = new Set();
762 this.seenDirectives = new Set();
763 // Keep track of overridden modules, so that we can collect all affected ones in the module tree.
764 this.overriddenModules = new Set();
765 // Store resolved styles for Components that have template overrides present and `styleUrls`
766 // defined at the same time.
767 this.existingComponentStyles = new Map();
768 this.resolvers = initResolvers();
769 this.componentToModuleScope = new Map();
770 // Map that keeps initial version of component/directive/pipe defs in case
771 // we compile a Type again, thus overriding respective static fields. This is
772 // required to make sure we restore defs to their initial states between test runs
773 // TODO: we should support the case with multiple defs on a type
774 this.initialNgDefs = new Map();
775 // Array that keeps cleanup operations for initial versions of component/directive/pipe/module
776 // defs in case TestBed makes changes to the originals.
777 this.defCleanupOps = [];
778 this._injector = null;
779 this.compilerProviders = null;
780 this.providerOverrides = [];
781 this.rootProviderOverrides = [];
782 // Overrides for injectables with `{providedIn: SomeModule}` need to be tracked and added to that
783 // module's provider list.
784 this.providerOverridesByModule = new Map();
785 this.providerOverridesByToken = new Map();
786 this.moduleProvidersOverridden = new Set();
787 this.testModuleRef = null;
788 class DynamicTestModule {
789 }
790 this.testModuleType = DynamicTestModule;
791 }
792 setCompilerProviders(providers) {
793 this.compilerProviders = providers;
794 this._injector = null;
795 }
796 configureTestingModule(moduleDef) {
797 // Enqueue any compilation tasks for the directly declared component.
798 if (moduleDef.declarations !== undefined) {
799 this.queueTypeArray(moduleDef.declarations, TestingModuleOverride.DECLARATION);
800 this.declarations.push(...moduleDef.declarations);
801 }
802 // Enqueue any compilation tasks for imported modules.
803 if (moduleDef.imports !== undefined) {
804 this.queueTypesFromModulesArray(moduleDef.imports);
805 this.imports.push(...moduleDef.imports);
806 }
807 if (moduleDef.providers !== undefined) {
808 this.providers.push(...moduleDef.providers);
809 }
810 if (moduleDef.schemas !== undefined) {
811 this.schemas.push(...moduleDef.schemas);
812 }
813 }
814 overrideModule(ngModule, override) {
815 this.overriddenModules.add(ngModule);
816 // Compile the module right away.
817 this.resolvers.module.addOverride(ngModule, override);
818 const metadata = this.resolvers.module.resolve(ngModule);
819 if (metadata === null) {
820 throw invalidTypeError(ngModule.name, 'NgModule');
821 }
822 this.recompileNgModule(ngModule, metadata);
823 // At this point, the module has a valid module def (ɵmod), but the override may have introduced
824 // new declarations or imported modules. Ingest any possible new types and add them to the
825 // current queue.
826 this.queueTypesFromModulesArray([ngModule]);
827 }
828 overrideComponent(component, override) {
829 this.resolvers.component.addOverride(component, override);
830 this.pendingComponents.add(component);
831 }
832 overrideDirective(directive, override) {
833 this.resolvers.directive.addOverride(directive, override);
834 this.pendingDirectives.add(directive);
835 }
836 overridePipe(pipe, override) {
837 this.resolvers.pipe.addOverride(pipe, override);
838 this.pendingPipes.add(pipe);
839 }
840 overrideProvider(token, provider) {
841 let providerDef;
842 if (provider.useFactory !== undefined) {
843 providerDef = {
844 provide: token,
845 useFactory: provider.useFactory,
846 deps: provider.deps || [],
847 multi: provider.multi
848 };
849 }
850 else if (provider.useValue !== undefined) {
851 providerDef = { provide: token, useValue: provider.useValue, multi: provider.multi };
852 }
853 else {
854 providerDef = { provide: token };
855 }
856 const injectableDef = typeof token !== 'string' ? ɵgetInjectableDef(token) : null;
857 const providedIn = injectableDef === null ? null : resolveForwardRef(injectableDef.providedIn);
858 const overridesBucket = providedIn === 'root' ? this.rootProviderOverrides : this.providerOverrides;
859 overridesBucket.push(providerDef);
860 // Keep overrides grouped by token as well for fast lookups using token
861 this.providerOverridesByToken.set(token, providerDef);
862 if (injectableDef !== null && providedIn !== null && typeof providedIn !== 'string') {
863 const existingOverrides = this.providerOverridesByModule.get(providedIn);
864 if (existingOverrides !== undefined) {
865 existingOverrides.push(providerDef);
866 }
867 else {
868 this.providerOverridesByModule.set(providedIn, [providerDef]);
869 }
870 }
871 }
872 overrideTemplateUsingTestingModule(type, template) {
873 const def = type[ɵNG_COMP_DEF];
874 const hasStyleUrls = () => {
875 const metadata = this.resolvers.component.resolve(type);
876 return !!metadata.styleUrls && metadata.styleUrls.length > 0;
877 };
878 const overrideStyleUrls = !!def && !isComponentDefPendingResolution(type) && hasStyleUrls();
879 // In Ivy, compiling a component does not require knowing the module providing the
880 // component's scope, so overrideTemplateUsingTestingModule can be implemented purely via
881 // overrideComponent. Important: overriding template requires full Component re-compilation,
882 // which may fail in case styleUrls are also present (thus Component is considered as required
883 // resolution). In order to avoid this, we preemptively set styleUrls to an empty array,
884 // preserve current styles available on Component def and restore styles back once compilation
885 // is complete.
886 const override = overrideStyleUrls ? { template, styles: [], styleUrls: [] } : { template };
887 this.overrideComponent(type, { set: override });
888 if (overrideStyleUrls && def.styles && def.styles.length > 0) {
889 this.existingComponentStyles.set(type, def.styles);
890 }
891 // Set the component's scope to be the testing module.
892 this.componentToModuleScope.set(type, TestingModuleOverride.OVERRIDE_TEMPLATE);
893 }
894 async compileComponents() {
895 this.clearComponentResolutionQueue();
896 // Run compilers for all queued types.
897 let needsAsyncResources = this.compileTypesSync();
898 // compileComponents() should not be async unless it needs to be.
899 if (needsAsyncResources) {
900 let resourceLoader;
901 let resolver = (url) => {
902 if (!resourceLoader) {
903 resourceLoader = this.injector.get(ResourceLoader);
904 }
905 return Promise.resolve(resourceLoader.get(url));
906 };
907 await resolveComponentResources(resolver);
908 }
909 }
910 finalize() {
911 // One last compile
912 this.compileTypesSync();
913 // Create the testing module itself.
914 this.compileTestModule();
915 this.applyTransitiveScopes();
916 this.applyProviderOverrides();
917 // Patch previously stored `styles` Component values (taken from ɵcmp), in case these
918 // Components have `styleUrls` fields defined and template override was requested.
919 this.patchComponentsWithExistingStyles();
920 // Clear the componentToModuleScope map, so that future compilations don't reset the scope of
921 // every component.
922 this.componentToModuleScope.clear();
923 const parentInjector = this.platform.injector;
924 this.testModuleRef = new ɵRender3NgModuleRef(this.testModuleType, parentInjector);
925 // ApplicationInitStatus.runInitializers() is marked @internal to core.
926 // Cast it to any before accessing it.
927 this.testModuleRef.injector.get(ApplicationInitStatus).runInitializers();
928 // Set locale ID after running app initializers, since locale information might be updated while
929 // running initializers. This is also consistent with the execution order while bootstrapping an
930 // app (see `packages/core/src/application_ref.ts` file).
931 const localeId = this.testModuleRef.injector.get(LOCALE_ID, ɵDEFAULT_LOCALE_ID);
932 ɵsetLocaleId(localeId);
933 return this.testModuleRef;
934 }
935 /**
936 * @internal
937 */
938 _compileNgModuleSync(moduleType) {
939 this.queueTypesFromModulesArray([moduleType]);
940 this.compileTypesSync();
941 this.applyProviderOverrides();
942 this.applyProviderOverridesToModule(moduleType);
943 this.applyTransitiveScopes();
944 }
945 /**
946 * @internal
947 */
948 async _compileNgModuleAsync(moduleType) {
949 this.queueTypesFromModulesArray([moduleType]);
950 await this.compileComponents();
951 this.applyProviderOverrides();
952 this.applyProviderOverridesToModule(moduleType);
953 this.applyTransitiveScopes();
954 }
955 /**
956 * @internal
957 */
958 _getModuleResolver() {
959 return this.resolvers.module;
960 }
961 /**
962 * @internal
963 */
964 _getComponentFactories(moduleType) {
965 return maybeUnwrapFn(moduleType.ɵmod.declarations).reduce((factories, declaration) => {
966 const componentDef = declaration.ɵcmp;
967 componentDef && factories.push(new ɵRender3ComponentFactory(componentDef, this.testModuleRef));
968 return factories;
969 }, []);
970 }
971 compileTypesSync() {
972 // Compile all queued components, directives, pipes.
973 let needsAsyncResources = false;
974 this.pendingComponents.forEach(declaration => {
975 needsAsyncResources = needsAsyncResources || isComponentDefPendingResolution(declaration);
976 const metadata = this.resolvers.component.resolve(declaration);
977 if (metadata === null) {
978 throw invalidTypeError(declaration.name, 'Component');
979 }
980 this.maybeStoreNgDef(ɵNG_COMP_DEF, declaration);
981 ɵcompileComponent(declaration, metadata);
982 });
983 this.pendingComponents.clear();
984 this.pendingDirectives.forEach(declaration => {
985 const metadata = this.resolvers.directive.resolve(declaration);
986 if (metadata === null) {
987 throw invalidTypeError(declaration.name, 'Directive');
988 }
989 this.maybeStoreNgDef(ɵNG_DIR_DEF, declaration);
990 ɵcompileDirective(declaration, metadata);
991 });
992 this.pendingDirectives.clear();
993 this.pendingPipes.forEach(declaration => {
994 const metadata = this.resolvers.pipe.resolve(declaration);
995 if (metadata === null) {
996 throw invalidTypeError(declaration.name, 'Pipe');
997 }
998 this.maybeStoreNgDef(ɵNG_PIPE_DEF, declaration);
999 ɵcompilePipe(declaration, metadata);
1000 });
1001 this.pendingPipes.clear();
1002 return needsAsyncResources;
1003 }
1004 applyTransitiveScopes() {
1005 if (this.overriddenModules.size > 0) {
1006 // Module overrides (via `TestBed.overrideModule`) might affect scopes that were previously
1007 // calculated and stored in `transitiveCompileScopes`. If module overrides are present,
1008 // collect all affected modules and reset scopes to force their re-calculation.
1009 const testingModuleDef = this.testModuleType[ɵNG_MOD_DEF];
1010 const affectedModules = this.collectModulesAffectedByOverrides(testingModuleDef.imports);
1011 if (affectedModules.size > 0) {
1012 affectedModules.forEach(moduleType => {
1013 this.storeFieldOfDefOnType(moduleType, ɵNG_MOD_DEF, 'transitiveCompileScopes');
1014 moduleType[ɵNG_MOD_DEF].transitiveCompileScopes = null;
1015 });
1016 }
1017 }
1018 const moduleToScope = new Map();
1019 const getScopeOfModule = (moduleType) => {
1020 if (!moduleToScope.has(moduleType)) {
1021 const isTestingModule = isTestingModuleOverride(moduleType);
1022 const realType = isTestingModule ? this.testModuleType : moduleType;
1023 moduleToScope.set(moduleType, ɵtransitiveScopesFor(realType));
1024 }
1025 return moduleToScope.get(moduleType);
1026 };
1027 this.componentToModuleScope.forEach((moduleType, componentType) => {
1028 const moduleScope = getScopeOfModule(moduleType);
1029 this.storeFieldOfDefOnType(componentType, ɵNG_COMP_DEF, 'directiveDefs');
1030 this.storeFieldOfDefOnType(componentType, ɵNG_COMP_DEF, 'pipeDefs');
1031 // `tView` that is stored on component def contains information about directives and pipes
1032 // that are in the scope of this component. Patching component scope will cause `tView` to be
1033 // changed. Store original `tView` before patching scope, so the `tView` (including scope
1034 // information) is restored back to its previous/original state before running next test.
1035 this.storeFieldOfDefOnType(componentType, ɵNG_COMP_DEF, 'tView');
1036 ɵpatchComponentDefWithScope(componentType.ɵcmp, moduleScope);
1037 });
1038 this.componentToModuleScope.clear();
1039 }
1040 applyProviderOverrides() {
1041 const maybeApplyOverrides = (field) => (type) => {
1042 const resolver = field === ɵNG_COMP_DEF ? this.resolvers.component : this.resolvers.directive;
1043 const metadata = resolver.resolve(type);
1044 if (this.hasProviderOverrides(metadata.providers)) {
1045 this.patchDefWithProviderOverrides(type, field);
1046 }
1047 };
1048 this.seenComponents.forEach(maybeApplyOverrides(ɵNG_COMP_DEF));
1049 this.seenDirectives.forEach(maybeApplyOverrides(ɵNG_DIR_DEF));
1050 this.seenComponents.clear();
1051 this.seenDirectives.clear();
1052 }
1053 applyProviderOverridesToModule(moduleType) {
1054 if (this.moduleProvidersOverridden.has(moduleType)) {
1055 return;
1056 }
1057 this.moduleProvidersOverridden.add(moduleType);
1058 const injectorDef = moduleType[ɵNG_INJ_DEF];
1059 if (this.providerOverridesByToken.size > 0) {
1060 const providers = [
1061 ...injectorDef.providers,
1062 ...(this.providerOverridesByModule.get(moduleType) || [])
1063 ];
1064 if (this.hasProviderOverrides(providers)) {
1065 this.maybeStoreNgDef(ɵNG_INJ_DEF, moduleType);
1066 this.storeFieldOfDefOnType(moduleType, ɵNG_INJ_DEF, 'providers');
1067 injectorDef.providers = this.getOverriddenProviders(providers);
1068 }
1069 // Apply provider overrides to imported modules recursively
1070 const moduleDef = moduleType[ɵNG_MOD_DEF];
1071 const imports = maybeUnwrapFn(moduleDef.imports);
1072 for (const importedModule of imports) {
1073 this.applyProviderOverridesToModule(importedModule);
1074 }
1075 // Also override the providers on any ModuleWithProviders imports since those don't appear in
1076 // the moduleDef.
1077 for (const importedModule of flatten(injectorDef.imports)) {
1078 if (isModuleWithProviders(importedModule)) {
1079 this.defCleanupOps.push({
1080 object: importedModule,
1081 fieldName: 'providers',
1082 originalValue: importedModule.providers
1083 });
1084 importedModule.providers = this.getOverriddenProviders(importedModule.providers);
1085 }
1086 }
1087 }
1088 }
1089 patchComponentsWithExistingStyles() {
1090 this.existingComponentStyles.forEach((styles, type) => type[ɵNG_COMP_DEF].styles = styles);
1091 this.existingComponentStyles.clear();
1092 }
1093 queueTypeArray(arr, moduleType) {
1094 for (const value of arr) {
1095 if (Array.isArray(value)) {
1096 this.queueTypeArray(value, moduleType);
1097 }
1098 else {
1099 this.queueType(value, moduleType);
1100 }
1101 }
1102 }
1103 recompileNgModule(ngModule, metadata) {
1104 // Cache the initial ngModuleDef as it will be overwritten.
1105 this.maybeStoreNgDef(ɵNG_MOD_DEF, ngModule);
1106 this.maybeStoreNgDef(ɵNG_INJ_DEF, ngModule);
1107 ɵcompileNgModuleDefs(ngModule, metadata);
1108 }
1109 queueType(type, moduleType) {
1110 const component = this.resolvers.component.resolve(type);
1111 if (component) {
1112 // Check whether a give Type has respective NG def (ɵcmp) and compile if def is
1113 // missing. That might happen in case a class without any Angular decorators extends another
1114 // class where Component/Directive/Pipe decorator is defined.
1115 if (isComponentDefPendingResolution(type) || !type.hasOwnProperty(ɵNG_COMP_DEF)) {
1116 this.pendingComponents.add(type);
1117 }
1118 this.seenComponents.add(type);
1119 // Keep track of the module which declares this component, so later the component's scope
1120 // can be set correctly. If the component has already been recorded here, then one of several
1121 // cases is true:
1122 // * the module containing the component was imported multiple times (common).
1123 // * the component is declared in multiple modules (which is an error).
1124 // * the component was in 'declarations' of the testing module, and also in an imported module
1125 // in which case the module scope will be TestingModuleOverride.DECLARATION.
1126 // * overrideTemplateUsingTestingModule was called for the component in which case the module
1127 // scope will be TestingModuleOverride.OVERRIDE_TEMPLATE.
1128 //
1129 // If the component was previously in the testing module's 'declarations' (meaning the
1130 // current value is TestingModuleOverride.DECLARATION), then `moduleType` is the component's
1131 // real module, which was imported. This pattern is understood to mean that the component
1132 // should use its original scope, but that the testing module should also contain the
1133 // component in its scope.
1134 if (!this.componentToModuleScope.has(type) ||
1135 this.componentToModuleScope.get(type) === TestingModuleOverride.DECLARATION) {
1136 this.componentToModuleScope.set(type, moduleType);
1137 }
1138 return;
1139 }
1140 const directive = this.resolvers.directive.resolve(type);
1141 if (directive) {
1142 if (!type.hasOwnProperty(ɵNG_DIR_DEF)) {
1143 this.pendingDirectives.add(type);
1144 }
1145 this.seenDirectives.add(type);
1146 return;
1147 }
1148 const pipe = this.resolvers.pipe.resolve(type);
1149 if (pipe && !type.hasOwnProperty(ɵNG_PIPE_DEF)) {
1150 this.pendingPipes.add(type);
1151 return;
1152 }
1153 }
1154 queueTypesFromModulesArray(arr) {
1155 // Because we may encounter the same NgModule while processing the imports and exports of an
1156 // NgModule tree, we cache them in this set so we can skip ones that have already been seen
1157 // encountered. In some test setups, this caching resulted in 10X runtime improvement.
1158 const processedNgModuleDefs = new Set();
1159 const queueTypesFromModulesArrayRecur = (arr) => {
1160 for (const value of arr) {
1161 if (Array.isArray(value)) {
1162 queueTypesFromModulesArrayRecur(value);
1163 }
1164 else if (hasNgModuleDef(value)) {
1165 const def = value.ɵmod;
1166 if (processedNgModuleDefs.has(def)) {
1167 continue;
1168 }
1169 processedNgModuleDefs.add(def);
1170 // Look through declarations, imports, and exports, and queue
1171 // everything found there.
1172 this.queueTypeArray(maybeUnwrapFn(def.declarations), value);
1173 queueTypesFromModulesArrayRecur(maybeUnwrapFn(def.imports));
1174 queueTypesFromModulesArrayRecur(maybeUnwrapFn(def.exports));
1175 }
1176 else if (isModuleWithProviders(value)) {
1177 queueTypesFromModulesArrayRecur([value.ngModule]);
1178 }
1179 }
1180 };
1181 queueTypesFromModulesArrayRecur(arr);
1182 }
1183 // When module overrides (via `TestBed.overrideModule`) are present, it might affect all modules
1184 // that import (even transitively) an overridden one. For all affected modules we need to
1185 // recalculate their scopes for a given test run and restore original scopes at the end. The goal
1186 // of this function is to collect all affected modules in a set for further processing. Example:
1187 // if we have the following module hierarchy: A -> B -> C (where `->` means `imports`) and module
1188 // `C` is overridden, we consider `A` and `B` as affected, since their scopes might become
1189 // invalidated with the override.
1190 collectModulesAffectedByOverrides(arr) {
1191 const seenModules = new Set();
1192 const affectedModules = new Set();
1193 const calcAffectedModulesRecur = (arr, path) => {
1194 for (const value of arr) {
1195 if (Array.isArray(value)) {
1196 // If the value is an array, just flatten it (by invoking this function recursively),
1197 // keeping "path" the same.
1198 calcAffectedModulesRecur(value, path);
1199 }
1200 else if (hasNgModuleDef(value)) {
1201 if (seenModules.has(value)) {
1202 // If we've seen this module before and it's included into "affected modules" list, mark
1203 // the whole path that leads to that module as affected, but do not descend into its
1204 // imports, since we already examined them before.
1205 if (affectedModules.has(value)) {
1206 path.forEach(item => affectedModules.add(item));
1207 }
1208 continue;
1209 }
1210 seenModules.add(value);
1211 if (this.overriddenModules.has(value)) {
1212 path.forEach(item => affectedModules.add(item));
1213 }
1214 // Examine module imports recursively to look for overridden modules.
1215 const moduleDef = value[ɵNG_MOD_DEF];
1216 calcAffectedModulesRecur(maybeUnwrapFn(moduleDef.imports), path.concat(value));
1217 }
1218 }
1219 };
1220 calcAffectedModulesRecur(arr, []);
1221 return affectedModules;
1222 }
1223 maybeStoreNgDef(prop, type) {
1224 if (!this.initialNgDefs.has(type)) {
1225 const currentDef = Object.getOwnPropertyDescriptor(type, prop);
1226 this.initialNgDefs.set(type, [prop, currentDef]);
1227 }
1228 }
1229 storeFieldOfDefOnType(type, defField, fieldName) {
1230 const def = type[defField];
1231 const originalValue = def[fieldName];
1232 this.defCleanupOps.push({ object: def, fieldName, originalValue });
1233 }
1234 /**
1235 * Clears current components resolution queue, but stores the state of the queue, so we can
1236 * restore it later. Clearing the queue is required before we try to compile components (via
1237 * `TestBed.compileComponents`), so that component defs are in sync with the resolution queue.
1238 */
1239 clearComponentResolutionQueue() {
1240 if (this.originalComponentResolutionQueue === null) {
1241 this.originalComponentResolutionQueue = new Map();
1242 }
1243 clearResolutionOfComponentResourcesQueue().forEach((value, key) => this.originalComponentResolutionQueue.set(key, value));
1244 }
1245 /*
1246 * Restores component resolution queue to the previously saved state. This operation is performed
1247 * as a part of restoring the state after completion of the current set of tests (that might
1248 * potentially mutate the state).
1249 */
1250 restoreComponentResolutionQueue() {
1251 if (this.originalComponentResolutionQueue !== null) {
1252 restoreComponentResolutionQueue(this.originalComponentResolutionQueue);
1253 this.originalComponentResolutionQueue = null;
1254 }
1255 }
1256 restoreOriginalState() {
1257 // Process cleanup ops in reverse order so the field's original value is restored correctly (in
1258 // case there were multiple overrides for the same field).
1259 forEachRight(this.defCleanupOps, (op) => {
1260 op.object[op.fieldName] = op.originalValue;
1261 });
1262 // Restore initial component/directive/pipe defs
1263 this.initialNgDefs.forEach((value, type) => {
1264 const [prop, descriptor] = value;
1265 if (!descriptor) {
1266 // Delete operations are generally undesirable since they have performance implications
1267 // on objects they were applied to. In this particular case, situations where this code
1268 // is invoked should be quite rare to cause any noticeable impact, since it's applied
1269 // only to some test cases (for example when class with no annotations extends some
1270 // @Component) when we need to clear 'ɵcmp' field on a given class to restore
1271 // its original state (before applying overrides and running tests).
1272 delete type[prop];
1273 }
1274 else {
1275 Object.defineProperty(type, prop, descriptor);
1276 }
1277 });
1278 this.initialNgDefs.clear();
1279 this.moduleProvidersOverridden.clear();
1280 this.restoreComponentResolutionQueue();
1281 // Restore the locale ID to the default value, this shouldn't be necessary but we never know
1282 ɵsetLocaleId(ɵDEFAULT_LOCALE_ID);
1283 }
1284 compileTestModule() {
1285 class RootScopeModule {
1286 }
1287 ɵcompileNgModuleDefs(RootScopeModule, {
1288 providers: [...this.rootProviderOverrides],
1289 });
1290 const ngZone = new NgZone({ enableLongStackTrace: true });
1291 const providers = [
1292 { provide: NgZone, useValue: ngZone },
1293 { provide: Compiler, useFactory: () => new R3TestCompiler(this) },
1294 ...this.providers,
1295 ...this.providerOverrides,
1296 ];
1297 const imports = [RootScopeModule, this.additionalModuleTypes, this.imports || []];
1298 // clang-format off
1299 ɵcompileNgModuleDefs(this.testModuleType, {
1300 declarations: this.declarations,
1301 imports,
1302 schemas: this.schemas,
1303 providers,
1304 }, /* allowDuplicateDeclarationsInRoot */ true);
1305 // clang-format on
1306 this.applyProviderOverridesToModule(this.testModuleType);
1307 }
1308 get injector() {
1309 if (this._injector !== null) {
1310 return this._injector;
1311 }
1312 const providers = [];
1313 const compilerOptions = this.platform.injector.get(COMPILER_OPTIONS);
1314 compilerOptions.forEach(opts => {
1315 if (opts.providers) {
1316 providers.push(opts.providers);
1317 }
1318 });
1319 if (this.compilerProviders !== null) {
1320 providers.push(...this.compilerProviders);
1321 }
1322 // TODO(ocombe): make this work with an Injector directly instead of creating a module for it
1323 class CompilerModule {
1324 }
1325 ɵcompileNgModuleDefs(CompilerModule, { providers });
1326 const CompilerModuleFactory = new ɵNgModuleFactory(CompilerModule);
1327 this._injector = CompilerModuleFactory.create(this.platform.injector).injector;
1328 return this._injector;
1329 }
1330 // get overrides for a specific provider (if any)
1331 getSingleProviderOverrides(provider) {
1332 const token = getProviderToken(provider);
1333 return this.providerOverridesByToken.get(token) || null;
1334 }
1335 getProviderOverrides(providers) {
1336 if (!providers || !providers.length || this.providerOverridesByToken.size === 0)
1337 return [];
1338 // There are two flattening operations here. The inner flatten() operates on the metadata's
1339 // providers and applies a mapping function which retrieves overrides for each incoming
1340 // provider. The outer flatten() then flattens the produced overrides array. If this is not
1341 // done, the array can contain other empty arrays (e.g. `[[], []]`) which leak into the
1342 // providers array and contaminate any error messages that might be generated.
1343 return flatten(flatten(providers, (provider) => this.getSingleProviderOverrides(provider) || []));
1344 }
1345 getOverriddenProviders(providers) {
1346 if (!providers || !providers.length || this.providerOverridesByToken.size === 0)
1347 return [];
1348 const flattenedProviders = flatten(providers);
1349 const overrides = this.getProviderOverrides(flattenedProviders);
1350 const overriddenProviders = [...flattenedProviders, ...overrides];
1351 const final = [];
1352 const seenOverriddenProviders = new Set();
1353 // We iterate through the list of providers in reverse order to make sure provider overrides
1354 // take precedence over the values defined in provider list. We also filter out all providers
1355 // that have overrides, keeping overridden values only. This is needed, since presence of a
1356 // provider with `ngOnDestroy` hook will cause this hook to be registered and invoked later.
1357 forEachRight(overriddenProviders, (provider) => {
1358 const token = getProviderToken(provider);
1359 if (this.providerOverridesByToken.has(token)) {
1360 if (!seenOverriddenProviders.has(token)) {
1361 seenOverriddenProviders.add(token);
1362 // Treat all overridden providers as `{multi: false}` (even if it's a multi-provider) to
1363 // make sure that provided override takes highest precedence and is not combined with
1364 // other instances of the same multi provider.
1365 final.unshift({ ...provider, multi: false });
1366 }
1367 }
1368 else {
1369 final.unshift(provider);
1370 }
1371 });
1372 return final;
1373 }
1374 hasProviderOverrides(providers) {
1375 return this.getProviderOverrides(providers).length > 0;
1376 }
1377 patchDefWithProviderOverrides(declaration, field) {
1378 const def = declaration[field];
1379 if (def && def.providersResolver) {
1380 this.maybeStoreNgDef(field, declaration);
1381 const resolver = def.providersResolver;
1382 const processProvidersFn = (providers) => this.getOverriddenProviders(providers);
1383 this.storeFieldOfDefOnType(declaration, field, 'providersResolver');
1384 def.providersResolver = (ngDef) => resolver(ngDef, processProvidersFn);
1385 }
1386 }
1387}
1388function initResolvers() {
1389 return {
1390 module: new NgModuleResolver(),
1391 component: new ComponentResolver(),
1392 directive: new DirectiveResolver(),
1393 pipe: new PipeResolver()
1394 };
1395}
1396function hasNgModuleDef(value) {
1397 return value.hasOwnProperty('ɵmod');
1398}
1399function maybeUnwrapFn(maybeFn) {
1400 return maybeFn instanceof Function ? maybeFn() : maybeFn;
1401}
1402function flatten(values, mapFn) {
1403 const out = [];
1404 values.forEach(value => {
1405 if (Array.isArray(value)) {
1406 out.push(...flatten(value, mapFn));
1407 }
1408 else {
1409 out.push(mapFn ? mapFn(value) : value);
1410 }
1411 });
1412 return out;
1413}
1414function getProviderField(provider, field) {
1415 return provider && typeof provider === 'object' && provider[field];
1416}
1417function getProviderToken(provider) {
1418 return getProviderField(provider, 'provide') || provider;
1419}
1420function isModuleWithProviders(value) {
1421 return value.hasOwnProperty('ngModule');
1422}
1423function forEachRight(values, fn) {
1424 for (let idx = values.length - 1; idx >= 0; idx--) {
1425 fn(values[idx], idx);
1426 }
1427}
1428function invalidTypeError(name, expectedType) {
1429 return new Error(`${name} class doesn't have @${expectedType} decorator or is missing metadata.`);
1430}
1431class R3TestCompiler {
1432 constructor(testBed) {
1433 this.testBed = testBed;
1434 }
1435 compileModuleSync(moduleType) {
1436 this.testBed._compileNgModuleSync(moduleType);
1437 return new ɵNgModuleFactory(moduleType);
1438 }
1439 async compileModuleAsync(moduleType) {
1440 await this.testBed._compileNgModuleAsync(moduleType);
1441 return new ɵNgModuleFactory(moduleType);
1442 }
1443 compileModuleAndAllComponentsSync(moduleType) {
1444 const ngModuleFactory = this.compileModuleSync(moduleType);
1445 const componentFactories = this.testBed._getComponentFactories(moduleType);
1446 return new ModuleWithComponentFactories(ngModuleFactory, componentFactories);
1447 }
1448 async compileModuleAndAllComponentsAsync(moduleType) {
1449 const ngModuleFactory = await this.compileModuleAsync(moduleType);
1450 const componentFactories = this.testBed._getComponentFactories(moduleType);
1451 return new ModuleWithComponentFactories(ngModuleFactory, componentFactories);
1452 }
1453 clearCache() { }
1454 clearCacheFor(type) { }
1455 getModuleId(moduleType) {
1456 const meta = this.testBed._getModuleResolver().resolve(moduleType);
1457 return meta && meta.id || undefined;
1458 }
1459}
1460
1461/**
1462 * @license
1463 * Copyright Google LLC All Rights Reserved.
1464 *
1465 * Use of this source code is governed by an MIT-style license that can be
1466 * found in the LICENSE file at https://angular.io/license
1467 */
1468/** Whether test modules should be torn down by default. */
1469const TEARDOWN_TESTING_MODULE_ON_DESTROY_DEFAULT = true;
1470/**
1471 * An abstract class for inserting the root test component element in a platform independent way.
1472 *
1473 * @publicApi
1474 */
1475class TestComponentRenderer {
1476 insertRootElement(rootElementId) { }
1477 removeAllRootElements() { }
1478}
1479/**
1480 * @publicApi
1481 */
1482const ComponentFixtureAutoDetect = new InjectionToken('ComponentFixtureAutoDetect');
1483/**
1484 * @publicApi
1485 */
1486const ComponentFixtureNoNgZone = new InjectionToken('ComponentFixtureNoNgZone');
1487
1488/**
1489 * @license
1490 * Copyright Google LLC All Rights Reserved.
1491 *
1492 * Use of this source code is governed by an MIT-style license that can be
1493 * found in the LICENSE file at https://angular.io/license
1494 */
1495let _nextRootElementId$1 = 0;
1496/**
1497 * @description
1498 * Configures and initializes environment for unit testing and provides methods for
1499 * creating components and services in unit tests.
1500 *
1501 * TestBed is the primary api for writing unit tests for Angular applications and libraries.
1502 *
1503 * Note: Use `TestBed` in tests. It will be set to either `TestBedViewEngine` or `TestBedRender3`
1504 * according to the compiler used.
1505 */
1506class TestBedRender3 {
1507 constructor() {
1508 // Properties
1509 this.platform = null;
1510 this.ngModule = null;
1511 this._compiler = null;
1512 this._testModuleRef = null;
1513 this._activeFixtures = [];
1514 this._globalCompilationChecked = false;
1515 }
1516 /**
1517 * Initialize the environment for testing with a compiler factory, a PlatformRef, and an
1518 * angular module. These are common to every test in the suite.
1519 *
1520 * This may only be called once, to set up the common providers for the current test
1521 * suite on the current platform. If you absolutely need to change the providers,
1522 * first use `resetTestEnvironment`.
1523 *
1524 * Test modules and platforms for individual platforms are available from
1525 * '@angular/<platform_name>/testing'.
1526 *
1527 * @publicApi
1528 */
1529 static initTestEnvironment(ngModule, platform, summariesOrOptions) {
1530 const testBed = _getTestBedRender3();
1531 testBed.initTestEnvironment(ngModule, platform, summariesOrOptions);
1532 return testBed;
1533 }
1534 /**
1535 * Reset the providers for the test injector.
1536 *
1537 * @publicApi
1538 */
1539 static resetTestEnvironment() {
1540 _getTestBedRender3().resetTestEnvironment();
1541 }
1542 static configureCompiler(config) {
1543 _getTestBedRender3().configureCompiler(config);
1544 return TestBedRender3;
1545 }
1546 /**
1547 * Allows overriding default providers, directives, pipes, modules of the test injector,
1548 * which are defined in test_injector.js
1549 */
1550 static configureTestingModule(moduleDef) {
1551 _getTestBedRender3().configureTestingModule(moduleDef);
1552 return TestBedRender3;
1553 }
1554 /**
1555 * Compile components with a `templateUrl` for the test's NgModule.
1556 * It is necessary to call this function
1557 * as fetching urls is asynchronous.
1558 */
1559 static compileComponents() {
1560 return _getTestBedRender3().compileComponents();
1561 }
1562 static overrideModule(ngModule, override) {
1563 _getTestBedRender3().overrideModule(ngModule, override);
1564 return TestBedRender3;
1565 }
1566 static overrideComponent(component, override) {
1567 _getTestBedRender3().overrideComponent(component, override);
1568 return TestBedRender3;
1569 }
1570 static overrideDirective(directive, override) {
1571 _getTestBedRender3().overrideDirective(directive, override);
1572 return TestBedRender3;
1573 }
1574 static overridePipe(pipe, override) {
1575 _getTestBedRender3().overridePipe(pipe, override);
1576 return TestBedRender3;
1577 }
1578 static overrideTemplate(component, template) {
1579 _getTestBedRender3().overrideComponent(component, { set: { template, templateUrl: null } });
1580 return TestBedRender3;
1581 }
1582 /**
1583 * Overrides the template of the given component, compiling the template
1584 * in the context of the TestingModule.
1585 *
1586 * Note: This works for JIT and AOTed components as well.
1587 */
1588 static overrideTemplateUsingTestingModule(component, template) {
1589 _getTestBedRender3().overrideTemplateUsingTestingModule(component, template);
1590 return TestBedRender3;
1591 }
1592 static overrideProvider(token, provider) {
1593 _getTestBedRender3().overrideProvider(token, provider);
1594 return TestBedRender3;
1595 }
1596 static inject(token, notFoundValue, flags) {
1597 return _getTestBedRender3().inject(token, notFoundValue, flags);
1598 }
1599 /** @deprecated from v9.0.0 use TestBed.inject */
1600 static get(token, notFoundValue = Injector.THROW_IF_NOT_FOUND, flags = InjectFlags.Default) {
1601 return _getTestBedRender3().inject(token, notFoundValue, flags);
1602 }
1603 static createComponent(component) {
1604 return _getTestBedRender3().createComponent(component);
1605 }
1606 static resetTestingModule() {
1607 _getTestBedRender3().resetTestingModule();
1608 return TestBedRender3;
1609 }
1610 static shouldTearDownTestingModule() {
1611 return _getTestBedRender3().shouldTearDownTestingModule();
1612 }
1613 static tearDownTestingModule() {
1614 _getTestBedRender3().tearDownTestingModule();
1615 }
1616 /**
1617 * Initialize the environment for testing with a compiler factory, a PlatformRef, and an
1618 * angular module. These are common to every test in the suite.
1619 *
1620 * This may only be called once, to set up the common providers for the current test
1621 * suite on the current platform. If you absolutely need to change the providers,
1622 * first use `resetTestEnvironment`.
1623 *
1624 * Test modules and platforms for individual platforms are available from
1625 * '@angular/<platform_name>/testing'.
1626 *
1627 * @publicApi
1628 */
1629 initTestEnvironment(ngModule, platform, summariesOrOptions) {
1630 if (this.platform || this.ngModule) {
1631 throw new Error('Cannot set base providers because it has already been called');
1632 }
1633 // If `summariesOrOptions` is a function, it means that it's
1634 // an AOT summaries factory which Ivy doesn't support.
1635 TestBedRender3._environmentTeardownOptions =
1636 typeof summariesOrOptions === 'function' ? undefined : summariesOrOptions?.teardown;
1637 this.platform = platform;
1638 this.ngModule = ngModule;
1639 this._compiler = new R3TestBedCompiler(this.platform, this.ngModule);
1640 }
1641 /**
1642 * Reset the providers for the test injector.
1643 *
1644 * @publicApi
1645 */
1646 resetTestEnvironment() {
1647 this.resetTestingModule();
1648 this._compiler = null;
1649 this.platform = null;
1650 this.ngModule = null;
1651 TestBedRender3._environmentTeardownOptions = undefined;
1652 }
1653 resetTestingModule() {
1654 this.checkGlobalCompilationFinished();
1655 ɵresetCompiledComponents();
1656 if (this._compiler !== null) {
1657 this.compiler.restoreOriginalState();
1658 }
1659 this._compiler = new R3TestBedCompiler(this.platform, this.ngModule);
1660 // We have to chain a couple of try/finally blocks, because each step can
1661 // throw errors and we don't want it to interrupt the next step and we also
1662 // want an error to be thrown at the end.
1663 try {
1664 this.destroyActiveFixtures();
1665 }
1666 finally {
1667 try {
1668 if (this.shouldTearDownTestingModule()) {
1669 this.tearDownTestingModule();
1670 }
1671 }
1672 finally {
1673 this._testModuleRef = null;
1674 this._instanceTeardownOptions = undefined;
1675 }
1676 }
1677 }
1678 configureCompiler(config) {
1679 if (config.useJit != null) {
1680 throw new Error('the Render3 compiler JiT mode is not configurable !');
1681 }
1682 if (config.providers !== undefined) {
1683 this.compiler.setCompilerProviders(config.providers);
1684 }
1685 }
1686 configureTestingModule(moduleDef) {
1687 this.assertNotInstantiated('R3TestBed.configureTestingModule', 'configure the test module');
1688 // Always re-assign the teardown options, even if they're undefined.
1689 // This ensures that we don't carry the options between tests.
1690 this._instanceTeardownOptions = moduleDef.teardown;
1691 this.compiler.configureTestingModule(moduleDef);
1692 }
1693 compileComponents() {
1694 return this.compiler.compileComponents();
1695 }
1696 inject(token, notFoundValue, flags) {
1697 if (token === TestBedRender3) {
1698 return this;
1699 }
1700 const UNDEFINED = {};
1701 const result = this.testModuleRef.injector.get(token, UNDEFINED, flags);
1702 return result === UNDEFINED ? this.compiler.injector.get(token, notFoundValue, flags) :
1703 result;
1704 }
1705 /** @deprecated from v9.0.0 use TestBed.inject */
1706 get(token, notFoundValue = Injector.THROW_IF_NOT_FOUND, flags = InjectFlags.Default) {
1707 return this.inject(token, notFoundValue, flags);
1708 }
1709 execute(tokens, fn, context) {
1710 const params = tokens.map(t => this.inject(t));
1711 return fn.apply(context, params);
1712 }
1713 overrideModule(ngModule, override) {
1714 this.assertNotInstantiated('overrideModule', 'override module metadata');
1715 this.compiler.overrideModule(ngModule, override);
1716 }
1717 overrideComponent(component, override) {
1718 this.assertNotInstantiated('overrideComponent', 'override component metadata');
1719 this.compiler.overrideComponent(component, override);
1720 }
1721 overrideTemplateUsingTestingModule(component, template) {
1722 this.assertNotInstantiated('R3TestBed.overrideTemplateUsingTestingModule', 'Cannot override template when the test module has already been instantiated');
1723 this.compiler.overrideTemplateUsingTestingModule(component, template);
1724 }
1725 overrideDirective(directive, override) {
1726 this.assertNotInstantiated('overrideDirective', 'override directive metadata');
1727 this.compiler.overrideDirective(directive, override);
1728 }
1729 overridePipe(pipe, override) {
1730 this.assertNotInstantiated('overridePipe', 'override pipe metadata');
1731 this.compiler.overridePipe(pipe, override);
1732 }
1733 /**
1734 * Overwrites all providers for the given token with the given provider definition.
1735 */
1736 overrideProvider(token, provider) {
1737 this.assertNotInstantiated('overrideProvider', 'override provider');
1738 this.compiler.overrideProvider(token, provider);
1739 }
1740 createComponent(type) {
1741 const testComponentRenderer = this.inject(TestComponentRenderer);
1742 const rootElId = `root${_nextRootElementId$1++}`;
1743 testComponentRenderer.insertRootElement(rootElId);
1744 const componentDef = type.ɵcmp;
1745 if (!componentDef) {
1746 throw new Error(`It looks like '${ɵstringify(type)}' has not been IVY compiled - it has no 'ɵcmp' field`);
1747 }
1748 // TODO: Don't cast as `InjectionToken<boolean>`, proper type is boolean[]
1749 const noNgZone = this.inject(ComponentFixtureNoNgZone, false);
1750 // TODO: Don't cast as `InjectionToken<boolean>`, proper type is boolean[]
1751 const autoDetect = this.inject(ComponentFixtureAutoDetect, false);
1752 const ngZone = noNgZone ? null : this.inject(NgZone, null);
1753 const componentFactory = new ɵRender3ComponentFactory(componentDef);
1754 const initComponent = () => {
1755 const componentRef = componentFactory.create(Injector.NULL, [], `#${rootElId}`, this.testModuleRef);
1756 return new ComponentFixture(componentRef, ngZone, autoDetect);
1757 };
1758 const fixture = ngZone ? ngZone.run(initComponent) : initComponent();
1759 this._activeFixtures.push(fixture);
1760 return fixture;
1761 }
1762 /**
1763 * @internal strip this from published d.ts files due to
1764 * https://github.com/microsoft/TypeScript/issues/36216
1765 */
1766 get compiler() {
1767 if (this._compiler === null) {
1768 throw new Error(`Need to call TestBed.initTestEnvironment() first`);
1769 }
1770 return this._compiler;
1771 }
1772 /**
1773 * @internal strip this from published d.ts files due to
1774 * https://github.com/microsoft/TypeScript/issues/36216
1775 */
1776 get testModuleRef() {
1777 if (this._testModuleRef === null) {
1778 this._testModuleRef = this.compiler.finalize();
1779 }
1780 return this._testModuleRef;
1781 }
1782 assertNotInstantiated(methodName, methodDescription) {
1783 if (this._testModuleRef !== null) {
1784 throw new Error(`Cannot ${methodDescription} when the test module has already been instantiated. ` +
1785 `Make sure you are not using \`inject\` before \`${methodName}\`.`);
1786 }
1787 }
1788 /**
1789 * Check whether the module scoping queue should be flushed, and flush it if needed.
1790 *
1791 * When the TestBed is reset, it clears the JIT module compilation queue, cancelling any
1792 * in-progress module compilation. This creates a potential hazard - the very first time the
1793 * TestBed is initialized (or if it's reset without being initialized), there may be pending
1794 * compilations of modules declared in global scope. These compilations should be finished.
1795 *
1796 * To ensure that globally declared modules have their components scoped properly, this function
1797 * is called whenever TestBed is initialized or reset. The _first_ time that this happens, prior
1798 * to any other operations, the scoping queue is flushed.
1799 */
1800 checkGlobalCompilationFinished() {
1801 // Checking _testNgModuleRef is null should not be necessary, but is left in as an additional
1802 // guard that compilations queued in tests (after instantiation) are never flushed accidentally.
1803 if (!this._globalCompilationChecked && this._testModuleRef === null) {
1804 ɵflushModuleScopingQueueAsMuchAsPossible();
1805 }
1806 this._globalCompilationChecked = true;
1807 }
1808 destroyActiveFixtures() {
1809 let errorCount = 0;
1810 this._activeFixtures.forEach((fixture) => {
1811 try {
1812 fixture.destroy();
1813 }
1814 catch (e) {
1815 errorCount++;
1816 console.error('Error during cleanup of component', {
1817 component: fixture.componentInstance,
1818 stacktrace: e,
1819 });
1820 }
1821 });
1822 this._activeFixtures = [];
1823 if (errorCount > 0 && this.shouldRethrowTeardownErrors()) {
1824 throw Error(`${errorCount} ${(errorCount === 1 ? 'component' : 'components')} ` +
1825 `threw errors during cleanup`);
1826 }
1827 }
1828 shouldRethrowTeardownErrors() {
1829 const instanceOptions = this._instanceTeardownOptions;
1830 const environmentOptions = TestBedRender3._environmentTeardownOptions;
1831 // If the new teardown behavior hasn't been configured, preserve the old behavior.
1832 if (!instanceOptions && !environmentOptions) {
1833 return TEARDOWN_TESTING_MODULE_ON_DESTROY_DEFAULT;
1834 }
1835 // Otherwise use the configured behavior or default to rethrowing.
1836 return instanceOptions?.rethrowErrors ?? environmentOptions?.rethrowErrors ??
1837 this.shouldTearDownTestingModule();
1838 }
1839 shouldTearDownTestingModule() {
1840 return this._instanceTeardownOptions?.destroyAfterEach ??
1841 TestBedRender3._environmentTeardownOptions?.destroyAfterEach ??
1842 TEARDOWN_TESTING_MODULE_ON_DESTROY_DEFAULT;
1843 }
1844 tearDownTestingModule() {
1845 // If the module ref has already been destroyed, we won't be able to get a test renderer.
1846 if (this._testModuleRef === null) {
1847 return;
1848 }
1849 // Resolve the renderer ahead of time, because we want to remove the root elements as the very
1850 // last step, but the injector will be destroyed as a part of the module ref destruction.
1851 const testRenderer = this.inject(TestComponentRenderer);
1852 try {
1853 this._testModuleRef.destroy();
1854 }
1855 catch (e) {
1856 if (this.shouldRethrowTeardownErrors()) {
1857 throw e;
1858 }
1859 else {
1860 console.error('Error during cleanup of a testing module', {
1861 component: this._testModuleRef.instance,
1862 stacktrace: e,
1863 });
1864 }
1865 }
1866 finally {
1867 testRenderer.removeAllRootElements?.();
1868 }
1869 }
1870}
1871let testBed$1;
1872function _getTestBedRender3() {
1873 return testBed$1 = testBed$1 || new TestBedRender3();
1874}
1875
1876/**
1877 * @license
1878 * Copyright Google LLC All Rights Reserved.
1879 *
1880 * Use of this source code is governed by an MIT-style license that can be
1881 * found in the LICENSE file at https://angular.io/license
1882 */
1883function unimplemented() {
1884 throw Error('unimplemented');
1885}
1886/**
1887 * Special interface to the compiler only used by testing
1888 *
1889 * @publicApi
1890 */
1891class TestingCompiler extends Compiler {
1892 get injector() {
1893 throw unimplemented();
1894 }
1895 overrideModule(module, overrides) {
1896 throw unimplemented();
1897 }
1898 overrideDirective(directive, overrides) {
1899 throw unimplemented();
1900 }
1901 overrideComponent(component, overrides) {
1902 throw unimplemented();
1903 }
1904 overridePipe(directive, overrides) {
1905 throw unimplemented();
1906 }
1907 /**
1908 * Allows to pass the compile summary from AOT compilation to the JIT compiler,
1909 * so that it can use the code generated by AOT.
1910 */
1911 loadAotSummaries(summaries) {
1912 throw unimplemented();
1913 }
1914 /**
1915 * Gets the component factory for the given component.
1916 * This assumes that the component has been compiled before calling this call using
1917 * `compileModuleAndAllComponents*`.
1918 */
1919 getComponentFactory(component) {
1920 throw unimplemented();
1921 }
1922 /**
1923 * Returns the component type that is stored in the given error.
1924 * This can be used for errors created by compileModule...
1925 */
1926 getComponentFromError(error) {
1927 throw unimplemented();
1928 }
1929}
1930TestingCompiler.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: TestingCompiler, deps: null, target: i0.ɵɵFactoryTarget.Injectable });
1931TestingCompiler.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: TestingCompiler });
1932i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.0.2", ngImport: i0, type: TestingCompiler, decorators: [{
1933 type: Injectable
1934 }] });
1935/**
1936 * A factory for creating a Compiler
1937 *
1938 * @publicApi
1939 */
1940class TestingCompilerFactory {
1941}
1942
1943/**
1944 * @license
1945 * Copyright Google LLC All Rights Reserved.
1946 *
1947 * Use of this source code is governed by an MIT-style license that can be
1948 * found in the LICENSE file at https://angular.io/license
1949 */
1950let _nextRootElementId = 0;
1951/**
1952 * @description
1953 * Configures and initializes environment for unit testing and provides methods for
1954 * creating components and services in unit tests.
1955 *
1956 * `TestBed` is the primary api for writing unit tests for Angular applications and libraries.
1957 *
1958 * Note: Use `TestBed` in tests. It will be set to either `TestBedViewEngine` or `TestBedRender3`
1959 * according to the compiler used.
1960 */
1961class TestBedViewEngine {
1962 constructor() {
1963 this._instantiated = false;
1964 this._compiler = null;
1965 this._moduleRef = null;
1966 this._moduleFactory = null;
1967 this._pendingModuleFactory = null;
1968 this._compilerOptions = [];
1969 this._moduleOverrides = [];
1970 this._componentOverrides = [];
1971 this._directiveOverrides = [];
1972 this._pipeOverrides = [];
1973 this._providers = [];
1974 this._declarations = [];
1975 this._imports = [];
1976 this._schemas = [];
1977 this._activeFixtures = [];
1978 this._testEnvAotSummaries = () => [];
1979 this._aotSummaries = [];
1980 this._templateOverrides = [];
1981 this._isRoot = true;
1982 this._rootProviderOverrides = [];
1983 this.platform = null;
1984 this.ngModule = null;
1985 }
1986 /**
1987 * Initialize the environment for testing with a compiler factory, a PlatformRef, and an
1988 * angular module. These are common to every test in the suite.
1989 *
1990 * This may only be called once, to set up the common providers for the current test
1991 * suite on the current platform. If you absolutely need to change the providers,
1992 * first use `resetTestEnvironment`.
1993 *
1994 * Test modules and platforms for individual platforms are available from
1995 * '@angular/<platform_name>/testing'.
1996 */
1997 static initTestEnvironment(ngModule, platform, summariesOrOptions) {
1998 const testBed = _getTestBedViewEngine();
1999 testBed.initTestEnvironment(ngModule, platform, summariesOrOptions);
2000 return testBed;
2001 }
2002 /**
2003 * Reset the providers for the test injector.
2004 */
2005 static resetTestEnvironment() {
2006 _getTestBedViewEngine().resetTestEnvironment();
2007 }
2008 static resetTestingModule() {
2009 _getTestBedViewEngine().resetTestingModule();
2010 return TestBedViewEngine;
2011 }
2012 /**
2013 * Allows overriding default compiler providers and settings
2014 * which are defined in test_injector.js
2015 */
2016 static configureCompiler(config) {
2017 _getTestBedViewEngine().configureCompiler(config);
2018 return TestBedViewEngine;
2019 }
2020 /**
2021 * Allows overriding default providers, directives, pipes, modules of the test injector,
2022 * which are defined in test_injector.js
2023 */
2024 static configureTestingModule(moduleDef) {
2025 _getTestBedViewEngine().configureTestingModule(moduleDef);
2026 return TestBedViewEngine;
2027 }
2028 /**
2029 * Compile components with a `templateUrl` for the test's NgModule.
2030 * It is necessary to call this function
2031 * as fetching urls is asynchronous.
2032 */
2033 static compileComponents() {
2034 return getTestBed().compileComponents();
2035 }
2036 static overrideModule(ngModule, override) {
2037 _getTestBedViewEngine().overrideModule(ngModule, override);
2038 return TestBedViewEngine;
2039 }
2040 static overrideComponent(component, override) {
2041 _getTestBedViewEngine().overrideComponent(component, override);
2042 return TestBedViewEngine;
2043 }
2044 static overrideDirective(directive, override) {
2045 _getTestBedViewEngine().overrideDirective(directive, override);
2046 return TestBedViewEngine;
2047 }
2048 static overridePipe(pipe, override) {
2049 _getTestBedViewEngine().overridePipe(pipe, override);
2050 return TestBedViewEngine;
2051 }
2052 static overrideTemplate(component, template) {
2053 _getTestBedViewEngine().overrideComponent(component, { set: { template, templateUrl: null } });
2054 return TestBedViewEngine;
2055 }
2056 /**
2057 * Overrides the template of the given component, compiling the template
2058 * in the context of the TestingModule.
2059 *
2060 * Note: This works for JIT and AOTed components as well.
2061 */
2062 static overrideTemplateUsingTestingModule(component, template) {
2063 _getTestBedViewEngine().overrideTemplateUsingTestingModule(component, template);
2064 return TestBedViewEngine;
2065 }
2066 static overrideProvider(token, provider) {
2067 _getTestBedViewEngine().overrideProvider(token, provider);
2068 return TestBedViewEngine;
2069 }
2070 static inject(token, notFoundValue, flags) {
2071 return _getTestBedViewEngine().inject(token, notFoundValue, flags);
2072 }
2073 /** @deprecated from v9.0.0 use TestBed.inject */
2074 static get(token, notFoundValue = Injector.THROW_IF_NOT_FOUND, flags = InjectFlags.Default) {
2075 return _getTestBedViewEngine().inject(token, notFoundValue, flags);
2076 }
2077 static createComponent(component) {
2078 return _getTestBedViewEngine().createComponent(component);
2079 }
2080 static shouldTearDownTestingModule() {
2081 return _getTestBedViewEngine().shouldTearDownTestingModule();
2082 }
2083 static tearDownTestingModule() {
2084 _getTestBedViewEngine().tearDownTestingModule();
2085 }
2086 /**
2087 * Initialize the environment for testing with a compiler factory, a PlatformRef, and an
2088 * angular module. These are common to every test in the suite.
2089 *
2090 * This may only be called once, to set up the common providers for the current test
2091 * suite on the current platform. If you absolutely need to change the providers,
2092 * first use `resetTestEnvironment`.
2093 *
2094 * Test modules and platforms for individual platforms are available from
2095 * '@angular/<platform_name>/testing'.
2096 */
2097 initTestEnvironment(ngModule, platform, summariesOrOptions) {
2098 if (this.platform || this.ngModule) {
2099 throw new Error('Cannot set base providers because it has already been called');
2100 }
2101 this.platform = platform;
2102 this.ngModule = ngModule;
2103 if (typeof summariesOrOptions === 'function') {
2104 this._testEnvAotSummaries = summariesOrOptions;
2105 TestBedViewEngine._environmentTeardownOptions = undefined;
2106 }
2107 else {
2108 this._testEnvAotSummaries = (summariesOrOptions?.aotSummaries) || (() => []);
2109 TestBedViewEngine._environmentTeardownOptions = summariesOrOptions?.teardown;
2110 }
2111 }
2112 /**
2113 * Reset the providers for the test injector.
2114 */
2115 resetTestEnvironment() {
2116 this.resetTestingModule();
2117 this.platform = null;
2118 this.ngModule = null;
2119 this._testEnvAotSummaries = () => [];
2120 TestBedViewEngine._environmentTeardownOptions = undefined;
2121 }
2122 resetTestingModule() {
2123 ɵclearOverrides();
2124 this._aotSummaries = [];
2125 this._templateOverrides = [];
2126 this._compiler = null;
2127 this._moduleOverrides = [];
2128 this._componentOverrides = [];
2129 this._directiveOverrides = [];
2130 this._pipeOverrides = [];
2131 this._isRoot = true;
2132 this._rootProviderOverrides = [];
2133 this._moduleFactory = null;
2134 this._pendingModuleFactory = null;
2135 this._compilerOptions = [];
2136 this._providers = [];
2137 this._declarations = [];
2138 this._imports = [];
2139 this._schemas = [];
2140 // We have to chain a couple of try/finally blocks, because each step can
2141 // throw errors and we don't want it to interrupt the next step and we also
2142 // want an error to be thrown at the end.
2143 try {
2144 this.destroyActiveFixtures();
2145 }
2146 finally {
2147 try {
2148 if (this.shouldTearDownTestingModule()) {
2149 this.tearDownTestingModule();
2150 }
2151 }
2152 finally {
2153 this._moduleRef = null;
2154 this._instanceTeardownOptions = undefined;
2155 this._instantiated = false;
2156 }
2157 }
2158 }
2159 configureCompiler(config) {
2160 this._assertNotInstantiated('TestBed.configureCompiler', 'configure the compiler');
2161 this._compilerOptions.push(config);
2162 }
2163 configureTestingModule(moduleDef) {
2164 this._assertNotInstantiated('TestBed.configureTestingModule', 'configure the test module');
2165 if (moduleDef.providers) {
2166 this._providers.push(...moduleDef.providers);
2167 }
2168 if (moduleDef.declarations) {
2169 this._declarations.push(...moduleDef.declarations);
2170 }
2171 if (moduleDef.imports) {
2172 this._imports.push(...moduleDef.imports);
2173 }
2174 if (moduleDef.schemas) {
2175 this._schemas.push(...moduleDef.schemas);
2176 }
2177 if (moduleDef.aotSummaries) {
2178 this._aotSummaries.push(moduleDef.aotSummaries);
2179 }
2180 // Always re-assign the teardown options, even if they're undefined.
2181 // This ensures that we don't carry the options between tests.
2182 this._instanceTeardownOptions = moduleDef.teardown;
2183 }
2184 compileComponents() {
2185 if (this._moduleFactory || this._instantiated) {
2186 return Promise.resolve(null);
2187 }
2188 const moduleType = this._createCompilerAndModule();
2189 this._pendingModuleFactory = moduleType;
2190 return this._compiler.compileModuleAndAllComponentsAsync(moduleType).then(result => {
2191 // If the module mismatches by the time the promise resolves, it means that the module has
2192 // already been destroyed and a new compilation has started. If that's the case, avoid
2193 // overwriting the module factory, because it can cause downstream errors.
2194 if (this._pendingModuleFactory === moduleType) {
2195 this._moduleFactory = result.ngModuleFactory;
2196 this._pendingModuleFactory = null;
2197 }
2198 });
2199 }
2200 _initIfNeeded() {
2201 if (this._instantiated) {
2202 return;
2203 }
2204 if (!this._moduleFactory) {
2205 try {
2206 const moduleType = this._createCompilerAndModule();
2207 this._moduleFactory =
2208 this._compiler.compileModuleAndAllComponentsSync(moduleType).ngModuleFactory;
2209 }
2210 catch (e) {
2211 const errorCompType = this._compiler.getComponentFromError(e);
2212 if (errorCompType) {
2213 throw new Error(`This test module uses the component ${ɵstringify(errorCompType)} which is using a "templateUrl" or "styleUrls", but they were never compiled. ` +
2214 `Please call "TestBed.compileComponents" before your test.`);
2215 }
2216 else {
2217 throw e;
2218 }
2219 }
2220 }
2221 for (const { component, templateOf } of this._templateOverrides) {
2222 const compFactory = this._compiler.getComponentFactory(templateOf);
2223 ɵoverrideComponentView(component, compFactory);
2224 }
2225 const ngZone = new NgZone({ enableLongStackTrace: true, shouldCoalesceEventChangeDetection: false });
2226 const providers = [{ provide: NgZone, useValue: ngZone }];
2227 const ngZoneInjector = Injector.create({
2228 providers: providers,
2229 parent: this.platform.injector,
2230 name: this._moduleFactory.moduleType.name
2231 });
2232 this._moduleRef = this._moduleFactory.create(ngZoneInjector);
2233 // ApplicationInitStatus.runInitializers() is marked @internal to core. So casting to any
2234 // before accessing it.
2235 try {
2236 this._moduleRef.injector.get(ApplicationInitStatus).runInitializers();
2237 }
2238 finally {
2239 this._instantiated = true;
2240 }
2241 }
2242 _createCompilerAndModule() {
2243 const providers = this._providers.concat([{ provide: TestBed, useValue: this }]);
2244 const declarations = [...this._declarations, ...this._templateOverrides.map(entry => entry.templateOf)];
2245 const rootScopeImports = [];
2246 const rootProviderOverrides = this._rootProviderOverrides;
2247 if (this._isRoot) {
2248 let RootScopeModule = class RootScopeModule {
2249 };
2250 RootScopeModule = __decorate([
2251 NgModule({
2252 providers: [
2253 ...rootProviderOverrides,
2254 ],
2255 jit: true,
2256 })
2257 ], RootScopeModule);
2258 rootScopeImports.push(RootScopeModule);
2259 }
2260 providers.push({ provide: ɵINJECTOR_SCOPE, useValue: this._isRoot ? 'root' : null });
2261 const imports = [rootScopeImports, this.ngModule, this._imports];
2262 const schemas = this._schemas;
2263 let DynamicTestModule = class DynamicTestModule {
2264 };
2265 DynamicTestModule = __decorate([
2266 NgModule({ providers, declarations, imports, schemas, jit: true })
2267 ], DynamicTestModule);
2268 const compilerFactory = this.platform.injector.get(TestingCompilerFactory);
2269 this._compiler = compilerFactory.createTestingCompiler(this._compilerOptions);
2270 for (const summary of [this._testEnvAotSummaries, ...this._aotSummaries]) {
2271 this._compiler.loadAotSummaries(summary);
2272 }
2273 this._moduleOverrides.forEach((entry) => this._compiler.overrideModule(entry[0], entry[1]));
2274 this._componentOverrides.forEach((entry) => this._compiler.overrideComponent(entry[0], entry[1]));
2275 this._directiveOverrides.forEach((entry) => this._compiler.overrideDirective(entry[0], entry[1]));
2276 this._pipeOverrides.forEach((entry) => this._compiler.overridePipe(entry[0], entry[1]));
2277 return DynamicTestModule;
2278 }
2279 _assertNotInstantiated(methodName, methodDescription) {
2280 if (this._instantiated) {
2281 throw new Error(`Cannot ${methodDescription} when the test module has already been instantiated. ` +
2282 `Make sure you are not using \`inject\` before \`${methodName}\`.`);
2283 }
2284 }
2285 inject(token, notFoundValue, flags) {
2286 this._initIfNeeded();
2287 if (token === TestBed) {
2288 return this;
2289 }
2290 // Tests can inject things from the ng module and from the compiler,
2291 // but the ng module can't inject things from the compiler and vice versa.
2292 const UNDEFINED = {};
2293 const result = this._moduleRef.injector.get(token, UNDEFINED, flags);
2294 return result === UNDEFINED ? this._compiler.injector.get(token, notFoundValue, flags) :
2295 result;
2296 }
2297 /** @deprecated from v9.0.0 use TestBed.inject */
2298 get(token, notFoundValue = Injector.THROW_IF_NOT_FOUND, flags = InjectFlags.Default) {
2299 return this.inject(token, notFoundValue, flags);
2300 }
2301 execute(tokens, fn, context) {
2302 this._initIfNeeded();
2303 const params = tokens.map(t => this.inject(t));
2304 return fn.apply(context, params);
2305 }
2306 overrideModule(ngModule, override) {
2307 this._assertNotInstantiated('overrideModule', 'override module metadata');
2308 this._moduleOverrides.push([ngModule, override]);
2309 }
2310 overrideComponent(component, override) {
2311 this._assertNotInstantiated('overrideComponent', 'override component metadata');
2312 this._componentOverrides.push([component, override]);
2313 }
2314 overrideDirective(directive, override) {
2315 this._assertNotInstantiated('overrideDirective', 'override directive metadata');
2316 this._directiveOverrides.push([directive, override]);
2317 }
2318 overridePipe(pipe, override) {
2319 this._assertNotInstantiated('overridePipe', 'override pipe metadata');
2320 this._pipeOverrides.push([pipe, override]);
2321 }
2322 overrideProvider(token, provider) {
2323 this._assertNotInstantiated('overrideProvider', 'override provider');
2324 this.overrideProviderImpl(token, provider);
2325 }
2326 overrideProviderImpl(token, provider, deprecated = false) {
2327 let def = null;
2328 if (typeof token !== 'string' && (def = ɵgetInjectableDef(token)) && def.providedIn === 'root') {
2329 if (provider.useFactory) {
2330 this._rootProviderOverrides.push({ provide: token, useFactory: provider.useFactory, deps: provider.deps || [] });
2331 }
2332 else {
2333 this._rootProviderOverrides.push({ provide: token, useValue: provider.useValue });
2334 }
2335 }
2336 let flags = 0;
2337 let value;
2338 if (provider.useFactory) {
2339 flags |= 1024 /* TypeFactoryProvider */;
2340 value = provider.useFactory;
2341 }
2342 else {
2343 flags |= 256 /* TypeValueProvider */;
2344 value = provider.useValue;
2345 }
2346 const deps = (provider.deps || []).map((dep) => {
2347 let depFlags = 0 /* None */;
2348 let depToken;
2349 if (Array.isArray(dep)) {
2350 dep.forEach((entry) => {
2351 if (entry instanceof Optional) {
2352 depFlags |= 2 /* Optional */;
2353 }
2354 else if (entry instanceof SkipSelf) {
2355 depFlags |= 1 /* SkipSelf */;
2356 }
2357 else {
2358 depToken = entry;
2359 }
2360 });
2361 }
2362 else {
2363 depToken = dep;
2364 }
2365 return [depFlags, depToken];
2366 });
2367 ɵoverrideProvider({ token, flags, deps, value, deprecatedBehavior: deprecated });
2368 }
2369 overrideTemplateUsingTestingModule(component, template) {
2370 this._assertNotInstantiated('overrideTemplateUsingTestingModule', 'override template');
2371 let OverrideComponent = class OverrideComponent {
2372 };
2373 OverrideComponent = __decorate([
2374 Component({ selector: 'empty', template, jit: true })
2375 ], OverrideComponent);
2376 this._templateOverrides.push({ component, templateOf: OverrideComponent });
2377 }
2378 createComponent(component) {
2379 this._initIfNeeded();
2380 const componentFactory = this._compiler.getComponentFactory(component);
2381 if (!componentFactory) {
2382 throw new Error(`Cannot create the component ${ɵstringify(component)} as it was not imported into the testing module!`);
2383 }
2384 // TODO: Don't cast as `InjectionToken<boolean>`, declared type is boolean[]
2385 const noNgZone = this.inject(ComponentFixtureNoNgZone, false);
2386 // TODO: Don't cast as `InjectionToken<boolean>`, declared type is boolean[]
2387 const autoDetect = this.inject(ComponentFixtureAutoDetect, false);
2388 const ngZone = noNgZone ? null : this.inject(NgZone, null);
2389 const testComponentRenderer = this.inject(TestComponentRenderer);
2390 const rootElId = `root${_nextRootElementId++}`;
2391 testComponentRenderer.insertRootElement(rootElId);
2392 const initComponent = () => {
2393 const componentRef = componentFactory.create(Injector.NULL, [], `#${rootElId}`, this._moduleRef);
2394 return new ComponentFixture(componentRef, ngZone, autoDetect);
2395 };
2396 const fixture = !ngZone ? initComponent() : ngZone.run(initComponent);
2397 this._activeFixtures.push(fixture);
2398 return fixture;
2399 }
2400 destroyActiveFixtures() {
2401 let errorCount = 0;
2402 this._activeFixtures.forEach((fixture) => {
2403 try {
2404 fixture.destroy();
2405 }
2406 catch (e) {
2407 errorCount++;
2408 console.error('Error during cleanup of component', {
2409 component: fixture.componentInstance,
2410 stacktrace: e,
2411 });
2412 }
2413 });
2414 this._activeFixtures = [];
2415 if (errorCount > 0 && this.shouldRethrowTeardownErrors()) {
2416 throw Error(`${errorCount} ${(errorCount === 1 ? 'component' : 'components')} ` +
2417 `threw errors during cleanup`);
2418 }
2419 }
2420 shouldRethrowTeardownErrors() {
2421 const instanceOptions = this._instanceTeardownOptions;
2422 const environmentOptions = TestBedViewEngine._environmentTeardownOptions;
2423 // If the new teardown behavior hasn't been configured, preserve the old behavior.
2424 if (!instanceOptions && !environmentOptions) {
2425 return TEARDOWN_TESTING_MODULE_ON_DESTROY_DEFAULT;
2426 }
2427 // Otherwise use the configured behavior or default to rethrowing.
2428 return instanceOptions?.rethrowErrors ?? environmentOptions?.rethrowErrors ??
2429 this.shouldTearDownTestingModule();
2430 }
2431 shouldTearDownTestingModule() {
2432 return this._instanceTeardownOptions?.destroyAfterEach ??
2433 TestBedViewEngine._environmentTeardownOptions?.destroyAfterEach ??
2434 TEARDOWN_TESTING_MODULE_ON_DESTROY_DEFAULT;
2435 }
2436 tearDownTestingModule() {
2437 // If the module ref has already been destroyed, we won't be able to get a test renderer.
2438 if (this._moduleRef === null) {
2439 return;
2440 }
2441 // Resolve the renderer ahead of time, because we want to remove the root elements as the very
2442 // last step, but the injector will be destroyed as a part of the module ref destruction.
2443 const testRenderer = this.inject(TestComponentRenderer);
2444 try {
2445 this._moduleRef.destroy();
2446 }
2447 catch (e) {
2448 if (this._instanceTeardownOptions?.rethrowErrors ??
2449 TestBedViewEngine._environmentTeardownOptions?.rethrowErrors ?? true) {
2450 throw e;
2451 }
2452 else {
2453 console.error('Error during cleanup of a testing module', {
2454 component: this._moduleRef.instance,
2455 stacktrace: e,
2456 });
2457 }
2458 }
2459 finally {
2460 testRenderer?.removeAllRootElements?.();
2461 }
2462 }
2463}
2464/**
2465 * @description
2466 * Configures and initializes environment for unit testing and provides methods for
2467 * creating components and services in unit tests.
2468 *
2469 * `TestBed` is the primary api for writing unit tests for Angular applications and libraries.
2470 *
2471 * Note: Use `TestBed` in tests. It will be set to either `TestBedViewEngine` or `TestBedRender3`
2472 * according to the compiler used.
2473 *
2474 * @publicApi
2475 */
2476const TestBed = ɵivyEnabled ? TestBedRender3 : TestBedViewEngine;
2477/**
2478 * Returns a singleton of the applicable `TestBed`.
2479 *
2480 * It will be either an instance of `TestBedViewEngine` or `TestBedRender3`.
2481 *
2482 * @publicApi
2483 */
2484const getTestBed = ɵivyEnabled ? _getTestBedRender3 : _getTestBedViewEngine;
2485let testBed;
2486function _getTestBedViewEngine() {
2487 return testBed = testBed || new TestBedViewEngine();
2488}
2489/**
2490 * Allows injecting dependencies in `beforeEach()` and `it()`.
2491 *
2492 * Example:
2493 *
2494 * ```
2495 * beforeEach(inject([Dependency, AClass], (dep, object) => {
2496 * // some code that uses `dep` and `object`
2497 * // ...
2498 * }));
2499 *
2500 * it('...', inject([AClass], (object) => {
2501 * object.doSomething();
2502 * expect(...);
2503 * })
2504 * ```
2505 *
2506 * @publicApi
2507 */
2508function inject(tokens, fn) {
2509 const testBed = getTestBed();
2510 // Not using an arrow function to preserve context passed from call site
2511 return function () {
2512 return testBed.execute(tokens, fn, this);
2513 };
2514}
2515/**
2516 * @publicApi
2517 */
2518class InjectSetupWrapper {
2519 constructor(_moduleDef) {
2520 this._moduleDef = _moduleDef;
2521 }
2522 _addModule() {
2523 const moduleDef = this._moduleDef();
2524 if (moduleDef) {
2525 getTestBed().configureTestingModule(moduleDef);
2526 }
2527 }
2528 inject(tokens, fn) {
2529 const self = this;
2530 // Not using an arrow function to preserve context passed from call site
2531 return function () {
2532 self._addModule();
2533 return inject(tokens, fn).call(this);
2534 };
2535 }
2536}
2537function withModule(moduleDef, fn) {
2538 if (fn) {
2539 // Not using an arrow function to preserve context passed from call site
2540 return function () {
2541 const testBed = getTestBed();
2542 if (moduleDef) {
2543 testBed.configureTestingModule(moduleDef);
2544 }
2545 return fn.apply(this);
2546 };
2547 }
2548 return new InjectSetupWrapper(() => moduleDef);
2549}
2550
2551/**
2552 * @license
2553 * Copyright Google LLC All Rights Reserved.
2554 *
2555 * Use of this source code is governed by an MIT-style license that can be
2556 * found in the LICENSE file at https://angular.io/license
2557 */
2558const _global = (typeof window === 'undefined' ? global : window);
2559// Reset the test providers and the fake async zone before each test.
2560if (_global.beforeEach) {
2561 _global.beforeEach(getCleanupHook(false));
2562}
2563// We provide both a `beforeEach` and `afterEach`, because the updated behavior for
2564// tearing down the module is supposed to run after the test so that we can associate
2565// teardown errors with the correct test.
2566if (_global.afterEach) {
2567 _global.afterEach(getCleanupHook(true));
2568}
2569function getCleanupHook(expectedTeardownValue) {
2570 return () => {
2571 if (TestBed.shouldTearDownTestingModule() ===
2572 expectedTeardownValue) {
2573 TestBed.resetTestingModule();
2574 resetFakeAsyncZone();
2575 }
2576 };
2577}
2578/**
2579 * This API should be removed. But doing so seems to break `google3` and so it requires a bit of
2580 * investigation.
2581 *
2582 * A work around is to mark it as `@codeGenApi` for now and investigate later.
2583 *
2584 * @codeGenApi
2585 */
2586// TODO(iminar): Remove this code in a safe way.
2587const __core_private_testing_placeholder__ = '';
2588
2589/**
2590 * @license
2591 * Copyright Google LLC All Rights Reserved.
2592 *
2593 * Use of this source code is governed by an MIT-style license that can be
2594 * found in the LICENSE file at https://angular.io/license
2595 */
2596
2597/**
2598 * @license
2599 * Copyright Google LLC All Rights Reserved.
2600 *
2601 * Use of this source code is governed by an MIT-style license that can be
2602 * found in the LICENSE file at https://angular.io/license
2603 */
2604
2605/**
2606 * @license
2607 * Copyright Google LLC All Rights Reserved.
2608 *
2609 * Use of this source code is governed by an MIT-style license that can be
2610 * found in the LICENSE file at https://angular.io/license
2611 */
2612
2613/**
2614 * @license
2615 * Copyright Google LLC All Rights Reserved.
2616 *
2617 * Use of this source code is governed by an MIT-style license that can be
2618 * found in the LICENSE file at https://angular.io/license
2619 */
2620// This file only reexports content of the `src` folder. Keep it that way.
2621
2622/**
2623 * @license
2624 * Copyright Google LLC All Rights Reserved.
2625 *
2626 * Use of this source code is governed by an MIT-style license that can be
2627 * found in the LICENSE file at https://angular.io/license
2628 */
2629
2630/**
2631 * Generated bundle index. Do not edit.
2632 */
2633
2634export { ComponentFixture, ComponentFixtureAutoDetect, ComponentFixtureNoNgZone, InjectSetupWrapper, TestBed, TestComponentRenderer, __core_private_testing_placeholder__, async, discardPeriodicTasks, fakeAsync, flush, flushMicrotasks, getTestBed, inject, resetFakeAsyncZone, tick, waitForAsync, withModule, MetadataOverrider as ɵMetadataOverrider, TestingCompiler as ɵTestingCompiler, TestingCompilerFactory as ɵTestingCompilerFactory };
2635//# sourceMappingURL=testing.mjs.map