fix(router): incorrect injector is used when instantiating components loaded lazily (#12817)
This commit is contained in:

committed by
Victor Berchet

parent
69dfcf7385
commit
52be848f94
@ -143,7 +143,8 @@ describe('applyRedirects', () => {
|
||||
describe('lazy loading', () => {
|
||||
it('should load config on demand', () => {
|
||||
const loadedConfig = new LoadedRouterConfig(
|
||||
[{path: 'b', component: ComponentB}], <any>'stubInjector', <any>'stubFactoryResolver');
|
||||
[{path: 'b', component: ComponentB}], <any>'stubInjector', <any>'stubFactoryResolver',
|
||||
<any>'injectorFactory');
|
||||
const loader = {
|
||||
load: (injector: any, p: any) => {
|
||||
if (injector !== 'providedInjector') throw 'Invalid Injector';
|
||||
@ -171,7 +172,8 @@ describe('applyRedirects', () => {
|
||||
|
||||
it('should load when all canLoad guards return true', () => {
|
||||
const loadedConfig = new LoadedRouterConfig(
|
||||
[{path: 'b', component: ComponentB}], <any>'stubInjector', <any>'stubFactoryResolver');
|
||||
[{path: 'b', component: ComponentB}], <any>'stubInjector', <any>'stubFactoryResolver',
|
||||
<any>'injectorFactory');
|
||||
const loader = {load: (injector: any, p: any) => of (loadedConfig)};
|
||||
|
||||
const guard = () => true;
|
||||
@ -191,7 +193,8 @@ describe('applyRedirects', () => {
|
||||
|
||||
it('should not load when any canLoad guards return false', () => {
|
||||
const loadedConfig = new LoadedRouterConfig(
|
||||
[{path: 'b', component: ComponentB}], <any>'stubInjector', <any>'stubFactoryResolver');
|
||||
[{path: 'b', component: ComponentB}], <any>'stubInjector', <any>'stubFactoryResolver',
|
||||
<any>'injectorFactory');
|
||||
const loader = {load: (injector: any, p: any) => of (loadedConfig)};
|
||||
|
||||
const trueGuard = () => true;
|
||||
@ -216,7 +219,8 @@ describe('applyRedirects', () => {
|
||||
|
||||
it('should not load when any canLoad guards is rejected (promises)', () => {
|
||||
const loadedConfig = new LoadedRouterConfig(
|
||||
[{path: 'b', component: ComponentB}], <any>'stubInjector', <any>'stubFactoryResolver');
|
||||
[{path: 'b', component: ComponentB}], <any>'stubInjector', <any>'stubFactoryResolver',
|
||||
<any>'injectorFactory');
|
||||
const loader = {load: (injector: any, p: any) => of (loadedConfig)};
|
||||
|
||||
const trueGuard = () => Promise.resolve(true);
|
||||
@ -237,7 +241,8 @@ describe('applyRedirects', () => {
|
||||
|
||||
it('should work with objects implementing the CanLoad interface', () => {
|
||||
const loadedConfig = new LoadedRouterConfig(
|
||||
[{path: 'b', component: ComponentB}], <any>'stubInjector', <any>'stubFactoryResolver');
|
||||
[{path: 'b', component: ComponentB}], <any>'stubInjector', <any>'stubFactoryResolver',
|
||||
<any>'injectorFactory');
|
||||
const loader = {load: (injector: any, p: any) => of (loadedConfig)};
|
||||
|
||||
const guard = {canLoad: () => Promise.resolve(true)};
|
||||
@ -254,7 +259,8 @@ describe('applyRedirects', () => {
|
||||
|
||||
it('should work with absolute redirects', () => {
|
||||
const loadedConfig = new LoadedRouterConfig(
|
||||
[{path: '', component: ComponentB}], <any>'stubInjector', <any>'stubFactoryResolver');
|
||||
[{path: '', component: ComponentB}], <any>'stubInjector', <any>'stubFactoryResolver',
|
||||
<any>'injectorFactory');
|
||||
|
||||
const loader = {load: (injector: any, p: any) => of (loadedConfig)};
|
||||
|
||||
@ -269,7 +275,8 @@ describe('applyRedirects', () => {
|
||||
|
||||
it('should load the configuration only once', () => {
|
||||
const loadedConfig = new LoadedRouterConfig(
|
||||
[{path: '', component: ComponentB}], <any>'stubInjector', <any>'stubFactoryResolver');
|
||||
[{path: '', component: ComponentB}], <any>'stubInjector', <any>'stubFactoryResolver',
|
||||
<any>'injectorFactory');
|
||||
|
||||
let called = false;
|
||||
const loader = {
|
||||
@ -295,7 +302,8 @@ describe('applyRedirects', () => {
|
||||
|
||||
it('should load the configuration of a wildcard route', () => {
|
||||
const loadedConfig = new LoadedRouterConfig(
|
||||
[{path: '', component: ComponentB}], <any>'stubInjector', <any>'stubFactoryResolver');
|
||||
[{path: '', component: ComponentB}], <any>'stubInjector', <any>'stubFactoryResolver',
|
||||
<any>'injectorFactory');
|
||||
|
||||
const loader = {load: (injector: any, p: any) => of (loadedConfig)};
|
||||
|
||||
@ -308,7 +316,8 @@ describe('applyRedirects', () => {
|
||||
|
||||
it('should load the configuration after a local redirect from a wildcard route', () => {
|
||||
const loadedConfig = new LoadedRouterConfig(
|
||||
[{path: '', component: ComponentB}], <any>'stubInjector', <any>'stubFactoryResolver');
|
||||
[{path: '', component: ComponentB}], <any>'stubInjector', <any>'stubFactoryResolver',
|
||||
<any>'injectorFactory');
|
||||
|
||||
const loader = {load: (injector: any, p: any) => of (loadedConfig)};
|
||||
|
||||
@ -322,7 +331,8 @@ describe('applyRedirects', () => {
|
||||
|
||||
it('should load the configuration after an absolute redirect from a wildcard route', () => {
|
||||
const loadedConfig = new LoadedRouterConfig(
|
||||
[{path: '', component: ComponentB}], <any>'stubInjector', <any>'stubFactoryResolver');
|
||||
[{path: '', component: ComponentB}], <any>'stubInjector', <any>'stubFactoryResolver',
|
||||
<any>'injectorFactory');
|
||||
|
||||
const loader = {load: (injector: any, p: any) => of (loadedConfig)};
|
||||
|
||||
|
@ -2024,54 +2024,78 @@ describe('Integration', () => {
|
||||
expect(location.path()).toEqual('/lazy2/loaded');
|
||||
})));
|
||||
|
||||
it('should use the injector of the lazily-loaded configuration',
|
||||
fakeAsync(inject(
|
||||
[Router, Location, NgModuleFactoryLoader],
|
||||
(router: Router, location: Location, loader: SpyNgModuleFactoryLoader) => {
|
||||
class LazyLoadedServiceDefinedInModule {}
|
||||
class LazyLoadedServiceDefinedInCmp {}
|
||||
|
||||
@Component({selector: 'lazy', template: 'lazy-loaded'})
|
||||
class LazyLoadedChildComponent {
|
||||
constructor(service: LazyLoadedServiceDefinedInCmp) {}
|
||||
}
|
||||
describe('should use the injector of the lazily-loaded configuration', () => {
|
||||
class LazyLoadedServiceDefinedInModule {}
|
||||
class LazyLoadedServiceDefinedInCmp {}
|
||||
|
||||
@Component({
|
||||
selector: 'lazy',
|
||||
template: '<router-outlet></router-outlet>',
|
||||
providers: [LazyLoadedServiceDefinedInCmp]
|
||||
})
|
||||
class LazyLoadedParentComponent {
|
||||
constructor(service: LazyLoadedServiceDefinedInModule) {}
|
||||
}
|
||||
@Component({
|
||||
selector: 'eager-parent',
|
||||
template: 'eager-parent <router-outlet></router-outlet>',
|
||||
})
|
||||
class EagerParentComponent {
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
declarations: [LazyLoadedParentComponent, LazyLoadedChildComponent],
|
||||
imports: [RouterModule.forChild([{
|
||||
path: '',
|
||||
children: [{
|
||||
path: 'loaded',
|
||||
component: LazyLoadedParentComponent,
|
||||
children: [{path: 'child', component: LazyLoadedChildComponent}]
|
||||
}]
|
||||
}])],
|
||||
providers: [LazyLoadedServiceDefinedInModule]
|
||||
})
|
||||
class LoadedModule {
|
||||
}
|
||||
@Component({selector: 'lazy-parent', template: 'lazy-parent <router-outlet></router-outlet>'})
|
||||
class LazyParentComponent {
|
||||
}
|
||||
|
||||
loader.stubbedModules = {expected: LoadedModule};
|
||||
@Component({selector: 'lazy-child', template: 'lazy-child'})
|
||||
class LazyChildComponent {
|
||||
constructor(
|
||||
lazy: LazyParentComponent, // should be able to inject lazy/direct parent
|
||||
lazyService: LazyLoadedServiceDefinedInModule, // should be able to inject lazy service
|
||||
eager:
|
||||
EagerParentComponent // should use the injector of the location to create a parent
|
||||
) {}
|
||||
}
|
||||
|
||||
const fixture = createRoot(router, RootCmp);
|
||||
@NgModule({
|
||||
declarations: [LazyParentComponent, LazyChildComponent],
|
||||
imports: [RouterModule.forChild([{
|
||||
path: '',
|
||||
children: [{
|
||||
path: 'lazy-parent',
|
||||
component: LazyParentComponent,
|
||||
children: [{path: 'lazy-child', component: LazyChildComponent}]
|
||||
}]
|
||||
}])],
|
||||
providers: [LazyLoadedServiceDefinedInModule]
|
||||
})
|
||||
class LoadedModule {
|
||||
}
|
||||
|
||||
router.resetConfig([{path: 'lazy', loadChildren: 'expected'}]);
|
||||
@NgModule({
|
||||
declarations: [EagerParentComponent],
|
||||
entryComponents: [EagerParentComponent],
|
||||
imports: [RouterModule]
|
||||
})
|
||||
class TestModule {
|
||||
}
|
||||
|
||||
router.navigateByUrl('/lazy/loaded/child');
|
||||
advance(fixture);
|
||||
beforeEach(() => { TestBed.configureTestingModule({imports: [TestModule]}); });
|
||||
|
||||
expect(location.path()).toEqual('/lazy/loaded/child');
|
||||
expect(fixture.nativeElement).toHaveText('lazy-loaded');
|
||||
})));
|
||||
it('should use the injector of the lazily-loaded configuration',
|
||||
fakeAsync(inject(
|
||||
[Router, Location, NgModuleFactoryLoader],
|
||||
(router: Router, location: Location, loader: SpyNgModuleFactoryLoader) => {
|
||||
loader.stubbedModules = {expected: LoadedModule};
|
||||
|
||||
const fixture = createRoot(router, RootCmp);
|
||||
|
||||
router.resetConfig([{
|
||||
path: 'eager-parent',
|
||||
component: EagerParentComponent,
|
||||
children: [{path: 'lazy', loadChildren: 'expected'}]
|
||||
}]);
|
||||
|
||||
router.navigateByUrl('/eager-parent/lazy/lazy-parent/lazy-child');
|
||||
advance(fixture);
|
||||
|
||||
expect(location.path()).toEqual('/eager-parent/lazy/lazy-parent/lazy-child');
|
||||
expect(fixture.nativeElement).toHaveText('eager-parent lazy-parent lazy-child');
|
||||
})));
|
||||
});
|
||||
|
||||
it('works when given a callback',
|
||||
fakeAsync(inject(
|
||||
|
Reference in New Issue
Block a user