@angular/core
Version:
Angular - the core framework
1 lines • 243 kB
Source Map (JSON)
{"version":3,"file":"testing.mjs","sources":["../../../../../k8-fastbuild-ST-46c76129e412/bin/packages/core/testing/src/async.ts","../../../../../k8-fastbuild-ST-46c76129e412/bin/packages/core/testing/src/application_error_handler.ts","../../../../../k8-fastbuild-ST-46c76129e412/bin/packages/core/testing/src/defer.ts","../../../../../k8-fastbuild-ST-46c76129e412/bin/packages/core/testing/src/test_bed_common.ts","../../../../../k8-fastbuild-ST-46c76129e412/bin/packages/core/testing/src/component_fixture.ts","../../../../../k8-fastbuild-ST-46c76129e412/bin/packages/core/testing/src/fake_async.ts","../../../../../k8-fastbuild-ST-46c76129e412/bin/packages/core/testing/src/metadata_overrider.ts","../../../../../k8-fastbuild-ST-46c76129e412/bin/packages/core/testing/src/resolvers.ts","../../../../../k8-fastbuild-ST-46c76129e412/bin/packages/core/testing/src/test_bed_compiler.ts","../../../../../k8-fastbuild-ST-46c76129e412/bin/packages/core/testing/src/test_bed.ts","../../../../../k8-fastbuild-ST-46c76129e412/bin/packages/core/primitives/dom-navigation/testing/fake_navigation.ts","../../../../../k8-fastbuild-ST-46c76129e412/bin/packages/core/testing/src/test_hooks.ts","../../../../../k8-fastbuild-ST-46c76129e412/bin/packages/core/testing/src/logger.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.dev/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 * ```ts\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.dev/license\n */\n\nimport {ErrorHandler, inject, NgZone, Injectable, EnvironmentInjector} from '../../src/core';\n\nexport const RETHROW_APPLICATION_ERRORS_DEFAULT = true;\n\n@Injectable()\nexport class TestBedApplicationErrorHandler {\n private readonly zone = inject(NgZone);\n private readonly injector = inject(EnvironmentInjector);\n private userErrorHandler?: ErrorHandler;\n readonly whenStableRejectFunctions: Set<(e: unknown) => void> = new Set();\n\n handleError(e: unknown) {\n try {\n this.zone.runOutsideAngular(() => {\n this.userErrorHandler ??= this.injector.get(ErrorHandler);\n this.userErrorHandler.handleError(e);\n });\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.dev/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 '../../src/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 /** @docs-private */\n constructor(\n private block: DeferBlockDetails,\n private componentFixture: ComponentFixture<unknown>,\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<void> {\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<DeferBlockFixture[]> {\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.dev/license\n */\n\nimport {\n InjectionToken,\n SchemaMetadata,\n ɵDeferBlockBehavior as DeferBlockBehavior,\n} from '../../src/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<boolean>('ComponentFixtureAutoDetect');\n\n/**\n * @publicApi\n */\nexport const ComponentFixtureNoNgZone = new InjectionToken<boolean>('ComponentFixtureNoNgZone');\n\n/**\n * @publicApi\n */\nexport interface TestModuleMetadata {\n providers?: any[];\n declarations?: any[];\n imports?: any[];\n schemas?: Array<SchemaMetadata | any[]>;\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 errors that happen during application change detection should be rethrown.\n *\n * When `true`, errors that are caught during application change detection will\n * be reported to the `ErrorHandler` and rethrown to prevent them from going\n * unnoticed in tests.\n *\n * When `false`, errors are only forwarded to the `ErrorHandler`, which by default\n * simply logs them to the console.\n *\n * Defaults to `true`.\n */\n rethrowApplicationErrors?: 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\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.dev/license\n */\n\nimport {Subscription} from 'rxjs';\nimport {\n ApplicationRef,\n ChangeDetectorRef,\n ComponentRef,\n DebugElement,\n ɵDeferBlockDetails as DeferBlockDetails,\n ɵEffectScheduler as EffectScheduler,\n ElementRef,\n getDebugNode,\n ɵgetDeferBlocks as getDeferBlocks,\n inject,\n NgZone,\n ɵNoopNgZone as NoopNgZone,\n RendererFactory2,\n ViewRef,\n ɵZONELESS_ENABLED as ZONELESS_ENABLED,\n ɵChangeDetectionScheduler,\n ɵNotificationSource,\n} from '../../src/core';\nimport {PendingTasksInternal} from '../../src/pending_tasks';\n\nimport {TestBedApplicationErrorHandler} from './application_error_handler';\nimport {DeferBlockFixture} from './defer';\nimport {ComponentFixtureAutoDetect, ComponentFixtureNoNgZone} from './test_bed_common';\n\ninterface TestAppRef {\n allTestViews: Set<ViewRef>;\n includeAllTestViews: boolean;\n autoDetectTestViews: Set<ViewRef>;\n}\n\n/**\n * Fixture for debugging and testing a component.\n *\n * @publicApi\n */\nexport class ComponentFixture<T> {\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 // 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 private readonly _testAppRef = this._appRef as unknown as TestAppRef;\n private readonly pendingTasks = inject(PendingTasksInternal);\n private readonly appErrorHandler = inject(TestBedApplicationErrorHandler);\n private readonly zonelessEnabled = inject(ZONELESS_ENABLED);\n private readonly scheduler = inject(ɵChangeDetectionScheduler);\n private readonly rootEffectScheduler = inject(EffectScheduler);\n private readonly autoDetectDefault = this.zonelessEnabled ? true : false;\n private autoDetect =\n inject(ComponentFixtureAutoDetect, {optional: true}) ?? this.autoDetectDefault;\n\n private subscriptions = new Subscription();\n\n // TODO(atscott): Remove this from public API\n ngZone = this._noZoneOptionIsSet ? null : this._ngZone;\n\n /** @docs-private */\n constructor(public componentRef: ComponentRef<T>) {\n this.changeDetectorRef = componentRef.changeDetectorRef;\n this.elementRef = componentRef.location;\n this.debugElement = <DebugElement>getDebugNode(this.elementRef.nativeElement);\n this.componentInstance = componentRef.instance;\n this.nativeElement = this.elementRef.nativeElement;\n this.componentRef = componentRef;\n\n this._testAppRef.allTestViews.add(this.componentRef.hostView);\n if (this.autoDetect) {\n this._testAppRef.autoDetectTestViews.add(this.componentRef.hostView);\n this.scheduler?.notify(ɵNotificationSource.ViewAttached);\n this.scheduler?.notify(ɵNotificationSource.MarkAncestorsForTraversal);\n }\n this.componentRef.hostView.onDestroy(() => {\n this._testAppRef.allTestViews.delete(this.componentRef.hostView);\n this._testAppRef.autoDetectTestViews.delete(this.componentRef.hostView);\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 // The rethrow here is to ensure that errors don't go unreported. Since `NgZone.onHandleError` returns `false`,\n // ZoneJS will not throw the error coming out of a task. Instead, the handling is defined by\n // the chain of parent delegates and whether they indicate the error is handled in some way (by returning `false`).\n // Unfortunately, 'onError' does not forward the information about whether the error was handled by a parent zone\n // so cannot know here whether throwing is appropriate. As a half-solution, we can check to see if we're inside\n // a fakeAsync context, which we know has its own error handling.\n // https://github.com/angular/angular/blob/db2f2d99c82aae52d8a0ae46616c6411d070b35e/packages/zone.js/lib/zone-spec/fake-async-test.ts#L783-L784\n // https://github.com/angular/angular/blob/db2f2d99c82aae52d8a0ae46616c6411d070b35e/packages/zone.js/lib/zone-spec/fake-async-test.ts#L473-L478\n if (typeof Zone === 'undefined' || Zone.current.get('FakeAsyncTestZoneSpec')) {\n return;\n }\n throw error;\n },\n }),\n );\n });\n }\n\n /**\n * Trigger a change detection cycle for the component.\n */\n detectChanges(checkNoChanges = true): void {\n const originalCheckNoChanges = this.componentRef.changeDetectorRef.checkNoChanges;\n try {\n if (!checkNoChanges) {\n this.componentRef.changeDetectorRef.checkNoChanges = () => {};\n }\n\n if (this.zonelessEnabled) {\n try {\n this._testAppRef.includeAllTestViews = true;\n this._appRef.tick();\n } finally {\n this._testAppRef.includeAllTestViews = false;\n }\n } else {\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 // Flush root effects before `detectChanges()`, to emulate the sequencing of `tick()`.\n this.rootEffectScheduler.flush();\n this.changeDetectorRef.detectChanges();\n this.checkNoChanges();\n });\n }\n } finally {\n this.componentRef.changeDetectorRef.checkNoChanges = originalCheckNoChanges;\n }\n }\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 * @param autoDetect Whether to autodetect changes. By default, `true`.\n * @deprecated For `autoDetect: true`, use `autoDetectChanges()`.\n * We have not seen a use-case for `autoDetect: false` but `changeDetectorRef.detach()` is a close equivalent.\n */\n autoDetectChanges(autoDetect: boolean): void;\n /**\n * Enables automatically synchronizing the view, as it would in an application.\n *\n * Also runs detectChanges once so that any existing change is detected.\n */\n autoDetectChanges(): void;\n autoDetectChanges(autoDetect = true): void {\n if (!autoDetect && this.zonelessEnabled) {\n throw new Error('Cannot set autoDetect to false with zoneless change detection.');\n }\n if (this._noZoneOptionIsSet && !this.zonelessEnabled) {\n throw new Error('Cannot call autoDetectChanges when ComponentFixtureNoNgZone is set.');\n }\n\n if (autoDetect) {\n this._testAppRef.autoDetectTestViews.add(this.componentRef.hostView);\n } else {\n this._testAppRef.autoDetectTestViews.delete(this.componentRef.hostView);\n }\n\n this.autoDetect = autoDetect;\n this.detectChanges();\n }\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;\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<any> {\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<DeferBlockFixture[]> {\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<any> {\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 this.subscriptions.unsubscribe();\n this._testAppRef.autoDetectTestViews.delete(this.componentRef.hostView);\n this._testAppRef.allTestViews.delete(this.componentRef.hostView);\n if (!this._isDestroyed) {\n this.componentRef.destroy();\n this._isDestroyed = true;\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.dev/license\n */\n\n// Needed for the global `Zone` ambient types to be available.\nimport type {} from 'zone.js';\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 && (Zone as any)['ProxyZoneSpec']?.isLoaded()) {\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 * ```ts\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 * ```ts\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.dev/license\n */\n\nimport {ɵstringify as stringify} from '../../src/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<any, string>();\n /**\n * Creates a new instance for the given metadata class\n * based on an old instance and overrides.\n */\n overrideMetadata<C extends T, T>(\n metadataClass: {new (options: T): C},\n oldMetadata: C,\n override: MetadataOverride<T>,\n ): C {\n const props: StringMap = {};\n if (oldMetadata) {\n _valueProps(oldMetadata).forEach((prop) => (props[prop] = (<any>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(<any>props);\n }\n}\n\nfunction removeMetadata(metadata: StringMap, remove: any, references: Map<any, string>) {\n const removeObjects = new Set<string>();\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<any, string>): string {\n let nextObjectId = 0;\n const objectIds = new Map<object, string>();\n const replacer = (key: any, value: any) => {\n if (value !== null && typeof value === 'object') {\n if (objectIds.has(value)) {\n return objectIds.get(value);\n }\n // Record an id for this object such that any later references use the object's id instead\n // of the object itself, in order to break cyclic pointers in objects.\n objectIds.set(value, `ɵobj#${nextObjectId++}`);\n\n // The first time an object is seen the object itself is serialized.\n return value;\n } else if (typeof value === 'function') {\n value = _serializeReference(value, references);\n }\n return value;\n };\n\n return `${propName}:${JSON.stringify(propValue, replacer)}`;\n}\n\nfunction _serializeReference(ref: any, references: Map<any, string>): string {\n let id = references.get(ref);\n if (!id) {\n id = `${stringify(ref)}${_nextReferenceId++}`;\n references.set(ref, id);\n }\n return id;\n}\n\nfunction _valueProps(obj: any): string[] {\n const props: string[] = [];\n // regular public props\n Object.keys(obj).forEach((prop) => {\n if (!prop.startsWith('_')) {\n props.push(prop);\n }\n });\n\n // getters\n let proto = obj;\n while ((proto = Object.getPrototypeOf(proto))) {\n Object.keys(proto).forEach((protoProp) => {\n const desc = Object.getOwnPropertyDescriptor(proto, protoProp);\n if (!protoProp.startsWith('_') && desc && 'get' in desc) {\n props.push(protoProp);\n }\n });\n }\n return props;\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.dev/license\n */\n\nimport {\n Component,\n Directive,\n NgModule,\n Pipe,\n Type,\n ɵReflectionCapabilities as ReflectionCapabilities,\n} from '../../src/core';\n\nimport {MetadataOverride} from './metadata_override';\nimport {MetadataOverrider} from './metadata_overrider';\n\nconst reflection = new ReflectionCapabilities();\n\n/**\n * Base interface to resolve `@Component`, `@Directive`, `@Pipe` and `@NgModule`.\n */\nexport interface Resolver<T> {\n addOverride(type: Type<any>, override: MetadataOverride<T>): void;\n setOverrides(overrides: Array<[Type<any>, MetadataOverride<T>]>): void;\n resolve(type: Type<any>): T | null;\n}\n\n/**\n * Allows to override ivy metadata for tests (via the `TestBed`).\n */\nabstract class OverrideResolver<T> implements Resolver<T> {\n private overrides = new Map<Type<any>, MetadataOverride<T>[]>();\n private resolved = new Map<Type<any>, T | null>();\n\n abstract get type(): any;\n\n addOverride(type: Type<any>, override: MetadataOverride<T>) {\n const overrides = this.overrides.get(type) || [];\n overrides.push(override);\n this.overrides.set(type, overrides);\n this.resolved.delete(type);\n }\n\n setOverrides(overrides: Array<[Type<any>, MetadataOverride<T>]>) {\n this.overrides.clear();\n overrides.forEach(([type, override]) => {\n this.addOverride(type, override);\n });\n }\n\n getAnnotation(type: Type<any>): T | null {\n const annotations = reflection.annotations(type);\n // Try to find the nearest known Type annotation and make sure that this annotation is an\n // instance of the type we are looking for, so we can use it for resolution. Note: there might\n // be multiple known annotations found due to the fact that Components can extend Directives (so\n // both Directive and Component annotations would be present), so we always check if the known\n // annotation has the right type.\n for (let i = annotations.length - 1; i >= 0; i--) {\n const annotation = annotations[i];\n const isKnownType =\n annotation instanceof Directive ||\n annotation instanceof Component ||\n annotation instanceof Pipe ||\n annotation instanceof NgModule;\n if (isKnownType) {\n return annotation instanceof this.type ? (annotation as unknown as T) : null;\n }\n }\n return null;\n }\n\n resolve(type: Type<any>): T | null {\n let resolved: T | null = this.resolved.get(type) || null;\n\n if (!resolved) {\n resolved = this.getAnnotation(type);\n if (resolved) {\n const overrides = this.overrides.get(type);\n if (overrides) {\n const overrider = new MetadataOverrider();\n overrides.forEach((override) => {\n resolved = overrider.overrideMetadata(this.type, resolved!, override);\n });\n }\n }\n this.resolved.set(type, resolved);\n }\n\n return resolved;\n }\n}\n\nexport class DirectiveResolver extends OverrideResolver<Directive> {\n override get type() {\n return Directive;\n }\n}\n\nexport class ComponentResolver extends OverrideResolver<Component> {\n override get type() {\n return Component;\n }\n}\n\nexport class PipeResolver extends OverrideResolver<Pipe> {\n override get type() {\n return Pipe;\n }\n}\n\nexport class NgModuleResolver extends OverrideResolver<NgModule> {\n override get type() {\n return NgModule;\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.dev/license\n */\n\nimport {ResourceLoader} from '@angular/compiler';\nimport {\n ApplicationInitStatus,\n ɵINTERNAL_APPLICATION_ERROR_HANDLER as INTERNAL_APPLICATION_ERROR_HANDLER,\n ɵChangeDetectionScheduler as ChangeDetectionScheduler,\n ɵChangeDetectionSchedulerImpl as ChangeDetectionSchedulerImpl,\n Compiler,\n COMPILER_OPTIONS,\n Component,\n Directive,\n Injector,\n inject,\n InjectorType,\n LOCALE_ID,\n ModuleWithComponentFactories,\n ModuleWithProviders,\n NgModule,\n NgModuleFactory,\n Pipe,\n PlatformRef,\n Provider,\n resolveForwardRef,\n StaticProvider,\n Type,\n ɵclearResolutionOfComponentResourcesQueue,\n ɵcompileComponent as compileComponent,\n ɵcompileDirective as compileDirective,\n ɵcompileNgModuleDefs as compileNgModuleDefs,\n ɵcompilePipe as compilePipe,\n ɵDEFAULT_LOCALE_ID as DEFAULT_LOCALE_ID,\n ɵDEFER_BLOCK_CONFIG as DEFER_BLOCK_CONFIG,\n ɵdepsTracker as depsTracker,\n ɵDirectiveDef as DirectiveDef,\n ɵgenerateStandaloneInDeclarationsError,\n ɵgetAsyncClassMetadataFn as getAsyncClassMetadataFn,\n ɵgetInjectableDef as getInjectableDef,\n ɵInternalEnvironmentProviders as InternalEnvironmentProviders,\n ɵinternalProvideZoneChangeDetection as internalProvideZoneChangeDetection,\n ɵisComponentDefPendingResolution,\n ɵisEnvironmentProviders as isEnvironmentProviders,\n ɵNG_COMP_DEF as NG_COMP_DEF,\n ɵNG_DIR_DEF as NG_DIR_DEF,\n ɵNG_INJ_DEF as NG_INJ_DEF,\n ɵNG_MOD_DEF as NG_MOD_DEF,\n ɵNG_PIPE_DEF as NG_PIPE_DEF,\n ɵNgModuleFactory as R3NgModuleFactory,\n ɵNgModuleTransitiveScopes as NgModuleTransitiveScopes,\n ɵNgModuleType as NgModuleType,\n ɵpatchComponentDefWithScope as patchComponentDefWithScope,\n ɵRender3ComponentFactory as ComponentFactory,\n ɵRender3NgModuleRef as NgModuleRef,\n ɵresolveComponentResources,\n ɵrestoreComponentResolutionQueue,\n ɵsetLocaleId as setLocaleId,\n ɵtransitiveScopesFor as transitiveScopesFor,\n ɵɵInjectableDeclaration as InjectableDeclaration,\n NgZone,\n ErrorHandler,\n ENVIRONMENT_INITIALIZER,\n} from '../../src/core';\n\nimport {ComponentDef, ComponentType} from '../../src/render3';\n\nimport {MetadataOverride} from './metadata_override';\nimport {\n ComponentResolver,\n DirectiveResolver,\n NgModuleResolver,\n PipeResolver,\n Resolver,\n} from './resolvers';\nimport {DEFER_BLOCK_DEFAULT_BEHAVIOR, TestModuleMetadata} from './test_bed_common';\nimport {\n RETHROW_APPLICATION_ERRORS_DEFAULT,\n TestBedApplicationErrorHandler,\n} from './application_error_handler';\n\nenum TestingModuleOverride {\n DECLARATION,\n OVERRIDE_TEMPLATE,\n}\n\nfunction isTestingModuleOverride(value: unknown): value is TestingModuleOverride {\n return (\n value === TestingModuleOverride.DECLARATION || value === TestingModuleOverride.OVERRIDE_TEMPLATE\n );\n}\n\nfunction assertNoStandaloneComponents(\n types: Type<any>[],\n resolver: Resolver<any>,\n location: string,\n) {\n types.forEach((type) => {\n if (!getAsyncClassMetadataFn(type)) {\n const component = resolver.resolve(type);\n if (component && (component.standalone == null || component.standalone)) {\n throw new Error(ɵgenerateStandaloneInDeclarationsError(type, location));\n }\n }\n });\n}\n\n// Resolvers for Angular decorators\ntype Resolvers = {\n module: Resolver<NgModule>;\n component: Resolver<Directive>;\n directive: Resolver<Component>;\n pipe: Resolver<Pipe>;\n};\n\ninterface CleanupOperation {\n fieldName: string;\n object: any;\n originalValue: unknown;\n}\n\nexport class TestBedCompiler {\n private originalComponentResolutionQueue: Map<Type<any>, Component> | null = null;\n\n // Testing module configuration\n private declarations: Type<any>[] = [];\n private imports: Type<any>[] = [];\n private providers: Provider[] = [];\n private schemas: any[] = [];\n\n // Queues of components/directives/pipes that should be recompiled.\n private pendingComponents = new Set<Type<any>>();\n private pendingDirectives = new Set<Type<any>>();\n private pendingPipes = new Set<Type<any>>();\n\n // Set of components with async metadata, i.e. components with `@defer` blocks\n // in their templates.\n private componentsWithAsyncMetadata = new Set<Type<unknown>>();\n\n // Keep track of all components and directives, so we can patch Providers onto defs later.\n private seenComponents = new Set<Type<any>>();\n private seenDirectives = new Set<Type<any>>();\n\n // Keep track of overridden modules, so that we can collect all affected ones in the module tree.\n private overriddenModules = new Set<NgModuleType<any>>();\n\n // Store resolved styles for Components that have template overrides present and `styleUrls`\n // defined at the same time.\n private existingComponentStyles = new Map<Type<any>, string[]>();\n\n private resolvers: Resolvers = initResolvers();\n\n // Map of component type to an NgModule that declares it.\n //\n // There are a couple special cases:\n // - for standalone components, the module scope value is `null`\n // - when a component is declared in `TestBed.configureTestingModule()` call or\n // a component's template is overridden via `TestBed.overrideTemplateUsingTestingModule()`.\n // we use a special value from the `TestingModuleOverride` enum.\n private componentToModuleScope = new Map<Type<any>, Type<any> | TestingModuleOverride | null>();\n\n // Map that keeps initial version of component/directive/pipe defs in case\n // we compile a Type again, thus overriding respective static fields. This is\n // required to make sure we restore defs to their initial states between test runs.\n // Note: one class may have multiple defs (for example: ɵmod and ɵinj in case of an\n // NgModule), store all of them in a map.\n private initialNgDefs = new Map<Type<any>, Map<string, PropertyDescriptor | undefined>>();\n\n // Array that keeps cleanup operations for initial versions of component/directive/pipe/module\n // defs in case TestBed makes changes to the originals.\n private defCleanupOps: CleanupOperation[] = [];\n\n private _injector: Injector | null = null;\n private compilerProviders: Provider[] | null = null;\n\n private providerOverrides: Provider[] = [];\n private rootProviderOverrides: Provider[] = [];\n // Overrides for injectables with `{providedIn: SomeModule}` need to be tracked and added to that\n // module's provider list.\n private providerOverridesByModule = new Map<InjectorType<any>, Provider[]>();\n private providerOverridesByToken = new Map<any, Provider>();\n private scopesWithOverriddenProviders = new Set<Type<any>>();\n\n private testModuleType: NgModuleType<any>;\n private testModuleRef: NgModuleRef<any> | null = null;\n\n private deferBlockBehavior = DEFER_BLOCK_DEFAULT_BEHAVIOR;\n private rethrowApplicationTickErrors = RETHROW_APPLICATION_ERRORS_DEFAULT;\n\n constructor(\n private platform: PlatformRef,\n private additionalModuleTypes: Type<any> | Type<any>[],\n ) {\n class DynamicTestModule {}\n this.testModuleType = DynamicTestModule as any;\n }\n\n setCompilerProviders(providers: Provider[] | null): void {\n this.compilerProviders = providers;\n this._injector = null;\n }\n\n configureTestingModule(moduleDef: TestModuleMetadata): void {\n // Enqueue any compilation tasks for the directly declared component.\n if (moduleDef.declarations !== undefined) {\n // Verify that there are no standalone components\n assertNoStandaloneComponents(\n moduleDef.declarations,\n this.resolvers.component,\n '\"TestBed.configureTestingModule\" call',\n );\n this.queueTypeArray(moduleDef.declarations, TestingModuleOverride.DECLARATION);\n this.declarations.push(...moduleDef.declarations);\n }\n\n // Enqueue any compilation tasks for imported modules.\n if (moduleDef.imports !== undefined) {\n this.queueTypesFromModulesArray(moduleDef.imports);\n this.imports.push(...moduleDef.imports);\n }\n\n if (moduleDef.providers !== undefined) {\n this.providers.push(...moduleDef.providers);\n }\n\n if (moduleDef.schemas !== undefined) {\n this.schemas.push(...moduleDef.schemas);\n }\n\n this.deferBlockBehavior = moduleDef.deferBlockBehavior ?? DEFER_BLOCK_DEFAULT_BEHAVIOR;\n this.rethrowApplicationTickErrors =\n moduleDef.rethrowApplicationErrors ?? RETHROW_APPLICATION_ERRORS_DEFAULT;\n }\n\n overrideModule(ngModule: Type<any>, override: MetadataOverride<NgModule>): void {\n depsTracker.clearScopeCacheFor(ngModule);\n this.overriddenModules.add(ngModule as NgModuleType<any>);\n\n // Compile the module right away.\n this.resolvers.module.addOverride(ngModule, override);\n const metadata = this.resolvers.module.resolve(ngModule);\n if (metadata === null) {\n throw invalidTypeError(ngModule.name, 'NgModule');\n }\n\n this.recompileNgModule(ngModule, metadata);\n\n // At this point, the module has a valid module def (ɵmod), but the override may have introduced\n // new declarations or imported modules. Ingest any possible new types and add them to the\n // current queue.\n this.queueTypesFromModulesArray([ngModule]);\n }\n\n overrideComponent(component: Type<any>, override: MetadataOverride<Component>): void {\n this.verifyNoStandaloneFlagOverrides(component, override);\n this.resolvers.component.addOverride(component, override);\n this.pendingComponents.add(component);\n\n // If this is a component with async metadata (i.e. a component with a `@defer` block\n // in a template) - store it for future processing.\n this.maybeRegisterComponentWithAsyncMetadata(component);\n }\n\n overrideDirective(directive: Type<any>, override: MetadataOverride<Directive>): void {\n this.verifyNoStandaloneFlagOverrides(directive, override);\n this.resolvers.directive.addOverride(directive, override);\n this.pendingDirectives.add(directive);\n }\n\n overridePipe(pipe: Type<any>, override: MetadataOverride<Pipe>): void {\n this.verifyNoStandaloneFlagOverrides(pipe, override);\n this.resolvers.pipe.addOverride(pipe, override);\n this.pendingPipes.add(pipe);\n }\n\n private verifyNoStandaloneFlagOverrides(\n type: Type<any>,\n override: MetadataOverride<Component | Directive | Pipe>,\n ) {\n if (\n override.add?.hasOwnProperty('standalone') ||\n override.set?.hasOwnProperty('standalone') ||\n override.remove?.hasOwnProperty('standalone')\n ) {\n throw new Error(\n `An override for the ${type.name} class has the \\`standalone\\` flag. ` +\n `Changing the \\`standalone\\` flag via TestBed overrides is not supported.`,\n );\n }\n }\n\n overrideProvider(\n token: any,\n provider: {useFactory?: Function; useValue?: any; deps?: any[]; multi?: boolean},\n ): void {\n let providerDef: Provider;\n if (provider.useFactory !== undefined) {\n providerDef = {\n provide: token,\n useFactory: provider.useFactory,\n deps: provider.deps || [],\n multi: provider.multi,\n };\n } else if (provider.useValue !== undefined) {\n providerDef = {provide: token, useValue: provider.useValue, multi: provider.multi};\n } else {\n providerDef = {provide: token};\n }\n\n const injectableDef: InjectableDeclaration<any> | null =\n typeof token !== 'string' ? getInjectableDef(token) : null;\n const providedIn = injectableDef === null ? null : resolveForwardRef(injectableDef.providedIn);\n const overridesBucket =\n providedIn === 'root' ? this.rootProviderOverrides : this.providerOverrides;\n overridesBucket.push(providerDef);\n\n // Keep overrides grouped by token as well for fast lookups using token\n this.providerOverridesByToken.set(token, providerDef);\n if (injectableDef !== null && providedIn !== null && typeof providedIn !== 'string') {\n const existingOverrides = this.providerOverridesByModule.get(providedIn);\n if (existingOverrides !== undefined) {\n existingOverrides.push(providerDef);\n } else {\n this.providerOverridesByModule.set(providedIn, [providerDef]);\n }\n }\n }\n\n overrideTemplateUsingTestingModule(type: Type<any>, template: string): void {\n const def = (type as any)[NG_COMP_DEF];\n const hasStyleUrls = (): boolean => {\n const metadata = this.resolvers.component.resolve(type)! as Component;\n return !!metadata.styleUrl || !!metadata.styleUrls?.length;\n };\n const overrideStyleUrls = !!def && !ɵisComponentDefPendingResolution(type) && hasStyleUrls();\n\n // In Ivy, compiling a component does not require knowing the module providing the\n // component's scope, so overrideTemplateUsingTestingModule can be implemented purely via\n // overrideComponent. Important: overriding template requires full Component re-compilation,\n // which may fail in case styleUrls are also present (thus Component is considered as required\n // resolution). In order to avoid this, we preemptively set styleUrls to an empty array,\n // preserve current styles available on Component def and restore styles back once compilation\n // is complete.\n const override = overrideStyleUrls\n ? {template, styles: [], styleUrls: [], styleUrl: undefined}\n : {template};\n this.overrideComponent(type, {set: over