| /** |
| * @license Angular v8.1.1 |
| * (c) 2010-2019 Google LLC. https://angular.io/ |
| * License: MIT |
| */ |
| |
| import { getDebugNode, RendererFactory2, InjectionToken, ɵstringify, ɵReflectionCapabilities, Directive, Component, Pipe, NgModule, ɵgetInjectableDef, ɵNG_COMPONENT_DEF, ɵRender3NgModuleRef, LOCALE_ID, ɵDEFAULT_LOCALE_ID, ɵsetLocaleId, ApplicationInitStatus, ɵRender3ComponentFactory, ɵcompileComponent, ɵNG_DIRECTIVE_DEF, ɵcompileDirective, ɵNG_PIPE_DEF, ɵcompilePipe, ɵpatchComponentDefWithScope, ɵNG_INJECTOR_DEF, ɵNG_MODULE_DEF, ɵcompileNgModuleDefs, NgZone, Compiler, COMPILER_OPTIONS, ɵNgModuleFactory, ModuleWithComponentFactories, ɵtransitiveScopesFor, Injector, InjectFlags, ɵresetCompiledComponents, ɵflushModuleScopingQueueAsMuchAsPossible, Injectable, ɵclearOverrides, ɵoverrideComponentView, ɵAPP_ROOT, ɵoverrideProvider, ɵivyEnabled, Optional, SkipSelf } from '@angular/core'; |
| import { __awaiter } from 'tslib'; |
| import { ResourceLoader } from '@angular/compiler'; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| /** @type {?} */ |
| const _global = (/** @type {?} */ ((typeof window === 'undefined' ? global : window))); |
| /** |
| * Wraps a test function in an asynchronous test zone. The test will automatically |
| * complete when all asynchronous calls within this zone are done. Can be used |
| * to wrap an {\@link inject} call. |
| * |
| * Example: |
| * |
| * ``` |
| * it('...', async(inject([AClass], (object) => { |
| * object.doSomething.then(() => { |
| * expect(...); |
| * }) |
| * }); |
| * ``` |
| * |
| * |
| * @param {?} fn |
| * @return {?} |
| */ |
| function asyncFallback(fn) { |
| // If we're running using the Jasmine test framework, adapt to call the 'done' |
| // function when asynchronous activity is finished. |
| if (_global.jasmine) { |
| // Not using an arrow function to preserve context passed from call site |
| return (/** |
| * @param {?} done |
| * @return {?} |
| */ |
| function (done) { |
| if (!done) { |
| // if we run beforeEach in @angular/core/testing/testing_internal then we get no done |
| // fake it here and assume sync. |
| done = (/** |
| * @return {?} |
| */ |
| function () { }); |
| done.fail = (/** |
| * @param {?} e |
| * @return {?} |
| */ |
| function (e) { throw e; }); |
| } |
| runInTestZone(fn, this, done, (/** |
| * @param {?} err |
| * @return {?} |
| */ |
| (err) => { |
| if (typeof err === 'string') { |
| return done.fail(new Error((/** @type {?} */ (err)))); |
| } |
| else { |
| done.fail(err); |
| } |
| })); |
| }); |
| } |
| // Otherwise, return a promise which will resolve when asynchronous activity |
| // is finished. This will be correctly consumed by the Mocha framework with |
| // it('...', async(myFn)); or can be used in a custom framework. |
| // Not using an arrow function to preserve context passed from call site |
| return (/** |
| * @return {?} |
| */ |
| function () { |
| return new Promise((/** |
| * @param {?} finishCallback |
| * @param {?} failCallback |
| * @return {?} |
| */ |
| (finishCallback, failCallback) => { |
| runInTestZone(fn, this, finishCallback, failCallback); |
| })); |
| }); |
| } |
| /** |
| * @param {?} fn |
| * @param {?} context |
| * @param {?} finishCallback |
| * @param {?} failCallback |
| * @return {?} |
| */ |
| function runInTestZone(fn, context, finishCallback, failCallback) { |
| /** @type {?} */ |
| const currentZone = Zone.current; |
| /** @type {?} */ |
| const AsyncTestZoneSpec = ((/** @type {?} */ (Zone)))['AsyncTestZoneSpec']; |
| if (AsyncTestZoneSpec === undefined) { |
| throw new Error('AsyncTestZoneSpec is needed for the async() test helper but could not be found. ' + |
| 'Please make sure that your environment includes zone.js/dist/async-test.js'); |
| } |
| /** @type {?} */ |
| const ProxyZoneSpec = (/** @type {?} */ (((/** @type {?} */ (Zone)))['ProxyZoneSpec'])); |
| if (ProxyZoneSpec === undefined) { |
| throw new Error('ProxyZoneSpec is needed for the async() test helper but could not be found. ' + |
| 'Please make sure that your environment includes zone.js/dist/proxy.js'); |
| } |
| /** @type {?} */ |
| const proxyZoneSpec = ProxyZoneSpec.get(); |
| ProxyZoneSpec.assertPresent(); |
| // We need to create the AsyncTestZoneSpec outside the ProxyZone. |
| // If we do it in ProxyZone then we will get to infinite recursion. |
| /** @type {?} */ |
| const proxyZone = Zone.current.getZoneWith('ProxyZoneSpec'); |
| /** @type {?} */ |
| const previousDelegate = proxyZoneSpec.getDelegate(); |
| (/** @type {?} */ ((/** @type {?} */ (proxyZone)).parent)).run((/** |
| * @return {?} |
| */ |
| () => { |
| /** @type {?} */ |
| const testZoneSpec = new AsyncTestZoneSpec((/** |
| * @return {?} |
| */ |
| () => { |
| // Need to restore the original zone. |
| currentZone.run((/** |
| * @return {?} |
| */ |
| () => { |
| if (proxyZoneSpec.getDelegate() == testZoneSpec) { |
| // Only reset the zone spec if it's sill this one. Otherwise, assume it's OK. |
| proxyZoneSpec.setDelegate(previousDelegate); |
| } |
| finishCallback(); |
| })); |
| }), (/** |
| * @param {?} error |
| * @return {?} |
| */ |
| (error) => { |
| // Need to restore the original zone. |
| currentZone.run((/** |
| * @return {?} |
| */ |
| () => { |
| if (proxyZoneSpec.getDelegate() == testZoneSpec) { |
| // Only reset the zone spec if it's sill this one. Otherwise, assume it's OK. |
| proxyZoneSpec.setDelegate(previousDelegate); |
| } |
| failCallback(error); |
| })); |
| }), 'test'); |
| proxyZoneSpec.setDelegate(testZoneSpec); |
| })); |
| return Zone.current.runGuarded(fn, context); |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * Wraps a test function in an asynchronous test zone. The test will automatically |
| * complete when all asynchronous calls within this zone are done. Can be used |
| * to wrap an {\@link inject} call. |
| * |
| * Example: |
| * |
| * ``` |
| * it('...', async(inject([AClass], (object) => { |
| * object.doSomething.then(() => { |
| * expect(...); |
| * }) |
| * }); |
| * ``` |
| * |
| * \@publicApi |
| * @param {?} fn |
| * @return {?} |
| */ |
| function async(fn) { |
| /** @type {?} */ |
| const _Zone = typeof Zone !== 'undefined' ? Zone : null; |
| if (!_Zone) { |
| return (/** |
| * @return {?} |
| */ |
| function () { |
| return Promise.reject('Zone is needed for the async() test helper but could not be found. ' + |
| 'Please make sure that your environment includes zone.js/dist/zone.js'); |
| }); |
| } |
| /** @type {?} */ |
| const asyncTest = _Zone && _Zone[_Zone.__symbol__('asyncTest')]; |
| if (typeof asyncTest === 'function') { |
| return asyncTest(fn); |
| } |
| // not using new version of zone.js |
| // TODO @JiaLiPassion, remove this after all library updated to |
| // newest version of zone.js(0.8.25) |
| return asyncFallback(fn); |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * Fixture for debugging and testing a component. |
| * |
| * \@publicApi |
| * @template T |
| */ |
| class ComponentFixture { |
| /** |
| * @param {?} componentRef |
| * @param {?} ngZone |
| * @param {?} _autoDetect |
| */ |
| constructor(componentRef, ngZone, _autoDetect) { |
| this.componentRef = componentRef; |
| this.ngZone = ngZone; |
| this._autoDetect = _autoDetect; |
| this._isStable = true; |
| this._isDestroyed = false; |
| this._resolve = null; |
| this._promise = null; |
| this._onUnstableSubscription = null; |
| this._onStableSubscription = null; |
| this._onMicrotaskEmptySubscription = null; |
| this._onErrorSubscription = null; |
| this.changeDetectorRef = componentRef.changeDetectorRef; |
| this.elementRef = componentRef.location; |
| this.debugElement = (/** @type {?} */ (getDebugNode(this.elementRef.nativeElement))); |
| this.componentInstance = componentRef.instance; |
| this.nativeElement = this.elementRef.nativeElement; |
| this.componentRef = componentRef; |
| this.ngZone = ngZone; |
| if (ngZone) { |
| // Create subscriptions outside the NgZone so that the callbacks run oustide |
| // of NgZone. |
| ngZone.runOutsideAngular((/** |
| * @return {?} |
| */ |
| () => { |
| this._onUnstableSubscription = |
| ngZone.onUnstable.subscribe({ next: (/** |
| * @return {?} |
| */ |
| () => { this._isStable = false; }) }); |
| this._onMicrotaskEmptySubscription = ngZone.onMicrotaskEmpty.subscribe({ |
| next: (/** |
| * @return {?} |
| */ |
| () => { |
| if (this._autoDetect) { |
| // Do a change detection run with checkNoChanges set to true to check |
| // there are no changes on the second run. |
| this.detectChanges(true); |
| } |
| }) |
| }); |
| this._onStableSubscription = ngZone.onStable.subscribe({ |
| next: (/** |
| * @return {?} |
| */ |
| () => { |
| this._isStable = true; |
| // Check whether there is a pending whenStable() completer to resolve. |
| if (this._promise !== null) { |
| // If so check whether there are no pending macrotasks before resolving. |
| // Do this check in the next tick so that ngZone gets a chance to update the state of |
| // pending macrotasks. |
| scheduleMicroTask((/** |
| * @return {?} |
| */ |
| () => { |
| if (!ngZone.hasPendingMacrotasks) { |
| if (this._promise !== null) { |
| (/** @type {?} */ (this._resolve))(true); |
| this._resolve = null; |
| this._promise = null; |
| } |
| } |
| })); |
| } |
| }) |
| }); |
| this._onErrorSubscription = |
| ngZone.onError.subscribe({ next: (/** |
| * @param {?} error |
| * @return {?} |
| */ |
| (error) => { throw error; }) }); |
| })); |
| } |
| } |
| /** |
| * @private |
| * @param {?} checkNoChanges |
| * @return {?} |
| */ |
| _tick(checkNoChanges) { |
| this.changeDetectorRef.detectChanges(); |
| if (checkNoChanges) { |
| this.checkNoChanges(); |
| } |
| } |
| /** |
| * Trigger a change detection cycle for the component. |
| * @param {?=} checkNoChanges |
| * @return {?} |
| */ |
| detectChanges(checkNoChanges = true) { |
| if (this.ngZone != null) { |
| // Run the change detection inside the NgZone so that any async tasks as part of the change |
| // detection are captured by the zone and can be waited for in isStable. |
| this.ngZone.run((/** |
| * @return {?} |
| */ |
| () => { this._tick(checkNoChanges); })); |
| } |
| else { |
| // Running without zone. Just do the change detection. |
| this._tick(checkNoChanges); |
| } |
| } |
| /** |
| * Do a change detection run to make sure there were no changes. |
| * @return {?} |
| */ |
| checkNoChanges() { this.changeDetectorRef.checkNoChanges(); } |
| /** |
| * Set whether the fixture should autodetect changes. |
| * |
| * Also runs detectChanges once so that any existing change is detected. |
| * @param {?=} autoDetect |
| * @return {?} |
| */ |
| autoDetectChanges(autoDetect = true) { |
| if (this.ngZone == null) { |
| throw new Error('Cannot call autoDetectChanges when ComponentFixtureNoNgZone is set'); |
| } |
| this._autoDetect = autoDetect; |
| this.detectChanges(); |
| } |
| /** |
| * Return whether the fixture is currently stable or has async tasks that have not been completed |
| * yet. |
| * @return {?} |
| */ |
| isStable() { return this._isStable && !(/** @type {?} */ (this.ngZone)).hasPendingMacrotasks; } |
| /** |
| * Get a promise that resolves when the fixture is stable. |
| * |
| * This can be used to resume testing after events have triggered asynchronous activity or |
| * asynchronous change detection. |
| * @return {?} |
| */ |
| whenStable() { |
| if (this.isStable()) { |
| return Promise.resolve(false); |
| } |
| else if (this._promise !== null) { |
| return this._promise; |
| } |
| else { |
| this._promise = new Promise((/** |
| * @param {?} res |
| * @return {?} |
| */ |
| res => { this._resolve = res; })); |
| return this._promise; |
| } |
| } |
| /** |
| * @private |
| * @return {?} |
| */ |
| _getRenderer() { |
| if (this._renderer === undefined) { |
| this._renderer = this.componentRef.injector.get(RendererFactory2, null); |
| } |
| return (/** @type {?} */ (this._renderer)); |
| } |
| /** |
| * Get a promise that resolves when the ui state is stable following animations. |
| * @return {?} |
| */ |
| whenRenderingDone() { |
| /** @type {?} */ |
| const renderer = this._getRenderer(); |
| if (renderer && renderer.whenRenderingDone) { |
| return renderer.whenRenderingDone(); |
| } |
| return this.whenStable(); |
| } |
| /** |
| * Trigger component destruction. |
| * @return {?} |
| */ |
| destroy() { |
| if (!this._isDestroyed) { |
| this.componentRef.destroy(); |
| if (this._onUnstableSubscription != null) { |
| this._onUnstableSubscription.unsubscribe(); |
| this._onUnstableSubscription = null; |
| } |
| if (this._onStableSubscription != null) { |
| this._onStableSubscription.unsubscribe(); |
| this._onStableSubscription = null; |
| } |
| if (this._onMicrotaskEmptySubscription != null) { |
| this._onMicrotaskEmptySubscription.unsubscribe(); |
| this._onMicrotaskEmptySubscription = null; |
| } |
| if (this._onErrorSubscription != null) { |
| this._onErrorSubscription.unsubscribe(); |
| this._onErrorSubscription = null; |
| } |
| this._isDestroyed = true; |
| } |
| } |
| } |
| /** |
| * @param {?} fn |
| * @return {?} |
| */ |
| function scheduleMicroTask(fn) { |
| Zone.current.scheduleMicroTask('scheduleMicrotask', fn); |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| /** |
| * fakeAsync has been moved to zone.js |
| * this file is for fallback in case old version of zone.js is used |
| * @type {?} |
| */ |
| const _Zone = typeof Zone !== 'undefined' ? Zone : null; |
| /** @type {?} */ |
| const FakeAsyncTestZoneSpec = _Zone && _Zone['FakeAsyncTestZoneSpec']; |
| /** @type {?} */ |
| const ProxyZoneSpec = _Zone && _Zone['ProxyZoneSpec']; |
| /** @type {?} */ |
| let _fakeAsyncTestZoneSpec = null; |
| /** |
| * Clears out the shared fake async zone for a test. |
| * To be called in a global `beforeEach`. |
| * |
| * \@publicApi |
| * @return {?} |
| */ |
| function resetFakeAsyncZoneFallback() { |
| _fakeAsyncTestZoneSpec = null; |
| // in node.js testing we may not have ProxyZoneSpec in which case there is nothing to reset. |
| ProxyZoneSpec && ProxyZoneSpec.assertPresent().resetDelegate(); |
| } |
| /** @type {?} */ |
| let _inFakeAsyncCall = false; |
| /** |
| * Wraps a function to be executed in the fakeAsync zone: |
| * - microtasks are manually executed by calling `flushMicrotasks()`, |
| * - timers are synchronous, `tick()` simulates the asynchronous passage of time. |
| * |
| * If there are any pending timers at the end of the function, an exception will be thrown. |
| * |
| * Can be used to wrap inject() calls. |
| * |
| * \@usageNotes |
| * ### Example |
| * |
| * {\@example core/testing/ts/fake_async.ts region='basic'} |
| * |
| * \@publicApi |
| * @param {?} fn |
| * @return {?} The function wrapped to be executed in the fakeAsync zone |
| * |
| */ |
| function fakeAsyncFallback(fn) { |
| // Not using an arrow function to preserve context passed from call site |
| return (/** |
| * @param {...?} args |
| * @return {?} |
| */ |
| function (...args) { |
| /** @type {?} */ |
| const proxyZoneSpec = ProxyZoneSpec.assertPresent(); |
| if (_inFakeAsyncCall) { |
| throw new Error('fakeAsync() calls can not be nested'); |
| } |
| _inFakeAsyncCall = true; |
| try { |
| if (!_fakeAsyncTestZoneSpec) { |
| if (proxyZoneSpec.getDelegate() instanceof FakeAsyncTestZoneSpec) { |
| throw new Error('fakeAsync() calls can not be nested'); |
| } |
| _fakeAsyncTestZoneSpec = new FakeAsyncTestZoneSpec(); |
| } |
| /** @type {?} */ |
| let res; |
| /** @type {?} */ |
| const lastProxyZoneSpec = proxyZoneSpec.getDelegate(); |
| proxyZoneSpec.setDelegate(_fakeAsyncTestZoneSpec); |
| try { |
| res = fn.apply(this, args); |
| flushMicrotasksFallback(); |
| } |
| finally { |
| proxyZoneSpec.setDelegate(lastProxyZoneSpec); |
| } |
| if (_fakeAsyncTestZoneSpec.pendingPeriodicTimers.length > 0) { |
| throw new Error(`${_fakeAsyncTestZoneSpec.pendingPeriodicTimers.length} ` + |
| `periodic timer(s) still in the queue.`); |
| } |
| if (_fakeAsyncTestZoneSpec.pendingTimers.length > 0) { |
| throw new Error(`${_fakeAsyncTestZoneSpec.pendingTimers.length} timer(s) still in the queue.`); |
| } |
| return res; |
| } |
| finally { |
| _inFakeAsyncCall = false; |
| resetFakeAsyncZoneFallback(); |
| } |
| }); |
| } |
| /** |
| * @return {?} |
| */ |
| function _getFakeAsyncZoneSpec() { |
| if (_fakeAsyncTestZoneSpec == null) { |
| throw new Error('The code should be running in the fakeAsync zone to call this function'); |
| } |
| return _fakeAsyncTestZoneSpec; |
| } |
| /** |
| * Simulates the asynchronous passage of time for the timers in the fakeAsync zone. |
| * |
| * The microtasks queue is drained at the very start of this function and after any timer callback |
| * has been executed. |
| * |
| * \@usageNotes |
| * ### Example |
| * |
| * {\@example core/testing/ts/fake_async.ts region='basic'} |
| * |
| * \@publicApi |
| * @param {?=} millis |
| * @return {?} |
| */ |
| function tickFallback(millis = 0) { |
| _getFakeAsyncZoneSpec().tick(millis); |
| } |
| /** |
| * Simulates the asynchronous passage of time for the timers in the fakeAsync zone by |
| * draining the macrotask queue until it is empty. The returned value is the milliseconds |
| * of time that would have been elapsed. |
| * |
| * \@publicApi |
| * @param {?=} maxTurns |
| * @return {?} The simulated time elapsed, in millis. |
| * |
| */ |
| function flushFallback(maxTurns) { |
| return _getFakeAsyncZoneSpec().flush(maxTurns); |
| } |
| /** |
| * Discard all remaining periodic tasks. |
| * |
| * \@publicApi |
| * @return {?} |
| */ |
| function discardPeriodicTasksFallback() { |
| /** @type {?} */ |
| const zoneSpec = _getFakeAsyncZoneSpec(); |
| zoneSpec.pendingPeriodicTimers.length = 0; |
| } |
| /** |
| * Flush any pending microtasks. |
| * |
| * \@publicApi |
| * @return {?} |
| */ |
| function flushMicrotasksFallback() { |
| _getFakeAsyncZoneSpec().flushMicrotasks(); |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** @type {?} */ |
| const _Zone$1 = typeof Zone !== 'undefined' ? Zone : null; |
| /** @type {?} */ |
| const fakeAsyncTestModule = _Zone$1 && _Zone$1[_Zone$1.__symbol__('fakeAsyncTest')]; |
| /** |
| * Clears out the shared fake async zone for a test. |
| * To be called in a global `beforeEach`. |
| * |
| * \@publicApi |
| * @return {?} |
| */ |
| function resetFakeAsyncZone() { |
| if (fakeAsyncTestModule) { |
| return fakeAsyncTestModule.resetFakeAsyncZone(); |
| } |
| else { |
| return resetFakeAsyncZoneFallback(); |
| } |
| } |
| /** |
| * Wraps a function to be executed in the fakeAsync zone: |
| * - microtasks are manually executed by calling `flushMicrotasks()`, |
| * - timers are synchronous, `tick()` simulates the asynchronous passage of time. |
| * |
| * If there are any pending timers at the end of the function, an exception will be thrown. |
| * |
| * Can be used to wrap inject() calls. |
| * |
| * \@usageNotes |
| * ### Example |
| * |
| * {\@example core/testing/ts/fake_async.ts region='basic'} |
| * |
| * \@publicApi |
| * @param {?} fn |
| * @return {?} The function wrapped to be executed in the fakeAsync zone |
| * |
| */ |
| function fakeAsync(fn) { |
| if (fakeAsyncTestModule) { |
| return fakeAsyncTestModule.fakeAsync(fn); |
| } |
| else { |
| return fakeAsyncFallback(fn); |
| } |
| } |
| /** |
| * Simulates the asynchronous passage of time for the timers in the fakeAsync zone. |
| * |
| * The microtasks queue is drained at the very start of this function and after any timer callback |
| * has been executed. |
| * |
| * \@usageNotes |
| * ### Example |
| * |
| * {\@example core/testing/ts/fake_async.ts region='basic'} |
| * |
| * \@publicApi |
| * @param {?=} millis |
| * @return {?} |
| */ |
| function tick(millis = 0) { |
| if (fakeAsyncTestModule) { |
| return fakeAsyncTestModule.tick(millis); |
| } |
| else { |
| return tickFallback(millis); |
| } |
| } |
| /** |
| * Simulates the asynchronous passage of time for the timers in the fakeAsync zone by |
| * draining the macrotask queue until it is empty. The returned value is the milliseconds |
| * of time that would have been elapsed. |
| * |
| * \@publicApi |
| * @param {?=} maxTurns |
| * @return {?} The simulated time elapsed, in millis. |
| * |
| */ |
| function flush(maxTurns) { |
| if (fakeAsyncTestModule) { |
| return fakeAsyncTestModule.flush(maxTurns); |
| } |
| else { |
| return flushFallback(maxTurns); |
| } |
| } |
| /** |
| * Discard all remaining periodic tasks. |
| * |
| * \@publicApi |
| * @return {?} |
| */ |
| function discardPeriodicTasks() { |
| if (fakeAsyncTestModule) { |
| return fakeAsyncTestModule.discardPeriodicTasks(); |
| } |
| else { |
| discardPeriodicTasksFallback(); |
| } |
| } |
| /** |
| * Flush any pending microtasks. |
| * |
| * \@publicApi |
| * @return {?} |
| */ |
| function flushMicrotasks() { |
| if (fakeAsyncTestModule) { |
| return fakeAsyncTestModule.flushMicrotasks(); |
| } |
| else { |
| return flushMicrotasksFallback(); |
| } |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| /** |
| * Injectable completer that allows signaling completion of an asynchronous test. Used internally. |
| */ |
| class AsyncTestCompleter { |
| constructor() { |
| this._promise = new Promise((/** |
| * @param {?} res |
| * @param {?} rej |
| * @return {?} |
| */ |
| (res, rej) => { |
| this._resolve = res; |
| this._reject = rej; |
| })); |
| } |
| /** |
| * @param {?=} value |
| * @return {?} |
| */ |
| done(value) { this._resolve(value); } |
| /** |
| * @param {?=} error |
| * @param {?=} stackTrace |
| * @return {?} |
| */ |
| fail(error, stackTrace) { this._reject(error); } |
| /** |
| * @return {?} |
| */ |
| get promise() { return this._promise; } |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * An abstract class for inserting the root test component element in a platform independent way. |
| * |
| * \@publicApi |
| */ |
| class TestComponentRenderer { |
| /** |
| * @param {?} rootElementId |
| * @return {?} |
| */ |
| insertRootElement(rootElementId) { } |
| } |
| /** |
| * \@publicApi |
| * @type {?} |
| */ |
| const ComponentFixtureAutoDetect = new InjectionToken('ComponentFixtureAutoDetect'); |
| /** |
| * \@publicApi |
| * @type {?} |
| */ |
| const ComponentFixtureNoNgZone = new InjectionToken('ComponentFixtureNoNgZone'); |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| /** |
| * Used to resolve resource URLs on `\@Component` when used with JIT compilation. |
| * |
| * Example: |
| * ``` |
| * \@Component({ |
| * selector: 'my-comp', |
| * templateUrl: 'my-comp.html', // This requires asynchronous resolution |
| * }) |
| * class MyComponent{ |
| * } |
| * |
| * // Calling `renderComponent` will fail because `renderComponent` is a synchronous process |
| * // and `MyComponent`'s `\@Component.templateUrl` needs to be resolved asynchronously. |
| * |
| * // Calling `resolveComponentResources()` will resolve `\@Component.templateUrl` into |
| * // `\@Component.template`, which allows `renderComponent` to proceed in a synchronous manner. |
| * |
| * // Use browser's `fetch()` function as the default resource resolution strategy. |
| * resolveComponentResources(fetch).then(() => { |
| * // After resolution all URLs have been converted into `template` strings. |
| * renderComponent(MyComponent); |
| * }); |
| * |
| * ``` |
| * |
| * NOTE: In AOT the resolution happens during compilation, and so there should be no need |
| * to call this method outside JIT mode. |
| * |
| * @param {?} resourceResolver a function which is responsible for returning a `Promise` to the |
| * contents of the resolved URL. Browser's `fetch()` method is a good default implementation. |
| * @return {?} |
| */ |
| function resolveComponentResources(resourceResolver) { |
| // Store all promises which are fetching the resources. |
| /** @type {?} */ |
| const componentResolved = []; |
| // Cache so that we don't fetch the same resource more than once. |
| /** @type {?} */ |
| const urlMap = new Map(); |
| /** |
| * @param {?} url |
| * @return {?} |
| */ |
| function cachedResourceResolve(url) { |
| /** @type {?} */ |
| let promise = urlMap.get(url); |
| if (!promise) { |
| /** @type {?} */ |
| const resp = resourceResolver(url); |
| urlMap.set(url, promise = resp.then(unwrapResponse)); |
| } |
| return promise; |
| } |
| componentResourceResolutionQueue.forEach((/** |
| * @param {?} component |
| * @param {?} type |
| * @return {?} |
| */ |
| (component, type) => { |
| /** @type {?} */ |
| const promises = []; |
| if (component.templateUrl) { |
| promises.push(cachedResourceResolve(component.templateUrl).then((/** |
| * @param {?} template |
| * @return {?} |
| */ |
| (template) => { |
| component.template = template; |
| }))); |
| } |
| /** @type {?} */ |
| const styleUrls = component.styleUrls; |
| /** @type {?} */ |
| const styles = component.styles || (component.styles = []); |
| /** @type {?} */ |
| const styleOffset = component.styles.length; |
| styleUrls && styleUrls.forEach((/** |
| * @param {?} styleUrl |
| * @param {?} index |
| * @return {?} |
| */ |
| (styleUrl, index) => { |
| styles.push(''); // pre-allocate array. |
| promises.push(cachedResourceResolve(styleUrl).then((/** |
| * @param {?} style |
| * @return {?} |
| */ |
| (style) => { |
| styles[styleOffset + index] = style; |
| styleUrls.splice(styleUrls.indexOf(styleUrl), 1); |
| if (styleUrls.length == 0) { |
| component.styleUrls = undefined; |
| } |
| }))); |
| })); |
| /** @type {?} */ |
| const fullyResolved = Promise.all(promises).then((/** |
| * @return {?} |
| */ |
| () => componentDefResolved(type))); |
| componentResolved.push(fullyResolved); |
| })); |
| clearResolutionOfComponentResourcesQueue(); |
| return Promise.all(componentResolved).then((/** |
| * @return {?} |
| */ |
| () => undefined)); |
| } |
| /** @type {?} */ |
| let componentResourceResolutionQueue = new Map(); |
| // Track when existing ngComponentDef for a Type is waiting on resources. |
| /** @type {?} */ |
| const componentDefPendingResolution = new Set(); |
| /** |
| * @param {?} type |
| * @return {?} |
| */ |
| function isComponentDefPendingResolution(type) { |
| return componentDefPendingResolution.has(type); |
| } |
| /** |
| * @return {?} |
| */ |
| function clearResolutionOfComponentResourcesQueue() { |
| /** @type {?} */ |
| const old = componentResourceResolutionQueue; |
| componentResourceResolutionQueue = new Map(); |
| return old; |
| } |
| /** |
| * @param {?} queue |
| * @return {?} |
| */ |
| function restoreComponentResolutionQueue(queue) { |
| componentDefPendingResolution.clear(); |
| queue.forEach((/** |
| * @param {?} _ |
| * @param {?} type |
| * @return {?} |
| */ |
| (_, type) => componentDefPendingResolution.add(type))); |
| componentResourceResolutionQueue = queue; |
| } |
| /** |
| * @param {?} response |
| * @return {?} |
| */ |
| function unwrapResponse(response) { |
| return typeof response == 'string' ? response : response.text(); |
| } |
| /** |
| * @param {?} type |
| * @return {?} |
| */ |
| function componentDefResolved(type) { |
| componentDefPendingResolution.delete(type); |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** @type {?} */ |
| let _nextReferenceId = 0; |
| class MetadataOverrider { |
| constructor() { |
| this._references = new Map(); |
| } |
| /** |
| * Creates a new instance for the given metadata class |
| * based on an old instance and overrides. |
| * @template C, T |
| * @param {?} metadataClass |
| * @param {?} oldMetadata |
| * @param {?} override |
| * @return {?} |
| */ |
| overrideMetadata(metadataClass, oldMetadata, override) { |
| /** @type {?} */ |
| const props = {}; |
| if (oldMetadata) { |
| _valueProps(oldMetadata).forEach((/** |
| * @param {?} prop |
| * @return {?} |
| */ |
| (prop) => props[prop] = ((/** @type {?} */ (oldMetadata)))[prop])); |
| } |
| if (override.set) { |
| if (override.remove || override.add) { |
| throw new Error(`Cannot set and add/remove ${ɵstringify(metadataClass)} at the same time!`); |
| } |
| setMetadata(props, override.set); |
| } |
| if (override.remove) { |
| removeMetadata(props, override.remove, this._references); |
| } |
| if (override.add) { |
| addMetadata(props, override.add); |
| } |
| return new metadataClass((/** @type {?} */ (props))); |
| } |
| } |
| /** |
| * @param {?} metadata |
| * @param {?} remove |
| * @param {?} references |
| * @return {?} |
| */ |
| function removeMetadata(metadata, remove, references) { |
| /** @type {?} */ |
| const removeObjects = new Set(); |
| for (const prop in remove) { |
| /** @type {?} */ |
| const removeValue = remove[prop]; |
| if (removeValue instanceof Array) { |
| removeValue.forEach((/** |
| * @param {?} value |
| * @return {?} |
| */ |
| (value) => { removeObjects.add(_propHashKey(prop, value, references)); })); |
| } |
| else { |
| removeObjects.add(_propHashKey(prop, removeValue, references)); |
| } |
| } |
| for (const prop in metadata) { |
| /** @type {?} */ |
| const propValue = metadata[prop]; |
| if (propValue instanceof Array) { |
| metadata[prop] = propValue.filter((/** |
| * @param {?} value |
| * @return {?} |
| */ |
| (value) => !removeObjects.has(_propHashKey(prop, value, references)))); |
| } |
| else { |
| if (removeObjects.has(_propHashKey(prop, propValue, references))) { |
| metadata[prop] = undefined; |
| } |
| } |
| } |
| } |
| /** |
| * @param {?} metadata |
| * @param {?} add |
| * @return {?} |
| */ |
| function addMetadata(metadata, add) { |
| for (const prop in add) { |
| /** @type {?} */ |
| const addValue = add[prop]; |
| /** @type {?} */ |
| const propValue = metadata[prop]; |
| if (propValue != null && propValue instanceof Array) { |
| metadata[prop] = propValue.concat(addValue); |
| } |
| else { |
| metadata[prop] = addValue; |
| } |
| } |
| } |
| /** |
| * @param {?} metadata |
| * @param {?} set |
| * @return {?} |
| */ |
| function setMetadata(metadata, set) { |
| for (const prop in set) { |
| metadata[prop] = set[prop]; |
| } |
| } |
| /** |
| * @param {?} propName |
| * @param {?} propValue |
| * @param {?} references |
| * @return {?} |
| */ |
| function _propHashKey(propName, propValue, references) { |
| /** @type {?} */ |
| const replacer = (/** |
| * @param {?} key |
| * @param {?} value |
| * @return {?} |
| */ |
| (key, value) => { |
| if (typeof value === 'function') { |
| value = _serializeReference(value, references); |
| } |
| return value; |
| }); |
| return `${propName}:${JSON.stringify(propValue, replacer)}`; |
| } |
| /** |
| * @param {?} ref |
| * @param {?} references |
| * @return {?} |
| */ |
| function _serializeReference(ref, references) { |
| /** @type {?} */ |
| let id = references.get(ref); |
| if (!id) { |
| id = `${ɵstringify(ref)}${_nextReferenceId++}`; |
| references.set(ref, id); |
| } |
| return id; |
| } |
| /** |
| * @param {?} obj |
| * @return {?} |
| */ |
| function _valueProps(obj) { |
| /** @type {?} */ |
| const props = []; |
| // regular public props |
| Object.keys(obj).forEach((/** |
| * @param {?} prop |
| * @return {?} |
| */ |
| (prop) => { |
| if (!prop.startsWith('_')) { |
| props.push(prop); |
| } |
| })); |
| // getters |
| /** @type {?} */ |
| let proto = obj; |
| while (proto = Object.getPrototypeOf(proto)) { |
| Object.keys(proto).forEach((/** |
| * @param {?} protoProp |
| * @return {?} |
| */ |
| (protoProp) => { |
| /** @type {?} */ |
| const desc = Object.getOwnPropertyDescriptor(proto, protoProp); |
| if (!protoProp.startsWith('_') && desc && 'get' in desc) { |
| props.push(protoProp); |
| } |
| })); |
| } |
| return props; |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** @type {?} */ |
| const reflection = new ɵReflectionCapabilities(); |
| /** |
| * Allows to override ivy metadata for tests (via the `TestBed`). |
| * @abstract |
| * @template T |
| */ |
| class OverrideResolver { |
| constructor() { |
| this.overrides = new Map(); |
| this.resolved = new Map(); |
| } |
| /** |
| * @param {?} type |
| * @param {?} override |
| * @return {?} |
| */ |
| addOverride(type, override) { |
| /** @type {?} */ |
| const overrides = this.overrides.get(type) || []; |
| overrides.push(override); |
| this.overrides.set(type, overrides); |
| this.resolved.delete(type); |
| } |
| /** |
| * @param {?} overrides |
| * @return {?} |
| */ |
| setOverrides(overrides) { |
| this.overrides.clear(); |
| overrides.forEach((/** |
| * @param {?} __0 |
| * @return {?} |
| */ |
| ([type, override]) => { this.addOverride(type, override); })); |
| } |
| /** |
| * @param {?} type |
| * @return {?} |
| */ |
| getAnnotation(type) { |
| /** @type {?} */ |
| const annotations = reflection.annotations(type); |
| // Try to find the nearest known Type annotation and make sure that this annotation is an |
| // instance of the type we are looking for, so we can use it for resolution. Note: there might |
| // be multiple known annotations found due to the fact that Components can extend Directives (so |
| // both Directive and Component annotations would be present), so we always check if the known |
| // annotation has the right type. |
| for (let i = annotations.length - 1; i >= 0; i--) { |
| /** @type {?} */ |
| const annotation = annotations[i]; |
| /** @type {?} */ |
| const isKnownType = annotation instanceof Directive || annotation instanceof Component || |
| annotation instanceof Pipe || annotation instanceof NgModule; |
| if (isKnownType) { |
| return annotation instanceof this.type ? annotation : null; |
| } |
| } |
| return null; |
| } |
| /** |
| * @param {?} type |
| * @return {?} |
| */ |
| resolve(type) { |
| /** @type {?} */ |
| let resolved = this.resolved.get(type) || null; |
| if (!resolved) { |
| resolved = this.getAnnotation(type); |
| if (resolved) { |
| /** @type {?} */ |
| const overrides = this.overrides.get(type); |
| if (overrides) { |
| /** @type {?} */ |
| const overrider = new MetadataOverrider(); |
| overrides.forEach((/** |
| * @param {?} override |
| * @return {?} |
| */ |
| override => { |
| resolved = overrider.overrideMetadata(this.type, (/** @type {?} */ (resolved)), override); |
| })); |
| } |
| } |
| this.resolved.set(type, resolved); |
| } |
| return resolved; |
| } |
| } |
| class DirectiveResolver extends OverrideResolver { |
| /** |
| * @return {?} |
| */ |
| get type() { return Directive; } |
| } |
| class ComponentResolver extends OverrideResolver { |
| /** |
| * @return {?} |
| */ |
| get type() { return Component; } |
| } |
| class PipeResolver extends OverrideResolver { |
| /** |
| * @return {?} |
| */ |
| get type() { return Pipe; } |
| } |
| class NgModuleResolver extends OverrideResolver { |
| /** |
| * @return {?} |
| */ |
| get type() { return NgModule; } |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** @enum {number} */ |
| const TestingModuleOverride = { |
| DECLARATION: 0, |
| OVERRIDE_TEMPLATE: 1, |
| }; |
| TestingModuleOverride[TestingModuleOverride.DECLARATION] = 'DECLARATION'; |
| TestingModuleOverride[TestingModuleOverride.OVERRIDE_TEMPLATE] = 'OVERRIDE_TEMPLATE'; |
| /** |
| * @param {?} value |
| * @return {?} |
| */ |
| function isTestingModuleOverride(value) { |
| return value === TestingModuleOverride.DECLARATION || |
| value === TestingModuleOverride.OVERRIDE_TEMPLATE; |
| } |
| class R3TestBedCompiler { |
| /** |
| * @param {?} platform |
| * @param {?} additionalModuleTypes |
| */ |
| constructor(platform, additionalModuleTypes) { |
| this.platform = platform; |
| this.additionalModuleTypes = additionalModuleTypes; |
| this.originalComponentResolutionQueue = null; |
| // Testing module configuration |
| this.declarations = []; |
| this.imports = []; |
| this.providers = []; |
| this.schemas = []; |
| // Queues of components/directives/pipes that should be recompiled. |
| this.pendingComponents = new Set(); |
| this.pendingDirectives = new Set(); |
| this.pendingPipes = new Set(); |
| // Keep track of all components and directives, so we can patch Providers onto defs later. |
| this.seenComponents = new Set(); |
| this.seenDirectives = new Set(); |
| // Store resolved styles for Components that have template overrides present and `styleUrls` |
| // defined at the same time. |
| this.existingComponentStyles = new Map(); |
| this.resolvers = initResolvers(); |
| this.componentToModuleScope = new Map(); |
| // Map that keeps initial version of component/directive/pipe defs in case |
| // we compile a Type again, thus overriding respective static fields. This is |
| // required to make sure we restore defs to their initial states between test runs |
| // TODO: we should support the case with multiple defs on a type |
| this.initialNgDefs = new Map(); |
| // Array that keeps cleanup operations for initial versions of component/directive/pipe/module |
| // defs in case TestBed makes changes to the originals. |
| this.defCleanupOps = []; |
| this._injector = null; |
| this.compilerProviders = null; |
| this.providerOverrides = []; |
| this.rootProviderOverrides = []; |
| this.providerOverridesByToken = new Map(); |
| this.moduleProvidersOverridden = new Set(); |
| this.testModuleRef = null; |
| class DynamicTestModule { |
| } |
| this.testModuleType = (/** @type {?} */ (DynamicTestModule)); |
| } |
| /** |
| * @param {?} providers |
| * @return {?} |
| */ |
| setCompilerProviders(providers) { |
| this.compilerProviders = providers; |
| this._injector = null; |
| } |
| /** |
| * @param {?} moduleDef |
| * @return {?} |
| */ |
| configureTestingModule(moduleDef) { |
| // Enqueue any compilation tasks for the directly declared component. |
| if (moduleDef.declarations !== undefined) { |
| this.queueTypeArray(moduleDef.declarations, TestingModuleOverride.DECLARATION); |
| this.declarations.push(...moduleDef.declarations); |
| } |
| // Enqueue any compilation tasks for imported modules. |
| if (moduleDef.imports !== undefined) { |
| this.queueTypesFromModulesArray(moduleDef.imports); |
| this.imports.push(...moduleDef.imports); |
| } |
| if (moduleDef.providers !== undefined) { |
| this.providers.push(...moduleDef.providers); |
| } |
| if (moduleDef.schemas !== undefined) { |
| this.schemas.push(...moduleDef.schemas); |
| } |
| } |
| /** |
| * @param {?} ngModule |
| * @param {?} override |
| * @return {?} |
| */ |
| overrideModule(ngModule, override) { |
| // Compile the module right away. |
| this.resolvers.module.addOverride(ngModule, override); |
| /** @type {?} */ |
| const metadata = this.resolvers.module.resolve(ngModule); |
| if (metadata === null) { |
| throw new Error(`${ngModule.name} is not an @NgModule or is missing metadata`); |
| } |
| this.recompileNgModule(ngModule); |
| // At this point, the module has a valid .ngModuleDef, but the override may have introduced |
| // new declarations or imported modules. Ingest any possible new types and add them to the |
| // current queue. |
| this.queueTypesFromModulesArray([ngModule]); |
| } |
| /** |
| * @param {?} component |
| * @param {?} override |
| * @return {?} |
| */ |
| overrideComponent(component, override) { |
| this.resolvers.component.addOverride(component, override); |
| this.pendingComponents.add(component); |
| } |
| /** |
| * @param {?} directive |
| * @param {?} override |
| * @return {?} |
| */ |
| overrideDirective(directive, override) { |
| this.resolvers.directive.addOverride(directive, override); |
| this.pendingDirectives.add(directive); |
| } |
| /** |
| * @param {?} pipe |
| * @param {?} override |
| * @return {?} |
| */ |
| overridePipe(pipe, override) { |
| this.resolvers.pipe.addOverride(pipe, override); |
| this.pendingPipes.add(pipe); |
| } |
| /** |
| * @param {?} token |
| * @param {?} provider |
| * @return {?} |
| */ |
| overrideProvider(token, provider) { |
| /** @type {?} */ |
| const providerDef = provider.useFactory ? |
| { |
| provide: token, |
| useFactory: provider.useFactory, |
| deps: provider.deps || [], |
| multi: provider.multi, |
| } : |
| { provide: token, useValue: provider.useValue, multi: provider.multi }; |
| /** @type {?} */ |
| let injectableDef; |
| /** @type {?} */ |
| const isRoot = (typeof token !== 'string' && (injectableDef = ɵgetInjectableDef(token)) && |
| injectableDef.providedIn === 'root'); |
| /** @type {?} */ |
| const overridesBucket = isRoot ? this.rootProviderOverrides : this.providerOverrides; |
| overridesBucket.push(providerDef); |
| // Keep overrides grouped by token as well for fast lookups using token |
| this.providerOverridesByToken.set(token, providerDef); |
| } |
| /** |
| * @param {?} type |
| * @param {?} template |
| * @return {?} |
| */ |
| overrideTemplateUsingTestingModule(type, template) { |
| /** @type {?} */ |
| const def = ((/** @type {?} */ (type)))[ɵNG_COMPONENT_DEF]; |
| /** @type {?} */ |
| const hasStyleUrls = (/** |
| * @return {?} |
| */ |
| () => { |
| /** @type {?} */ |
| const metadata = (/** @type {?} */ ((/** @type {?} */ (this.resolvers.component.resolve(type))))); |
| return !!metadata.styleUrls && metadata.styleUrls.length > 0; |
| }); |
| /** @type {?} */ |
| const overrideStyleUrls = !!def && !isComponentDefPendingResolution(type) && hasStyleUrls(); |
| // In Ivy, compiling a component does not require knowing the module providing the |
| // component's scope, so overrideTemplateUsingTestingModule can be implemented purely via |
| // overrideComponent. Important: overriding template requires full Component re-compilation, |
| // which may fail in case styleUrls are also present (thus Component is considered as required |
| // resolution). In order to avoid this, we preemptively set styleUrls to an empty array, |
| // preserve current styles available on Component def and restore styles back once compilation |
| // is complete. |
| /** @type {?} */ |
| const override = overrideStyleUrls ? { template, styles: [], styleUrls: [] } : { template }; |
| this.overrideComponent(type, { set: override }); |
| if (overrideStyleUrls && def.styles && def.styles.length > 0) { |
| this.existingComponentStyles.set(type, def.styles); |
| } |
| // Set the component's scope to be the testing module. |
| this.componentToModuleScope.set(type, TestingModuleOverride.OVERRIDE_TEMPLATE); |
| } |
| /** |
| * @return {?} |
| */ |
| compileComponents() { |
| return __awaiter(this, void 0, void 0, function* () { |
| this.clearComponentResolutionQueue(); |
| // Run compilers for all queued types. |
| /** @type {?} */ |
| let needsAsyncResources = this.compileTypesSync(); |
| // compileComponents() should not be async unless it needs to be. |
| if (needsAsyncResources) { |
| /** @type {?} */ |
| let resourceLoader; |
| /** @type {?} */ |
| let resolver = (/** |
| * @param {?} url |
| * @return {?} |
| */ |
| (url) => { |
| if (!resourceLoader) { |
| resourceLoader = this.injector.get(ResourceLoader); |
| } |
| return Promise.resolve(resourceLoader.get(url)); |
| }); |
| yield resolveComponentResources(resolver); |
| } |
| }); |
| } |
| /** |
| * @return {?} |
| */ |
| finalize() { |
| // One last compile |
| this.compileTypesSync(); |
| // Create the testing module itself. |
| this.compileTestModule(); |
| this.applyTransitiveScopes(); |
| this.applyProviderOverrides(); |
| // Patch previously stored `styles` Component values (taken from ngComponentDef), in case these |
| // Components have `styleUrls` fields defined and template override was requested. |
| this.patchComponentsWithExistingStyles(); |
| // Clear the componentToModuleScope map, so that future compilations don't reset the scope of |
| // every component. |
| this.componentToModuleScope.clear(); |
| /** @type {?} */ |
| const parentInjector = this.platform.injector; |
| this.testModuleRef = new ɵRender3NgModuleRef(this.testModuleType, parentInjector); |
| // Set the locale ID, it can be overridden for the tests |
| /** @type {?} */ |
| const localeId = this.testModuleRef.injector.get(LOCALE_ID, ɵDEFAULT_LOCALE_ID); |
| ɵsetLocaleId(localeId); |
| // ApplicationInitStatus.runInitializers() is marked @internal to core. |
| // Cast it to any before accessing it. |
| ((/** @type {?} */ (this.testModuleRef.injector.get(ApplicationInitStatus)))).runInitializers(); |
| return this.testModuleRef; |
| } |
| /** |
| * \@internal |
| * @param {?} moduleType |
| * @return {?} |
| */ |
| _compileNgModuleSync(moduleType) { |
| this.queueTypesFromModulesArray([moduleType]); |
| this.compileTypesSync(); |
| this.applyProviderOverrides(); |
| this.applyProviderOverridesToModule(moduleType); |
| this.applyTransitiveScopes(); |
| } |
| /** |
| * \@internal |
| * @param {?} moduleType |
| * @return {?} |
| */ |
| _compileNgModuleAsync(moduleType) { |
| return __awaiter(this, void 0, void 0, function* () { |
| this.queueTypesFromModulesArray([moduleType]); |
| yield this.compileComponents(); |
| this.applyProviderOverrides(); |
| this.applyProviderOverridesToModule(moduleType); |
| this.applyTransitiveScopes(); |
| }); |
| } |
| /** |
| * \@internal |
| * @return {?} |
| */ |
| _getModuleResolver() { return this.resolvers.module; } |
| /** |
| * \@internal |
| * @param {?} moduleType |
| * @return {?} |
| */ |
| _getComponentFactories(moduleType) { |
| return maybeUnwrapFn(moduleType.ngModuleDef.declarations).reduce((/** |
| * @param {?} factories |
| * @param {?} declaration |
| * @return {?} |
| */ |
| (factories, declaration) => { |
| /** @nocollapse @type {?} */ |
| const componentDef = ((/** @type {?} */ (declaration))).ngComponentDef; |
| componentDef && factories.push(new ɵRender3ComponentFactory(componentDef, (/** @type {?} */ (this.testModuleRef)))); |
| return factories; |
| }), (/** @type {?} */ ([]))); |
| } |
| /** |
| * @private |
| * @return {?} |
| */ |
| compileTypesSync() { |
| // Compile all queued components, directives, pipes. |
| /** @type {?} */ |
| let needsAsyncResources = false; |
| this.pendingComponents.forEach((/** |
| * @param {?} declaration |
| * @return {?} |
| */ |
| declaration => { |
| needsAsyncResources = needsAsyncResources || isComponentDefPendingResolution(declaration); |
| /** @type {?} */ |
| const metadata = (/** @type {?} */ (this.resolvers.component.resolve(declaration))); |
| this.maybeStoreNgDef(ɵNG_COMPONENT_DEF, declaration); |
| ɵcompileComponent(declaration, metadata); |
| })); |
| this.pendingComponents.clear(); |
| this.pendingDirectives.forEach((/** |
| * @param {?} declaration |
| * @return {?} |
| */ |
| declaration => { |
| /** @type {?} */ |
| const metadata = (/** @type {?} */ (this.resolvers.directive.resolve(declaration))); |
| this.maybeStoreNgDef(ɵNG_DIRECTIVE_DEF, declaration); |
| ɵcompileDirective(declaration, metadata); |
| })); |
| this.pendingDirectives.clear(); |
| this.pendingPipes.forEach((/** |
| * @param {?} declaration |
| * @return {?} |
| */ |
| declaration => { |
| /** @type {?} */ |
| const metadata = (/** @type {?} */ (this.resolvers.pipe.resolve(declaration))); |
| this.maybeStoreNgDef(ɵNG_PIPE_DEF, declaration); |
| ɵcompilePipe(declaration, metadata); |
| })); |
| this.pendingPipes.clear(); |
| return needsAsyncResources; |
| } |
| /** |
| * @private |
| * @return {?} |
| */ |
| applyTransitiveScopes() { |
| /** @type {?} */ |
| const moduleToScope = new Map(); |
| /** @type {?} */ |
| const getScopeOfModule = (/** |
| * @param {?} moduleType |
| * @return {?} |
| */ |
| (moduleType) => { |
| if (!moduleToScope.has(moduleType)) { |
| /** @type {?} */ |
| const realType = isTestingModuleOverride(moduleType) ? this.testModuleType : moduleType; |
| moduleToScope.set(moduleType, ɵtransitiveScopesFor(realType)); |
| } |
| return (/** @type {?} */ (moduleToScope.get(moduleType))); |
| }); |
| this.componentToModuleScope.forEach((/** |
| * @param {?} moduleType |
| * @param {?} componentType |
| * @return {?} |
| */ |
| (moduleType, componentType) => { |
| /** @type {?} */ |
| const moduleScope = getScopeOfModule(moduleType); |
| this.storeFieldOfDefOnType(componentType, ɵNG_COMPONENT_DEF, 'directiveDefs'); |
| this.storeFieldOfDefOnType(componentType, ɵNG_COMPONENT_DEF, 'pipeDefs'); |
| ɵpatchComponentDefWithScope(((/** @type {?} */ (componentType))).ngComponentDef, moduleScope); |
| })); |
| this.componentToModuleScope.clear(); |
| } |
| /** |
| * @private |
| * @return {?} |
| */ |
| applyProviderOverrides() { |
| /** @type {?} */ |
| const maybeApplyOverrides = (/** |
| * @param {?} field |
| * @return {?} |
| */ |
| (field) => (/** |
| * @param {?} type |
| * @return {?} |
| */ |
| (type) => { |
| /** @type {?} */ |
| const resolver = field === ɵNG_COMPONENT_DEF ? this.resolvers.component : this.resolvers.directive; |
| /** @type {?} */ |
| const metadata = (/** @type {?} */ (resolver.resolve(type))); |
| if (this.hasProviderOverrides(metadata.providers)) { |
| this.patchDefWithProviderOverrides(type, field); |
| } |
| })); |
| this.seenComponents.forEach(maybeApplyOverrides(ɵNG_COMPONENT_DEF)); |
| this.seenDirectives.forEach(maybeApplyOverrides(ɵNG_DIRECTIVE_DEF)); |
| this.seenComponents.clear(); |
| this.seenDirectives.clear(); |
| } |
| /** |
| * @private |
| * @param {?} moduleType |
| * @return {?} |
| */ |
| applyProviderOverridesToModule(moduleType) { |
| if (this.moduleProvidersOverridden.has(moduleType)) { |
| return; |
| } |
| this.moduleProvidersOverridden.add(moduleType); |
| /** @type {?} */ |
| const injectorDef = ((/** @type {?} */ (moduleType)))[ɵNG_INJECTOR_DEF]; |
| if (this.providerOverridesByToken.size > 0) { |
| if (this.hasProviderOverrides(injectorDef.providers)) { |
| this.maybeStoreNgDef(ɵNG_INJECTOR_DEF, moduleType); |
| this.storeFieldOfDefOnType(moduleType, ɵNG_INJECTOR_DEF, 'providers'); |
| injectorDef.providers = this.getOverriddenProviders(injectorDef.providers); |
| } |
| // Apply provider overrides to imported modules recursively |
| /** @type {?} */ |
| const moduleDef = ((/** @type {?} */ (moduleType)))[ɵNG_MODULE_DEF]; |
| for (const importType of moduleDef.imports) { |
| this.applyProviderOverridesToModule(importType); |
| } |
| } |
| } |
| /** |
| * @private |
| * @return {?} |
| */ |
| patchComponentsWithExistingStyles() { |
| this.existingComponentStyles.forEach((/** |
| * @param {?} styles |
| * @param {?} type |
| * @return {?} |
| */ |
| (styles, type) => ((/** @type {?} */ (type)))[ɵNG_COMPONENT_DEF].styles = styles)); |
| this.existingComponentStyles.clear(); |
| } |
| /** |
| * @private |
| * @param {?} arr |
| * @param {?} moduleType |
| * @return {?} |
| */ |
| queueTypeArray(arr, moduleType) { |
| for (const value of arr) { |
| if (Array.isArray(value)) { |
| this.queueTypeArray(value, moduleType); |
| } |
| else { |
| this.queueType(value, moduleType); |
| } |
| } |
| } |
| /** |
| * @private |
| * @param {?} ngModule |
| * @return {?} |
| */ |
| recompileNgModule(ngModule) { |
| /** @type {?} */ |
| const metadata = this.resolvers.module.resolve(ngModule); |
| if (metadata === null) { |
| throw new Error(`Unable to resolve metadata for NgModule: ${ngModule.name}`); |
| } |
| // Cache the initial ngModuleDef as it will be overwritten. |
| this.maybeStoreNgDef(ɵNG_MODULE_DEF, ngModule); |
| this.maybeStoreNgDef(ɵNG_INJECTOR_DEF, ngModule); |
| ɵcompileNgModuleDefs((/** @type {?} */ (ngModule)), metadata); |
| } |
| /** |
| * @private |
| * @param {?} type |
| * @param {?} moduleType |
| * @return {?} |
| */ |
| queueType(type, moduleType) { |
| /** @type {?} */ |
| const component = this.resolvers.component.resolve(type); |
| if (component) { |
| // Check whether a give Type has respective NG def (ngComponentDef) and compile if def is |
| // missing. That might happen in case a class without any Angular decorators extends another |
| // class where Component/Directive/Pipe decorator is defined. |
| if (isComponentDefPendingResolution(type) || !type.hasOwnProperty(ɵNG_COMPONENT_DEF)) { |
| this.pendingComponents.add(type); |
| } |
| this.seenComponents.add(type); |
| // Keep track of the module which declares this component, so later the component's scope |
| // can be set correctly. If the component has already been recorded here, then one of several |
| // cases is true: |
| // * the module containing the component was imported multiple times (common). |
| // * the component is declared in multiple modules (which is an error). |
| // * the component was in 'declarations' of the testing module, and also in an imported module |
| // in which case the module scope will be TestingModuleOverride.DECLARATION. |
| // * overrideTemplateUsingTestingModule was called for the component in which case the module |
| // scope will be TestingModuleOverride.OVERRIDE_TEMPLATE. |
| // |
| // If the component was previously in the testing module's 'declarations' (meaning the |
| // current value is TestingModuleOverride.DECLARATION), then `moduleType` is the component's |
| // real module, which was imported. This pattern is understood to mean that the component |
| // should use its original scope, but that the testing module should also contain the |
| // component in its scope. |
| if (!this.componentToModuleScope.has(type) || |
| this.componentToModuleScope.get(type) === TestingModuleOverride.DECLARATION) { |
| this.componentToModuleScope.set(type, moduleType); |
| } |
| return; |
| } |
| /** @type {?} */ |
| const directive = this.resolvers.directive.resolve(type); |
| if (directive) { |
| if (!type.hasOwnProperty(ɵNG_DIRECTIVE_DEF)) { |
| this.pendingDirectives.add(type); |
| } |
| this.seenDirectives.add(type); |
| return; |
| } |
| /** @type {?} */ |
| const pipe = this.resolvers.pipe.resolve(type); |
| if (pipe && !type.hasOwnProperty(ɵNG_PIPE_DEF)) { |
| this.pendingPipes.add(type); |
| return; |
| } |
| } |
| /** |
| * @private |
| * @param {?} arr |
| * @return {?} |
| */ |
| queueTypesFromModulesArray(arr) { |
| for (const value of arr) { |
| if (Array.isArray(value)) { |
| this.queueTypesFromModulesArray(value); |
| } |
| else if (hasNgModuleDef(value)) { |
| /** @nocollapse @type {?} */ |
| const def = value.ngModuleDef; |
| // Look through declarations, imports, and exports, and queue everything found there. |
| this.queueTypeArray(maybeUnwrapFn(def.declarations), value); |
| this.queueTypesFromModulesArray(maybeUnwrapFn(def.imports)); |
| this.queueTypesFromModulesArray(maybeUnwrapFn(def.exports)); |
| } |
| } |
| } |
| /** |
| * @private |
| * @param {?} prop |
| * @param {?} type |
| * @return {?} |
| */ |
| maybeStoreNgDef(prop, type) { |
| if (!this.initialNgDefs.has(type)) { |
| /** @type {?} */ |
| const currentDef = Object.getOwnPropertyDescriptor(type, prop); |
| this.initialNgDefs.set(type, [prop, currentDef]); |
| } |
| } |
| /** |
| * @private |
| * @param {?} type |
| * @param {?} defField |
| * @param {?} field |
| * @return {?} |
| */ |
| storeFieldOfDefOnType(type, defField, field) { |
| /** @type {?} */ |
| const def = ((/** @type {?} */ (type)))[defField]; |
| /** @type {?} */ |
| const original = def[field]; |
| this.defCleanupOps.push({ field, def, original }); |
| } |
| /** |
| * Clears current components resolution queue, but stores the state of the queue, so we can |
| * restore it later. Clearing the queue is required before we try to compile components (via |
| * `TestBed.compileComponents`), so that component defs are in sync with the resolution queue. |
| * @private |
| * @return {?} |
| */ |
| clearComponentResolutionQueue() { |
| if (this.originalComponentResolutionQueue === null) { |
| this.originalComponentResolutionQueue = new Map(); |
| } |
| clearResolutionOfComponentResourcesQueue().forEach((/** |
| * @param {?} value |
| * @param {?} key |
| * @return {?} |
| */ |
| (value, key) => (/** @type {?} */ (this.originalComponentResolutionQueue)).set(key, value))); |
| } |
| /* |
| * Restores component resolution queue to the previously saved state. This operation is performed |
| * as a part of restoring the state after completion of the current set of tests (that might |
| * potentially mutate the state). |
| */ |
| /** |
| * @private |
| * @return {?} |
| */ |
| restoreComponentResolutionQueue() { |
| if (this.originalComponentResolutionQueue !== null) { |
| restoreComponentResolutionQueue(this.originalComponentResolutionQueue); |
| this.originalComponentResolutionQueue = null; |
| } |
| } |
| /** |
| * @return {?} |
| */ |
| restoreOriginalState() { |
| for (const op of this.defCleanupOps) { |
| op.def[op.field] = op.original; |
| } |
| // Restore initial component/directive/pipe defs |
| this.initialNgDefs.forEach((/** |
| * @param {?} value |
| * @param {?} type |
| * @return {?} |
| */ |
| (value, type) => { |
| const [prop, descriptor] = value; |
| if (!descriptor) { |
| // Delete operations are generally undesirable since they have performance implications |
| // on objects they were applied to. In this particular case, situations where this code is |
| // invoked should be quite rare to cause any noticable impact, since it's applied only to |
| // some test cases (for example when class with no annotations extends some @Component) |
| // when we need to clear 'ngComponentDef' field on a given class to restore its original |
| // state (before applying overrides and running tests). |
| delete ((/** @type {?} */ (type)))[prop]; |
| } |
| else { |
| Object.defineProperty(type, prop, descriptor); |
| } |
| })); |
| this.initialNgDefs.clear(); |
| this.moduleProvidersOverridden.clear(); |
| this.restoreComponentResolutionQueue(); |
| // Restore the locale ID to the default value, this shouldn't be necessary but we never know |
| ɵsetLocaleId(ɵDEFAULT_LOCALE_ID); |
| } |
| /** |
| * @private |
| * @return {?} |
| */ |
| compileTestModule() { |
| class RootScopeModule { |
| } |
| ɵcompileNgModuleDefs((/** @type {?} */ (RootScopeModule)), { |
| providers: [...this.rootProviderOverrides], |
| }); |
| /** @type {?} */ |
| const ngZone = new NgZone({ enableLongStackTrace: true }); |
| /** @type {?} */ |
| const providers = [ |
| { provide: NgZone, useValue: ngZone }, |
| { provide: Compiler, useFactory: (/** |
| * @return {?} |
| */ |
| () => new R3TestCompiler(this)) }, |
| ...this.providers, |
| ...this.providerOverrides, |
| ]; |
| /** @type {?} */ |
| const imports = [RootScopeModule, this.additionalModuleTypes, this.imports || []]; |
| // clang-format off |
| ɵcompileNgModuleDefs(this.testModuleType, { |
| declarations: this.declarations, |
| imports, |
| schemas: this.schemas, |
| providers, |
| }, /* allowDuplicateDeclarationsInRoot */ true); |
| // clang-format on |
| this.applyProviderOverridesToModule(this.testModuleType); |
| } |
| /** |
| * @return {?} |
| */ |
| get injector() { |
| if (this._injector !== null) { |
| return this._injector; |
| } |
| /** @type {?} */ |
| const providers = []; |
| /** @type {?} */ |
| const compilerOptions = this.platform.injector.get(COMPILER_OPTIONS); |
| compilerOptions.forEach((/** |
| * @param {?} opts |
| * @return {?} |
| */ |
| opts => { |
| if (opts.providers) { |
| providers.push(opts.providers); |
| } |
| })); |
| if (this.compilerProviders !== null) { |
| providers.push(...this.compilerProviders); |
| } |
| // TODO(ocombe): make this work with an Injector directly instead of creating a module for it |
| class CompilerModule { |
| } |
| ɵcompileNgModuleDefs((/** @type {?} */ (CompilerModule)), { providers }); |
| /** @type {?} */ |
| const CompilerModuleFactory = new ɵNgModuleFactory(CompilerModule); |
| this._injector = CompilerModuleFactory.create(this.platform.injector).injector; |
| return this._injector; |
| } |
| // get overrides for a specific provider (if any) |
| /** |
| * @private |
| * @param {?} provider |
| * @return {?} |
| */ |
| getSingleProviderOverrides(provider) { |
| /** @type {?} */ |
| const token = getProviderToken(provider); |
| return this.providerOverridesByToken.get(token) || null; |
| } |
| /** |
| * @private |
| * @param {?=} providers |
| * @return {?} |
| */ |
| getProviderOverrides(providers) { |
| if (!providers || !providers.length || this.providerOverridesByToken.size === 0) |
| return []; |
| // There are two flattening operations here. The inner flatten() operates on the metadata's |
| // providers and applies a mapping function which retrieves overrides for each incoming |
| // provider. The outer flatten() then flattens the produced overrides array. If this is not |
| // done, the array can contain other empty arrays (e.g. `[[], []]`) which leak into the |
| // providers array and contaminate any error messages that might be generated. |
| return flatten(flatten(providers, (/** |
| * @param {?} provider |
| * @return {?} |
| */ |
| (provider) => this.getSingleProviderOverrides(provider) || []))); |
| } |
| /** |
| * @private |
| * @param {?=} providers |
| * @return {?} |
| */ |
| getOverriddenProviders(providers) { |
| if (!providers || !providers.length || this.providerOverridesByToken.size === 0) |
| return []; |
| /** @type {?} */ |
| const overrides = this.getProviderOverrides(providers); |
| /** @type {?} */ |
| const hasMultiProviderOverrides = overrides.some(isMultiProvider); |
| /** @type {?} */ |
| const overriddenProviders = [...providers, ...overrides]; |
| // No additional processing is required in case we have no multi providers to override |
| if (!hasMultiProviderOverrides) { |
| return overriddenProviders; |
| } |
| /** @type {?} */ |
| const final = []; |
| /** @type {?} */ |
| const seenMultiProviders = new Set(); |
| // We iterate through the list of providers in reverse order to make sure multi provider |
| // overrides take precedence over the values defined in provider list. We also fiter out all |
| // multi providers that have overrides, keeping overridden values only. |
| forEachRight(overriddenProviders, (/** |
| * @param {?} provider |
| * @return {?} |
| */ |
| (provider) => { |
| /** @type {?} */ |
| const token = getProviderToken(provider); |
| if (isMultiProvider(provider) && this.providerOverridesByToken.has(token)) { |
| if (!seenMultiProviders.has(token)) { |
| seenMultiProviders.add(token); |
| if (provider && provider.useValue && Array.isArray(provider.useValue)) { |
| forEachRight(provider.useValue, (/** |
| * @param {?} value |
| * @return {?} |
| */ |
| (value) => { |
| // Unwrap provider override array into individual providers in final set. |
| final.unshift({ provide: token, useValue: value, multi: true }); |
| })); |
| } |
| else { |
| final.unshift(provider); |
| } |
| } |
| } |
| else { |
| final.unshift(provider); |
| } |
| })); |
| return final; |
| } |
| /** |
| * @private |
| * @param {?=} providers |
| * @return {?} |
| */ |
| hasProviderOverrides(providers) { |
| return this.getProviderOverrides(providers).length > 0; |
| } |
| /** |
| * @private |
| * @param {?} declaration |
| * @param {?} field |
| * @return {?} |
| */ |
| patchDefWithProviderOverrides(declaration, field) { |
| /** @type {?} */ |
| const def = ((/** @type {?} */ (declaration)))[field]; |
| if (def && def.providersResolver) { |
| this.maybeStoreNgDef(field, declaration); |
| /** @type {?} */ |
| const resolver = def.providersResolver; |
| /** @type {?} */ |
| const processProvidersFn = (/** |
| * @param {?} providers |
| * @return {?} |
| */ |
| (providers) => this.getOverriddenProviders(providers)); |
| this.storeFieldOfDefOnType(declaration, field, 'providersResolver'); |
| def.providersResolver = (/** |
| * @param {?} ngDef |
| * @return {?} |
| */ |
| (ngDef) => resolver(ngDef, processProvidersFn)); |
| } |
| } |
| } |
| /** |
| * @return {?} |
| */ |
| function initResolvers() { |
| return { |
| module: new NgModuleResolver(), |
| component: new ComponentResolver(), |
| directive: new DirectiveResolver(), |
| pipe: new PipeResolver() |
| }; |
| } |
| /** |
| * @template T |
| * @param {?} value |
| * @return {?} |
| */ |
| function hasNgModuleDef(value) { |
| return value.hasOwnProperty('ngModuleDef'); |
| } |
| /** |
| * @template T |
| * @param {?} maybeFn |
| * @return {?} |
| */ |
| function maybeUnwrapFn(maybeFn) { |
| return maybeFn instanceof Function ? maybeFn() : maybeFn; |
| } |
| /** |
| * @template T |
| * @param {?} values |
| * @param {?=} mapFn |
| * @return {?} |
| */ |
| function flatten(values, mapFn) { |
| /** @type {?} */ |
| const out = []; |
| values.forEach((/** |
| * @param {?} value |
| * @return {?} |
| */ |
| value => { |
| if (Array.isArray(value)) { |
| out.push(...flatten(value, mapFn)); |
| } |
| else { |
| out.push(mapFn ? mapFn(value) : value); |
| } |
| })); |
| return out; |
| } |
| /** |
| * @param {?} provider |
| * @param {?} field |
| * @return {?} |
| */ |
| function getProviderField(provider, field) { |
| return provider && typeof provider === 'object' && ((/** @type {?} */ (provider)))[field]; |
| } |
| /** |
| * @param {?} provider |
| * @return {?} |
| */ |
| function getProviderToken(provider) { |
| return getProviderField(provider, 'provide') || provider; |
| } |
| /** |
| * @param {?} provider |
| * @return {?} |
| */ |
| function isMultiProvider(provider) { |
| return !!getProviderField(provider, 'multi'); |
| } |
| /** |
| * @template T |
| * @param {?} values |
| * @param {?} fn |
| * @return {?} |
| */ |
| function forEachRight(values, fn) { |
| for (let idx = values.length - 1; idx >= 0; idx--) { |
| fn(values[idx], idx); |
| } |
| } |
| class R3TestCompiler { |
| /** |
| * @param {?} testBed |
| */ |
| constructor(testBed) { |
| this.testBed = testBed; |
| } |
| /** |
| * @template T |
| * @param {?} moduleType |
| * @return {?} |
| */ |
| compileModuleSync(moduleType) { |
| this.testBed._compileNgModuleSync(moduleType); |
| return new ɵNgModuleFactory(moduleType); |
| } |
| /** |
| * @template T |
| * @param {?} moduleType |
| * @return {?} |
| */ |
| compileModuleAsync(moduleType) { |
| return __awaiter(this, void 0, void 0, function* () { |
| yield this.testBed._compileNgModuleAsync(moduleType); |
| return new ɵNgModuleFactory(moduleType); |
| }); |
| } |
| /** |
| * @template T |
| * @param {?} moduleType |
| * @return {?} |
| */ |
| compileModuleAndAllComponentsSync(moduleType) { |
| /** @type {?} */ |
| const ngModuleFactory = this.compileModuleSync(moduleType); |
| /** @type {?} */ |
| const componentFactories = this.testBed._getComponentFactories((/** @type {?} */ (moduleType))); |
| return new ModuleWithComponentFactories(ngModuleFactory, componentFactories); |
| } |
| /** |
| * @template T |
| * @param {?} moduleType |
| * @return {?} |
| */ |
| compileModuleAndAllComponentsAsync(moduleType) { |
| return __awaiter(this, void 0, void 0, function* () { |
| /** @type {?} */ |
| const ngModuleFactory = yield this.compileModuleAsync(moduleType); |
| /** @type {?} */ |
| const componentFactories = this.testBed._getComponentFactories((/** @type {?} */ (moduleType))); |
| return new ModuleWithComponentFactories(ngModuleFactory, componentFactories); |
| }); |
| } |
| /** |
| * @return {?} |
| */ |
| clearCache() { } |
| /** |
| * @param {?} type |
| * @return {?} |
| */ |
| clearCacheFor(type) { } |
| /** |
| * @param {?} moduleType |
| * @return {?} |
| */ |
| getModuleId(moduleType) { |
| /** @type {?} */ |
| const meta = this.testBed._getModuleResolver().resolve(moduleType); |
| return meta && meta.id || undefined; |
| } |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** @type {?} */ |
| let _nextRootElementId = 0; |
| /** @type {?} */ |
| const UNDEFINED = Symbol('UNDEFINED'); |
| /** |
| * \@description |
| * Configures and initializes environment for unit testing and provides methods for |
| * creating components and services in unit tests. |
| * |
| * TestBed is the primary api for writing unit tests for Angular applications and libraries. |
| * |
| * Note: Use `TestBed` in tests. It will be set to either `TestBedViewEngine` or `TestBedRender3` |
| * according to the compiler used. |
| */ |
| class TestBedRender3 { |
| constructor() { |
| // Properties |
| this.platform = (/** @type {?} */ (null)); |
| this.ngModule = (/** @type {?} */ (null)); |
| this._compiler = null; |
| this._testModuleRef = null; |
| this._activeFixtures = []; |
| this._globalCompilationChecked = false; |
| } |
| /** |
| * Initialize the environment for testing with a compiler factory, a PlatformRef, and an |
| * angular module. These are common to every test in the suite. |
| * |
| * This may only be called once, to set up the common providers for the current test |
| * suite on the current platform. If you absolutely need to change the providers, |
| * first use `resetTestEnvironment`. |
| * |
| * Test modules and platforms for individual platforms are available from |
| * '\@angular/<platform_name>/testing'. |
| * |
| * \@publicApi |
| * @param {?} ngModule |
| * @param {?} platform |
| * @param {?=} aotSummaries |
| * @return {?} |
| */ |
| static initTestEnvironment(ngModule, platform, aotSummaries) { |
| /** @type {?} */ |
| const testBed = _getTestBedRender3(); |
| testBed.initTestEnvironment(ngModule, platform, aotSummaries); |
| return testBed; |
| } |
| /** |
| * Reset the providers for the test injector. |
| * |
| * \@publicApi |
| * @return {?} |
| */ |
| static resetTestEnvironment() { _getTestBedRender3().resetTestEnvironment(); } |
| /** |
| * @param {?} config |
| * @return {?} |
| */ |
| static configureCompiler(config) { |
| _getTestBedRender3().configureCompiler(config); |
| return (/** @type {?} */ ((/** @type {?} */ (TestBedRender3)))); |
| } |
| /** |
| * Allows overriding default providers, directives, pipes, modules of the test injector, |
| * which are defined in test_injector.js |
| * @param {?} moduleDef |
| * @return {?} |
| */ |
| static configureTestingModule(moduleDef) { |
| _getTestBedRender3().configureTestingModule(moduleDef); |
| return (/** @type {?} */ ((/** @type {?} */ (TestBedRender3)))); |
| } |
| /** |
| * Compile components with a `templateUrl` for the test's NgModule. |
| * It is necessary to call this function |
| * as fetching urls is asynchronous. |
| * @return {?} |
| */ |
| static compileComponents() { return _getTestBedRender3().compileComponents(); } |
| /** |
| * @param {?} ngModule |
| * @param {?} override |
| * @return {?} |
| */ |
| static overrideModule(ngModule, override) { |
| _getTestBedRender3().overrideModule(ngModule, override); |
| return (/** @type {?} */ ((/** @type {?} */ (TestBedRender3)))); |
| } |
| /** |
| * @param {?} component |
| * @param {?} override |
| * @return {?} |
| */ |
| static overrideComponent(component, override) { |
| _getTestBedRender3().overrideComponent(component, override); |
| return (/** @type {?} */ ((/** @type {?} */ (TestBedRender3)))); |
| } |
| /** |
| * @param {?} directive |
| * @param {?} override |
| * @return {?} |
| */ |
| static overrideDirective(directive, override) { |
| _getTestBedRender3().overrideDirective(directive, override); |
| return (/** @type {?} */ ((/** @type {?} */ (TestBedRender3)))); |
| } |
| /** |
| * @param {?} pipe |
| * @param {?} override |
| * @return {?} |
| */ |
| static overridePipe(pipe, override) { |
| _getTestBedRender3().overridePipe(pipe, override); |
| return (/** @type {?} */ ((/** @type {?} */ (TestBedRender3)))); |
| } |
| /** |
| * @param {?} component |
| * @param {?} template |
| * @return {?} |
| */ |
| static overrideTemplate(component, template) { |
| _getTestBedRender3().overrideComponent(component, { set: { template, templateUrl: (/** @type {?} */ (null)) } }); |
| return (/** @type {?} */ ((/** @type {?} */ (TestBedRender3)))); |
| } |
| /** |
| * Overrides the template of the given component, compiling the template |
| * in the context of the TestingModule. |
| * |
| * Note: This works for JIT and AOTed components as well. |
| * @param {?} component |
| * @param {?} template |
| * @return {?} |
| */ |
| static overrideTemplateUsingTestingModule(component, template) { |
| _getTestBedRender3().overrideTemplateUsingTestingModule(component, template); |
| return (/** @type {?} */ ((/** @type {?} */ (TestBedRender3)))); |
| } |
| /** |
| * @param {?} token |
| * @param {?} provider |
| * @return {?} |
| */ |
| static overrideProvider(token, provider) { |
| _getTestBedRender3().overrideProvider(token, provider); |
| return (/** @type {?} */ ((/** @type {?} */ (TestBedRender3)))); |
| } |
| /** |
| * @param {?} token |
| * @param {?=} notFoundValue |
| * @param {?=} flags |
| * @return {?} |
| */ |
| static get(token, notFoundValue = Injector.THROW_IF_NOT_FOUND, flags = InjectFlags.Default) { |
| return _getTestBedRender3().get(token, notFoundValue); |
| } |
| /** |
| * @template T |
| * @param {?} component |
| * @return {?} |
| */ |
| static createComponent(component) { |
| return _getTestBedRender3().createComponent(component); |
| } |
| /** |
| * @return {?} |
| */ |
| static resetTestingModule() { |
| _getTestBedRender3().resetTestingModule(); |
| return (/** @type {?} */ ((/** @type {?} */ (TestBedRender3)))); |
| } |
| /** |
| * Initialize the environment for testing with a compiler factory, a PlatformRef, and an |
| * angular module. These are common to every test in the suite. |
| * |
| * This may only be called once, to set up the common providers for the current test |
| * suite on the current platform. If you absolutely need to change the providers, |
| * first use `resetTestEnvironment`. |
| * |
| * Test modules and platforms for individual platforms are available from |
| * '\@angular/<platform_name>/testing'. |
| * |
| * \@publicApi |
| * @param {?} ngModule |
| * @param {?} platform |
| * @param {?=} aotSummaries |
| * @return {?} |
| */ |
| initTestEnvironment(ngModule, platform, aotSummaries) { |
| if (this.platform || this.ngModule) { |
| throw new Error('Cannot set base providers because it has already been called'); |
| } |
| this.platform = platform; |
| this.ngModule = ngModule; |
| this._compiler = new R3TestBedCompiler(this.platform, this.ngModule); |
| } |
| /** |
| * Reset the providers for the test injector. |
| * |
| * \@publicApi |
| * @return {?} |
| */ |
| resetTestEnvironment() { |
| this.resetTestingModule(); |
| this._compiler = null; |
| this.platform = (/** @type {?} */ (null)); |
| this.ngModule = (/** @type {?} */ (null)); |
| } |
| /** |
| * @return {?} |
| */ |
| resetTestingModule() { |
| this.checkGlobalCompilationFinished(); |
| ɵresetCompiledComponents(); |
| if (this._compiler !== null) { |
| this.compiler.restoreOriginalState(); |
| } |
| this._compiler = new R3TestBedCompiler(this.platform, this.ngModule); |
| this._testModuleRef = null; |
| this.destroyActiveFixtures(); |
| } |
| /** |
| * @param {?} config |
| * @return {?} |
| */ |
| configureCompiler(config) { |
| if (config.useJit != null) { |
| throw new Error('the Render3 compiler JiT mode is not configurable !'); |
| } |
| if (config.providers !== undefined) { |
| this.compiler.setCompilerProviders(config.providers); |
| } |
| } |
| /** |
| * @param {?} moduleDef |
| * @return {?} |
| */ |
| configureTestingModule(moduleDef) { |
| this.assertNotInstantiated('R3TestBed.configureTestingModule', 'configure the test module'); |
| this.compiler.configureTestingModule(moduleDef); |
| } |
| /** |
| * @return {?} |
| */ |
| compileComponents() { return this.compiler.compileComponents(); } |
| /** |
| * @param {?} token |
| * @param {?=} notFoundValue |
| * @param {?=} flags |
| * @return {?} |
| */ |
| get(token, notFoundValue = Injector.THROW_IF_NOT_FOUND, flags = InjectFlags.Default) { |
| if (token === TestBedRender3) { |
| return this; |
| } |
| /** @type {?} */ |
| const result = this.testModuleRef.injector.get(token, UNDEFINED, flags); |
| return result === UNDEFINED ? this.compiler.injector.get(token, notFoundValue, flags) : result; |
| } |
| /** |
| * @param {?} tokens |
| * @param {?} fn |
| * @param {?=} context |
| * @return {?} |
| */ |
| execute(tokens, fn, context) { |
| /** @type {?} */ |
| const params = tokens.map((/** |
| * @param {?} t |
| * @return {?} |
| */ |
| t => this.get(t))); |
| return fn.apply(context, params); |
| } |
| /** |
| * @param {?} ngModule |
| * @param {?} override |
| * @return {?} |
| */ |
| overrideModule(ngModule, override) { |
| this.assertNotInstantiated('overrideModule', 'override module metadata'); |
| this.compiler.overrideModule(ngModule, override); |
| } |
| /** |
| * @param {?} component |
| * @param {?} override |
| * @return {?} |
| */ |
| overrideComponent(component, override) { |
| this.assertNotInstantiated('overrideComponent', 'override component metadata'); |
| this.compiler.overrideComponent(component, override); |
| } |
| /** |
| * @param {?} component |
| * @param {?} template |
| * @return {?} |
| */ |
| overrideTemplateUsingTestingModule(component, template) { |
| this.assertNotInstantiated('R3TestBed.overrideTemplateUsingTestingModule', 'Cannot override template when the test module has already been instantiated'); |
| this.compiler.overrideTemplateUsingTestingModule(component, template); |
| } |
| /** |
| * @param {?} directive |
| * @param {?} override |
| * @return {?} |
| */ |
| overrideDirective(directive, override) { |
| this.assertNotInstantiated('overrideDirective', 'override directive metadata'); |
| this.compiler.overrideDirective(directive, override); |
| } |
| /** |
| * @param {?} pipe |
| * @param {?} override |
| * @return {?} |
| */ |
| overridePipe(pipe, override) { |
| this.assertNotInstantiated('overridePipe', 'override pipe metadata'); |
| this.compiler.overridePipe(pipe, override); |
| } |
| /** |
| * Overwrites all providers for the given token with the given provider definition. |
| * @param {?} token |
| * @param {?} provider |
| * @return {?} |
| */ |
| overrideProvider(token, provider) { |
| this.compiler.overrideProvider(token, provider); |
| } |
| /** |
| * @template T |
| * @param {?} type |
| * @return {?} |
| */ |
| createComponent(type) { |
| /** @type {?} */ |
| const testComponentRenderer = this.get(TestComponentRenderer); |
| /** @type {?} */ |
| const rootElId = `root-ng-internal-isolated-${_nextRootElementId++}`; |
| testComponentRenderer.insertRootElement(rootElId); |
| /** @nocollapse @type {?} */ |
| const componentDef = ((/** @type {?} */ (type))).ngComponentDef; |
| if (!componentDef) { |
| throw new Error(`It looks like '${ɵstringify(type)}' has not been IVY compiled - it has no 'ngComponentDef' field`); |
| } |
| // TODO: Don't cast as `any`, proper type is boolean[] |
| /** @type {?} */ |
| const noNgZone = this.get((/** @type {?} */ (ComponentFixtureNoNgZone)), false); |
| // TODO: Don't cast as `any`, proper type is boolean[] |
| /** @type {?} */ |
| const autoDetect = this.get((/** @type {?} */ (ComponentFixtureAutoDetect)), false); |
| /** @type {?} */ |
| const ngZone = noNgZone ? null : this.get((/** @type {?} */ (NgZone)), null); |
| /** @type {?} */ |
| const componentFactory = new ɵRender3ComponentFactory(componentDef); |
| /** @type {?} */ |
| const initComponent = (/** |
| * @return {?} |
| */ |
| () => { |
| /** @type {?} */ |
| const componentRef = componentFactory.create(Injector.NULL, [], `#${rootElId}`, this.testModuleRef); |
| return new ComponentFixture(componentRef, ngZone, autoDetect); |
| }); |
| /** @type {?} */ |
| const fixture = ngZone ? ngZone.run(initComponent) : initComponent(); |
| this._activeFixtures.push(fixture); |
| return fixture; |
| } |
| /** |
| * @private |
| * @return {?} |
| */ |
| get compiler() { |
| if (this._compiler === null) { |
| throw new Error(`Need to call TestBed.initTestEnvironment() first`); |
| } |
| return this._compiler; |
| } |
| /** |
| * @private |
| * @return {?} |
| */ |
| get testModuleRef() { |
| if (this._testModuleRef === null) { |
| this._testModuleRef = this.compiler.finalize(); |
| } |
| return this._testModuleRef; |
| } |
| /** |
| * @private |
| * @param {?} methodName |
| * @param {?} methodDescription |
| * @return {?} |
| */ |
| assertNotInstantiated(methodName, methodDescription) { |
| if (this._testModuleRef !== null) { |
| throw new Error(`Cannot ${methodDescription} when the test module has already been instantiated. ` + |
| `Make sure you are not using \`inject\` before \`${methodName}\`.`); |
| } |
| } |
| /** |
| * Check whether the module scoping queue should be flushed, and flush it if needed. |
| * |
| * When the TestBed is reset, it clears the JIT module compilation queue, cancelling any |
| * in-progress module compilation. This creates a potential hazard - the very first time the |
| * TestBed is initialized (or if it's reset without being initialized), there may be pending |
| * compilations of modules declared in global scope. These compilations should be finished. |
| * |
| * To ensure that globally declared modules have their components scoped properly, this function |
| * is called whenever TestBed is initialized or reset. The _first_ time that this happens, prior |
| * to any other operations, the scoping queue is flushed. |
| * @private |
| * @return {?} |
| */ |
| checkGlobalCompilationFinished() { |
| // Checking _testNgModuleRef is null should not be necessary, but is left in as an additional |
| // guard that compilations queued in tests (after instantiation) are never flushed accidentally. |
| if (!this._globalCompilationChecked && this._testModuleRef === null) { |
| ɵflushModuleScopingQueueAsMuchAsPossible(); |
| } |
| this._globalCompilationChecked = true; |
| } |
| /** |
| * @private |
| * @return {?} |
| */ |
| destroyActiveFixtures() { |
| this._activeFixtures.forEach((/** |
| * @param {?} fixture |
| * @return {?} |
| */ |
| (fixture) => { |
| try { |
| fixture.destroy(); |
| } |
| catch (e) { |
| console.error('Error during cleanup of component', { |
| component: fixture.componentInstance, |
| stacktrace: e, |
| }); |
| } |
| })); |
| this._activeFixtures = []; |
| } |
| } |
| /** @type {?} */ |
| let testBed; |
| /** |
| * @return {?} |
| */ |
| function _getTestBedRender3() { |
| return testBed = testBed || new TestBedRender3(); |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * @return {?} |
| */ |
| function unimplemented() { |
| throw Error('unimplemented'); |
| } |
| /** |
| * Special interface to the compiler only used by testing |
| * |
| * \@publicApi |
| */ |
| class TestingCompiler extends Compiler { |
| /** |
| * @return {?} |
| */ |
| get injector() { throw unimplemented(); } |
| /** |
| * @param {?} module |
| * @param {?} overrides |
| * @return {?} |
| */ |
| overrideModule(module, overrides) { |
| throw unimplemented(); |
| } |
| /** |
| * @param {?} directive |
| * @param {?} overrides |
| * @return {?} |
| */ |
| overrideDirective(directive, overrides) { |
| throw unimplemented(); |
| } |
| /** |
| * @param {?} component |
| * @param {?} overrides |
| * @return {?} |
| */ |
| overrideComponent(component, overrides) { |
| throw unimplemented(); |
| } |
| /** |
| * @param {?} directive |
| * @param {?} overrides |
| * @return {?} |
| */ |
| overridePipe(directive, overrides) { |
| throw unimplemented(); |
| } |
| /** |
| * Allows to pass the compile summary from AOT compilation to the JIT compiler, |
| * so that it can use the code generated by AOT. |
| * @param {?} summaries |
| * @return {?} |
| */ |
| loadAotSummaries(summaries) { throw unimplemented(); } |
| /** |
| * Gets the component factory for the given component. |
| * This assumes that the component has been compiled before calling this call using |
| * `compileModuleAndAllComponents*`. |
| * @template T |
| * @param {?} component |
| * @return {?} |
| */ |
| getComponentFactory(component) { throw unimplemented(); } |
| /** |
| * Returns the component type that is stored in the given error. |
| * This can be used for errors created by compileModule... |
| * @param {?} error |
| * @return {?} |
| */ |
| getComponentFromError(error) { throw unimplemented(); } |
| } |
| TestingCompiler.decorators = [ |
| { type: Injectable } |
| ]; |
| /** |
| * A factory for creating a Compiler |
| * |
| * \@publicApi |
| * @abstract |
| */ |
| class TestingCompilerFactory { |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** @type {?} */ |
| const UNDEFINED$1 = new Object(); |
| /** @type {?} */ |
| let _nextRootElementId$1 = 0; |
| // WARNING: interface has both a type and a value, skipping emit |
| /** |
| * \@description |
| * Configures and initializes environment for unit testing and provides methods for |
| * creating components and services in unit tests. |
| * |
| * `TestBed` is the primary api for writing unit tests for Angular applications and libraries. |
| * |
| * Note: Use `TestBed` in tests. It will be set to either `TestBedViewEngine` or `TestBedRender3` |
| * according to the compiler used. |
| */ |
| class TestBedViewEngine { |
| constructor() { |
| this._instantiated = false; |
| this._compiler = (/** @type {?} */ (null)); |
| this._moduleRef = (/** @type {?} */ (null)); |
| this._moduleFactory = (/** @type {?} */ (null)); |
| this._compilerOptions = []; |
| this._moduleOverrides = []; |
| this._componentOverrides = []; |
| this._directiveOverrides = []; |
| this._pipeOverrides = []; |
| this._providers = []; |
| this._declarations = []; |
| this._imports = []; |
| this._schemas = []; |
| this._activeFixtures = []; |
| this._testEnvAotSummaries = (/** |
| * @return {?} |
| */ |
| () => []); |
| this._aotSummaries = []; |
| this._templateOverrides = []; |
| this._isRoot = true; |
| this._rootProviderOverrides = []; |
| this.platform = (/** @type {?} */ (null)); |
| this.ngModule = (/** @type {?} */ (null)); |
| } |
| /** |
| * Initialize the environment for testing with a compiler factory, a PlatformRef, and an |
| * angular module. These are common to every test in the suite. |
| * |
| * This may only be called once, to set up the common providers for the current test |
| * suite on the current platform. If you absolutely need to change the providers, |
| * first use `resetTestEnvironment`. |
| * |
| * Test modules and platforms for individual platforms are available from |
| * '\@angular/<platform_name>/testing'. |
| * @param {?} ngModule |
| * @param {?} platform |
| * @param {?=} aotSummaries |
| * @return {?} |
| */ |
| static initTestEnvironment(ngModule, platform, aotSummaries) { |
| /** @type {?} */ |
| const testBed = _getTestBedViewEngine(); |
| testBed.initTestEnvironment(ngModule, platform, aotSummaries); |
| return testBed; |
| } |
| /** |
| * Reset the providers for the test injector. |
| * @return {?} |
| */ |
| static resetTestEnvironment() { _getTestBedViewEngine().resetTestEnvironment(); } |
| /** |
| * @return {?} |
| */ |
| static resetTestingModule() { |
| _getTestBedViewEngine().resetTestingModule(); |
| return (/** @type {?} */ ((/** @type {?} */ (TestBedViewEngine)))); |
| } |
| /** |
| * Allows overriding default compiler providers and settings |
| * which are defined in test_injector.js |
| * @param {?} config |
| * @return {?} |
| */ |
| static configureCompiler(config) { |
| _getTestBedViewEngine().configureCompiler(config); |
| return (/** @type {?} */ ((/** @type {?} */ (TestBedViewEngine)))); |
| } |
| /** |
| * Allows overriding default providers, directives, pipes, modules of the test injector, |
| * which are defined in test_injector.js |
| * @param {?} moduleDef |
| * @return {?} |
| */ |
| static configureTestingModule(moduleDef) { |
| _getTestBedViewEngine().configureTestingModule(moduleDef); |
| return (/** @type {?} */ ((/** @type {?} */ (TestBedViewEngine)))); |
| } |
| /** |
| * Compile components with a `templateUrl` for the test's NgModule. |
| * It is necessary to call this function |
| * as fetching urls is asynchronous. |
| * @return {?} |
| */ |
| static compileComponents() { return getTestBed().compileComponents(); } |
| /** |
| * @param {?} ngModule |
| * @param {?} override |
| * @return {?} |
| */ |
| static overrideModule(ngModule, override) { |
| _getTestBedViewEngine().overrideModule(ngModule, override); |
| return (/** @type {?} */ ((/** @type {?} */ (TestBedViewEngine)))); |
| } |
| /** |
| * @param {?} component |
| * @param {?} override |
| * @return {?} |
| */ |
| static overrideComponent(component, override) { |
| _getTestBedViewEngine().overrideComponent(component, override); |
| return (/** @type {?} */ ((/** @type {?} */ (TestBedViewEngine)))); |
| } |
| /** |
| * @param {?} directive |
| * @param {?} override |
| * @return {?} |
| */ |
| static overrideDirective(directive, override) { |
| _getTestBedViewEngine().overrideDirective(directive, override); |
| return (/** @type {?} */ ((/** @type {?} */ (TestBedViewEngine)))); |
| } |
| /** |
| * @param {?} pipe |
| * @param {?} override |
| * @return {?} |
| */ |
| static overridePipe(pipe, override) { |
| _getTestBedViewEngine().overridePipe(pipe, override); |
| return (/** @type {?} */ ((/** @type {?} */ (TestBedViewEngine)))); |
| } |
| /** |
| * @param {?} component |
| * @param {?} template |
| * @return {?} |
| */ |
| static overrideTemplate(component, template) { |
| _getTestBedViewEngine().overrideComponent(component, { set: { template, templateUrl: (/** @type {?} */ (null)) } }); |
| return (/** @type {?} */ ((/** @type {?} */ (TestBedViewEngine)))); |
| } |
| /** |
| * Overrides the template of the given component, compiling the template |
| * in the context of the TestingModule. |
| * |
| * Note: This works for JIT and AOTed components as well. |
| * @param {?} component |
| * @param {?} template |
| * @return {?} |
| */ |
| static overrideTemplateUsingTestingModule(component, template) { |
| _getTestBedViewEngine().overrideTemplateUsingTestingModule(component, template); |
| return (/** @type {?} */ ((/** @type {?} */ (TestBedViewEngine)))); |
| } |
| /** |
| * @param {?} token |
| * @param {?} provider |
| * @return {?} |
| */ |
| static overrideProvider(token, provider) { |
| _getTestBedViewEngine().overrideProvider(token, (/** @type {?} */ (provider))); |
| return (/** @type {?} */ ((/** @type {?} */ (TestBedViewEngine)))); |
| } |
| /** |
| * @param {?} token |
| * @param {?=} notFoundValue |
| * @param {?=} flags |
| * @return {?} |
| */ |
| static get(token, notFoundValue = Injector.THROW_IF_NOT_FOUND, flags = InjectFlags.Default) { |
| return _getTestBedViewEngine().get(token, notFoundValue, flags); |
| } |
| /** |
| * @template T |
| * @param {?} component |
| * @return {?} |
| */ |
| static createComponent(component) { |
| return _getTestBedViewEngine().createComponent(component); |
| } |
| /** |
| * Initialize the environment for testing with a compiler factory, a PlatformRef, and an |
| * angular module. These are common to every test in the suite. |
| * |
| * This may only be called once, to set up the common providers for the current test |
| * suite on the current platform. If you absolutely need to change the providers, |
| * first use `resetTestEnvironment`. |
| * |
| * Test modules and platforms for individual platforms are available from |
| * '\@angular/<platform_name>/testing'. |
| * @param {?} ngModule |
| * @param {?} platform |
| * @param {?=} aotSummaries |
| * @return {?} |
| */ |
| initTestEnvironment(ngModule, platform, aotSummaries) { |
| if (this.platform || this.ngModule) { |
| throw new Error('Cannot set base providers because it has already been called'); |
| } |
| this.platform = platform; |
| this.ngModule = ngModule; |
| if (aotSummaries) { |
| this._testEnvAotSummaries = aotSummaries; |
| } |
| } |
| /** |
| * Reset the providers for the test injector. |
| * @return {?} |
| */ |
| resetTestEnvironment() { |
| this.resetTestingModule(); |
| this.platform = (/** @type {?} */ (null)); |
| this.ngModule = (/** @type {?} */ (null)); |
| this._testEnvAotSummaries = (/** |
| * @return {?} |
| */ |
| () => []); |
| } |
| /** |
| * @return {?} |
| */ |
| resetTestingModule() { |
| ɵclearOverrides(); |
| this._aotSummaries = []; |
| this._templateOverrides = []; |
| this._compiler = (/** @type {?} */ (null)); |
| this._moduleOverrides = []; |
| this._componentOverrides = []; |
| this._directiveOverrides = []; |
| this._pipeOverrides = []; |
| this._isRoot = true; |
| this._rootProviderOverrides = []; |
| this._moduleRef = (/** @type {?} */ (null)); |
| this._moduleFactory = (/** @type {?} */ (null)); |
| this._compilerOptions = []; |
| this._providers = []; |
| this._declarations = []; |
| this._imports = []; |
| this._schemas = []; |
| this._instantiated = false; |
| this._activeFixtures.forEach((/** |
| * @param {?} fixture |
| * @return {?} |
| */ |
| (fixture) => { |
| try { |
| fixture.destroy(); |
| } |
| catch (e) { |
| console.error('Error during cleanup of component', { |
| component: fixture.componentInstance, |
| stacktrace: e, |
| }); |
| } |
| })); |
| this._activeFixtures = []; |
| } |
| /** |
| * @param {?} config |
| * @return {?} |
| */ |
| configureCompiler(config) { |
| this._assertNotInstantiated('TestBed.configureCompiler', 'configure the compiler'); |
| this._compilerOptions.push(config); |
| } |
| /** |
| * @param {?} moduleDef |
| * @return {?} |
| */ |
| configureTestingModule(moduleDef) { |
| this._assertNotInstantiated('TestBed.configureTestingModule', 'configure the test module'); |
| if (moduleDef.providers) { |
| this._providers.push(...moduleDef.providers); |
| } |
| if (moduleDef.declarations) { |
| this._declarations.push(...moduleDef.declarations); |
| } |
| if (moduleDef.imports) { |
| this._imports.push(...moduleDef.imports); |
| } |
| if (moduleDef.schemas) { |
| this._schemas.push(...moduleDef.schemas); |
| } |
| if (moduleDef.aotSummaries) { |
| this._aotSummaries.push(moduleDef.aotSummaries); |
| } |
| } |
| /** |
| * @return {?} |
| */ |
| compileComponents() { |
| if (this._moduleFactory || this._instantiated) { |
| return Promise.resolve(null); |
| } |
| /** @type {?} */ |
| const moduleType = this._createCompilerAndModule(); |
| return this._compiler.compileModuleAndAllComponentsAsync(moduleType) |
| .then((/** |
| * @param {?} moduleAndComponentFactories |
| * @return {?} |
| */ |
| (moduleAndComponentFactories) => { |
| this._moduleFactory = moduleAndComponentFactories.ngModuleFactory; |
| })); |
| } |
| /** |
| * @private |
| * @return {?} |
| */ |
| _initIfNeeded() { |
| if (this._instantiated) { |
| return; |
| } |
| if (!this._moduleFactory) { |
| try { |
| /** @type {?} */ |
| const moduleType = this._createCompilerAndModule(); |
| this._moduleFactory = |
| this._compiler.compileModuleAndAllComponentsSync(moduleType).ngModuleFactory; |
| } |
| catch (e) { |
| /** @type {?} */ |
| const errorCompType = this._compiler.getComponentFromError(e); |
| if (errorCompType) { |
| throw new Error(`This test module uses the component ${ɵstringify(errorCompType)} which is using a "templateUrl" or "styleUrls", but they were never compiled. ` + |
| `Please call "TestBed.compileComponents" before your test.`); |
| } |
| else { |
| throw e; |
| } |
| } |
| } |
| for (const { component, templateOf } of this._templateOverrides) { |
| /** @type {?} */ |
| const compFactory = this._compiler.getComponentFactory(templateOf); |
| ɵoverrideComponentView(component, compFactory); |
| } |
| /** @type {?} */ |
| const ngZone = new NgZone({ enableLongStackTrace: true }); |
| /** @type {?} */ |
| const providers = [{ provide: NgZone, useValue: ngZone }]; |
| /** @type {?} */ |
| const ngZoneInjector = Injector.create({ |
| providers: providers, |
| parent: this.platform.injector, |
| name: this._moduleFactory.moduleType.name |
| }); |
| this._moduleRef = this._moduleFactory.create(ngZoneInjector); |
| // ApplicationInitStatus.runInitializers() is marked @internal to core. So casting to any |
| // before accessing it. |
| ((/** @type {?} */ (this._moduleRef.injector.get(ApplicationInitStatus)))).runInitializers(); |
| this._instantiated = true; |
| } |
| /** |
| * @private |
| * @return {?} |
| */ |
| _createCompilerAndModule() { |
| /** @type {?} */ |
| const providers = this._providers.concat([{ provide: TestBed, useValue: this }]); |
| /** @type {?} */ |
| const declarations = [...this._declarations, ...this._templateOverrides.map((/** |
| * @param {?} entry |
| * @return {?} |
| */ |
| entry => entry.templateOf))]; |
| /** @type {?} */ |
| const rootScopeImports = []; |
| /** @type {?} */ |
| const rootProviderOverrides = this._rootProviderOverrides; |
| if (this._isRoot) { |
| class RootScopeModule { |
| } |
| RootScopeModule.decorators = [ |
| { type: NgModule, args: [{ |
| providers: [ |
| ...rootProviderOverrides, |
| ], |
| jit: true, |
| },] }, |
| ]; |
| rootScopeImports.push(RootScopeModule); |
| } |
| providers.push({ provide: ɵAPP_ROOT, useValue: this._isRoot }); |
| /** @type {?} */ |
| const imports = [rootScopeImports, this.ngModule, this._imports]; |
| /** @type {?} */ |
| const schemas = this._schemas; |
| class DynamicTestModule { |
| } |
| DynamicTestModule.decorators = [ |
| { type: NgModule, args: [{ providers, declarations, imports, schemas, jit: true },] }, |
| ]; |
| /** @type {?} */ |
| const compilerFactory = this.platform.injector.get(TestingCompilerFactory); |
| this._compiler = compilerFactory.createTestingCompiler(this._compilerOptions); |
| for (const summary of [this._testEnvAotSummaries, ...this._aotSummaries]) { |
| this._compiler.loadAotSummaries(summary); |
| } |
| this._moduleOverrides.forEach((/** |
| * @param {?} entry |
| * @return {?} |
| */ |
| (entry) => this._compiler.overrideModule(entry[0], entry[1]))); |
| this._componentOverrides.forEach((/** |
| * @param {?} entry |
| * @return {?} |
| */ |
| (entry) => this._compiler.overrideComponent(entry[0], entry[1]))); |
| this._directiveOverrides.forEach((/** |
| * @param {?} entry |
| * @return {?} |
| */ |
| (entry) => this._compiler.overrideDirective(entry[0], entry[1]))); |
| this._pipeOverrides.forEach((/** |
| * @param {?} entry |
| * @return {?} |
| */ |
| (entry) => this._compiler.overridePipe(entry[0], entry[1]))); |
| return DynamicTestModule; |
| } |
| /** |
| * @private |
| * @param {?} methodName |
| * @param {?} methodDescription |
| * @return {?} |
| */ |
| _assertNotInstantiated(methodName, methodDescription) { |
| if (this._instantiated) { |
| throw new Error(`Cannot ${methodDescription} when the test module has already been instantiated. ` + |
| `Make sure you are not using \`inject\` before \`${methodName}\`.`); |
| } |
| } |
| /** |
| * @param {?} token |
| * @param {?=} notFoundValue |
| * @param {?=} flags |
| * @return {?} |
| */ |
| get(token, notFoundValue = Injector.THROW_IF_NOT_FOUND, flags = InjectFlags.Default) { |
| this._initIfNeeded(); |
| if (token === TestBed) { |
| return this; |
| } |
| // Tests can inject things from the ng module and from the compiler, |
| // but the ng module can't inject things from the compiler and vice versa. |
| /** @type {?} */ |
| const result = this._moduleRef.injector.get(token, UNDEFINED$1, flags); |
| return result === UNDEFINED$1 ? this._compiler.injector.get(token, notFoundValue, flags) : result; |
| } |
| /** |
| * @param {?} tokens |
| * @param {?} fn |
| * @param {?=} context |
| * @return {?} |
| */ |
| execute(tokens, fn, context) { |
| this._initIfNeeded(); |
| /** @type {?} */ |
| const params = tokens.map((/** |
| * @param {?} t |
| * @return {?} |
| */ |
| t => this.get(t))); |
| return fn.apply(context, params); |
| } |
| /** |
| * @param {?} ngModule |
| * @param {?} override |
| * @return {?} |
| */ |
| overrideModule(ngModule, override) { |
| this._assertNotInstantiated('overrideModule', 'override module metadata'); |
| this._moduleOverrides.push([ngModule, override]); |
| } |
| /** |
| * @param {?} component |
| * @param {?} override |
| * @return {?} |
| */ |
| overrideComponent(component, override) { |
| this._assertNotInstantiated('overrideComponent', 'override component metadata'); |
| this._componentOverrides.push([component, override]); |
| } |
| /** |
| * @param {?} directive |
| * @param {?} override |
| * @return {?} |
| */ |
| overrideDirective(directive, override) { |
| this._assertNotInstantiated('overrideDirective', 'override directive metadata'); |
| this._directiveOverrides.push([directive, override]); |
| } |
| /** |
| * @param {?} pipe |
| * @param {?} override |
| * @return {?} |
| */ |
| overridePipe(pipe, override) { |
| this._assertNotInstantiated('overridePipe', 'override pipe metadata'); |
| this._pipeOverrides.push([pipe, override]); |
| } |
| /** |
| * @param {?} token |
| * @param {?} provider |
| * @return {?} |
| */ |
| overrideProvider(token, provider) { |
| this.overrideProviderImpl(token, provider); |
| } |
| /** |
| * @private |
| * @param {?} token |
| * @param {?} provider |
| * @param {?=} deprecated |
| * @return {?} |
| */ |
| overrideProviderImpl(token, provider, deprecated = false) { |
| /** @type {?} */ |
| let def = null; |
| if (typeof token !== 'string' && (def = ɵgetInjectableDef(token)) && def.providedIn === 'root') { |
| if (provider.useFactory) { |
| this._rootProviderOverrides.push({ provide: token, useFactory: provider.useFactory, deps: provider.deps || [] }); |
| } |
| else { |
| this._rootProviderOverrides.push({ provide: token, useValue: provider.useValue }); |
| } |
| } |
| /** @type {?} */ |
| let flags = 0; |
| /** @type {?} */ |
| let value; |
| if (provider.useFactory) { |
| flags |= 1024 /* TypeFactoryProvider */; |
| value = provider.useFactory; |
| } |
| else { |
| flags |= 256 /* TypeValueProvider */; |
| value = provider.useValue; |
| } |
| /** @type {?} */ |
| const deps = (provider.deps || []).map((/** |
| * @param {?} dep |
| * @return {?} |
| */ |
| (dep) => { |
| /** @type {?} */ |
| let depFlags = 0 /* None */; |
| /** @type {?} */ |
| let depToken; |
| if (Array.isArray(dep)) { |
| dep.forEach((/** |
| * @param {?} entry |
| * @return {?} |
| */ |
| (entry) => { |
| if (entry instanceof Optional) { |
| depFlags |= 2 /* Optional */; |
| } |
| else if (entry instanceof SkipSelf) { |
| depFlags |= 1 /* SkipSelf */; |
| } |
| else { |
| depToken = entry; |
| } |
| })); |
| } |
| else { |
| depToken = dep; |
| } |
| return [depFlags, depToken]; |
| })); |
| ɵoverrideProvider({ token, flags, deps, value, deprecatedBehavior: deprecated }); |
| } |
| /** |
| * @param {?} component |
| * @param {?} template |
| * @return {?} |
| */ |
| overrideTemplateUsingTestingModule(component, template) { |
| this._assertNotInstantiated('overrideTemplateUsingTestingModule', 'override template'); |
| class OverrideComponent { |
| } |
| OverrideComponent.decorators = [ |
| { type: Component, args: [{ selector: 'empty', template, jit: true },] }, |
| ]; |
| this._templateOverrides.push({ component, templateOf: OverrideComponent }); |
| } |
| /** |
| * @template T |
| * @param {?} component |
| * @return {?} |
| */ |
| createComponent(component) { |
| this._initIfNeeded(); |
| /** @type {?} */ |
| const componentFactory = this._compiler.getComponentFactory(component); |
| if (!componentFactory) { |
| throw new Error(`Cannot create the component ${ɵstringify(component)} as it was not imported into the testing module!`); |
| } |
| // TODO: Don't cast as `any`, proper type is boolean[] |
| /** @type {?} */ |
| const noNgZone = this.get((/** @type {?} */ (ComponentFixtureNoNgZone)), false); |
| // TODO: Don't cast as `any`, proper type is boolean[] |
| /** @type {?} */ |
| const autoDetect = this.get((/** @type {?} */ (ComponentFixtureAutoDetect)), false); |
| /** @type {?} */ |
| const ngZone = noNgZone ? null : this.get((/** @type {?} */ (NgZone)), null); |
| /** @type {?} */ |
| const testComponentRenderer = this.get(TestComponentRenderer); |
| /** @type {?} */ |
| const rootElId = `root${_nextRootElementId$1++}`; |
| testComponentRenderer.insertRootElement(rootElId); |
| /** @type {?} */ |
| const initComponent = (/** |
| * @return {?} |
| */ |
| () => { |
| /** @type {?} */ |
| const componentRef = componentFactory.create(Injector.NULL, [], `#${rootElId}`, this._moduleRef); |
| return new ComponentFixture(componentRef, ngZone, autoDetect); |
| }); |
| /** @type {?} */ |
| const fixture = !ngZone ? initComponent() : ngZone.run(initComponent); |
| this._activeFixtures.push(fixture); |
| return fixture; |
| } |
| } |
| /** |
| * \@description |
| * Configures and initializes environment for unit testing and provides methods for |
| * creating components and services in unit tests. |
| * |
| * `TestBed` is the primary api for writing unit tests for Angular applications and libraries. |
| * |
| * Note: Use `TestBed` in tests. It will be set to either `TestBedViewEngine` or `TestBedRender3` |
| * according to the compiler used. |
| * |
| * \@publicApi |
| * @type {?} |
| */ |
| const TestBed = ɵivyEnabled ? (/** @type {?} */ ((/** @type {?} */ (TestBedRender3)))) : (/** @type {?} */ ((/** @type {?} */ (TestBedViewEngine)))); |
| /** |
| * Returns a singleton of the applicable `TestBed`. |
| * |
| * It will be either an instance of `TestBedViewEngine` or `TestBedRender3`. |
| * |
| * \@publicApi |
| * @type {?} |
| */ |
| const getTestBed = ɵivyEnabled ? _getTestBedRender3 : _getTestBedViewEngine; |
| /** @type {?} */ |
| let testBed$1; |
| /** |
| * @return {?} |
| */ |
| function _getTestBedViewEngine() { |
| return testBed$1 = testBed$1 || new TestBedViewEngine(); |
| } |
| /** |
| * Allows injecting dependencies in `beforeEach()` and `it()`. |
| * |
| * Example: |
| * |
| * ``` |
| * beforeEach(inject([Dependency, AClass], (dep, object) => { |
| * // some code that uses `dep` and `object` |
| * // ... |
| * })); |
| * |
| * it('...', inject([AClass], (object) => { |
| * object.doSomething(); |
| * expect(...); |
| * }) |
| * ``` |
| * |
| * Notes: |
| * - inject is currently a function because of some Traceur limitation the syntax should |
| * eventually |
| * becomes `it('...', \@Inject (object: AClass, async: AsyncTestCompleter) => { ... });` |
| * |
| * \@publicApi |
| * @param {?} tokens |
| * @param {?} fn |
| * @return {?} |
| */ |
| function inject(tokens, fn) { |
| /** @type {?} */ |
| const testBed = getTestBed(); |
| if (tokens.indexOf(AsyncTestCompleter) >= 0) { |
| // Not using an arrow function to preserve context passed from call site |
| return (/** |
| * @return {?} |
| */ |
| function () { |
| // Return an async test method that returns a Promise if AsyncTestCompleter is one of |
| // the injected tokens. |
| return testBed.compileComponents().then((/** |
| * @return {?} |
| */ |
| () => { |
| /** @type {?} */ |
| const completer = testBed.get(AsyncTestCompleter); |
| testBed.execute(tokens, fn, this); |
| return completer.promise; |
| })); |
| }); |
| } |
| else { |
| // Not using an arrow function to preserve context passed from call site |
| return (/** |
| * @return {?} |
| */ |
| function () { return testBed.execute(tokens, fn, this); }); |
| } |
| } |
| /** |
| * \@publicApi |
| */ |
| class InjectSetupWrapper { |
| /** |
| * @param {?} _moduleDef |
| */ |
| constructor(_moduleDef) { |
| this._moduleDef = _moduleDef; |
| } |
| /** |
| * @private |
| * @return {?} |
| */ |
| _addModule() { |
| /** @type {?} */ |
| const moduleDef = this._moduleDef(); |
| if (moduleDef) { |
| getTestBed().configureTestingModule(moduleDef); |
| } |
| } |
| /** |
| * @param {?} tokens |
| * @param {?} fn |
| * @return {?} |
| */ |
| inject(tokens, fn) { |
| /** @type {?} */ |
| const self = this; |
| // Not using an arrow function to preserve context passed from call site |
| return (/** |
| * @return {?} |
| */ |
| function () { |
| self._addModule(); |
| return inject(tokens, fn).call(this); |
| }); |
| } |
| } |
| /** |
| * @param {?} moduleDef |
| * @param {?=} fn |
| * @return {?} |
| */ |
| function withModule(moduleDef, fn) { |
| if (fn) { |
| // Not using an arrow function to preserve context passed from call site |
| return (/** |
| * @return {?} |
| */ |
| function () { |
| /** @type {?} */ |
| const testBed = getTestBed(); |
| if (moduleDef) { |
| testBed.configureTestingModule(moduleDef); |
| } |
| return fn.apply(this); |
| }); |
| } |
| return new InjectSetupWrapper((/** |
| * @return {?} |
| */ |
| () => moduleDef)); |
| } |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** @type {?} */ |
| const _global$1 = (/** @type {?} */ ((typeof window === 'undefined' ? global : window))); |
| // Reset the test providers and the fake async zone before each test. |
| if (_global$1.beforeEach) { |
| _global$1.beforeEach((/** |
| * @return {?} |
| */ |
| () => { |
| TestBed.resetTestingModule(); |
| resetFakeAsyncZone(); |
| })); |
| } |
| // TODO(juliemr): remove this, only used because we need to export something to have compilation |
| // work. |
| /** @type {?} */ |
| const __core_private_testing_placeholder__ = ''; |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| /** |
| * @license |
| * Copyright Google Inc. All Rights Reserved. |
| * |
| * Use of this source code is governed by an MIT-style license that can be |
| * found in the LICENSE file at https://angular.io/license |
| */ |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| |
| /** |
| * @fileoverview added by tsickle |
| * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc |
| */ |
| |
| /** |
| * Generated bundle index. Do not edit. |
| */ |
| |
| export { TestBedRender3 as ɵangular_packages_core_testing_testing_b, _getTestBedRender3 as ɵangular_packages_core_testing_testing_c, TestBedViewEngine as ɵangular_packages_core_testing_testing_a, TestBed, getTestBed, inject, InjectSetupWrapper, withModule, MetadataOverrider as ɵMetadataOverrider, async, ComponentFixture, resetFakeAsyncZone, fakeAsync, tick, flush, discardPeriodicTasks, flushMicrotasks, TestComponentRenderer, ComponentFixtureAutoDetect, ComponentFixtureNoNgZone, __core_private_testing_placeholder__, TestingCompiler as ɵTestingCompiler, TestingCompilerFactory as ɵTestingCompilerFactory }; |
| //# sourceMappingURL=testing.js.map |