Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
{"version":3,"file":"testing.mjs","sources":["../../../../../../packages/core/testing/src/async.ts","../../../../../../packages/core/testing/src/defer.ts","../../../../../../packages/core/testing/src/test_bed_common.ts","../../../../../../packages/core/testing/src/application_error_handler.ts","../../../../../../packages/core/testing/src/component_fixture.ts","../../../../../../packages/core/testing/src/fake_async.ts","../../../../../../packages/core/testing/src/metadata_overrider.ts","../../../../../../packages/core/testing/src/resolvers.ts","../../../../../../packages/core/testing/src/test_bed_compiler.ts","../../../../../../packages/core/testing/src/test_bed.ts","../../../../../../packages/core/testing/src/test_hooks.ts","../../../../../../packages/core/testing/src/testing.ts","../../../../../../packages/core/testing/public_api.ts","../../../../../../packages/core/testing/index.ts","../../../../../../packages/core/testing/testing.ts"],"sourcesContent":["/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n/**\n * Wraps a test function in an asynchronous test zone. The test will automatically\n * complete when all asynchronous calls within this zone are done. Can be used\n * to wrap an {@link inject} call.\n *\n * Example:\n *\n * ```\n * it('...', waitForAsync(inject([AClass], (object) => {\n * object.doSomething.then(() => {\n * expect(...);\n * })\n * })));\n * ```\n *\n * @publicApi\n */\nexport function waitForAsync(fn: Function): (done: any) => any {\n const _Zone: any = typeof Zone !== 'undefined' ? Zone : null;\n if (!_Zone) {\n return function () {\n return Promise.reject(\n 'Zone is needed for the waitForAsync() test helper but could not be found. ' +\n 'Please make sure that your environment includes zone.js',\n );\n };\n }\n const asyncTest = _Zone && _Zone[_Zone.__symbol__('asyncTest')];\n if (typeof asyncTest === 'function') {\n return asyncTest(fn);\n }\n return function () {\n return Promise.reject(\n 'zone-testing.js is needed for the async() test helper but could not be found. ' +\n 'Please make sure that your environment includes zone.js/testing',\n );\n };\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n ɵCONTAINER_HEADER_OFFSET as CONTAINER_HEADER_OFFSET,\n ɵDeferBlockDetails as DeferBlockDetails,\n ɵDeferBlockState as DeferBlockState,\n ɵgetDeferBlocks as getDeferBlocks,\n ɵrenderDeferBlockState as renderDeferBlockState,\n ɵtriggerResourceLoading as triggerResourceLoading,\n} from '@angular/core';\n\nimport type {ComponentFixture} from './component_fixture';\n\n/**\n * Represents an individual defer block for testing purposes.\n *\n * @publicApi\n */\nexport class DeferBlockFixture {\n /** @nodoc */\n constructor(\n private block: DeferBlockDetails,\n private componentFixture: ComponentFixture,\n ) {}\n\n /**\n * Renders the specified state of the defer fixture.\n * @param state the defer state to render\n */\n async render(state: DeferBlockState): Promise {\n if (!hasStateTemplate(state, this.block)) {\n const stateAsString = getDeferBlockStateNameFromEnum(state);\n throw new Error(\n `Tried to render this defer block in the \\`${stateAsString}\\` state, ` +\n `but there was no @${stateAsString.toLowerCase()} block defined in a template.`,\n );\n }\n if (state === DeferBlockState.Complete) {\n await triggerResourceLoading(this.block.tDetails, this.block.lView, this.block.tNode);\n }\n // If the `render` method is used explicitly - skip timer-based scheduling for\n // `@placeholder` and `@loading` blocks and render them immediately.\n const skipTimerScheduling = true;\n renderDeferBlockState(state, this.block.tNode, this.block.lContainer, skipTimerScheduling);\n this.componentFixture.detectChanges();\n }\n\n /**\n * Retrieves all nested child defer block fixtures\n * in a given defer block.\n */\n getDeferBlocks(): Promise {\n const deferBlocks: DeferBlockDetails[] = [];\n // An LContainer that represents a defer block has at most 1 view, which is\n // located right after an LContainer header. Get a hold of that view and inspect\n // it for nested defer blocks.\n const deferBlockFixtures = [];\n if (this.block.lContainer.length >= CONTAINER_HEADER_OFFSET) {\n const lView = this.block.lContainer[CONTAINER_HEADER_OFFSET];\n getDeferBlocks(lView, deferBlocks);\n for (const block of deferBlocks) {\n deferBlockFixtures.push(new DeferBlockFixture(block, this.componentFixture));\n }\n }\n return Promise.resolve(deferBlockFixtures);\n }\n}\n\nfunction hasStateTemplate(state: DeferBlockState, block: DeferBlockDetails) {\n switch (state) {\n case DeferBlockState.Placeholder:\n return block.tDetails.placeholderTmplIndex !== null;\n case DeferBlockState.Loading:\n return block.tDetails.loadingTmplIndex !== null;\n case DeferBlockState.Error:\n return block.tDetails.errorTmplIndex !== null;\n case DeferBlockState.Complete:\n return true;\n default:\n return false;\n }\n}\n\nfunction getDeferBlockStateNameFromEnum(state: DeferBlockState) {\n switch (state) {\n case DeferBlockState.Placeholder:\n return 'Placeholder';\n case DeferBlockState.Loading:\n return 'Loading';\n case DeferBlockState.Error:\n return 'Error';\n default:\n return 'Main';\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n InjectionToken,\n SchemaMetadata,\n ɵDeferBlockBehavior as DeferBlockBehavior,\n} from '@angular/core';\n\n/** Whether test modules should be torn down by default. */\nexport const TEARDOWN_TESTING_MODULE_ON_DESTROY_DEFAULT = true;\n\n/** Whether unknown elements in templates should throw by default. */\nexport const THROW_ON_UNKNOWN_ELEMENTS_DEFAULT = false;\n\n/** Whether unknown properties in templates should throw by default. */\nexport const THROW_ON_UNKNOWN_PROPERTIES_DEFAULT = false;\n\n/** Whether defer blocks should use manual triggering or play through normally. */\nexport const DEFER_BLOCK_DEFAULT_BEHAVIOR = DeferBlockBehavior.Playthrough;\n\n/**\n * An abstract class for inserting the root test component element in a platform independent way.\n *\n * @publicApi\n */\nexport class TestComponentRenderer {\n insertRootElement(rootElementId: string) {}\n removeAllRootElements?() {}\n}\n\n/**\n * @publicApi\n */\nexport const ComponentFixtureAutoDetect = new InjectionToken('ComponentFixtureAutoDetect');\n\n/**\n * @publicApi\n */\nexport const ComponentFixtureNoNgZone = new InjectionToken('ComponentFixtureNoNgZone');\n\n/**\n * @publicApi\n */\nexport interface TestModuleMetadata {\n providers?: any[];\n declarations?: any[];\n imports?: any[];\n schemas?: Array;\n teardown?: ModuleTeardownOptions;\n /**\n * Whether NG0304 runtime errors should be thrown when unknown elements are present in component's\n * template. Defaults to `false`, where the error is simply logged. If set to `true`, the error is\n * thrown.\n * @see [NG8001](/errors/NG8001) for the description of the problem and how to fix it\n */\n errorOnUnknownElements?: boolean;\n /**\n * Whether errors should be thrown when unknown properties are present in component's template.\n * Defaults to `false`, where the error is simply logged.\n * If set to `true`, the error is thrown.\n * @see [NG8002](/errors/NG8002) for the description of the error and how to fix it\n */\n errorOnUnknownProperties?: boolean;\n\n /**\n * Whether defer blocks should behave with manual triggering or play through normally.\n * Defaults to `manual`.\n */\n deferBlockBehavior?: DeferBlockBehavior;\n\n /** @internal */\n _rethrowApplicationTickErrors?: boolean;\n}\n\n/**\n * @publicApi\n */\nexport interface TestEnvironmentOptions {\n /**\n * Configures the test module teardown behavior in `TestBed`.\n */\n teardown?: ModuleTeardownOptions;\n /**\n * Whether errors should be thrown when unknown elements are present in component's template.\n * Defaults to `false`, where the error is simply logged.\n * If set to `true`, the error is thrown.\n * @see [NG8001](/errors/NG8001) for the description of the error and how to fix it\n */\n errorOnUnknownElements?: boolean;\n /**\n * Whether errors should be thrown when unknown properties are present in component's template.\n * Defaults to `false`, where the error is simply logged.\n * If set to `true`, the error is thrown.\n * @see [NG8002](/errors/NG8002) for the description of the error and how to fix it\n */\n errorOnUnknownProperties?: boolean;\n}\n\n/**\n * Configures the test module teardown behavior in `TestBed`.\n * @publicApi\n */\nexport interface ModuleTeardownOptions {\n /** Whether the test module should be destroyed after every test. Defaults to `true`. */\n destroyAfterEach: boolean;\n\n /** Whether errors during test module destruction should be re-thrown. Defaults to `true`. */\n rethrowErrors?: boolean;\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ErrorHandler, inject, NgZone, Injectable, InjectionToken} from '@angular/core';\n\nexport const RETHROW_APPLICATION_ERRORS = new InjectionToken('rethrow application errors');\n\n@Injectable()\nexport class TestBedApplicationErrorHandler {\n private readonly zone = inject(NgZone);\n private readonly userErrorHandler = inject(ErrorHandler);\n readonly whenStableRejectFunctions: Set<(e: unknown) => void> = new Set();\n\n handleError(e: unknown) {\n try {\n this.zone.runOutsideAngular(() => this.userErrorHandler.handleError(e));\n } catch (userError: unknown) {\n e = userError;\n }\n\n // Instead of throwing the error when there are outstanding `fixture.whenStable` promises,\n // reject those promises with the error. This allows developers to write\n // expectAsync(fix.whenStable()).toBeRejected();\n if (this.whenStableRejectFunctions.size > 0) {\n for (const fn of this.whenStableRejectFunctions.values()) {\n fn(e);\n }\n this.whenStableRejectFunctions.clear();\n } else {\n throw e;\n }\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {\n ApplicationRef,\n ChangeDetectorRef,\n ComponentRef,\n DebugElement,\n ElementRef,\n getDebugNode,\n inject,\n NgZone,\n RendererFactory2,\n ViewRef,\n ɵDeferBlockDetails as DeferBlockDetails,\n ɵdetectChangesInViewIfRequired,\n ɵEffectScheduler as EffectScheduler,\n ɵgetDeferBlocks as getDeferBlocks,\n ɵNoopNgZone as NoopNgZone,\n ɵPendingTasks as PendingTasks,\n} from '@angular/core';\nimport {Subject, Subscription} from 'rxjs';\n\nimport {DeferBlockFixture} from './defer';\nimport {ComponentFixtureAutoDetect, ComponentFixtureNoNgZone} from './test_bed_common';\nimport {TestBedApplicationErrorHandler} from './application_error_handler';\n\n/**\n * Fixture for debugging and testing a component.\n *\n * @publicApi\n */\nexport abstract class ComponentFixture {\n /**\n * The DebugElement associated with the root element of this component.\n */\n debugElement: DebugElement;\n\n /**\n * The instance of the root component class.\n */\n componentInstance: T;\n\n /**\n * The native element at the root of the component.\n */\n nativeElement: any;\n\n /**\n * The ElementRef for the element at the root of the component.\n */\n elementRef: ElementRef;\n\n /**\n * The ChangeDetectorRef for the component\n */\n changeDetectorRef: ChangeDetectorRef;\n\n private _renderer: RendererFactory2 | null | undefined;\n private _isDestroyed: boolean = false;\n /** @internal */\n protected readonly _noZoneOptionIsSet = inject(ComponentFixtureNoNgZone, {optional: true});\n /** @internal */\n protected _ngZone: NgZone = this._noZoneOptionIsSet ? new NoopNgZone() : inject(NgZone);\n /** @internal */\n protected _effectRunner = inject(EffectScheduler);\n // Inject ApplicationRef to ensure NgZone stableness causes after render hooks to run\n // This will likely happen as a result of fixture.detectChanges because it calls ngZone.run\n // This is a crazy way of doing things but hey, it's the world we live in.\n // The zoneless scheduler should instead do this more imperatively by attaching\n // the `ComponentRef` to `ApplicationRef` and calling `appRef.tick` as the `detectChanges`\n // behavior.\n /** @internal */\n protected readonly _appRef = inject(ApplicationRef);\n /** @internal */\n protected readonly _testAppRef = this._appRef as unknown as TestAppRef;\n private readonly pendingTasks = inject(PendingTasks);\n private readonly appErrorHandler = inject(TestBedApplicationErrorHandler);\n\n // TODO(atscott): Remove this from public API\n ngZone = this._noZoneOptionIsSet ? null : this._ngZone;\n\n /** @nodoc */\n constructor(public componentRef: ComponentRef) {\n this.changeDetectorRef = componentRef.changeDetectorRef;\n this.elementRef = componentRef.location;\n this.debugElement = getDebugNode(this.elementRef.nativeElement);\n this.componentInstance = componentRef.instance;\n this.nativeElement = this.elementRef.nativeElement;\n this.componentRef = componentRef;\n }\n\n /**\n * Trigger a change detection cycle for the component.\n */\n abstract detectChanges(checkNoChanges?: boolean): void;\n\n /**\n * Do a change detection run to make sure there were no changes.\n */\n checkNoChanges(): void {\n this.changeDetectorRef.checkNoChanges();\n }\n\n /**\n * Set whether the fixture should autodetect changes.\n *\n * Also runs detectChanges once so that any existing change is detected.\n */\n abstract autoDetectChanges(autoDetect?: boolean): void;\n\n /**\n * Return whether the fixture is currently stable or has async tasks that have not been completed\n * yet.\n */\n isStable(): boolean {\n return !this.pendingTasks.hasPendingTasks.value;\n }\n\n /**\n * Get a promise that resolves when the fixture is stable.\n *\n * This can be used to resume testing after events have triggered asynchronous activity or\n * asynchronous change detection.\n */\n whenStable(): Promise {\n if (this.isStable()) {\n return Promise.resolve(false);\n }\n\n return new Promise((resolve, reject) => {\n this.appErrorHandler.whenStableRejectFunctions.add(reject);\n this._appRef.whenStable().then(() => {\n this.appErrorHandler.whenStableRejectFunctions.delete(reject);\n resolve(true);\n });\n });\n }\n\n /**\n * Retrieves all defer block fixtures in the component fixture.\n */\n getDeferBlocks(): Promise {\n const deferBlocks: DeferBlockDetails[] = [];\n const lView = (this.componentRef.hostView as any)['_lView'];\n getDeferBlocks(lView, deferBlocks);\n\n const deferBlockFixtures = [];\n for (const block of deferBlocks) {\n deferBlockFixtures.push(new DeferBlockFixture(block, this));\n }\n\n return Promise.resolve(deferBlockFixtures);\n }\n\n private _getRenderer() {\n if (this._renderer === undefined) {\n this._renderer = this.componentRef.injector.get(RendererFactory2, null);\n }\n return this._renderer as RendererFactory2 | null;\n }\n\n /**\n * Get a promise that resolves when the ui state is stable following animations.\n */\n whenRenderingDone(): Promise {\n const renderer = this._getRenderer();\n if (renderer && renderer.whenRenderingDone) {\n return renderer.whenRenderingDone();\n }\n return this.whenStable();\n }\n\n /**\n * Trigger component destruction.\n */\n destroy(): void {\n if (!this._isDestroyed) {\n this.componentRef.destroy();\n this._isDestroyed = true;\n }\n }\n}\n\n/**\n * ComponentFixture behavior that actually attaches the component to the application to ensure\n * behaviors between fixture and application do not diverge. `detectChanges` is disabled by default\n * (instead, tests should wait for the scheduler to detect changes), `whenStable` is directly the\n * `ApplicationRef.isStable`, and `autoDetectChanges` cannot be disabled.\n */\nexport class ScheduledComponentFixture extends ComponentFixture {\n private _autoDetect = inject(ComponentFixtureAutoDetect, {optional: true}) ?? true;\n\n initialize(): void {\n if (this._autoDetect) {\n this._appRef.attachView(this.componentRef.hostView);\n }\n }\n\n override detectChanges(checkNoChanges = true): void {\n if (!checkNoChanges) {\n throw new Error(\n 'Cannot disable `checkNoChanges` in this configuration. ' +\n 'Use `fixture.componentRef.hostView.changeDetectorRef.detectChanges()` instead.',\n );\n }\n this._effectRunner.flush();\n this._appRef.tick();\n this._effectRunner.flush();\n }\n\n override autoDetectChanges(autoDetect = true): void {\n if (!autoDetect) {\n throw new Error(\n 'Cannot disable autoDetect after it has been enabled when using the zoneless scheduler. ' +\n 'To disable autoDetect, add `{provide: ComponentFixtureAutoDetect, useValue: false}` to the TestBed providers.',\n );\n } else if (!this._autoDetect) {\n this._autoDetect = autoDetect;\n this._appRef.attachView(this.componentRef.hostView);\n }\n this.detectChanges();\n }\n}\n\ninterface TestAppRef {\n externalTestViews: Set;\n beforeRender: Subject;\n afterTick: Subject;\n}\n\n/**\n * ComponentFixture behavior that attempts to act as a \"mini application\".\n */\nexport class PseudoApplicationComponentFixture extends ComponentFixture {\n private _subscriptions = new Subscription();\n private _autoDetect = inject(ComponentFixtureAutoDetect, {optional: true}) ?? false;\n private afterTickSubscription: Subscription | undefined = undefined;\n private beforeRenderSubscription: Subscription | undefined = undefined;\n\n initialize(): void {\n if (this._autoDetect) {\n this.subscribeToAppRefEvents();\n }\n this.componentRef.hostView.onDestroy(() => {\n this.unsubscribeFromAppRefEvents();\n });\n // Create subscriptions outside the NgZone so that the callbacks run outside\n // of NgZone.\n this._ngZone.runOutsideAngular(() => {\n this._subscriptions.add(\n this._ngZone.onError.subscribe({\n next: (error: any) => {\n throw error;\n },\n }),\n );\n });\n }\n\n override detectChanges(checkNoChanges = true): void {\n this._effectRunner.flush();\n // Run the change detection inside the NgZone so that any async tasks as part of the change\n // detection are captured by the zone and can be waited for in isStable.\n this._ngZone.run(() => {\n this.changeDetectorRef.detectChanges();\n if (checkNoChanges) {\n this.checkNoChanges();\n }\n });\n // Run any effects that were created/dirtied during change detection. Such effects might become\n // dirty in response to input signals changing.\n this._effectRunner.flush();\n }\n\n override autoDetectChanges(autoDetect = true): void {\n if (this._noZoneOptionIsSet) {\n throw new Error('Cannot call autoDetectChanges when ComponentFixtureNoNgZone is set.');\n }\n\n if (autoDetect !== this._autoDetect) {\n if (autoDetect) {\n this.subscribeToAppRefEvents();\n } else {\n this.unsubscribeFromAppRefEvents();\n }\n }\n\n this._autoDetect = autoDetect;\n this.detectChanges();\n }\n\n private subscribeToAppRefEvents() {\n this._ngZone.runOutsideAngular(() => {\n this.afterTickSubscription = this._testAppRef.afterTick.subscribe(() => {\n this.checkNoChanges();\n });\n this.beforeRenderSubscription = this._testAppRef.beforeRender.subscribe((isFirstPass) => {\n try {\n ɵdetectChangesInViewIfRequired(\n (this.componentRef.hostView as any)._lView,\n (this.componentRef.hostView as any).notifyErrorHandler,\n isFirstPass,\n false /** zoneless enabled */,\n );\n } catch (e: unknown) {\n // If an error occurred during change detection, remove the test view from the application\n // ref tracking. Note that this isn't exactly desirable but done this way because of how\n // things used to work with `autoDetect` and uncaught errors. Ideally we would surface\n // this error to the error handler instead and continue refreshing the view like\n // what would happen in the application.\n this.unsubscribeFromAppRefEvents();\n\n throw e;\n }\n });\n this._testAppRef.externalTestViews.add(this.componentRef.hostView);\n });\n }\n\n private unsubscribeFromAppRefEvents() {\n this.afterTickSubscription?.unsubscribe();\n this.beforeRenderSubscription?.unsubscribe();\n this.afterTickSubscription = undefined;\n this.beforeRenderSubscription = undefined;\n this._testAppRef.externalTestViews.delete(this.componentRef.hostView);\n }\n\n override destroy(): void {\n this.unsubscribeFromAppRefEvents();\n this._subscriptions.unsubscribe();\n super.destroy();\n }\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\nconst _Zone: any = typeof Zone !== 'undefined' ? Zone : null;\nconst fakeAsyncTestModule = _Zone && _Zone[_Zone.__symbol__('fakeAsyncTest')];\n\nconst fakeAsyncTestModuleNotLoadedErrorMessage = `zone-testing.js is needed for the fakeAsync() test helper but could not be found.\n Please make sure that your environment includes zone.js/testing`;\n\n/**\n * Clears out the shared fake async zone for a test.\n * To be called in a global `beforeEach`.\n *\n * @publicApi\n */\nexport function resetFakeAsyncZone(): void {\n if (fakeAsyncTestModule) {\n return fakeAsyncTestModule.resetFakeAsyncZone();\n }\n throw new Error(fakeAsyncTestModuleNotLoadedErrorMessage);\n}\n\nexport function resetFakeAsyncZoneIfExists(): void {\n if (fakeAsyncTestModule) {\n fakeAsyncTestModule.resetFakeAsyncZone();\n }\n}\n\n/**\n * Wraps a function to be executed in the `fakeAsync` zone:\n * - Microtasks are manually executed by calling `flushMicrotasks()`.\n * - Timers are synchronous; `tick()` simulates the asynchronous passage of time.\n *\n * Can be used to wrap `inject()` calls.\n *\n * @param fn The function that you want to wrap in the `fakeAsync` zone.\n * @param options\n * - flush: When true, will drain the macrotask queue after the test function completes.\n * When false, will throw an exception at the end of the function if there are pending timers.\n *\n * @usageNotes\n * ### Example\n *\n * {@example core/testing/ts/fake_async.ts region='basic'}\n *\n *\n * @returns The function wrapped to be executed in the `fakeAsync` zone.\n * Any arguments passed when calling this returned function will be passed through to the `fn`\n * function in the parameters when it is called.\n *\n * @publicApi\n */\nexport function fakeAsync(fn: Function, options?: {flush?: boolean}): (...args: any[]) => any {\n if (fakeAsyncTestModule) {\n return fakeAsyncTestModule.fakeAsync(fn, options);\n }\n throw new Error(fakeAsyncTestModuleNotLoadedErrorMessage);\n}\n\n/**\n * Simulates the asynchronous passage of time for the timers in the `fakeAsync` zone.\n *\n * The microtasks queue is drained at the very start of this function and after any timer callback\n * has been executed.\n *\n * @param millis The number of milliseconds to advance the virtual timer.\n * @param tickOptions The options to pass to the `tick()` function.\n *\n * @usageNotes\n *\n * The `tick()` option is a flag called `processNewMacroTasksSynchronously`,\n * which determines whether or not to invoke new macroTasks.\n *\n * If you provide a `tickOptions` object, but do not specify a\n * `processNewMacroTasksSynchronously` property (`tick(100, {})`),\n * then `processNewMacroTasksSynchronously` defaults to true.\n *\n * If you omit the `tickOptions` parameter (`tick(100))`), then\n * `tickOptions` defaults to `{processNewMacroTasksSynchronously: true}`.\n *\n * ### Example\n *\n * {@example core/testing/ts/fake_async.ts region='basic'}\n *\n * The following example includes a nested timeout (new macroTask), and\n * the `tickOptions` parameter is allowed to default. In this case,\n * `processNewMacroTasksSynchronously` defaults to true, and the nested\n * function is executed on each tick.\n *\n * ```\n * it ('test with nested setTimeout', fakeAsync(() => {\n * let nestedTimeoutInvoked = false;\n * function funcWithNestedTimeout() {\n * setTimeout(() => {\n * nestedTimeoutInvoked = true;\n * });\n * };\n * setTimeout(funcWithNestedTimeout);\n * tick();\n * expect(nestedTimeoutInvoked).toBe(true);\n * }));\n * ```\n *\n * In the following case, `processNewMacroTasksSynchronously` is explicitly\n * set to false, so the nested timeout function is not invoked.\n *\n * ```\n * it ('test with nested setTimeout', fakeAsync(() => {\n * let nestedTimeoutInvoked = false;\n * function funcWithNestedTimeout() {\n * setTimeout(() => {\n * nestedTimeoutInvoked = true;\n * });\n * };\n * setTimeout(funcWithNestedTimeout);\n * tick(0, {processNewMacroTasksSynchronously: false});\n * expect(nestedTimeoutInvoked).toBe(false);\n * }));\n * ```\n *\n *\n * @publicApi\n */\nexport function tick(\n millis: number = 0,\n tickOptions: {processNewMacroTasksSynchronously: boolean} = {\n processNewMacroTasksSynchronously: true,\n },\n): void {\n if (fakeAsyncTestModule) {\n return fakeAsyncTestModule.tick(millis, tickOptions);\n }\n throw new Error(fakeAsyncTestModuleNotLoadedErrorMessage);\n}\n\n/**\n * Flushes any pending microtasks and simulates the asynchronous passage of time for the timers in\n * the `fakeAsync` zone by\n * draining the macrotask queue until it is empty.\n *\n * @param maxTurns The maximum number of times the scheduler attempts to clear its queue before\n * throwing an error.\n * @returns The simulated time elapsed, in milliseconds.\n *\n * @publicApi\n */\nexport function flush(maxTurns?: number): number {\n if (fakeAsyncTestModule) {\n return fakeAsyncTestModule.flush(maxTurns);\n }\n throw new Error(fakeAsyncTestModuleNotLoadedErrorMessage);\n}\n\n/**\n * Discard all remaining periodic tasks.\n *\n * @publicApi\n */\nexport function discardPeriodicTasks(): void {\n if (fakeAsyncTestModule) {\n return fakeAsyncTestModule.discardPeriodicTasks();\n }\n throw new Error(fakeAsyncTestModuleNotLoadedErrorMessage);\n}\n\n/**\n * Flush any pending microtasks.\n *\n * @publicApi\n */\nexport function flushMicrotasks(): void {\n if (fakeAsyncTestModule) {\n return fakeAsyncTestModule.flushMicrotasks();\n }\n throw new Error(fakeAsyncTestModuleNotLoadedErrorMessage);\n}\n","/**\n * @license\n * Copyright Google LLC All Rights Reserved.\n *\n * Use of this source code is governed by an MIT-style license that can be\n * found in the LICENSE file at https://angular.io/license\n */\n\nimport {ɵstringify as stringify} from '@angular/core';\n\nimport {MetadataOverride} from './metadata_override';\n\ntype StringMap = {\n [key: string]: any;\n};\n\nlet _nextReferenceId = 0;\n\nexport class MetadataOverrider {\n private _references = new Map();\n /**\n * Creates a new instance for the given metadata class\n * based on an old instance and overrides.\n */\n overrideMetadata(\n metadataClass: {new (options: T): C},\n oldMetadata: C,\n override: MetadataOverride,\n ): C {\n const props: StringMap = {};\n if (oldMetadata) {\n _valueProps(oldMetadata).forEach((prop) => (props[prop] = (oldMetadata)[prop]));\n }\n\n if (override.set) {\n if (override.remove || override.add) {\n throw new Error(`Cannot set and add/remove ${stringify(metadataClass)} at the same time!`);\n }\n setMetadata(props, override.set);\n }\n if (override.remove) {\n removeMetadata(props, override.remove, this._references);\n }\n if (override.add) {\n addMetadata(props, override.add);\n }\n return new metadataClass(props);\n }\n}\n\nfunction removeMetadata(metadata: StringMap, remove: any, references: Map) {\n const removeObjects = new Set();\n for (const prop in remove) {\n const removeValue = remove[prop];\n if (Array.isArray(removeValue)) {\n removeValue.forEach((value: any) => {\n removeObjects.add(_propHashKey(prop, value, references));\n });\n } else {\n removeObjects.add(_propHashKey(prop, removeValue, references));\n }\n }\n\n for (const prop in metadata) {\n const propValue = metadata[prop];\n if (Array.isArray(propValue)) {\n metadata[prop] = propValue.filter(\n (value: any) => !removeObjects.has(_propHashKey(prop, value, references)),\n );\n } else {\n if (removeObjects.has(_propHashKey(prop, propValue, references))) {\n metadata[prop] = undefined;\n }\n }\n }\n}\n\nfunction addMetadata(metadata: StringMap, add: any) {\n for (const prop in add) {\n const addValue = add[prop];\n const propValue = metadata[prop];\n if (propValue != null && Array.isArray(propValue)) {\n metadata[prop] = propValue.concat(addValue);\n } else {\n metadata[prop] = addValue;\n }\n }\n}\n\nfunction setMetadata(metadata: StringMap, set: any) {\n for (const prop in set) {\n metadata[prop] = set[prop];\n }\n}\n\nfunction _propHashKey(propName: any, propValue: any, references: Map): string {\n let nextObjectId = 0;\n const objectIds = new Map