/
githubmirror
/
angular
Обзор
Документация
Войти
/
githubmirror
/
angular
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
devtools/projects/ng-devtools-backend/src/lib/router-tree/router-tree.spec.ts
640 строк
17 KB
hawkgs
refactor(devtools): reorganize backend code
20 июл 2026, 12:15
20 июл 2026, 12:15
a7ebf1c
Код
Авторство
О чём код?
/** * @license * Copyright Google LLC 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.dev/license */ import {getRouterCallableConstructRef, parseRoutes} from './router-tree'; describe('parseRoutes', () => { it('should work without any routes', () => { const routes: any[] = []; const parsedRoutes = parseRoutes(routes as any); expect(parsedRoutes).toEqual({ component: 'App Root', path: 'App Root', children: [], isAux: false, isLazy: false, isActive: true, }); }); it('should work with single route', () => { const nestedRouter = { config: [], }; const parsedRoutes = parseRoutes(nestedRouter as any); expect(parsedRoutes).toEqual({ 'component': 'App Root', 'path': 'App Root', 'children': [], 'isAux': false, 'isLazy': false, 'isActive': true, }); }); it('should work with nested routes', () => { function titleResolver() { return 'title'; } const redirectResolver = () => 'redirect'; const nestedRouter = { config: [ { outlet: 'outlet', path: 'component-one', component: { name: 'component-one', }, }, { path: 'component-two', component: { name: 'component-two', }, data: { name: 'component-two', }, title: 'Component Two', children: [ { path: 'component-two-one', component: { name: 'component-two-one', }, title: () => 'Component Two One', _loadedConfig: { routes: [ { path: 'component-two-one-one', component: { name: 'component-two-one-one', }, }, ], }, }, { path: 'component-two-two', component: { name: 'component-two-two', }, title: titleResolver, }, ], }, { loadChildren: true, path: 'lazy', }, { path: 'redirect', redirectTo: 'redirectTo', }, { path: 'redirect-fn', redirectTo: () => '/target', }, { path: 'redirect-named-fn', redirectTo: redirectResolver, }, ], }; const parsedRoutes = parseRoutes(nestedRouter as any); expect(parsedRoutes).toEqual({ 'component': 'App Root', 'path': 'App Root', 'children': [ { 'component': 'component-one', 'canActivateGuards': [], 'canActivateChildGuards': [], 'canMatchGuards': [], 'canDeactivateGuards': [], 'providers': [], 'path': '/(outlet:component-one)', 'pathMatch': undefined, 'isAux': true, 'isLazy': false, 'isActive': false, }, { 'component': 'component-two', 'canActivateGuards': [], 'canActivateChildGuards': [], 'canMatchGuards': [], 'canDeactivateGuards': [], 'providers': [], 'path': '/component-two', 'pathMatch': undefined, 'title': 'Component Two', 'data': {name: 'component-two'}, 'isAux': false, 'isLazy': false, 'isActive': false, 'children': [ { 'component': 'component-two-one', 'canActivateGuards': [], 'canActivateChildGuards': [], 'canMatchGuards': [], 'canDeactivateGuards': [], 'providers': [], 'path': '/component-two/component-two-one', 'pathMatch': undefined, 'title': '[Function]', 'isAux': false, 'isLazy': false, 'isActive': false, }, { 'component': 'component-two-two', 'canActivateGuards': [], 'canActivateChildGuards': [], 'canMatchGuards': [], 'canDeactivateGuards': [], 'providers': [], 'path': '/component-two/component-two-two', 'pathMatch': undefined, 'title': 'titleResolver', 'isAux': false, 'isLazy': false, 'isActive': false, }, ], }, { 'component': 'lazy [Lazy]', 'canActivateGuards': [], 'canActivateChildGuards': [], 'canMatchGuards': [], 'canDeactivateGuards': [], 'providers': [], 'path': '/lazy', 'pathMatch': undefined, 'isAux': false, 'isLazy': true, 'isActive': false, }, { 'component': 'no-name-route', 'canActivateGuards': [], 'canActivateChildGuards': [], 'canMatchGuards': [], 'canDeactivateGuards': [], 'providers': [], 'path': '/redirect', 'pathMatch': undefined, 'isAux': false, 'isLazy': false, 'isActive': false, 'redirectTo': 'redirectTo', }, { 'component': 'no-name-route', 'canActivateGuards': [], 'canActivateChildGuards': [], 'canMatchGuards': [], 'canDeactivateGuards': [], 'providers': [], 'path': '/redirect-fn', 'pathMatch': undefined, 'isAux': false, 'isLazy': false, 'isActive': false, 'redirectTo': '[Function]', }, { 'component': 'no-name-route', 'canActivateGuards': [], 'canActivateChildGuards': [], 'canMatchGuards': [], 'canDeactivateGuards': [], 'providers': [], 'path': '/redirect-named-fn', 'pathMatch': undefined, 'isAux': false, 'isLazy': false, 'isActive': false, 'redirectTo': 'redirectResolver', }, ], 'isAux': false, 'isLazy': false, 'isActive': true, } as any); }); it('should handle guards with named functions', () => { function canActivateGuard() { return true; } const nestedRouter = { config: [ { path: 'protected', component: 'ProtectedComponent', canActivate: [canActivateGuard], }, ], }; const parsedRoutes = parseRoutes(nestedRouter as any); expect(parsedRoutes.children![0].canActivateGuards).toEqual(['canActivateGuard']); }); it('should handle guards with arrow functions', () => { const arrowGuard = () => true; const nestedRouter = { config: [ { path: 'protected', component: 'ProtectedComponent', canActivate: [arrowGuard], }, ], }; const parsedRoutes = parseRoutes(nestedRouter as any); expect(parsedRoutes.children![0].canActivateGuards).toEqual(['arrowGuard']); }); it('should handle guards with class instances', () => { class AuthGuard { canActivate() { return true; } } const nestedRouter = { config: [ { path: 'protected', component: 'ProtectedComponent', canActivate: [AuthGuard], }, ], }; const parsedRoutes = parseRoutes(nestedRouter as any); expect(parsedRoutes.children![0].canActivateGuards).toEqual(['AuthGuard']); }); it('should handle multiple guard types', () => { function canActivateGuard() { return true; } const canMatchGuard = () => true; class CanDeactivateGuard { canDeactivate() { return true; } } const nestedRouter = { config: [ { path: 'multi-guard', component: 'MultiGuardComponent', canActivate: [ canActivateGuard, function () { return true; }, () => true, ], canMatch: [canMatchGuard], canDeactivate: [CanDeactivateGuard], }, ], }; const parsedRoutes = parseRoutes(nestedRouter as any); expect(parsedRoutes.children![0].canActivateGuards).toEqual([ 'canActivateGuard', '[Function]', '[Function]', ]); expect(parsedRoutes.children![0].canMatchGuards).toEqual(['canMatchGuard']); expect(parsedRoutes.children![0].canDeactivateGuards).toEqual(['CanDeactivateGuard']); }); it('should handle matcher function', () => { function customMatcher() { return null; } const nestedRouter = { config: [ { matcher: customMatcher, component: {name: 'MatcherComponent'}, }, ], }; const parsedRoutes = parseRoutes(nestedRouter as any); expect(parsedRoutes.children![0].matcher).toEqual('customMatcher'); expect(parsedRoutes.children![0].path).toEqual('[Matcher]'); }); it('should handle runGuardsAndResolvers with string values', () => { const nestedRouter = { config: [ { path: 'always', component: {name: 'Component'}, runGuardsAndResolvers: 'always', }, { path: 'params', component: {name: 'Component2'}, runGuardsAndResolvers: 'paramsOrQueryParamsChange', }, ], }; const parsedRoutes = parseRoutes(nestedRouter as any); expect(parsedRoutes.children![0].runGuardsAndResolvers).toEqual('always'); expect(parsedRoutes.children![1].runGuardsAndResolvers).toEqual('paramsOrQueryParamsChange'); }); it('should handle runGuardsAndResolvers with function', () => { function customRerunLogic() { return true; } const nestedRouter = { config: [ { path: 'custom', component: {name: 'Component'}, runGuardsAndResolvers: customRerunLogic, }, ], }; const parsedRoutes = parseRoutes(nestedRouter as any); expect(parsedRoutes.children![0].runGuardsAndResolvers).toEqual('customRerunLogic'); }); it('should handle resolvers with named functions', () => { function userResolver() { return {id: 1, name: 'User'}; } const nestedRouter = { config: [ { path: 'user', component: 'UserComponent', resolve: { user: userResolver, }, }, ], }; const parsedRoutes = parseRoutes(nestedRouter as any); expect(parsedRoutes.children![0].resolvers).toEqual({user: 'userResolver'}); }); it('should handle resolvers with arrow functions', () => { const dataResolver = () => ({data: 'value'}); const nestedRouter = { config: [ { path: 'data', component: 'DataComponent', resolve: { data: dataResolver, }, }, ], }; const parsedRoutes = parseRoutes(nestedRouter as any); expect(parsedRoutes.children![0].resolvers).toEqual({data: 'dataResolver'}); }); it('should handle multiple resolvers on a single route', () => { function userResolver() { return {id: 1}; } const settingsResolver = () => ({theme: 'dark'}); class PermissionsResolver { resolve() { return ['read', 'write']; } } const nestedRouter = { config: [ { path: 'dashboard', component: 'DashboardComponent', resolve: { user: userResolver, settings: settingsResolver, permissions: PermissionsResolver, }, }, ], }; const parsedRoutes = parseRoutes(nestedRouter as any); expect(parsedRoutes.children![0].resolvers).toEqual({ user: 'userResolver', settings: 'settingsResolver', permissions: 'PermissionsResolver', }); }); it('should handle nested routes with resolvers', () => { function parentResolver() { return {parent: 'data'}; } function childResolver() { return {child: 'data'}; } const nestedRouter = { config: [ { path: 'parent', component: 'ParentComponent', resolve: { parentData: parentResolver, }, children: [ { path: 'child', component: 'ChildComponent', resolve: { childData: childResolver, }, }, ], }, ], }; const parsedRoutes = parseRoutes(nestedRouter as any); expect(parsedRoutes.children![0].resolvers).toEqual({parentData: 'parentResolver'}); expect(parsedRoutes.children![0].children![0].resolvers).toEqual({ childData: 'childResolver', }); }); }); describe('getRouterCallableConstructRef', () => { class MockComponent {} class MockService {} function mockResolver() {} function mockTitle() {} function mockRedirectTo() {} function mockMatcher() {} function mockRunGuardsAndResolvers() {} function mockCanActivate() {} function mockCanDeactivate() {} class MockCanActivateChild {} class MockCanMatch {} const MOCK_ROUTES = [ { path: '', providers: [MockService], _loadedRoutes: [ { path: 'foo', component: MockComponent, children: [ { path: 'foo', resolve: { auth: mockResolver, }, }, { path: 'bar', redirectTo: mockRedirectTo as any, _loadedRoutes: [ { path: 'foo', title: mockTitle as any, }, { path: 'bar', runGuardsAndResolvers: mockRunGuardsAndResolvers as any, }, { path: 'baz', canActivate: [mockCanActivate], canActivateChild: [MockCanActivateChild], canDeactivate: [mockCanDeactivate], }, { path: 'qux', canMatch: [MockCanMatch], }, ], }, { path: 'baz', matcher: mockMatcher as any, }, ], }, { path: 'bar', }, ], }, ]; it(`should return null if the callable doesn't exist`, () => { const ref = getRouterCallableConstructRef(MOCK_ROUTES, 'component', 'NonExistent'); expect(ref).toEqual(null); }); it('should return null if there is a callable with the provided name but wrongly typed', () => { const ref = getRouterCallableConstructRef(MOCK_ROUTES, 'providers', 'MockComponent'); expect(ref).toEqual(null); }); it('should find a component class', () => { const ref = getRouterCallableConstructRef(MOCK_ROUTES, 'component', 'MockComponent'); expect(ref).toEqual(MockComponent); }); it('should find a resolver function', () => { const ref = getRouterCallableConstructRef(MOCK_ROUTES, 'resolvers', 'mockResolver'); expect(ref).toEqual(mockResolver); }); it('should find a title function', () => { const ref = getRouterCallableConstructRef(MOCK_ROUTES, 'title', 'mockTitle'); expect(ref).toEqual(mockTitle); }); it('should find a redirectTo function', () => { const ref = getRouterCallableConstructRef(MOCK_ROUTES, 'redirectTo', 'mockRedirectTo'); expect(ref).toEqual(mockRedirectTo); }); it('should find a matcher function', () => { const ref = getRouterCallableConstructRef(MOCK_ROUTES, 'matcher', 'mockMatcher'); expect(ref).toEqual(mockMatcher); }); it('should find a runGuardsAndResolvers function', () => { const ref = getRouterCallableConstructRef( MOCK_ROUTES, 'runGuardsAndResolvers', 'mockRunGuardsAndResolvers', ); expect(ref).toEqual(mockRunGuardsAndResolvers); }); it('should find a canActivate function', () => { const ref = getRouterCallableConstructRef(MOCK_ROUTES, 'canActivate', 'mockCanActivate'); expect(ref).toEqual(mockCanActivate); }); it('should find a canDeactivate function', () => { const ref = getRouterCallableConstructRef(MOCK_ROUTES, 'canDeactivate', 'mockCanDeactivate'); expect(ref).toEqual(mockCanDeactivate); }); it('should find a canActivateChild class', () => { const ref = getRouterCallableConstructRef( MOCK_ROUTES, 'canActivateChild', 'MockCanActivateChild', ); expect(ref).toEqual(MockCanActivateChild); }); it('should find a canMatch class', () => { const ref = getRouterCallableConstructRef(MOCK_ROUTES, 'canMatch', 'MockCanMatch'); expect(ref).toEqual(MockCanMatch); }); });