@angular/core 20.0.0-next.4 → 20.0.0-next.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/api.d-DQLNOR5l.d.ts +297 -0
- package/discovery.d-CFs2MaLO.d.ts +7383 -0
- package/{event_dispatcher.d-pVP0-wST.d.ts → event_dispatcher.d-DlbccpYq.d.ts} +3 -2
- package/fesm2022/attribute-BWp59EjE.mjs +24 -0
- package/fesm2022/attribute-BWp59EjE.mjs.map +1 -0
- package/fesm2022/core.mjs +586 -36873
- package/fesm2022/core.mjs.map +1 -1
- package/fesm2022/debug_node-z_3NG8qT.mjs +32079 -0
- package/fesm2022/debug_node-z_3NG8qT.mjs.map +1 -0
- package/fesm2022/primitives/di.mjs +18 -4
- package/fesm2022/primitives/di.mjs.map +1 -1
- package/fesm2022/primitives/event-dispatch.mjs +2 -16
- package/fesm2022/primitives/event-dispatch.mjs.map +1 -1
- package/fesm2022/primitives/signals.mjs +5 -3
- package/fesm2022/primitives/signals.mjs.map +1 -1
- package/fesm2022/resource-CPPwEcg7.mjs +619 -0
- package/fesm2022/resource-CPPwEcg7.mjs.map +1 -0
- package/fesm2022/root_effect_scheduler-VSXfCzDX.mjs +3847 -0
- package/fesm2022/root_effect_scheduler-VSXfCzDX.mjs.map +1 -0
- package/fesm2022/rxjs-interop.mjs +16 -9
- package/fesm2022/rxjs-interop.mjs.map +1 -1
- package/fesm2022/{untracked-DkcXpNb_.mjs → signal-B6pMq7KS.mjs} +16 -114
- package/fesm2022/signal-B6pMq7KS.mjs.map +1 -0
- package/fesm2022/testing.mjs +265 -201
- package/fesm2022/testing.mjs.map +1 -1
- package/fesm2022/untracked-Bz5WMeU1.mjs +117 -0
- package/fesm2022/untracked-Bz5WMeU1.mjs.map +1 -0
- package/fesm2022/weak_ref-BaIq-pgY.mjs +12 -0
- package/fesm2022/weak_ref-BaIq-pgY.mjs.map +1 -0
- package/{weak_ref.d-BZ7gyRag.d.ts → graph.d-BcIOep_B.d.ts} +3 -24
- package/index.d.ts +2624 -10909
- package/ng_i18n_closure_mode.d-C9d2CaSt.d.ts +832 -0
- package/package.json +3 -3
- package/primitives/di/index.d.ts +3 -2
- package/primitives/event-dispatch/index.d.ts +3 -3
- package/primitives/signals/index.d.ts +8 -4
- package/rxjs-interop/index.d.ts +10 -7
- package/schematics/bundles/{apply_import_manager-CeNv8GIG.js → apply_import_manager-DnMqg1pY.js} +6 -6
- package/schematics/bundles/{compiler_host-DwM3ugW3.js → change_tracker-UMPkv-eH.js} +3 -121
- package/schematics/bundles/checker-BFBQyesT.js +17719 -0
- package/schematics/bundles/cleanup-unused-imports.js +25 -19
- package/schematics/bundles/{checker-k591b6WQ.js → compiler-BQ7R7w2v.js} +1325 -18286
- package/schematics/bundles/compiler_host-CAfDJO3W.js +129 -0
- package/schematics/bundles/control-flow-migration.js +28 -40
- package/schematics/bundles/document-core.js +96 -0
- package/schematics/bundles/imports-CIX-JgAN.js +1 -1
- package/schematics/bundles/{index-B4OAlHh8.js → index-Cv4Q415G.js} +641 -547
- package/schematics/bundles/{index-BhELUmYx.js → index-D8tMJPKa.js} +35 -34
- package/schematics/bundles/inject-flags.js +14 -13
- package/schematics/bundles/inject-migration.js +29 -10
- package/schematics/bundles/leading_space-D9nQ8UQC.js +1 -1
- package/schematics/bundles/{migrate_ts_type_references-Be0TNYen.js → migrate_ts_type_references-Cq_ZBuT4.js} +21 -20
- package/schematics/bundles/ng_decorators-DznZ5jMl.js +1 -1
- package/schematics/bundles/nodes-B16H9JUd.js +1 -1
- package/schematics/bundles/output-migration.js +88 -25
- package/schematics/bundles/{run_in_devkit-CkvEksWP.js → project_paths-ql6qcf_c.js} +254 -243
- package/schematics/bundles/project_tsconfig_paths-CDVxT6Ov.js +1 -1
- package/schematics/bundles/property_name-BBwFuqMe.js +1 -1
- package/schematics/bundles/route-lazy-loading.js +7 -5
- package/schematics/bundles/self-closing-tags-migration.js +25 -19
- package/schematics/bundles/signal-input-migration.js +26 -20
- package/schematics/bundles/signal-queries-migration.js +51 -33
- package/schematics/bundles/signals.js +8 -7
- package/schematics/bundles/standalone-migration.js +11 -9
- package/schematics/bundles/symbol-VPWguRxr.js +1 -1
- package/schematics/bundles/test-bed-get.js +13 -12
- package/schematics/collection.json +0 -6
- package/schematics/migrations.json +11 -0
- package/signal.d-E0e5nW1p.d.ts +31 -0
- package/testing/index.d.ts +16 -28
- package/weak_ref.d-eGOEP9S1.d.ts +9 -0
- package/fesm2022/injector-BlLwZ2sr.mjs +0 -24
- package/fesm2022/injector-BlLwZ2sr.mjs.map +0 -1
- package/fesm2022/untracked-DkcXpNb_.mjs.map +0 -1
- package/navigation_types.d-DgDrF5rp.d.ts +0 -121
- package/schematics/ng-generate/control-flow-migration/schema.json +0 -20
package/fesm2022/testing.mjs
CHANGED
|
@@ -1,14 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @license Angular v20.0.0-next.
|
|
2
|
+
* @license Angular v20.0.0-next.6
|
|
3
3
|
* (c) 2010-2025 Google LLC. https://angular.io/
|
|
4
4
|
* License: MIT
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import * as i0 from '@angular/core';
|
|
8
|
-
import { ɵDeferBlockState as _DeferBlockState, ɵtriggerResourceLoading as _triggerResourceLoading, ɵrenderDeferBlockState as _renderDeferBlockState, ɵCONTAINER_HEADER_OFFSET as _CONTAINER_HEADER_OFFSET, ɵgetDeferBlocks as _getDeferBlocks, InjectionToken, ɵDeferBlockBehavior as _DeferBlockBehavior, inject as inject$1, NgZone, ErrorHandler, Injectable, ɵNoopNgZone as _NoopNgZone, ApplicationRef, ɵPendingTasksInternal as _PendingTasksInternal, ɵZONELESS_ENABLED as _ZONELESS_ENABLED, ɵChangeDetectionScheduler as _ChangeDetectionScheduler, ɵEffectScheduler as _EffectScheduler, getDebugNode, RendererFactory2, ɵstringify as _stringify, Pipe, Directive, Component, NgModule, ɵReflectionCapabilities as _ReflectionCapabilities, ɵUSE_RUNTIME_DEPS_TRACKER_FOR_JIT as _USE_RUNTIME_DEPS_TRACKER_FOR_JIT, ɵdepsTracker as _depsTracker, ɵgetInjectableDef as _getInjectableDef, resolveForwardRef, ɵisComponentDefPendingResolution as _isComponentDefPendingResolution, ɵgetAsyncClassMetadataFn as _getAsyncClassMetadataFn, ɵresolveComponentResources as _resolveComponentResources, ɵRender3NgModuleRef as _Render3NgModuleRef, ApplicationInitStatus, LOCALE_ID, ɵDEFAULT_LOCALE_ID as _DEFAULT_LOCALE_ID, ɵsetLocaleId as _setLocaleId, ɵRender3ComponentFactory as _Render3ComponentFactory, ɵNG_COMP_DEF as _NG_COMP_DEF, ɵcompileComponent as _compileComponent, ɵNG_DIR_DEF as _NG_DIR_DEF, ɵcompileDirective as _compileDirective, ɵNG_PIPE_DEF as _NG_PIPE_DEF, ɵcompilePipe as _compilePipe, ɵNG_MOD_DEF as _NG_MOD_DEF, ɵpatchComponentDefWithScope as _patchComponentDefWithScope, ɵNG_INJ_DEF as _NG_INJ_DEF, ɵcompileNgModuleDefs as _compileNgModuleDefs, ɵclearResolutionOfComponentResourcesQueue as _clearResolutionOfComponentResourcesQueue, ɵrestoreComponentResolutionQueue as _restoreComponentResolutionQueue, ɵinternalProvideZoneChangeDetection as _internalProvideZoneChangeDetection, ɵChangeDetectionSchedulerImpl as _ChangeDetectionSchedulerImpl, Compiler, ɵDEFER_BLOCK_CONFIG as _DEFER_BLOCK_CONFIG, ɵINTERNAL_APPLICATION_ERROR_HANDLER as _INTERNAL_APPLICATION_ERROR_HANDLER, COMPILER_OPTIONS, Injector, ɵtransitiveScopesFor as _transitiveScopesFor, ɵgenerateStandaloneInDeclarationsError as _generateStandaloneInDeclarationsError, ɵNgModuleFactory as _NgModuleFactory, ModuleWithComponentFactories, ɵisEnvironmentProviders as _isEnvironmentProviders, ɵsetAllowDuplicateNgModuleIdsForTest as _setAllowDuplicateNgModuleIdsForTest, ɵresetCompiledComponents as _resetCompiledComponents, ɵsetUnknownElementStrictMode as _setUnknownElementStrictMode, ɵsetUnknownPropertyStrictMode as _setUnknownPropertyStrictMode, ɵgetUnknownElementStrictMode as _getUnknownElementStrictMode, ɵgetUnknownPropertyStrictMode as _getUnknownPropertyStrictMode, runInInjectionContext, EnvironmentInjector, ɵflushModuleScopingQueueAsMuchAsPossible as _flushModuleScopingQueueAsMuchAsPossible } from '@angular/core';
|
|
9
|
-
export { ɵDeferBlockBehavior as DeferBlockBehavior, ɵDeferBlockState as DeferBlockState } from '@angular/core';
|
|
10
7
|
import { Subscription } from 'rxjs';
|
|
8
|
+
import { DeferBlockState, triggerResourceLoading, renderDeferBlockState, getDeferBlocks, DeferBlockBehavior, NgZone, Injectable, NoopNgZone, ApplicationRef, getDebugNode, RendererFactory2, Pipe, Directive, Component, NgModule, ReflectionCapabilities, depsTracker, isComponentDefPendingResolution, getAsyncClassMetadataFn, resolveComponentResources, NgModuleRef, ApplicationInitStatus, LOCALE_ID, DEFAULT_LOCALE_ID, setLocaleId, ComponentFactory, compileComponent, compileDirective, compilePipe, patchComponentDefWithScope, compileNgModuleDefs, clearResolutionOfComponentResourcesQueue, restoreComponentResolutionQueue, internalProvideZoneChangeDetection, ChangeDetectionSchedulerImpl, Compiler, DEFER_BLOCK_CONFIG, COMPILER_OPTIONS, transitiveScopesFor, generateStandaloneInDeclarationsError, NgModuleFactory, ModuleWithComponentFactories, resetCompiledComponents, ɵsetUnknownElementStrictMode as _setUnknownElementStrictMode, ɵsetUnknownPropertyStrictMode as _setUnknownPropertyStrictMode, ɵgetUnknownElementStrictMode as _getUnknownElementStrictMode, ɵgetUnknownPropertyStrictMode as _getUnknownPropertyStrictMode, flushModuleScopingQueueAsMuchAsPossible, setAllowDuplicateNgModuleIdsForTest } from './debug_node-z_3NG8qT.mjs';
|
|
9
|
+
import { CONTAINER_HEADER_OFFSET, InjectionToken, inject as inject$1, EnvironmentInjector, ErrorHandler, PendingTasksInternal, ZONELESS_ENABLED, ChangeDetectionScheduler, EffectScheduler, stringify, getInjectableDef, resolveForwardRef, NG_COMP_DEF, NG_DIR_DEF, NG_PIPE_DEF, NG_INJ_DEF, NG_MOD_DEF, ENVIRONMENT_INITIALIZER, INTERNAL_APPLICATION_ERROR_HANDLER, Injector, isEnvironmentProviders, runInInjectionContext } from './root_effect_scheduler-VSXfCzDX.mjs';
|
|
10
|
+
import * as i0 from '@angular/core';
|
|
11
11
|
import { ResourceLoader } from '@angular/compiler';
|
|
12
|
+
import './signal-B6pMq7KS.mjs';
|
|
13
|
+
import '@angular/core/primitives/signals';
|
|
14
|
+
import 'rxjs/operators';
|
|
15
|
+
import './attribute-BWp59EjE.mjs';
|
|
16
|
+
import './primitives/di.mjs';
|
|
17
|
+
import '@angular/core/primitives/di';
|
|
12
18
|
|
|
13
19
|
/**
|
|
14
20
|
* Wraps a test function in an asynchronous test zone. The test will automatically
|
|
@@ -68,13 +74,13 @@ class DeferBlockFixture {
|
|
|
68
74
|
throw new Error(`Tried to render this defer block in the \`${stateAsString}\` state, ` +
|
|
69
75
|
`but there was no @${stateAsString.toLowerCase()} block defined in a template.`);
|
|
70
76
|
}
|
|
71
|
-
if (state ===
|
|
72
|
-
await
|
|
77
|
+
if (state === DeferBlockState.Complete) {
|
|
78
|
+
await triggerResourceLoading(this.block.tDetails, this.block.lView, this.block.tNode);
|
|
73
79
|
}
|
|
74
80
|
// If the `render` method is used explicitly - skip timer-based scheduling for
|
|
75
81
|
// `@placeholder` and `@loading` blocks and render them immediately.
|
|
76
82
|
const skipTimerScheduling = true;
|
|
77
|
-
|
|
83
|
+
renderDeferBlockState(state, this.block.tNode, this.block.lContainer, skipTimerScheduling);
|
|
78
84
|
this.componentFixture.detectChanges();
|
|
79
85
|
}
|
|
80
86
|
/**
|
|
@@ -87,9 +93,9 @@ class DeferBlockFixture {
|
|
|
87
93
|
// located right after an LContainer header. Get a hold of that view and inspect
|
|
88
94
|
// it for nested defer blocks.
|
|
89
95
|
const deferBlockFixtures = [];
|
|
90
|
-
if (this.block.lContainer.length >=
|
|
91
|
-
const lView = this.block.lContainer[
|
|
92
|
-
|
|
96
|
+
if (this.block.lContainer.length >= CONTAINER_HEADER_OFFSET) {
|
|
97
|
+
const lView = this.block.lContainer[CONTAINER_HEADER_OFFSET];
|
|
98
|
+
getDeferBlocks(lView, deferBlocks);
|
|
93
99
|
for (const block of deferBlocks) {
|
|
94
100
|
deferBlockFixtures.push(new DeferBlockFixture(block, this.componentFixture));
|
|
95
101
|
}
|
|
@@ -99,13 +105,13 @@ class DeferBlockFixture {
|
|
|
99
105
|
}
|
|
100
106
|
function hasStateTemplate(state, block) {
|
|
101
107
|
switch (state) {
|
|
102
|
-
case
|
|
108
|
+
case DeferBlockState.Placeholder:
|
|
103
109
|
return block.tDetails.placeholderTmplIndex !== null;
|
|
104
|
-
case
|
|
110
|
+
case DeferBlockState.Loading:
|
|
105
111
|
return block.tDetails.loadingTmplIndex !== null;
|
|
106
|
-
case
|
|
112
|
+
case DeferBlockState.Error:
|
|
107
113
|
return block.tDetails.errorTmplIndex !== null;
|
|
108
|
-
case
|
|
114
|
+
case DeferBlockState.Complete:
|
|
109
115
|
return true;
|
|
110
116
|
default:
|
|
111
117
|
return false;
|
|
@@ -113,11 +119,11 @@ function hasStateTemplate(state, block) {
|
|
|
113
119
|
}
|
|
114
120
|
function getDeferBlockStateNameFromEnum(state) {
|
|
115
121
|
switch (state) {
|
|
116
|
-
case
|
|
122
|
+
case DeferBlockState.Placeholder:
|
|
117
123
|
return 'Placeholder';
|
|
118
|
-
case
|
|
124
|
+
case DeferBlockState.Loading:
|
|
119
125
|
return 'Loading';
|
|
120
|
-
case
|
|
126
|
+
case DeferBlockState.Error:
|
|
121
127
|
return 'Error';
|
|
122
128
|
default:
|
|
123
129
|
return 'Main';
|
|
@@ -131,7 +137,7 @@ const THROW_ON_UNKNOWN_ELEMENTS_DEFAULT = false;
|
|
|
131
137
|
/** Whether unknown properties in templates should throw by default. */
|
|
132
138
|
const THROW_ON_UNKNOWN_PROPERTIES_DEFAULT = false;
|
|
133
139
|
/** Whether defer blocks should use manual triggering or play through normally. */
|
|
134
|
-
const DEFER_BLOCK_DEFAULT_BEHAVIOR =
|
|
140
|
+
const DEFER_BLOCK_DEFAULT_BEHAVIOR = DeferBlockBehavior.Playthrough;
|
|
135
141
|
/**
|
|
136
142
|
* An abstract class for inserting the root test component element in a platform independent way.
|
|
137
143
|
*
|
|
@@ -153,11 +159,15 @@ const ComponentFixtureNoNgZone = new InjectionToken('ComponentFixtureNoNgZone');
|
|
|
153
159
|
const RETHROW_APPLICATION_ERRORS_DEFAULT = true;
|
|
154
160
|
class TestBedApplicationErrorHandler {
|
|
155
161
|
zone = inject$1(NgZone);
|
|
156
|
-
|
|
162
|
+
injector = inject$1(EnvironmentInjector);
|
|
163
|
+
userErrorHandler;
|
|
157
164
|
whenStableRejectFunctions = new Set();
|
|
158
165
|
handleError(e) {
|
|
159
166
|
try {
|
|
160
|
-
this.zone.runOutsideAngular(() =>
|
|
167
|
+
this.zone.runOutsideAngular(() => {
|
|
168
|
+
this.userErrorHandler ??= this.injector.get(ErrorHandler);
|
|
169
|
+
this.userErrorHandler.handleError(e);
|
|
170
|
+
});
|
|
161
171
|
}
|
|
162
172
|
catch (userError) {
|
|
163
173
|
e = userError;
|
|
@@ -214,7 +224,7 @@ class ComponentFixture {
|
|
|
214
224
|
/** @internal */
|
|
215
225
|
_noZoneOptionIsSet = inject$1(ComponentFixtureNoNgZone, { optional: true });
|
|
216
226
|
/** @internal */
|
|
217
|
-
_ngZone = this._noZoneOptionIsSet ? new
|
|
227
|
+
_ngZone = this._noZoneOptionIsSet ? new NoopNgZone() : inject$1(NgZone);
|
|
218
228
|
// Inject ApplicationRef to ensure NgZone stableness causes after render hooks to run
|
|
219
229
|
// This will likely happen as a result of fixture.detectChanges because it calls ngZone.run
|
|
220
230
|
// This is a crazy way of doing things but hey, it's the world we live in.
|
|
@@ -224,11 +234,11 @@ class ComponentFixture {
|
|
|
224
234
|
/** @internal */
|
|
225
235
|
_appRef = inject$1(ApplicationRef);
|
|
226
236
|
_testAppRef = this._appRef;
|
|
227
|
-
pendingTasks = inject$1(
|
|
237
|
+
pendingTasks = inject$1(PendingTasksInternal);
|
|
228
238
|
appErrorHandler = inject$1(TestBedApplicationErrorHandler);
|
|
229
|
-
zonelessEnabled = inject$1(
|
|
230
|
-
scheduler = inject$1(
|
|
231
|
-
rootEffectScheduler = inject$1(
|
|
239
|
+
zonelessEnabled = inject$1(ZONELESS_ENABLED);
|
|
240
|
+
scheduler = inject$1(ChangeDetectionScheduler);
|
|
241
|
+
rootEffectScheduler = inject$1(EffectScheduler);
|
|
232
242
|
autoDetectDefault = this.zonelessEnabled ? true : false;
|
|
233
243
|
autoDetect = inject$1(ComponentFixtureAutoDetect, { optional: true }) ?? this.autoDetectDefault;
|
|
234
244
|
subscriptions = new Subscription();
|
|
@@ -340,7 +350,7 @@ class ComponentFixture {
|
|
|
340
350
|
* yet.
|
|
341
351
|
*/
|
|
342
352
|
isStable() {
|
|
343
|
-
return !this.pendingTasks.hasPendingTasks
|
|
353
|
+
return !this.pendingTasks.hasPendingTasks;
|
|
344
354
|
}
|
|
345
355
|
/**
|
|
346
356
|
* Get a promise that resolves when the fixture is stable.
|
|
@@ -366,7 +376,7 @@ class ComponentFixture {
|
|
|
366
376
|
getDeferBlocks() {
|
|
367
377
|
const deferBlocks = [];
|
|
368
378
|
const lView = this.componentRef.hostView['_lView'];
|
|
369
|
-
|
|
379
|
+
getDeferBlocks(lView, deferBlocks);
|
|
370
380
|
const deferBlockFixtures = [];
|
|
371
381
|
for (const block of deferBlocks) {
|
|
372
382
|
deferBlockFixtures.push(new DeferBlockFixture(block, this));
|
|
@@ -579,7 +589,7 @@ class MetadataOverrider {
|
|
|
579
589
|
}
|
|
580
590
|
if (override.set) {
|
|
581
591
|
if (override.remove || override.add) {
|
|
582
|
-
throw new Error(`Cannot set and add/remove ${
|
|
592
|
+
throw new Error(`Cannot set and add/remove ${stringify(metadataClass)} at the same time!`);
|
|
583
593
|
}
|
|
584
594
|
setMetadata(props, override.set);
|
|
585
595
|
}
|
|
@@ -658,7 +668,7 @@ function _propHashKey(propName, propValue, references) {
|
|
|
658
668
|
function _serializeReference(ref, references) {
|
|
659
669
|
let id = references.get(ref);
|
|
660
670
|
if (!id) {
|
|
661
|
-
id = `${
|
|
671
|
+
id = `${stringify(ref)}${_nextReferenceId++}`;
|
|
662
672
|
references.set(ref, id);
|
|
663
673
|
}
|
|
664
674
|
return id;
|
|
@@ -684,7 +694,7 @@ function _valueProps(obj) {
|
|
|
684
694
|
return props;
|
|
685
695
|
}
|
|
686
696
|
|
|
687
|
-
const reflection = new
|
|
697
|
+
const reflection = new ReflectionCapabilities();
|
|
688
698
|
/**
|
|
689
699
|
* Allows to override ivy metadata for tests (via the `TestBed`).
|
|
690
700
|
*/
|
|
@@ -771,10 +781,10 @@ function isTestingModuleOverride(value) {
|
|
|
771
781
|
}
|
|
772
782
|
function assertNoStandaloneComponents(types, resolver, location) {
|
|
773
783
|
types.forEach((type) => {
|
|
774
|
-
if (!
|
|
784
|
+
if (!getAsyncClassMetadataFn(type)) {
|
|
775
785
|
const component = resolver.resolve(type);
|
|
776
786
|
if (component && (component.standalone == null || component.standalone)) {
|
|
777
|
-
throw new Error(
|
|
787
|
+
throw new Error(generateStandaloneInDeclarationsError(type, location));
|
|
778
788
|
}
|
|
779
789
|
}
|
|
780
790
|
});
|
|
@@ -869,8 +879,8 @@ class TestBedCompiler {
|
|
|
869
879
|
moduleDef.rethrowApplicationErrors ?? RETHROW_APPLICATION_ERRORS_DEFAULT;
|
|
870
880
|
}
|
|
871
881
|
overrideModule(ngModule, override) {
|
|
872
|
-
|
|
873
|
-
|
|
882
|
+
{
|
|
883
|
+
depsTracker.clearScopeCacheFor(ngModule);
|
|
874
884
|
}
|
|
875
885
|
this.overriddenModules.add(ngModule);
|
|
876
886
|
// Compile the module right away.
|
|
@@ -927,7 +937,7 @@ class TestBedCompiler {
|
|
|
927
937
|
else {
|
|
928
938
|
providerDef = { provide: token };
|
|
929
939
|
}
|
|
930
|
-
const injectableDef = typeof token !== 'string' ?
|
|
940
|
+
const injectableDef = typeof token !== 'string' ? getInjectableDef(token) : null;
|
|
931
941
|
const providedIn = injectableDef === null ? null : resolveForwardRef(injectableDef.providedIn);
|
|
932
942
|
const overridesBucket = providedIn === 'root' ? this.rootProviderOverrides : this.providerOverrides;
|
|
933
943
|
overridesBucket.push(providerDef);
|
|
@@ -944,12 +954,12 @@ class TestBedCompiler {
|
|
|
944
954
|
}
|
|
945
955
|
}
|
|
946
956
|
overrideTemplateUsingTestingModule(type, template) {
|
|
947
|
-
const def = type[
|
|
957
|
+
const def = type[NG_COMP_DEF];
|
|
948
958
|
const hasStyleUrls = () => {
|
|
949
959
|
const metadata = this.resolvers.component.resolve(type);
|
|
950
960
|
return !!metadata.styleUrl || !!metadata.styleUrls?.length;
|
|
951
961
|
};
|
|
952
|
-
const overrideStyleUrls = !!def && !
|
|
962
|
+
const overrideStyleUrls = !!def && !isComponentDefPendingResolution(type) && hasStyleUrls();
|
|
953
963
|
// In Ivy, compiling a component does not require knowing the module providing the
|
|
954
964
|
// component's scope, so overrideTemplateUsingTestingModule can be implemented purely via
|
|
955
965
|
// overrideComponent. Important: overriding template requires full Component re-compilation,
|
|
@@ -972,7 +982,7 @@ class TestBedCompiler {
|
|
|
972
982
|
return;
|
|
973
983
|
const promises = [];
|
|
974
984
|
for (const component of this.componentsWithAsyncMetadata) {
|
|
975
|
-
const asyncMetadataFn =
|
|
985
|
+
const asyncMetadataFn = getAsyncClassMetadataFn(component);
|
|
976
986
|
if (asyncMetadataFn) {
|
|
977
987
|
promises.push(asyncMetadataFn());
|
|
978
988
|
}
|
|
@@ -1009,7 +1019,7 @@ class TestBedCompiler {
|
|
|
1009
1019
|
}
|
|
1010
1020
|
return Promise.resolve(resourceLoader.get(url));
|
|
1011
1021
|
};
|
|
1012
|
-
await
|
|
1022
|
+
await resolveComponentResources(resolver);
|
|
1013
1023
|
}
|
|
1014
1024
|
}
|
|
1015
1025
|
finalize() {
|
|
@@ -1026,15 +1036,15 @@ class TestBedCompiler {
|
|
|
1026
1036
|
// every component.
|
|
1027
1037
|
this.componentToModuleScope.clear();
|
|
1028
1038
|
const parentInjector = this.platform.injector;
|
|
1029
|
-
this.testModuleRef = new
|
|
1039
|
+
this.testModuleRef = new NgModuleRef(this.testModuleType, parentInjector, []);
|
|
1030
1040
|
// ApplicationInitStatus.runInitializers() is marked @internal to core.
|
|
1031
1041
|
// Cast it to any before accessing it.
|
|
1032
1042
|
this.testModuleRef.injector.get(ApplicationInitStatus).runInitializers();
|
|
1033
1043
|
// Set locale ID after running app initializers, since locale information might be updated while
|
|
1034
1044
|
// running initializers. This is also consistent with the execution order while bootstrapping an
|
|
1035
1045
|
// app (see `packages/core/src/application_ref.ts` file).
|
|
1036
|
-
const localeId = this.testModuleRef.injector.get(LOCALE_ID,
|
|
1037
|
-
|
|
1046
|
+
const localeId = this.testModuleRef.injector.get(LOCALE_ID, DEFAULT_LOCALE_ID);
|
|
1047
|
+
setLocaleId(localeId);
|
|
1038
1048
|
return this.testModuleRef;
|
|
1039
1049
|
}
|
|
1040
1050
|
/**
|
|
@@ -1069,7 +1079,7 @@ class TestBedCompiler {
|
|
|
1069
1079
|
_getComponentFactories(moduleType) {
|
|
1070
1080
|
return maybeUnwrapFn(moduleType.ɵmod.declarations).reduce((factories, declaration) => {
|
|
1071
1081
|
const componentDef = declaration.ɵcmp;
|
|
1072
|
-
componentDef && factories.push(new
|
|
1082
|
+
componentDef && factories.push(new ComponentFactory(componentDef, this.testModuleRef));
|
|
1073
1083
|
return factories;
|
|
1074
1084
|
}, []);
|
|
1075
1085
|
}
|
|
@@ -1077,20 +1087,20 @@ class TestBedCompiler {
|
|
|
1077
1087
|
// Compile all queued components, directives, pipes.
|
|
1078
1088
|
let needsAsyncResources = false;
|
|
1079
1089
|
this.pendingComponents.forEach((declaration) => {
|
|
1080
|
-
if (
|
|
1090
|
+
if (getAsyncClassMetadataFn(declaration)) {
|
|
1081
1091
|
throw new Error(`Component '${declaration.name}' has unresolved metadata. ` +
|
|
1082
1092
|
`Please call \`await TestBed.compileComponents()\` before running this test.`);
|
|
1083
1093
|
}
|
|
1084
|
-
needsAsyncResources = needsAsyncResources ||
|
|
1094
|
+
needsAsyncResources = needsAsyncResources || isComponentDefPendingResolution(declaration);
|
|
1085
1095
|
const metadata = this.resolvers.component.resolve(declaration);
|
|
1086
1096
|
if (metadata === null) {
|
|
1087
1097
|
throw invalidTypeError(declaration.name, 'Component');
|
|
1088
1098
|
}
|
|
1089
|
-
this.maybeStoreNgDef(
|
|
1090
|
-
|
|
1091
|
-
|
|
1099
|
+
this.maybeStoreNgDef(NG_COMP_DEF, declaration);
|
|
1100
|
+
{
|
|
1101
|
+
depsTracker.clearScopeCacheFor(declaration);
|
|
1092
1102
|
}
|
|
1093
|
-
|
|
1103
|
+
compileComponent(declaration, metadata);
|
|
1094
1104
|
});
|
|
1095
1105
|
this.pendingComponents.clear();
|
|
1096
1106
|
this.pendingDirectives.forEach((declaration) => {
|
|
@@ -1098,8 +1108,8 @@ class TestBedCompiler {
|
|
|
1098
1108
|
if (metadata === null) {
|
|
1099
1109
|
throw invalidTypeError(declaration.name, 'Directive');
|
|
1100
1110
|
}
|
|
1101
|
-
this.maybeStoreNgDef(
|
|
1102
|
-
|
|
1111
|
+
this.maybeStoreNgDef(NG_DIR_DEF, declaration);
|
|
1112
|
+
compileDirective(declaration, metadata);
|
|
1103
1113
|
});
|
|
1104
1114
|
this.pendingDirectives.clear();
|
|
1105
1115
|
this.pendingPipes.forEach((declaration) => {
|
|
@@ -1107,8 +1117,8 @@ class TestBedCompiler {
|
|
|
1107
1117
|
if (metadata === null) {
|
|
1108
1118
|
throw invalidTypeError(declaration.name, 'Pipe');
|
|
1109
1119
|
}
|
|
1110
|
-
this.maybeStoreNgDef(
|
|
1111
|
-
|
|
1120
|
+
this.maybeStoreNgDef(NG_PIPE_DEF, declaration);
|
|
1121
|
+
compilePipe(declaration, metadata);
|
|
1112
1122
|
});
|
|
1113
1123
|
this.pendingPipes.clear();
|
|
1114
1124
|
return needsAsyncResources;
|
|
@@ -1118,16 +1128,12 @@ class TestBedCompiler {
|
|
|
1118
1128
|
// Module overrides (via `TestBed.overrideModule`) might affect scopes that were previously
|
|
1119
1129
|
// calculated and stored in `transitiveCompileScopes`. If module overrides are present,
|
|
1120
1130
|
// collect all affected modules and reset scopes to force their re-calculation.
|
|
1121
|
-
const testingModuleDef = this.testModuleType[
|
|
1131
|
+
const testingModuleDef = this.testModuleType[NG_MOD_DEF];
|
|
1122
1132
|
const affectedModules = this.collectModulesAffectedByOverrides(testingModuleDef.imports);
|
|
1123
1133
|
if (affectedModules.size > 0) {
|
|
1124
1134
|
affectedModules.forEach((moduleType) => {
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
moduleType[_NG_MOD_DEF].transitiveCompileScopes = null;
|
|
1128
|
-
}
|
|
1129
|
-
else {
|
|
1130
|
-
_depsTracker.clearScopeCacheFor(moduleType);
|
|
1135
|
+
{
|
|
1136
|
+
depsTracker.clearScopeCacheFor(moduleType);
|
|
1131
1137
|
}
|
|
1132
1138
|
});
|
|
1133
1139
|
}
|
|
@@ -1137,16 +1143,16 @@ class TestBedCompiler {
|
|
|
1137
1143
|
if (!moduleToScope.has(moduleType)) {
|
|
1138
1144
|
const isTestingModule = isTestingModuleOverride(moduleType);
|
|
1139
1145
|
const realType = isTestingModule ? this.testModuleType : moduleType;
|
|
1140
|
-
moduleToScope.set(moduleType,
|
|
1146
|
+
moduleToScope.set(moduleType, transitiveScopesFor(realType));
|
|
1141
1147
|
}
|
|
1142
1148
|
return moduleToScope.get(moduleType);
|
|
1143
1149
|
};
|
|
1144
1150
|
this.componentToModuleScope.forEach((moduleType, componentType) => {
|
|
1145
1151
|
if (moduleType !== null) {
|
|
1146
1152
|
const moduleScope = getScopeOfModule(moduleType);
|
|
1147
|
-
this.storeFieldOfDefOnType(componentType,
|
|
1148
|
-
this.storeFieldOfDefOnType(componentType,
|
|
1149
|
-
|
|
1153
|
+
this.storeFieldOfDefOnType(componentType, NG_COMP_DEF, 'directiveDefs');
|
|
1154
|
+
this.storeFieldOfDefOnType(componentType, NG_COMP_DEF, 'pipeDefs');
|
|
1155
|
+
patchComponentDefWithScope(getComponentDef(componentType), moduleScope);
|
|
1150
1156
|
}
|
|
1151
1157
|
// `tView` that is stored on component def contains information about directives and pipes
|
|
1152
1158
|
// that are in the scope of this component. Patching component scope will cause `tView` to be
|
|
@@ -1155,20 +1161,20 @@ class TestBedCompiler {
|
|
|
1155
1161
|
// Resetting `tView` is also needed for cases when we apply provider overrides and those
|
|
1156
1162
|
// providers are defined on component's level, in which case they may end up included into
|
|
1157
1163
|
// `tView.blueprint`.
|
|
1158
|
-
this.storeFieldOfDefOnType(componentType,
|
|
1164
|
+
this.storeFieldOfDefOnType(componentType, NG_COMP_DEF, 'tView');
|
|
1159
1165
|
});
|
|
1160
1166
|
this.componentToModuleScope.clear();
|
|
1161
1167
|
}
|
|
1162
1168
|
applyProviderOverrides() {
|
|
1163
1169
|
const maybeApplyOverrides = (field) => (type) => {
|
|
1164
|
-
const resolver = field ===
|
|
1170
|
+
const resolver = field === NG_COMP_DEF ? this.resolvers.component : this.resolvers.directive;
|
|
1165
1171
|
const metadata = resolver.resolve(type);
|
|
1166
1172
|
if (this.hasProviderOverrides(metadata.providers)) {
|
|
1167
1173
|
this.patchDefWithProviderOverrides(type, field);
|
|
1168
1174
|
}
|
|
1169
1175
|
};
|
|
1170
|
-
this.seenComponents.forEach(maybeApplyOverrides(
|
|
1171
|
-
this.seenDirectives.forEach(maybeApplyOverrides(
|
|
1176
|
+
this.seenComponents.forEach(maybeApplyOverrides(NG_COMP_DEF));
|
|
1177
|
+
this.seenDirectives.forEach(maybeApplyOverrides(NG_DIR_DEF));
|
|
1172
1178
|
this.seenComponents.clear();
|
|
1173
1179
|
this.seenDirectives.clear();
|
|
1174
1180
|
}
|
|
@@ -1191,7 +1197,7 @@ class TestBedCompiler {
|
|
|
1191
1197
|
// detailed error messages. The fact that the code relies on this line being
|
|
1192
1198
|
// present here is suspicious and should be refactored in a way that the line
|
|
1193
1199
|
// below can be moved (for ex. after an early exit check below).
|
|
1194
|
-
const injectorDef = type[
|
|
1200
|
+
const injectorDef = type[NG_INJ_DEF];
|
|
1195
1201
|
// No provider overrides, exit early.
|
|
1196
1202
|
if (this.providerOverridesByToken.size === 0)
|
|
1197
1203
|
return;
|
|
@@ -1209,12 +1215,12 @@ class TestBedCompiler {
|
|
|
1209
1215
|
...(this.providerOverridesByModule.get(type) || []),
|
|
1210
1216
|
];
|
|
1211
1217
|
if (this.hasProviderOverrides(providers)) {
|
|
1212
|
-
this.maybeStoreNgDef(
|
|
1213
|
-
this.storeFieldOfDefOnType(type,
|
|
1218
|
+
this.maybeStoreNgDef(NG_INJ_DEF, type);
|
|
1219
|
+
this.storeFieldOfDefOnType(type, NG_INJ_DEF, 'providers');
|
|
1214
1220
|
injectorDef.providers = this.getOverriddenProviders(providers);
|
|
1215
1221
|
}
|
|
1216
1222
|
// Apply provider overrides to imported modules recursively
|
|
1217
|
-
const moduleDef = type[
|
|
1223
|
+
const moduleDef = type[NG_MOD_DEF];
|
|
1218
1224
|
const imports = maybeUnwrapFn(moduleDef.imports);
|
|
1219
1225
|
for (const importedModule of imports) {
|
|
1220
1226
|
this.applyProviderOverridesInScope(importedModule);
|
|
@@ -1234,7 +1240,7 @@ class TestBedCompiler {
|
|
|
1234
1240
|
}
|
|
1235
1241
|
}
|
|
1236
1242
|
patchComponentsWithExistingStyles() {
|
|
1237
|
-
this.existingComponentStyles.forEach((styles, type) => (type[
|
|
1243
|
+
this.existingComponentStyles.forEach((styles, type) => (type[NG_COMP_DEF].styles = styles));
|
|
1238
1244
|
this.existingComponentStyles.clear();
|
|
1239
1245
|
}
|
|
1240
1246
|
queueTypeArray(arr, moduleType) {
|
|
@@ -1249,12 +1255,12 @@ class TestBedCompiler {
|
|
|
1249
1255
|
}
|
|
1250
1256
|
recompileNgModule(ngModule, metadata) {
|
|
1251
1257
|
// Cache the initial ngModuleDef as it will be overwritten.
|
|
1252
|
-
this.maybeStoreNgDef(
|
|
1253
|
-
this.maybeStoreNgDef(
|
|
1254
|
-
|
|
1258
|
+
this.maybeStoreNgDef(NG_MOD_DEF, ngModule);
|
|
1259
|
+
this.maybeStoreNgDef(NG_INJ_DEF, ngModule);
|
|
1260
|
+
compileNgModuleDefs(ngModule, metadata);
|
|
1255
1261
|
}
|
|
1256
1262
|
maybeRegisterComponentWithAsyncMetadata(type) {
|
|
1257
|
-
const asyncMetadataFn =
|
|
1263
|
+
const asyncMetadataFn = getAsyncClassMetadataFn(type);
|
|
1258
1264
|
if (asyncMetadataFn) {
|
|
1259
1265
|
this.componentsWithAsyncMetadata.add(type);
|
|
1260
1266
|
}
|
|
@@ -1268,7 +1274,7 @@ class TestBedCompiler {
|
|
|
1268
1274
|
// Check whether a give Type has respective NG def (ɵcmp) and compile if def is
|
|
1269
1275
|
// missing. That might happen in case a class without any Angular decorators extends another
|
|
1270
1276
|
// class where Component/Directive/Pipe decorator is defined.
|
|
1271
|
-
if (
|
|
1277
|
+
if (isComponentDefPendingResolution(type) || !type.hasOwnProperty(NG_COMP_DEF)) {
|
|
1272
1278
|
this.pendingComponents.add(type);
|
|
1273
1279
|
}
|
|
1274
1280
|
this.seenComponents.add(type);
|
|
@@ -1295,14 +1301,14 @@ class TestBedCompiler {
|
|
|
1295
1301
|
}
|
|
1296
1302
|
const directive = this.resolvers.directive.resolve(type);
|
|
1297
1303
|
if (directive) {
|
|
1298
|
-
if (!type.hasOwnProperty(
|
|
1304
|
+
if (!type.hasOwnProperty(NG_DIR_DEF)) {
|
|
1299
1305
|
this.pendingDirectives.add(type);
|
|
1300
1306
|
}
|
|
1301
1307
|
this.seenDirectives.add(type);
|
|
1302
1308
|
return;
|
|
1303
1309
|
}
|
|
1304
1310
|
const pipe = this.resolvers.pipe.resolve(type);
|
|
1305
|
-
if (pipe && !type.hasOwnProperty(
|
|
1311
|
+
if (pipe && !type.hasOwnProperty(NG_PIPE_DEF)) {
|
|
1306
1312
|
this.pendingPipes.add(type);
|
|
1307
1313
|
return;
|
|
1308
1314
|
}
|
|
@@ -1390,7 +1396,7 @@ class TestBedCompiler {
|
|
|
1390
1396
|
path.forEach((item) => affectedModules.add(item));
|
|
1391
1397
|
}
|
|
1392
1398
|
// Examine module imports recursively to look for overridden modules.
|
|
1393
|
-
const moduleDef = value[
|
|
1399
|
+
const moduleDef = value[NG_MOD_DEF];
|
|
1394
1400
|
calcAffectedModulesRecur(maybeUnwrapFn(moduleDef.imports), path.concat(value));
|
|
1395
1401
|
}
|
|
1396
1402
|
}
|
|
@@ -1428,7 +1434,7 @@ class TestBedCompiler {
|
|
|
1428
1434
|
if (this.originalComponentResolutionQueue === null) {
|
|
1429
1435
|
this.originalComponentResolutionQueue = new Map();
|
|
1430
1436
|
}
|
|
1431
|
-
|
|
1437
|
+
clearResolutionOfComponentResourcesQueue().forEach((value, key) => this.originalComponentResolutionQueue.set(key, value));
|
|
1432
1438
|
}
|
|
1433
1439
|
/*
|
|
1434
1440
|
* Restores component resolution queue to the previously saved state. This operation is performed
|
|
@@ -1437,7 +1443,7 @@ class TestBedCompiler {
|
|
|
1437
1443
|
*/
|
|
1438
1444
|
restoreComponentResolutionQueue() {
|
|
1439
1445
|
if (this.originalComponentResolutionQueue !== null) {
|
|
1440
|
-
|
|
1446
|
+
restoreComponentResolutionQueue(this.originalComponentResolutionQueue);
|
|
1441
1447
|
this.originalComponentResolutionQueue = null;
|
|
1442
1448
|
}
|
|
1443
1449
|
}
|
|
@@ -1449,8 +1455,8 @@ class TestBedCompiler {
|
|
|
1449
1455
|
});
|
|
1450
1456
|
// Restore initial component/directive/pipe defs
|
|
1451
1457
|
this.initialNgDefs.forEach((defs, type) => {
|
|
1452
|
-
|
|
1453
|
-
|
|
1458
|
+
{
|
|
1459
|
+
depsTracker.clearScopeCacheFor(type);
|
|
1454
1460
|
}
|
|
1455
1461
|
defs.forEach((descriptor, prop) => {
|
|
1456
1462
|
if (!descriptor) {
|
|
@@ -1471,24 +1477,31 @@ class TestBedCompiler {
|
|
|
1471
1477
|
this.scopesWithOverriddenProviders.clear();
|
|
1472
1478
|
this.restoreComponentResolutionQueue();
|
|
1473
1479
|
// Restore the locale ID to the default value, this shouldn't be necessary but we never know
|
|
1474
|
-
|
|
1480
|
+
setLocaleId(DEFAULT_LOCALE_ID);
|
|
1475
1481
|
}
|
|
1476
1482
|
compileTestModule() {
|
|
1477
1483
|
class RootScopeModule {
|
|
1478
1484
|
}
|
|
1479
|
-
|
|
1485
|
+
compileNgModuleDefs(RootScopeModule, {
|
|
1480
1486
|
providers: [
|
|
1481
1487
|
...this.rootProviderOverrides,
|
|
1482
|
-
|
|
1488
|
+
internalProvideZoneChangeDetection({}),
|
|
1483
1489
|
TestBedApplicationErrorHandler,
|
|
1484
|
-
{ provide:
|
|
1490
|
+
{ provide: ChangeDetectionScheduler, useExisting: ChangeDetectionSchedulerImpl },
|
|
1491
|
+
{
|
|
1492
|
+
provide: ENVIRONMENT_INITIALIZER,
|
|
1493
|
+
multi: true,
|
|
1494
|
+
useValue: () => {
|
|
1495
|
+
inject$1(ErrorHandler);
|
|
1496
|
+
},
|
|
1497
|
+
},
|
|
1485
1498
|
],
|
|
1486
1499
|
});
|
|
1487
1500
|
const providers = [
|
|
1488
1501
|
{ provide: Compiler, useFactory: () => new R3TestCompiler(this) },
|
|
1489
|
-
{ provide:
|
|
1502
|
+
{ provide: DEFER_BLOCK_CONFIG, useValue: { behavior: this.deferBlockBehavior } },
|
|
1490
1503
|
{
|
|
1491
|
-
provide:
|
|
1504
|
+
provide: INTERNAL_APPLICATION_ERROR_HANDLER,
|
|
1492
1505
|
useFactory: () => {
|
|
1493
1506
|
if (this.rethrowApplicationTickErrors) {
|
|
1494
1507
|
const handler = inject$1(TestBedApplicationErrorHandler);
|
|
@@ -1507,7 +1520,7 @@ class TestBedCompiler {
|
|
|
1507
1520
|
...this.providerOverrides,
|
|
1508
1521
|
];
|
|
1509
1522
|
const imports = [RootScopeModule, this.additionalModuleTypes, this.imports || []];
|
|
1510
|
-
|
|
1523
|
+
compileNgModuleDefs(this.testModuleType, {
|
|
1511
1524
|
declarations: this.declarations,
|
|
1512
1525
|
imports,
|
|
1513
1526
|
schemas: this.schemas,
|
|
@@ -1633,7 +1646,7 @@ function identityFn(value) {
|
|
|
1633
1646
|
function flattenProviders(providers, mapFn = identityFn) {
|
|
1634
1647
|
const out = [];
|
|
1635
1648
|
for (let provider of providers) {
|
|
1636
|
-
if (
|
|
1649
|
+
if (isEnvironmentProviders(provider)) {
|
|
1637
1650
|
provider = provider.ɵproviders;
|
|
1638
1651
|
}
|
|
1639
1652
|
if (Array.isArray(provider)) {
|
|
@@ -1669,11 +1682,11 @@ class R3TestCompiler {
|
|
|
1669
1682
|
}
|
|
1670
1683
|
compileModuleSync(moduleType) {
|
|
1671
1684
|
this.testBed._compileNgModuleSync(moduleType);
|
|
1672
|
-
return new
|
|
1685
|
+
return new NgModuleFactory(moduleType);
|
|
1673
1686
|
}
|
|
1674
1687
|
async compileModuleAsync(moduleType) {
|
|
1675
1688
|
await this.testBed._compileNgModuleAsync(moduleType);
|
|
1676
|
-
return new
|
|
1689
|
+
return new NgModuleFactory(moduleType);
|
|
1677
1690
|
}
|
|
1678
1691
|
compileModuleAndAllComponentsSync(moduleType) {
|
|
1679
1692
|
const ngModuleFactory = this.compileModuleSync(moduleType);
|
|
@@ -1839,7 +1852,7 @@ class TestBedImpl {
|
|
|
1839
1852
|
/**
|
|
1840
1853
|
* Runs the given function in the `EnvironmentInjector` context of `TestBed`.
|
|
1841
1854
|
*
|
|
1842
|
-
* @see {@link EnvironmentInjector#runInContext}
|
|
1855
|
+
* @see {@link https://angular.dev/api/core/EnvironmentInjector#runInContext}
|
|
1843
1856
|
*/
|
|
1844
1857
|
static runInInjectionContext(fn) {
|
|
1845
1858
|
return TestBedImpl.INSTANCE.runInInjectionContext(fn);
|
|
@@ -1901,7 +1914,7 @@ class TestBedImpl {
|
|
|
1901
1914
|
// used to track the state of the NgModule registry and reset it correctly. Instead, when we
|
|
1902
1915
|
// know we're in a testing scenario, we disable the check for duplicate NgModule registration
|
|
1903
1916
|
// completely.
|
|
1904
|
-
|
|
1917
|
+
setAllowDuplicateNgModuleIdsForTest(true);
|
|
1905
1918
|
}
|
|
1906
1919
|
/**
|
|
1907
1920
|
* Reset the providers for the test injector.
|
|
@@ -1914,11 +1927,11 @@ class TestBedImpl {
|
|
|
1914
1927
|
this.platform = null;
|
|
1915
1928
|
this.ngModule = null;
|
|
1916
1929
|
TestBedImpl._environmentTeardownOptions = undefined;
|
|
1917
|
-
|
|
1930
|
+
setAllowDuplicateNgModuleIdsForTest(false);
|
|
1918
1931
|
}
|
|
1919
1932
|
resetTestingModule() {
|
|
1920
1933
|
this.checkGlobalCompilationFinished();
|
|
1921
|
-
|
|
1934
|
+
resetCompiledComponents();
|
|
1922
1935
|
if (this._compiler !== null) {
|
|
1923
1936
|
this.compiler.restoreOriginalState();
|
|
1924
1937
|
}
|
|
@@ -2040,15 +2053,15 @@ class TestBedImpl {
|
|
|
2040
2053
|
const testComponentRenderer = this.inject(TestComponentRenderer);
|
|
2041
2054
|
const rootElId = `root${_nextRootElementId++}`;
|
|
2042
2055
|
testComponentRenderer.insertRootElement(rootElId);
|
|
2043
|
-
if (
|
|
2056
|
+
if (getAsyncClassMetadataFn(type)) {
|
|
2044
2057
|
throw new Error(`Component '${type.name}' has unresolved metadata. ` +
|
|
2045
2058
|
`Please call \`await TestBed.compileComponents()\` before running this test.`);
|
|
2046
2059
|
}
|
|
2047
2060
|
const componentDef = type.ɵcmp;
|
|
2048
2061
|
if (!componentDef) {
|
|
2049
|
-
throw new Error(`It looks like '${
|
|
2062
|
+
throw new Error(`It looks like '${stringify(type)}' has not been compiled.`);
|
|
2050
2063
|
}
|
|
2051
|
-
const componentFactory = new
|
|
2064
|
+
const componentFactory = new ComponentFactory(componentDef);
|
|
2052
2065
|
const initComponent = () => {
|
|
2053
2066
|
const componentRef = componentFactory.create(Injector.NULL, [], `#${rootElId}`, this.testModuleRef);
|
|
2054
2067
|
return this.runInInjectionContext(() => new ComponentFixture(componentRef));
|
|
@@ -2101,7 +2114,7 @@ class TestBedImpl {
|
|
|
2101
2114
|
// Checking _testNgModuleRef is null should not be necessary, but is left in as an additional
|
|
2102
2115
|
// guard that compilations queued in tests (after instantiation) are never flushed accidentally.
|
|
2103
2116
|
if (!this.globalCompilationChecked && this._testModuleRef === null) {
|
|
2104
|
-
|
|
2117
|
+
flushModuleScopingQueueAsMuchAsPossible();
|
|
2105
2118
|
}
|
|
2106
2119
|
this.globalCompilationChecked = true;
|
|
2107
2120
|
}
|
|
@@ -2189,7 +2202,7 @@ class TestBedImpl {
|
|
|
2189
2202
|
* @developerPreview
|
|
2190
2203
|
*/
|
|
2191
2204
|
flushEffects() {
|
|
2192
|
-
this.inject(
|
|
2205
|
+
this.inject(EffectScheduler).flush();
|
|
2193
2206
|
}
|
|
2194
2207
|
}
|
|
2195
2208
|
/**
|
|
@@ -2430,7 +2443,7 @@ class FakeNavigation {
|
|
|
2430
2443
|
historyState: null,
|
|
2431
2444
|
});
|
|
2432
2445
|
const result = new InternalNavigationResult(this);
|
|
2433
|
-
this.userAgentNavigate(destination, result, {
|
|
2446
|
+
const intercepted = this.userAgentNavigate(destination, result, {
|
|
2434
2447
|
navigationType,
|
|
2435
2448
|
cancelable: true,
|
|
2436
2449
|
canIntercept: true,
|
|
@@ -2439,6 +2452,9 @@ class FakeNavigation {
|
|
|
2439
2452
|
hashChange,
|
|
2440
2453
|
info: options?.info,
|
|
2441
2454
|
});
|
|
2455
|
+
if (!intercepted) {
|
|
2456
|
+
this.updateNavigationEntriesForSameDocumentNavigation(this.navigateEvent);
|
|
2457
|
+
}
|
|
2442
2458
|
return {
|
|
2443
2459
|
committed: result.committed,
|
|
2444
2460
|
finished: result.finished,
|
|
@@ -2462,7 +2478,7 @@ class FakeNavigation {
|
|
|
2462
2478
|
historyState: data,
|
|
2463
2479
|
});
|
|
2464
2480
|
const result = new InternalNavigationResult(this);
|
|
2465
|
-
this.userAgentNavigate(destination, result, {
|
|
2481
|
+
const intercepted = this.userAgentNavigate(destination, result, {
|
|
2466
2482
|
navigationType,
|
|
2467
2483
|
cancelable: true,
|
|
2468
2484
|
canIntercept: true,
|
|
@@ -2470,6 +2486,10 @@ class FakeNavigation {
|
|
|
2470
2486
|
userInitiated: false,
|
|
2471
2487
|
hashChange,
|
|
2472
2488
|
});
|
|
2489
|
+
if (intercepted) {
|
|
2490
|
+
return;
|
|
2491
|
+
}
|
|
2492
|
+
this.updateNavigationEntriesForSameDocumentNavigation(this.navigateEvent);
|
|
2473
2493
|
}
|
|
2474
2494
|
/** Equivalent to `navigation.traverseTo()`. */
|
|
2475
2495
|
traverseTo(key, options) {
|
|
@@ -2514,7 +2534,7 @@ class FakeNavigation {
|
|
|
2514
2534
|
this.traversalQueue.set(entry.key, result);
|
|
2515
2535
|
this.runTraversal(() => {
|
|
2516
2536
|
this.traversalQueue.delete(entry.key);
|
|
2517
|
-
const
|
|
2537
|
+
const intercepted = this.userAgentNavigate(destination, result, {
|
|
2518
2538
|
navigationType: 'traverse',
|
|
2519
2539
|
cancelable: true,
|
|
2520
2540
|
canIntercept: true,
|
|
@@ -2523,8 +2543,9 @@ class FakeNavigation {
|
|
|
2523
2543
|
hashChange,
|
|
2524
2544
|
info: options?.info,
|
|
2525
2545
|
});
|
|
2526
|
-
|
|
2527
|
-
|
|
2546
|
+
if (!intercepted) {
|
|
2547
|
+
this.userAgentTraverse(this.navigateEvent);
|
|
2548
|
+
}
|
|
2528
2549
|
});
|
|
2529
2550
|
return {
|
|
2530
2551
|
committed: result.committed,
|
|
@@ -2594,7 +2615,7 @@ class FakeNavigation {
|
|
|
2594
2615
|
sameDocument: entry.sameDocument,
|
|
2595
2616
|
});
|
|
2596
2617
|
const result = new InternalNavigationResult(this);
|
|
2597
|
-
const
|
|
2618
|
+
const intercepted = this.userAgentNavigate(destination, result, {
|
|
2598
2619
|
navigationType: 'traverse',
|
|
2599
2620
|
cancelable: true,
|
|
2600
2621
|
canIntercept: true,
|
|
@@ -2602,8 +2623,9 @@ class FakeNavigation {
|
|
|
2602
2623
|
userInitiated: false,
|
|
2603
2624
|
hashChange,
|
|
2604
2625
|
});
|
|
2605
|
-
|
|
2606
|
-
|
|
2626
|
+
if (!intercepted) {
|
|
2627
|
+
this.userAgentTraverse(this.navigateEvent);
|
|
2628
|
+
}
|
|
2607
2629
|
});
|
|
2608
2630
|
}
|
|
2609
2631
|
/** Runs a traversal synchronously or asynchronously */
|
|
@@ -2647,7 +2669,10 @@ class FakeNavigation {
|
|
|
2647
2669
|
isDisposed() {
|
|
2648
2670
|
return this.disposed;
|
|
2649
2671
|
}
|
|
2650
|
-
/**
|
|
2672
|
+
/**
|
|
2673
|
+
* Implementation for all navigations and traversals.
|
|
2674
|
+
* @returns true if the event was intercepted, otherwise false
|
|
2675
|
+
*/
|
|
2651
2676
|
userAgentNavigate(destination, result, options) {
|
|
2652
2677
|
// The first navigation should disallow any future calls to set the initial
|
|
2653
2678
|
// entry.
|
|
@@ -2669,35 +2694,11 @@ class FakeNavigation {
|
|
|
2669
2694
|
result,
|
|
2670
2695
|
});
|
|
2671
2696
|
}
|
|
2672
|
-
/**
|
|
2673
|
-
* Implementation to commit a navigation.
|
|
2674
|
-
* https://whatpr.org/html/10919/nav-history-apis.html#navigateevent-commit
|
|
2675
|
-
* @internal
|
|
2676
|
-
*/
|
|
2677
|
-
commitNavigateEvent(navigateEvent) {
|
|
2678
|
-
navigateEvent.interceptionState = 'committed';
|
|
2679
|
-
const from = this.currentEntry;
|
|
2680
|
-
if (!from) {
|
|
2681
|
-
throw new Error('cannot commit navigation when current entry is null');
|
|
2682
|
-
}
|
|
2683
|
-
if (!navigateEvent.sameDocument) {
|
|
2684
|
-
const error = new Error('Cannot navigate to a non-same-document URL.');
|
|
2685
|
-
navigateEvent.cancel(error);
|
|
2686
|
-
throw error;
|
|
2687
|
-
}
|
|
2688
|
-
// "If navigationType is "push" or "replace", then run the URL and history update steps given document and event's destination's URL, with serialiedData set to event's classic history API state and historyHandling set to navigationType."
|
|
2689
|
-
if (navigateEvent.navigationType === 'push' || navigateEvent.navigationType === 'replace') {
|
|
2690
|
-
this.urlAndHistoryUpdateSteps(navigateEvent);
|
|
2691
|
-
}
|
|
2692
|
-
else if (navigateEvent.navigationType === 'reload') {
|
|
2693
|
-
this.updateNavigationEntriesForSameDocumentNavigation(navigateEvent);
|
|
2694
|
-
}
|
|
2695
|
-
else ;
|
|
2696
|
-
}
|
|
2697
2697
|
/**
|
|
2698
2698
|
* Implementation for a push or replace navigation.
|
|
2699
2699
|
* https://whatpr.org/html/10919/browsing-the-web.html#url-and-history-update-steps
|
|
2700
2700
|
* https://whatpr.org/html/10919/nav-history-apis.html#update-the-navigation-api-entries-for-a-same-document-navigation
|
|
2701
|
+
* @internal
|
|
2701
2702
|
*/
|
|
2702
2703
|
urlAndHistoryUpdateSteps(navigateEvent) {
|
|
2703
2704
|
this.updateNavigationEntriesForSameDocumentNavigation(navigateEvent);
|
|
@@ -2711,17 +2712,25 @@ class FakeNavigation {
|
|
|
2711
2712
|
* > If targetEntry's document is equal to displayedDocument, then perform updateDocument.
|
|
2712
2713
|
* https://whatpr.org/html/10919/browsing-the-web.html#update-document-for-history-step-application
|
|
2713
2714
|
* which then goes to https://whatpr.org/html/10919/nav-history-apis.html#update-the-navigation-api-entries-for-a-same-document-navigation
|
|
2715
|
+
* @internal
|
|
2714
2716
|
*/
|
|
2715
2717
|
userAgentTraverse(navigateEvent) {
|
|
2718
|
+
const oldUrl = this.currentEntry.url;
|
|
2716
2719
|
this.updateNavigationEntriesForSameDocumentNavigation(navigateEvent);
|
|
2717
2720
|
// Happens as part of "updating the document" steps https://whatpr.org/html/10919/browsing-the-web.html#updating-the-document
|
|
2718
2721
|
const popStateEvent = createPopStateEvent({
|
|
2719
2722
|
state: navigateEvent.destination.getHistoryState(),
|
|
2720
2723
|
});
|
|
2721
2724
|
this.window.dispatchEvent(popStateEvent);
|
|
2722
|
-
|
|
2725
|
+
if (navigateEvent.hashChange) {
|
|
2726
|
+
const hashchangeEvent = createHashChangeEvent(oldUrl, this.currentEntry.url);
|
|
2727
|
+
this.window.dispatchEvent(hashchangeEvent);
|
|
2728
|
+
}
|
|
2723
2729
|
}
|
|
2724
|
-
/**
|
|
2730
|
+
/**
|
|
2731
|
+
* https://whatpr.org/html/10919/nav-history-apis.html#update-the-navigation-api-entries-for-a-same-document-navigation
|
|
2732
|
+
* @internal
|
|
2733
|
+
*/
|
|
2725
2734
|
updateNavigationEntriesForSameDocumentNavigation({ destination, navigationType, result, }) {
|
|
2726
2735
|
const oldCurrentNHE = this.currentEntry;
|
|
2727
2736
|
const disposedNHEs = [];
|
|
@@ -2892,24 +2901,35 @@ function dispatchNavigateEvent({ cancelable, canIntercept, userInitiated, hashCh
|
|
|
2892
2901
|
event.formData = null;
|
|
2893
2902
|
event.result = result;
|
|
2894
2903
|
event.sameDocument = sameDocument;
|
|
2895
|
-
|
|
2896
|
-
let
|
|
2897
|
-
|
|
2904
|
+
let precommitHandlers = [];
|
|
2905
|
+
let handlers = [];
|
|
2906
|
+
// https://whatpr.org/html/10919/nav-history-apis.html#dom-navigateevent-intercept
|
|
2898
2907
|
event.intercept = function (options) {
|
|
2899
2908
|
if (!this.canIntercept) {
|
|
2900
2909
|
throw new DOMException(`Cannot intercept when canIntercept is 'false'`, 'SecurityError');
|
|
2901
2910
|
}
|
|
2902
2911
|
this.interceptionState = 'intercepted';
|
|
2903
2912
|
event.sameDocument = true;
|
|
2913
|
+
const precommitHandler = options?.precommitHandler;
|
|
2914
|
+
if (precommitHandler) {
|
|
2915
|
+
if (!this.cancelable) {
|
|
2916
|
+
throw new DOMException(`Cannot use precommitHandler when cancelable is 'false'`, 'InvalidStateError');
|
|
2917
|
+
}
|
|
2918
|
+
precommitHandlers.push(precommitHandler);
|
|
2919
|
+
}
|
|
2920
|
+
if (event.interceptionState !== 'none' && event.interceptionState !== 'intercepted') {
|
|
2921
|
+
throw new Error('Event interceptionState should be "none" or "intercepted"');
|
|
2922
|
+
}
|
|
2923
|
+
event.interceptionState = 'intercepted';
|
|
2904
2924
|
const handler = options?.handler;
|
|
2905
2925
|
if (handler) {
|
|
2906
|
-
|
|
2926
|
+
handlers.push(handler);
|
|
2907
2927
|
}
|
|
2908
2928
|
// override old options with new ones. UA _may_ report a console warning if new options differ from previous
|
|
2909
|
-
event.commitOption = options?.commit ?? event.commitOption;
|
|
2910
|
-
event.scrollBehavior = options?.scroll ?? event.scrollBehavior;
|
|
2911
2929
|
event.focusResetBehavior = options?.focusReset ?? event.focusResetBehavior;
|
|
2930
|
+
event.scrollBehavior = options?.scroll ?? event.scrollBehavior;
|
|
2912
2931
|
};
|
|
2932
|
+
// https://whatpr.org/html/10919/nav-history-apis.html#dom-navigateevent-scroll
|
|
2913
2933
|
event.scroll = function () {
|
|
2914
2934
|
if (event.interceptionState !== 'committed') {
|
|
2915
2935
|
throw new DOMException(`Failed to execute 'scroll' on 'NavigateEvent': scroll() must be ` +
|
|
@@ -2917,43 +2937,54 @@ function dispatchNavigateEvent({ cancelable, canIntercept, userInitiated, hashCh
|
|
|
2917
2937
|
}
|
|
2918
2938
|
processScrollBehavior(event);
|
|
2919
2939
|
};
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
|
|
2940
|
+
// https://whatpr.org/html/10919/nav-history-apis.html#dom-navigationprecommitcontroller-redirect
|
|
2941
|
+
function redirect(url) {
|
|
2942
|
+
if (event.interceptionState === 'none') {
|
|
2943
|
+
throw new Error('cannot redirect when event is not intercepted');
|
|
2924
2944
|
}
|
|
2925
|
-
if (
|
|
2926
|
-
throw new DOMException(`
|
|
2927
|
-
`called if commit behavior is not "after-transition",.`, 'InvalidStateError');
|
|
2945
|
+
if (event.interceptionState !== 'intercepted') {
|
|
2946
|
+
throw new DOMException(`cannot redirect when event is not in 'intercepted' state`, 'InvalidStateError');
|
|
2928
2947
|
}
|
|
2929
|
-
if (
|
|
2930
|
-
throw new DOMException(`
|
|
2931
|
-
|
|
2948
|
+
if (event.navigationType !== 'push' && event.navigationType !== 'replace') {
|
|
2949
|
+
throw new DOMException(`cannot redirect when navigationType is not 'push' or 'replace`, 'InvalidStateError');
|
|
2950
|
+
}
|
|
2951
|
+
const toUrl = new URL(url, navigation.currentEntry.url);
|
|
2952
|
+
event.destination.url = toUrl.href;
|
|
2953
|
+
}
|
|
2954
|
+
// https://whatpr.org/html/10919/nav-history-apis.html#inner-navigate-event-firing-algorithm
|
|
2955
|
+
// "Let commit be the following steps:"
|
|
2956
|
+
function commit() {
|
|
2957
|
+
if (result.signal.aborted) {
|
|
2958
|
+
return;
|
|
2932
2959
|
}
|
|
2933
|
-
this.interceptionState = 'committed';
|
|
2934
|
-
result.navigation.commitNavigateEvent(event);
|
|
2935
|
-
};
|
|
2936
|
-
// Internal only.
|
|
2937
|
-
event.cancel = function (reason) {
|
|
2938
|
-
result.committedReject(reason);
|
|
2939
|
-
result.finishedReject(reason);
|
|
2940
|
-
};
|
|
2941
|
-
function dispatch() {
|
|
2942
|
-
navigation.navigateEvent = event;
|
|
2943
|
-
navigation.eventTarget.dispatchEvent(event);
|
|
2944
|
-
dispatchedNavigateEvent = true;
|
|
2945
2960
|
if (event.interceptionState !== 'none') {
|
|
2961
|
+
event.interceptionState = 'committed';
|
|
2962
|
+
if (!navigation.currentEntry) {
|
|
2963
|
+
throw new Error('from history entry should not be null');
|
|
2964
|
+
}
|
|
2946
2965
|
navigation.transition = new InternalNavigationTransition(navigation.currentEntry, navigationType);
|
|
2947
|
-
|
|
2948
|
-
|
|
2966
|
+
switch (event.navigationType) {
|
|
2967
|
+
case 'push':
|
|
2968
|
+
case 'replace': {
|
|
2969
|
+
navigation.urlAndHistoryUpdateSteps(event);
|
|
2970
|
+
break;
|
|
2971
|
+
}
|
|
2972
|
+
case 'reload': {
|
|
2973
|
+
navigation.updateNavigationEntriesForSameDocumentNavigation(event);
|
|
2974
|
+
break;
|
|
2975
|
+
}
|
|
2976
|
+
case 'traverse': {
|
|
2977
|
+
navigation.userAgentTraverse(event);
|
|
2978
|
+
break;
|
|
2979
|
+
}
|
|
2949
2980
|
}
|
|
2950
2981
|
}
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
event.commit(/** internal */ true);
|
|
2982
|
+
const promisesList = handlers.map((handler) => handler());
|
|
2983
|
+
if (promisesList.length === 0) {
|
|
2984
|
+
promisesList.push(Promise.resolve());
|
|
2955
2985
|
}
|
|
2956
|
-
Promise.all(
|
|
2986
|
+
Promise.all(promisesList)
|
|
2987
|
+
.then(() => {
|
|
2957
2988
|
// Follows steps outlined under "Wait for all of promisesList, with the following success steps:"
|
|
2958
2989
|
// in the spec https://html.spec.whatwg.org/multipage/nav-history-apis.html#navigate-event-firing.
|
|
2959
2990
|
if (result.signal.aborted) {
|
|
@@ -2963,9 +2994,6 @@ function dispatchNavigateEvent({ cancelable, canIntercept, userInitiated, hashCh
|
|
|
2963
2994
|
throw new Error("Navigation's ongoing event not equal to resolved event");
|
|
2964
2995
|
}
|
|
2965
2996
|
navigation.navigateEvent = null;
|
|
2966
|
-
if (event.interceptionState === 'intercepted') {
|
|
2967
|
-
navigation.commitNavigateEvent(event);
|
|
2968
|
-
}
|
|
2969
2997
|
finishNavigationEvent(event, true);
|
|
2970
2998
|
const navigatesuccessEvent = new Event('navigatesuccess', { bubbles: false, cancelable });
|
|
2971
2999
|
navigation.eventTarget.dispatchEvent(navigatesuccessEvent);
|
|
@@ -2974,39 +3002,66 @@ function dispatchNavigateEvent({ cancelable, canIntercept, userInitiated, hashCh
|
|
|
2974
3002
|
navigation.transition.finishedResolve();
|
|
2975
3003
|
}
|
|
2976
3004
|
navigation.transition = null;
|
|
2977
|
-
}
|
|
2978
|
-
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
|
|
2982
|
-
|
|
2983
|
-
|
|
2984
|
-
|
|
2985
|
-
|
|
3005
|
+
})
|
|
3006
|
+
.catch((reason) => event.cancel(reason));
|
|
3007
|
+
}
|
|
3008
|
+
// Internal only.
|
|
3009
|
+
// https://whatpr.org/html/10919/nav-history-apis.html#inner-navigate-event-firing-algorithm
|
|
3010
|
+
// "Let cancel be the following steps given reason"
|
|
3011
|
+
event.cancel = function (reason) {
|
|
3012
|
+
if (result.signal.aborted) {
|
|
3013
|
+
return;
|
|
3014
|
+
}
|
|
3015
|
+
if (event !== navigation.navigateEvent) {
|
|
3016
|
+
throw new Error("Navigation's ongoing event not equal to resolved event");
|
|
3017
|
+
}
|
|
3018
|
+
navigation.navigateEvent = null;
|
|
3019
|
+
if (event.interceptionState !== 'intercepted') {
|
|
2986
3020
|
finishNavigationEvent(event, false);
|
|
2987
|
-
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
|
|
2993
|
-
|
|
2994
|
-
|
|
3021
|
+
}
|
|
3022
|
+
const navigateerrorEvent = new Event('navigateerror', { bubbles: false, cancelable });
|
|
3023
|
+
navigation.eventTarget.dispatchEvent(navigateerrorEvent);
|
|
3024
|
+
result.finishedReject(reason);
|
|
3025
|
+
if (navigation.transition !== null) {
|
|
3026
|
+
navigation.transition.finishedReject(reason);
|
|
3027
|
+
}
|
|
3028
|
+
navigation.transition = null;
|
|
3029
|
+
};
|
|
3030
|
+
function dispatch() {
|
|
3031
|
+
navigation.navigateEvent = event;
|
|
3032
|
+
navigation.eventTarget.dispatchEvent(event);
|
|
3033
|
+
if (precommitHandlers.length === 0) {
|
|
3034
|
+
commit();
|
|
3035
|
+
}
|
|
3036
|
+
else {
|
|
3037
|
+
const precommitController = { redirect };
|
|
3038
|
+
const precommitPromisesList = precommitHandlers.map((handler) => handler(precommitController));
|
|
3039
|
+
Promise.all(precommitPromisesList)
|
|
3040
|
+
.then(() => commit())
|
|
3041
|
+
.catch((reason) => event.cancel(reason));
|
|
3042
|
+
}
|
|
2995
3043
|
}
|
|
2996
3044
|
dispatch();
|
|
2997
|
-
return event;
|
|
3045
|
+
return event.interceptionState !== 'none';
|
|
2998
3046
|
}
|
|
2999
3047
|
/** https://whatpr.org/html/10919/nav-history-apis.html#navigateevent-finish */
|
|
3000
3048
|
function finishNavigationEvent(event, didFulfill) {
|
|
3001
|
-
if (event.interceptionState === '
|
|
3002
|
-
throw new Error('Attempting to finish navigation event that was
|
|
3049
|
+
if (event.interceptionState === 'finished') {
|
|
3050
|
+
throw new Error('Attempting to finish navigation event that was already finished');
|
|
3051
|
+
}
|
|
3052
|
+
if (event.interceptionState === 'intercepted') {
|
|
3053
|
+
if (didFulfill === true) {
|
|
3054
|
+
throw new Error('didFulfill should be false');
|
|
3055
|
+
}
|
|
3056
|
+
// assert precommit handlers is not empty
|
|
3057
|
+
event.interceptionState = 'finished';
|
|
3058
|
+
return;
|
|
3003
3059
|
}
|
|
3004
3060
|
if (event.interceptionState === 'none') {
|
|
3005
3061
|
return;
|
|
3006
3062
|
}
|
|
3063
|
+
potentiallyResetFocus(event);
|
|
3007
3064
|
if (didFulfill) {
|
|
3008
|
-
// TODO(atscott): https://github.com/whatwg/html/issues/11087 focus reset is not guarded by didFulfill in the spec
|
|
3009
|
-
potentiallyResetFocus(event);
|
|
3010
3065
|
potentiallyResetScroll(event);
|
|
3011
3066
|
}
|
|
3012
3067
|
event.interceptionState = 'finished';
|
|
@@ -3060,6 +3115,15 @@ function createPopStateEvent({ state }) {
|
|
|
3060
3115
|
event.state = state;
|
|
3061
3116
|
return event;
|
|
3062
3117
|
}
|
|
3118
|
+
function createHashChangeEvent(newURL, oldURL) {
|
|
3119
|
+
const event = new Event('hashchange', {
|
|
3120
|
+
bubbles: false,
|
|
3121
|
+
cancelable: false,
|
|
3122
|
+
});
|
|
3123
|
+
event.newURL = newURL;
|
|
3124
|
+
event.oldURL = oldURL;
|
|
3125
|
+
return event;
|
|
3126
|
+
}
|
|
3063
3127
|
/**
|
|
3064
3128
|
* Fake equivalent of `NavigationDestination`.
|
|
3065
3129
|
*/
|
|
@@ -3153,5 +3217,5 @@ class InternalNavigationResult {
|
|
|
3153
3217
|
}
|
|
3154
3218
|
}
|
|
3155
3219
|
|
|
3156
|
-
export { ComponentFixture, ComponentFixtureAutoDetect, ComponentFixtureNoNgZone, DeferBlockFixture, InjectSetupWrapper, TestBed, TestComponentRenderer, __core_private_testing_placeholder__, discardPeriodicTasks, fakeAsync, flush, flushMicrotasks, getTestBed, inject, resetFakeAsyncZone, tick, waitForAsync, withModule, FakeNavigation as ɵFakeNavigation, MetadataOverrider as ɵMetadataOverrider };
|
|
3220
|
+
export { ComponentFixture, ComponentFixtureAutoDetect, ComponentFixtureNoNgZone, DeferBlockBehavior, DeferBlockFixture, DeferBlockState, InjectSetupWrapper, TestBed, TestComponentRenderer, __core_private_testing_placeholder__, discardPeriodicTasks, fakeAsync, flush, flushMicrotasks, getTestBed, inject, resetFakeAsyncZone, tick, waitForAsync, withModule, FakeNavigation as ɵFakeNavigation, MetadataOverrider as ɵMetadataOverrider };
|
|
3157
3221
|
//# sourceMappingURL=testing.mjs.map
|