
BREAKING CHANGE: The public API for `DebugNode` was accidentally too broad. This change removes 1. Public constructor. Since `DebugNode` is a way for Angular to communicate information on to the developer there is no reason why the developer should ever need to Instantiate the `DebugNode` 2. We are also removing `removeChild`, `addChild`, `insertBefore`, and `insertChildAfter`. All of these methods are used by Angular to constructor the correct `DebugNode` tree. There is no reason why the developer should ever be constructing a `DebugNode` tree And these methods should have never been made public. 3. All properties have been change to `readonly` since `DebugNode` is used by Angular to communicate to developer and there is no reason why these APIs should be writable. While technically breaking change we don’t expect anyone to be effected by this change. PR Close #27223
253 lines
9.2 KiB
TypeScript
253 lines
9.2 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright Google Inc. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
* found in the LICENSE file at https://angular.io/license
|
|
*/
|
|
|
|
import {Compiler, Component, NgModule, NgModuleFactoryLoader, NgModuleRef} from '@angular/core';
|
|
import {TestBed, fakeAsync, inject, tick} from '@angular/core/testing';
|
|
import {fixmeIvy} from '@angular/private/testing';
|
|
import {PreloadAllModules, PreloadingStrategy, RouterPreloader} from '@angular/router';
|
|
|
|
import {Route, RouteConfigLoadEnd, RouteConfigLoadStart, Router, RouterModule} from '../index';
|
|
import {LoadedRouterConfig} from '../src/config';
|
|
import {RouterTestingModule, SpyNgModuleFactoryLoader} from '../testing';
|
|
|
|
describe('RouterPreloader', () => {
|
|
@Component({template: ''})
|
|
class LazyLoadedCmp {
|
|
}
|
|
|
|
describe('should not load configurations with canLoad guard', () => {
|
|
@NgModule({
|
|
declarations: [LazyLoadedCmp],
|
|
imports: [RouterModule.forChild([{path: 'LoadedModule1', component: LazyLoadedCmp}])]
|
|
})
|
|
class LoadedModule {
|
|
}
|
|
|
|
beforeEach(() => {
|
|
TestBed.configureTestingModule({
|
|
imports: [RouterTestingModule.withRoutes(
|
|
[{path: 'lazy', loadChildren: 'expected', canLoad: ['someGuard']}])],
|
|
providers: [{provide: PreloadingStrategy, useExisting: PreloadAllModules}]
|
|
});
|
|
});
|
|
|
|
|
|
it('should work',
|
|
fakeAsync(inject(
|
|
[NgModuleFactoryLoader, RouterPreloader, Router],
|
|
(loader: SpyNgModuleFactoryLoader, preloader: RouterPreloader, router: Router) => {
|
|
loader.stubbedModules = {expected: LoadedModule};
|
|
|
|
preloader.preload().subscribe(() => {});
|
|
|
|
tick();
|
|
|
|
const c = router.config;
|
|
expect((c[0] as any)._loadedConfig).not.toBeDefined();
|
|
})));
|
|
});
|
|
|
|
describe('should preload configurations', () => {
|
|
beforeEach(() => {
|
|
TestBed.configureTestingModule({
|
|
imports: [RouterTestingModule.withRoutes([{path: 'lazy', loadChildren: 'expected'}])],
|
|
providers: [{provide: PreloadingStrategy, useExisting: PreloadAllModules}]
|
|
});
|
|
});
|
|
|
|
|
|
fixmeIvy('unknown') &&
|
|
it('should work',
|
|
fakeAsync(inject(
|
|
[NgModuleFactoryLoader, RouterPreloader, Router, NgModuleRef],
|
|
(loader: SpyNgModuleFactoryLoader, preloader: RouterPreloader, router: Router,
|
|
testModule: NgModuleRef<any>) => {
|
|
const events: Array<RouteConfigLoadStart|RouteConfigLoadEnd> = [];
|
|
@NgModule({
|
|
declarations: [LazyLoadedCmp],
|
|
imports: [RouterModule.forChild(
|
|
[{path: 'LoadedModule2', component: LazyLoadedCmp}])]
|
|
})
|
|
class LoadedModule2 {
|
|
}
|
|
|
|
@NgModule({
|
|
imports: [RouterModule.forChild(
|
|
[{path: 'LoadedModule1', loadChildren: 'expected2'}])]
|
|
})
|
|
class LoadedModule1 {
|
|
}
|
|
|
|
router.events.subscribe(e => {
|
|
if (e instanceof RouteConfigLoadEnd || e instanceof RouteConfigLoadStart) {
|
|
events.push(e);
|
|
}
|
|
});
|
|
|
|
loader.stubbedModules = {
|
|
expected: LoadedModule1,
|
|
expected2: LoadedModule2,
|
|
};
|
|
|
|
preloader.preload().subscribe(() => {});
|
|
|
|
tick();
|
|
|
|
const c = router.config;
|
|
expect(c[0].loadChildren).toEqual('expected');
|
|
|
|
const loadedConfig: LoadedRouterConfig = (c[0] as any)._loadedConfig !;
|
|
const module: any = loadedConfig.module;
|
|
expect(loadedConfig.routes[0].path).toEqual('LoadedModule1');
|
|
expect(module._parent).toBe(testModule);
|
|
|
|
const loadedConfig2: LoadedRouterConfig =
|
|
(loadedConfig.routes[0] as any)._loadedConfig !;
|
|
const module2: any = loadedConfig2.module;
|
|
expect(loadedConfig2.routes[0].path).toEqual('LoadedModule2');
|
|
expect(module2._parent).toBe(module);
|
|
|
|
expect(events.map(e => e.toString())).toEqual([
|
|
'RouteConfigLoadStart(path: lazy)',
|
|
'RouteConfigLoadEnd(path: lazy)',
|
|
'RouteConfigLoadStart(path: LoadedModule1)',
|
|
'RouteConfigLoadEnd(path: LoadedModule1)',
|
|
]);
|
|
})));
|
|
});
|
|
|
|
describe('should support modules that have already been loaded', () => {
|
|
beforeEach(() => {
|
|
TestBed.configureTestingModule({
|
|
imports: [RouterTestingModule.withRoutes([{path: 'lazy', loadChildren: 'expected'}])],
|
|
providers: [{provide: PreloadingStrategy, useExisting: PreloadAllModules}]
|
|
});
|
|
});
|
|
|
|
fixmeIvy('FW-???: Cannot read property \'declarations\' of undefined') &&
|
|
it('should work',
|
|
fakeAsync(inject(
|
|
[NgModuleFactoryLoader, RouterPreloader, Router, NgModuleRef, Compiler],
|
|
(loader: SpyNgModuleFactoryLoader, preloader: RouterPreloader, router: Router,
|
|
testModule: NgModuleRef<any>, compiler: Compiler) => {
|
|
@NgModule()
|
|
class LoadedModule2 {
|
|
}
|
|
|
|
const module2 = compiler.compileModuleSync(LoadedModule2).create(null);
|
|
|
|
@NgModule({
|
|
imports: [RouterModule.forChild([
|
|
<Route>{
|
|
path: 'LoadedModule2',
|
|
loadChildren: 'no',
|
|
_loadedConfig: {
|
|
routes: [{path: 'LoadedModule3', loadChildren: 'expected3'}],
|
|
module: module2,
|
|
}
|
|
},
|
|
])]
|
|
})
|
|
class LoadedModule1 {
|
|
}
|
|
|
|
@NgModule({imports: [RouterModule.forChild([])]})
|
|
class LoadedModule3 {
|
|
}
|
|
|
|
loader.stubbedModules = {
|
|
expected: LoadedModule1,
|
|
expected3: LoadedModule3,
|
|
};
|
|
|
|
preloader.preload().subscribe(() => {});
|
|
|
|
tick();
|
|
|
|
const c = router.config;
|
|
|
|
const loadedConfig: LoadedRouterConfig = (c[0] as any)._loadedConfig !;
|
|
const module: any = loadedConfig.module;
|
|
expect(module._parent).toBe(testModule);
|
|
|
|
const loadedConfig2: LoadedRouterConfig =
|
|
(loadedConfig.routes[0] as any)._loadedConfig !;
|
|
const loadedConfig3: LoadedRouterConfig =
|
|
(loadedConfig2.routes[0] as any)._loadedConfig !;
|
|
const module3: any = loadedConfig3.module;
|
|
expect(module3._parent).toBe(module2);
|
|
})));
|
|
});
|
|
|
|
describe('should ignore errors', () => {
|
|
@NgModule({
|
|
declarations: [LazyLoadedCmp],
|
|
imports: [RouterModule.forChild([{path: 'LoadedModule1', component: LazyLoadedCmp}])]
|
|
})
|
|
class LoadedModule {
|
|
}
|
|
|
|
beforeEach(() => {
|
|
TestBed.configureTestingModule({
|
|
imports: [RouterTestingModule.withRoutes([
|
|
{path: 'lazy1', loadChildren: 'expected1'}, {path: 'lazy2', loadChildren: 'expected2'}
|
|
])],
|
|
providers: [{provide: PreloadingStrategy, useExisting: PreloadAllModules}]
|
|
});
|
|
});
|
|
|
|
|
|
it('should work',
|
|
fakeAsync(inject(
|
|
[NgModuleFactoryLoader, RouterPreloader, Router],
|
|
(loader: SpyNgModuleFactoryLoader, preloader: RouterPreloader, router: Router) => {
|
|
loader.stubbedModules = {expected2: LoadedModule};
|
|
|
|
preloader.preload().subscribe(() => {});
|
|
|
|
tick();
|
|
|
|
const c = router.config;
|
|
expect((c[0] as any)._loadedConfig).not.toBeDefined();
|
|
expect((c[1] as any)._loadedConfig).toBeDefined();
|
|
})));
|
|
});
|
|
|
|
describe('should copy loaded configs', () => {
|
|
const configs = [{path: 'LoadedModule1', component: LazyLoadedCmp}];
|
|
@NgModule({declarations: [LazyLoadedCmp], imports: [RouterModule.forChild(configs)]})
|
|
class LoadedModule {
|
|
}
|
|
|
|
beforeEach(() => {
|
|
TestBed.configureTestingModule({
|
|
imports: [RouterTestingModule.withRoutes([{path: 'lazy1', loadChildren: 'expected'}])],
|
|
providers: [{provide: PreloadingStrategy, useExisting: PreloadAllModules}]
|
|
});
|
|
});
|
|
|
|
|
|
it('should work',
|
|
fakeAsync(inject(
|
|
[NgModuleFactoryLoader, RouterPreloader, Router],
|
|
(loader: SpyNgModuleFactoryLoader, preloader: RouterPreloader, router: Router) => {
|
|
loader.stubbedModules = {expected: LoadedModule};
|
|
|
|
preloader.preload().subscribe(() => {});
|
|
|
|
tick();
|
|
|
|
const c = router.config as{_loadedConfig: LoadedRouterConfig}[];
|
|
expect(c[0]._loadedConfig).toBeDefined();
|
|
expect(c[0]._loadedConfig !.routes).not.toBe(configs);
|
|
expect(c[0]._loadedConfig !.routes[0]).not.toBe(configs[0]);
|
|
expect(c[0]._loadedConfig !.routes[0].component).toBe(configs[0].component);
|
|
})));
|
|
});
|
|
});
|