chore(router): clang-format

This commit is contained in:
vsavkin 2016-06-21 11:49:42 -07:00
parent 92d8bf9619
commit d1f93072a8
10 changed files with 1514 additions and 1419 deletions

View File

@ -1,200 +1,212 @@
import {DefaultUrlSerializer} from '../src/url_serializer';
import {TreeNode} from '../src/utils/tree';
import {UrlTree, UrlSegment, equalPathsWithParams} from '../src/url_tree';
import {RouterConfig} from '../src/config';
import {applyRedirects} from '../src/apply_redirects';
import {RouterConfig} from '../src/config';
import {DefaultUrlSerializer} from '../src/url_serializer';
import {UrlSegment, UrlTree, equalPathsWithParams} from '../src/url_tree';
import {TreeNode} from '../src/utils/tree';
describe('applyRedirects', () => {
it("should return the same url tree when no redirects", () => {
checkRedirect([
{path: 'a', component: ComponentA, children: [{path: 'b', component: ComponentB}]}
], "/a/b", (t:UrlTree) => {
compareTrees(t, tree('/a/b'));
});
it('should return the same url tree when no redirects', () => {
checkRedirect(
[{path: 'a', component: ComponentA, children: [{path: 'b', component: ComponentB}]}],
'/a/b', (t: UrlTree) => { compareTrees(t, tree('/a/b')); });
});
it("should add new segments when needed", () => {
checkRedirect([
{path: 'a/b', redirectTo: 'a/b/c'},
{path: '**', component: ComponentC}
], "/a/b", (t:UrlTree) => {
compareTrees(t, tree('/a/b/c'));
});
it('should add new segments when needed', () => {
checkRedirect(
[{path: 'a/b', redirectTo: 'a/b/c'}, {path: '**', component: ComponentC}], '/a/b',
(t: UrlTree) => { compareTrees(t, tree('/a/b/c')); });
});
it("should handle positional parameters", () => {
checkRedirect([
{path: 'a/:aid/b/:bid', redirectTo: 'newa/:aid/newb/:bid'},
{path: '**', component: ComponentC}
], "/a/1/b/2", (t:UrlTree) => {
compareTrees(t, tree('/newa/1/newb/2'));
});
it('should handle positional parameters', () => {
checkRedirect(
[
{path: 'a/:aid/b/:bid', redirectTo: 'newa/:aid/newb/:bid'},
{path: '**', component: ComponentC}
],
'/a/1/b/2', (t: UrlTree) => { compareTrees(t, tree('/newa/1/newb/2')); });
});
it("should throw when cannot handle a positional parameter", () => {
applyRedirects(tree("/a/1"), [
it('should throw when cannot handle a positional parameter', () => {
applyRedirects(tree('/a/1'), [
{path: 'a/:id', redirectTo: 'a/:other'}
]).subscribe(() => {}, (e) => {
expect(e.message).toEqual("Cannot redirect to 'a/:other'. Cannot find ':other'.");
expect(e.message).toEqual('Cannot redirect to \'a/:other\'. Cannot find \':other\'.');
});
});
it("should pass matrix parameters", () => {
checkRedirect([
{path: 'a/:id', redirectTo: 'd/a/:id/e'},
{path: '**', component: ComponentC}
], "/a;p1=1/1;p2=2", (t:UrlTree) => {
compareTrees(t, tree('/d/a;p1=1/1;p2=2/e'));
});
it('should pass matrix parameters', () => {
checkRedirect(
[{path: 'a/:id', redirectTo: 'd/a/:id/e'}, {path: '**', component: ComponentC}],
'/a;p1=1/1;p2=2', (t: UrlTree) => { compareTrees(t, tree('/d/a;p1=1/1;p2=2/e')); });
});
it("should handle preserve secondary routes", () => {
checkRedirect([
{path: 'a/:id', redirectTo: 'd/a/:id/e'},
{path: 'c/d', component: ComponentA, outlet: 'aux'},
{path: '**', component: ComponentC}
], "/a/1(aux:c/d)", (t:UrlTree) => {
compareTrees(t, tree('/d/a/1/e(aux:c/d)'));
});
it('should handle preserve secondary routes', () => {
checkRedirect(
[
{path: 'a/:id', redirectTo: 'd/a/:id/e'},
{path: 'c/d', component: ComponentA, outlet: 'aux'}, {path: '**', component: ComponentC}
],
'/a/1(aux:c/d)', (t: UrlTree) => { compareTrees(t, tree('/d/a/1/e(aux:c/d)')); });
});
it("should redirect secondary routes", () => {
checkRedirect([
{path: 'a/:id', component: ComponentA},
{path: 'c/d', redirectTo: 'f/c/d/e', outlet: 'aux'},
{path: '**', component: ComponentC, outlet: 'aux'}
], "/a/1(aux:c/d)", (t:UrlTree) => {
compareTrees(t, tree('/a/1(aux:f/c/d/e)'));
});
it('should redirect secondary routes', () => {
checkRedirect(
[
{path: 'a/:id', component: ComponentA},
{path: 'c/d', redirectTo: 'f/c/d/e', outlet: 'aux'},
{path: '**', component: ComponentC, outlet: 'aux'}
],
'/a/1(aux:c/d)', (t: UrlTree) => { compareTrees(t, tree('/a/1(aux:f/c/d/e)')); });
});
it("should use the configuration of the route redirected to", () => {
checkRedirect([
{path: 'a', component: ComponentA, children: [
{path: 'b', component: ComponentB},
]},
{path: 'c', redirectTo: 'a'}
], "c/b", (t:UrlTree) => {
compareTrees(t, tree('a/b'));
});
it('should use the configuration of the route redirected to', () => {
checkRedirect(
[
{
path: 'a',
component: ComponentA,
children: [
{path: 'b', component: ComponentB},
]
},
{path: 'c', redirectTo: 'a'}
],
'c/b', (t: UrlTree) => { compareTrees(t, tree('a/b')); });
});
it("should redirect empty path", () => {
checkRedirect([
{path: 'a', component: ComponentA, children: [
{path: 'b', component: ComponentB},
]},
{path: '', redirectTo: 'a'}
], "b", (t:UrlTree) => {
compareTrees(t, tree('a/b'));
});
it('should redirect empty path', () => {
checkRedirect(
[
{
path: 'a',
component: ComponentA,
children: [
{path: 'b', component: ComponentB},
]
},
{path: '', redirectTo: 'a'}
],
'b', (t: UrlTree) => { compareTrees(t, tree('a/b')); });
});
it("should redirect empty path (global redirect)", () => {
checkRedirect([
{path: 'a', component: ComponentA, children: [
{path: 'b', component: ComponentB},
]},
{path: '', redirectTo: '/a/b'}
], "", (t:UrlTree) => {
compareTrees(t, tree('a/b'));
});
it('should redirect empty path (global redirect)', () => {
checkRedirect(
[
{
path: 'a',
component: ComponentA,
children: [
{path: 'b', component: ComponentB},
]
},
{path: '', redirectTo: '/a/b'}
],
'', (t: UrlTree) => { compareTrees(t, tree('a/b')); });
});
xit("should support nested redirects", () => {
checkRedirect([
{path: 'a', component: ComponentA, children: [
{path: 'b', component: ComponentB},
{path: '', redirectTo: 'b'}
]},
{path: '', redirectTo: 'a'}
], "", (t:UrlTree) => {
compareTrees(t, tree('a/b'));
});
xit('should support nested redirects', () => {
checkRedirect(
[
{
path: 'a',
component: ComponentA,
children: [{path: 'b', component: ComponentB}, {path: '', redirectTo: 'b'}]
},
{path: '', redirectTo: 'a'}
],
'', (t: UrlTree) => { compareTrees(t, tree('a/b')); });
});
xit("should support nested redirects (when redirected to an empty path)", () => {
checkRedirect([
{path: '', component: ComponentA, children: [
{path: 'b', component: ComponentB},
{path: '', redirectTo: 'b'}
]},
{path: 'a', redirectTo: ''}
], "a", (t:UrlTree) => {
compareTrees(t, tree('b'));
});
xit('should support nested redirects (when redirected to an empty path)', () => {
checkRedirect(
[
{
path: '',
component: ComponentA,
children: [{path: 'b', component: ComponentB}, {path: '', redirectTo: 'b'}]
},
{path: 'a', redirectTo: ''}
],
'a', (t: UrlTree) => { compareTrees(t, tree('b')); });
});
xit("should support redirects with both main and aux", () => {
checkRedirect([
{path: 'a', children: [
{path: 'b', component: ComponentB},
{path: '', redirectTo: 'b'},
xit('should support redirects with both main and aux', () => {
checkRedirect(
[
{
path: 'a',
children: [
{path: 'b', component: ComponentB}, {path: '', redirectTo: 'b'},
{path: 'c', component: ComponentC, outlet: 'aux'},
{path: '', redirectTo: 'c', outlet: 'aux'}
]},
{path: 'a', redirectTo: ''}
], "a", (t:UrlTree) => {
compareTrees(t, tree('a/(b//aux:c)'));
});
{path: 'c', component: ComponentC, outlet: 'aux'},
{path: '', redirectTo: 'c', outlet: 'aux'}
]
},
{path: 'a', redirectTo: ''}
],
'a', (t: UrlTree) => { compareTrees(t, tree('a/(b//aux:c)')); });
});
it("should redirect empty path route only when terminal", () => {
it('should redirect empty path route only when terminal', () => {
const config = [
{path: 'a', component: ComponentA, children: [
{path: 'b', component: ComponentB},
]},
{
path: 'a',
component: ComponentA,
children: [
{path: 'b', component: ComponentB},
]
},
{path: '', redirectTo: 'a', terminal: true}
];
applyRedirects(tree("b"), config).subscribe((_) => {
throw "Should not be reached";
}, e => {
expect(e.message).toEqual("Cannot match any routes: 'b'");
});
applyRedirects(tree('b'), config)
.subscribe(
(_) => { throw 'Should not be reached'; },
e => { expect(e.message).toEqual('Cannot match any routes: \'b\''); });
});
it("should redirect wild cards", () => {
checkRedirect([
{path: '404', component: ComponentA},
{path: '**', redirectTo: '/404'},
], "/a/1(aux:c/d)", (t:UrlTree) => {
compareTrees(t, tree('/404'));
});
it('should redirect wild cards', () => {
checkRedirect(
[
{path: '404', component: ComponentA},
{path: '**', redirectTo: '/404'},
],
'/a/1(aux:c/d)', (t: UrlTree) => { compareTrees(t, tree('/404')); });
});
it("should support global redirects", () => {
checkRedirect([
{path: 'a', component: ComponentA, children: [
{path: 'b/:id', redirectTo: '/global/:id'}
]},
{path: '**', component: ComponentC}
], "/a/b/1", (t:UrlTree) => {
compareTrees(t, tree('/global/1'));
});
it('should support global redirects', () => {
checkRedirect(
[
{
path: 'a',
component: ComponentA,
children: [{path: 'b/:id', redirectTo: '/global/:id'}]
},
{path: '**', component: ComponentC}
],
'/a/b/1', (t: UrlTree) => { compareTrees(t, tree('/global/1')); });
});
});
function checkRedirect(config: RouterConfig, url: string, callback: any): void {
applyRedirects(tree(url), config).subscribe(callback, e => {
throw e;
});
applyRedirects(tree(url), config).subscribe(callback, e => { throw e; });
}
function tree(url: string): UrlTree {
return new DefaultUrlSerializer().parse(url);
}
function compareTrees(actual: UrlTree, expected: UrlTree): void{
function compareTrees(actual: UrlTree, expected: UrlTree): void {
const serializer = new DefaultUrlSerializer();
const error = `"${serializer.serialize(actual)}" is not equal to "${serializer.serialize(expected)}"`;
const error =
`"${serializer.serialize(actual)}" is not equal to "${serializer.serialize(expected)}"`;
compareSegments(actual.root, expected.root, error);
}
function compareSegments(actual: UrlSegment, expected: UrlSegment, error: string): void{
function compareSegments(actual: UrlSegment, expected: UrlSegment, error: string): void {
expect(actual).toBeDefined(error);
expect(equalPathsWithParams(actual.pathsWithParams, expected.pathsWithParams)).toEqual(true, error);
expect(equalPathsWithParams(actual.pathsWithParams, expected.pathsWithParams))
.toEqual(true, error);
expect(Object.keys(actual.children).length).toEqual(Object.keys(expected.children).length, error);

View File

@ -1,63 +1,46 @@
import {validateConfig} from '../src/config';
describe('config', () => {
describe("validateConfig", () => {
it("should not throw when no errors", () => {
validateConfig([
{path: '', redirectTo: 'b'},
{path: 'b', component: ComponentA}
]);
describe('validateConfig', () => {
it('should not throw when no errors', () => {
validateConfig([{path: '', redirectTo: 'b'}, {path: 'b', component: ComponentA}]);
});
it("should throw when redirectTo and children are used together", () => {
it('should throw when redirectTo and children are used together', () => {
expect(() => {
validateConfig([
{
path: 'a', redirectTo: 'b', children: [
{path: 'b', component: ComponentA}
]
}
]);
}).toThrowError(`Invalid configuration of route 'a': redirectTo and children cannot be used together`);
validateConfig(
[{path: 'a', redirectTo: 'b', children: [{path: 'b', component: ComponentA}]}]);
})
.toThrowError(
`Invalid configuration of route 'a': redirectTo and children cannot be used together`);
});
it("should throw when component and redirectTo are used together", () => {
expect(() => {
validateConfig([
{path: 'a', component: ComponentA, redirectTo: 'b'}
]);
}).toThrowError(`Invalid configuration of route 'a': redirectTo and component cannot be used together`);
it('should throw when component and redirectTo are used together', () => {
expect(() => { validateConfig([{path: 'a', component: ComponentA, redirectTo: 'b'}]); })
.toThrowError(
`Invalid configuration of route 'a': redirectTo and component cannot be used together`);
});
it("should throw when path is missing", () => {
it('should throw when path is missing', () => {
expect(() => {
validateConfig([
{component: '', redirectTo: 'b'}
]);
validateConfig([{component: '', redirectTo: 'b'}]);
}).toThrowError(`Invalid route configuration: routes must have path specified`);
});
it("should throw when none of component and children or direct are missing", () => {
expect(() => {
validateConfig([
{path: 'a'}
]);
}).toThrowError(`Invalid configuration of route 'a': component, redirectTo, children must be provided`);
it('should throw when none of component and children or direct are missing', () => {
expect(() => { validateConfig([{path: 'a'}]); })
.toThrowError(
`Invalid configuration of route 'a': component, redirectTo, children must be provided`);
});
it("should throw when path starts with a slash", () => {
it('should throw when path starts with a slash', () => {
expect(() => {
validateConfig([
<any>{path: '/a', componenta: '', redirectTo: 'b'}
]);
validateConfig([<any>{path: '/a', componenta: '', redirectTo: 'b'}]);
}).toThrowError(`Invalid route configuration of route '/a': path cannot start with a slash`);
});
});
});
class ComponentA {
}
class ComponentB {
}
class ComponentC {
}
class ComponentA {}
class ComponentB {}
class ComponentC {}

View File

@ -1,21 +1,26 @@
import {DefaultUrlSerializer} from '../src/url_serializer';
import {UrlTree, UrlSegment} from '../src/url_tree';
import {TreeNode} from '../src/utils/tree';
import {Params, PRIMARY_OUTLET} from '../src/shared';
import {ActivatedRoute, RouterState, RouterStateSnapshot, createEmptyState, advanceActivatedRoute} from '../src/router_state';
import {RouterConfig} from '../src/config';
import {createRouterState} from '../src/create_router_state';
import {recognize} from '../src/recognize';
import {RouterConfig} from '../src/config';
import {ActivatedRoute, RouterState, RouterStateSnapshot, advanceActivatedRoute, createEmptyState} from '../src/router_state';
import {PRIMARY_OUTLET, Params} from '../src/shared';
import {DefaultUrlSerializer} from '../src/url_serializer';
import {UrlSegment, UrlTree} from '../src/url_tree';
import {TreeNode} from '../src/utils/tree';
describe('create router state', () => {
const emptyState = () => createEmptyState(new UrlTree(new UrlSegment([], {}), {}, null), RootComponent);
const emptyState = () =>
createEmptyState(new UrlTree(new UrlSegment([], {}), {}, null), RootComponent);
it('should work create new state', () => {
const state = createRouterState(createState([
{path: 'a', component: ComponentA},
{path: 'b', component: ComponentB, outlet: 'left'},
{path: 'c', component: ComponentC, outlet: 'right'}
], "a(left:b//right:c)"), emptyState());
const state = createRouterState(
createState(
[
{path: 'a', component: ComponentA},
{path: 'b', component: ComponentB, outlet: 'left'},
{path: 'c', component: ComponentC, outlet: 'right'}
],
'a(left:b//right:c)'),
emptyState());
checkActivatedRoute(state.root, RootComponent);
@ -27,14 +32,13 @@ describe('create router state', () => {
it('should reuse existing nodes when it can', () => {
const config = [
{path: 'a', component: ComponentA},
{path: 'b', component: ComponentB, outlet: 'left'},
{path: 'a', component: ComponentA}, {path: 'b', component: ComponentB, outlet: 'left'},
{path: 'c', component: ComponentC, outlet: 'left'}
];
const prevState = createRouterState(createState(config, "a(left:b)"), emptyState());
const prevState = createRouterState(createState(config, 'a(left:b)'), emptyState());
advanceState(prevState);
const state = createRouterState(createState(config, "a(left:c)"), prevState);
const state = createRouterState(createState(config, 'a(left:c)'), prevState);
expect(prevState.root).toBe(state.root);
const prevC = prevState.children(prevState.root);
@ -46,17 +50,17 @@ describe('create router state', () => {
});
it('should handle componentless routes', () => {
const config = [
{ path: 'a/:id', children: [
{ path: 'b', component: ComponentA },
{ path: 'c', component: ComponentB, outlet: 'right' }
] }
];
const config = [{
path: 'a/:id',
children: [
{path: 'b', component: ComponentA}, {path: 'c', component: ComponentB, outlet: 'right'}
]
}];
const prevState = createRouterState(createState(config, "a/1;p=11/(b//right:c)"), emptyState());
const prevState = createRouterState(createState(config, 'a/1;p=11/(b//right:c)'), emptyState());
advanceState(prevState);
const state = createRouterState(createState(config, "a/2;p=22/(b//right:c)"), prevState);
const state = createRouterState(createState(config, 'a/2;p=22/(b//right:c)'), prevState);
expect(prevState.root).toBe(state.root);
const prevP = prevState.firstChild(prevState.root);
@ -87,7 +91,8 @@ function createState(config: RouterConfig, url: string): RouterStateSnapshot {
return res;
}
function checkActivatedRoute(actual: ActivatedRoute, cmp: Function, outlet: string = PRIMARY_OUTLET):void {
function checkActivatedRoute(
actual: ActivatedRoute, cmp: Function, outlet: string = PRIMARY_OUTLET): void {
if (actual === null) {
expect(actual).toBeDefined();
} else {

View File

@ -1,182 +1,191 @@
import {DefaultUrlSerializer} from '../src/url_serializer';
import {UrlTree, UrlPathWithParams, UrlSegment} from '../src/url_tree';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import {createUrlTree} from '../src/create_url_tree';
import {ActivatedRoute, ActivatedRouteSnapshot, advanceActivatedRoute} from '../src/router_state';
import {PRIMARY_OUTLET, Params} from '../src/shared';
import {createUrlTree} from '../src/create_url_tree';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import {DefaultUrlSerializer} from '../src/url_serializer';
import {UrlPathWithParams, UrlSegment, UrlTree} from '../src/url_tree';
describe('createUrlTree', () => {
const serializer = new DefaultUrlSerializer();
it("should navigate to the root", () => {
const p = serializer.parse("/");
const t = createRoot(p, ["/"]);
expect(serializer.serialize(t)).toEqual("/");
it('should navigate to the root', () => {
const p = serializer.parse('/');
const t = createRoot(p, ['/']);
expect(serializer.serialize(t)).toEqual('/');
});
it("should support nested segments", () => {
const p = serializer.parse("/a/b");
const t = createRoot(p, ["/one", 11, "two", 22]);
expect(serializer.serialize(t)).toEqual("/one/11/two/22");
it('should support nested segments', () => {
const p = serializer.parse('/a/b');
const t = createRoot(p, ['/one', 11, 'two', 22]);
expect(serializer.serialize(t)).toEqual('/one/11/two/22');
});
it("should stringify positional parameters", () => {
const p = serializer.parse("/a/b");
const t = createRoot(p, ["/one", 11]);
it('should stringify positional parameters', () => {
const p = serializer.parse('/a/b');
const t = createRoot(p, ['/one', 11]);
const params = t.root.children[PRIMARY_OUTLET].pathsWithParams;
expect(params[0].path).toEqual("one");
expect(params[1].path).toEqual("11");
expect(params[0].path).toEqual('one');
expect(params[1].path).toEqual('11');
});
it("should preserve secondary segments", () => {
const p = serializer.parse("/a/11/b(right:c)");
const t = createRoot(p, ["/a", 11, 'd']);
expect(serializer.serialize(t)).toEqual("/a/11/d(right:c)");
it('should preserve secondary segments', () => {
const p = serializer.parse('/a/11/b(right:c)');
const t = createRoot(p, ['/a', 11, 'd']);
expect(serializer.serialize(t)).toEqual('/a/11/d(right:c)');
});
it("should support updating secondary segments", () => {
const p = serializer.parse("/a(right:b)");
const t = createRoot(p, ["right:c", 11, 'd']);
expect(serializer.serialize(t)).toEqual("/a(right:c/11/d)");
it('should support updating secondary segments', () => {
const p = serializer.parse('/a(right:b)');
const t = createRoot(p, ['right:c', 11, 'd']);
expect(serializer.serialize(t)).toEqual('/a(right:c/11/d)');
});
it("should support updating secondary segments (nested case)", () => {
const p = serializer.parse("/a/(b//right:c)");
const t = createRoot(p, ["a", "right:d", 11, 'e']);
expect(serializer.serialize(t)).toEqual("/a/(b//right:d/11/e)");
it('should support updating secondary segments (nested case)', () => {
const p = serializer.parse('/a/(b//right:c)');
const t = createRoot(p, ['a', 'right:d', 11, 'e']);
expect(serializer.serialize(t)).toEqual('/a/(b//right:d/11/e)');
});
it('should update matrix parameters', () => {
const p = serializer.parse("/a;pp=11");
const t = createRoot(p, ["/a", {pp: 22, dd: 33}]);
expect(serializer.serialize(t)).toEqual("/a;pp=22;dd=33");
const p = serializer.parse('/a;pp=11');
const t = createRoot(p, ['/a', {pp: 22, dd: 33}]);
expect(serializer.serialize(t)).toEqual('/a;pp=22;dd=33');
});
it('should create matrix parameters', () => {
const p = serializer.parse("/a");
const t = createRoot(p, ["/a", {pp: 22, dd: 33}]);
expect(serializer.serialize(t)).toEqual("/a;pp=22;dd=33");
const p = serializer.parse('/a');
const t = createRoot(p, ['/a', {pp: 22, dd: 33}]);
expect(serializer.serialize(t)).toEqual('/a;pp=22;dd=33');
});
it('should create matrix parameters together with other segments', () => {
const p = serializer.parse("/a");
const t = createRoot(p, ["/a", "/b", {aa: 22, bb: 33}]);
expect(serializer.serialize(t)).toEqual("/a/b;aa=22;bb=33");
const p = serializer.parse('/a');
const t = createRoot(p, ['/a', '/b', {aa: 22, bb: 33}]);
expect(serializer.serialize(t)).toEqual('/a/b;aa=22;bb=33');
});
describe("relative navigation", () => {
it("should work", () => {
const p = serializer.parse("/a/(c//left:cp)(left:ap)");
const t = create(p.root.children[PRIMARY_OUTLET], 0, p, ["c2"]);
expect(serializer.serialize(t)).toEqual("/a/(c2//left:cp)(left:ap)");
describe('relative navigation', () => {
it('should work', () => {
const p = serializer.parse('/a/(c//left:cp)(left:ap)');
const t = create(p.root.children[PRIMARY_OUTLET], 0, p, ['c2']);
expect(serializer.serialize(t)).toEqual('/a/(c2//left:cp)(left:ap)');
});
it("should work when the first command starts with a ./", () => {
const p = serializer.parse("/a/(c//left:cp)(left:ap)");
const t = create(p.root.children[PRIMARY_OUTLET], 0, p, ["./c2"]);
expect(serializer.serialize(t)).toEqual("/a/(c2//left:cp)(left:ap)");
it('should work when the first command starts with a ./', () => {
const p = serializer.parse('/a/(c//left:cp)(left:ap)');
const t = create(p.root.children[PRIMARY_OUTLET], 0, p, ['./c2']);
expect(serializer.serialize(t)).toEqual('/a/(c2//left:cp)(left:ap)');
});
it("should work when the first command is ./)", () => {
const p = serializer.parse("/a/(c//left:cp)(left:ap)");
const t = create(p.root.children[PRIMARY_OUTLET], 0, p, ["./", "c2"]);
expect(serializer.serialize(t)).toEqual("/a/(c2//left:cp)(left:ap)");
it('should work when the first command is ./)', () => {
const p = serializer.parse('/a/(c//left:cp)(left:ap)');
const t = create(p.root.children[PRIMARY_OUTLET], 0, p, ['./', 'c2']);
expect(serializer.serialize(t)).toEqual('/a/(c2//left:cp)(left:ap)');
});
it("should work when given params", () => {
const p = serializer.parse("/a/(c//left:cp)(left:ap)");
it('should work when given params', () => {
const p = serializer.parse('/a/(c//left:cp)(left:ap)');
const t = create(p.root.children[PRIMARY_OUTLET], 0, p, [{'x': 99}]);
expect(serializer.serialize(t)).toEqual("/a/(c;x=99//left:cp)(left:ap)");
expect(serializer.serialize(t)).toEqual('/a/(c;x=99//left:cp)(left:ap)');
});
it("should work when index > 0", () => {
const p = serializer.parse("/a/c");
const t = create(p.root.children[PRIMARY_OUTLET], 1, p, ["c2"]);
expect(serializer.serialize(t)).toEqual("/a/c/c2");
it('should work when index > 0', () => {
const p = serializer.parse('/a/c');
const t = create(p.root.children[PRIMARY_OUTLET], 1, p, ['c2']);
expect(serializer.serialize(t)).toEqual('/a/c/c2');
});
it("should support going to a parent (within a segment)", () => {
const p = serializer.parse("/a/c");
const t = create(p.root.children[PRIMARY_OUTLET], 1, p, ["../c2"]);
expect(serializer.serialize(t)).toEqual("/a/c2");
it('should support going to a parent (within a segment)', () => {
const p = serializer.parse('/a/c');
const t = create(p.root.children[PRIMARY_OUTLET], 1, p, ['../c2']);
expect(serializer.serialize(t)).toEqual('/a/c2');
});
it("should work when given ../", () => {
const p = serializer.parse("/a/c");
const t = create(p.root.children[PRIMARY_OUTLET], 1, p, ["../", "c2"]);
expect(serializer.serialize(t)).toEqual("/a/c2");
it('should work when given ../', () => {
const p = serializer.parse('/a/c');
const t = create(p.root.children[PRIMARY_OUTLET], 1, p, ['../', 'c2']);
expect(serializer.serialize(t)).toEqual('/a/c2');
});
it("should support setting matrix params", () => {
const p = serializer.parse("/a/(c//left:cp)(left:ap)");
it('should support setting matrix params', () => {
const p = serializer.parse('/a/(c//left:cp)(left:ap)');
const t = create(p.root.children[PRIMARY_OUTLET], 0, p, ['../', {x: 5}]);
expect(serializer.serialize(t)).toEqual("/a;x=5(left:ap)");
expect(serializer.serialize(t)).toEqual('/a;x=5(left:ap)');
});
xit("should support going to a parent (across segments)", () => {
const p = serializer.parse("/q/(a/(c//left:cp)//left:qp)(left:ap)");
xit('should support going to a parent (across segments)', () => {
const p = serializer.parse('/q/(a/(c//left:cp)//left:qp)(left:ap)');
const t = create(p.root.children[PRIMARY_OUTLET].children[PRIMARY_OUTLET], 0, p, ['../../q2']);
expect(serializer.serialize(t)).toEqual("/q2(left:ap)");
const t =
create(p.root.children[PRIMARY_OUTLET].children[PRIMARY_OUTLET], 0, p, ['../../q2']);
expect(serializer.serialize(t)).toEqual('/q2(left:ap)');
});
xit("should navigate to the root", () => {
const p = serializer.parse("/a/c");
xit('should navigate to the root', () => {
const p = serializer.parse('/a/c');
const t = create(p.root.children[PRIMARY_OUTLET], 0, p, ['../']);
expect(serializer.serialize(t)).toEqual("");
expect(serializer.serialize(t)).toEqual('');
});
it("should throw when too many ..", () => {
const p = serializer.parse("/a/(c//left:cp)(left:ap)");
expect(() => create(p.root.children[PRIMARY_OUTLET], 0, p, ['../../'])).toThrowError("Invalid number of '../'");
it('should throw when too many ..', () => {
const p = serializer.parse('/a/(c//left:cp)(left:ap)');
expect(() => create(p.root.children[PRIMARY_OUTLET], 0, p, ['../../']))
.toThrowError('Invalid number of \'../\'');
});
});
it("should set query params", () => {
const p = serializer.parse("/");
it('should set query params', () => {
const p = serializer.parse('/');
const t = createRoot(p, [], {a: 'hey'});
expect(t.queryParams).toEqual({a: 'hey'});
});
it("should stringify query params", () => {
const p = serializer.parse("/");
it('should stringify query params', () => {
const p = serializer.parse('/');
const t = createRoot(p, [], <any>{a: 1});
expect(t.queryParams).toEqual({a: '1'});
});
it("should reuse old query params when given undefined", () => {
const p = serializer.parse("/?a=1");
it('should reuse old query params when given undefined', () => {
const p = serializer.parse('/?a=1');
const t = createRoot(p, [], undefined);
expect(t.queryParams).toEqual({a: '1'});
});
it("should set fragment", () => {
const p = serializer.parse("/");
const t = createRoot(p, [], {}, "fragment");
expect(t.fragment).toEqual("fragment");
it('should set fragment', () => {
const p = serializer.parse('/');
const t = createRoot(p, [], {}, 'fragment');
expect(t.fragment).toEqual('fragment');
});
it("should reused old fragment when given undefined", () => {
const p = serializer.parse("/#fragment");
it('should reused old fragment when given undefined', () => {
const p = serializer.parse('/#fragment');
const t = createRoot(p, [], undefined, undefined);
expect(t.fragment).toEqual("fragment");
expect(t.fragment).toEqual('fragment');
});
});
function createRoot(tree: UrlTree, commands: any[], queryParams?: Params, fragment?: string) {
const s = new ActivatedRouteSnapshot([], <any>{}, PRIMARY_OUTLET, "someComponent", null, tree.root, -1);
const a = new ActivatedRoute(new BehaviorSubject(null), new BehaviorSubject(null), PRIMARY_OUTLET, "someComponent", s);
const s =
new ActivatedRouteSnapshot([], <any>{}, PRIMARY_OUTLET, 'someComponent', null, tree.root, -1);
const a = new ActivatedRoute(
new BehaviorSubject(null), new BehaviorSubject(null), PRIMARY_OUTLET, 'someComponent', s);
advanceActivatedRoute(a);
return createUrlTree(a, tree, commands, queryParams, fragment);
}
function create(segment: UrlSegment, startIndex: number, tree: UrlTree, commands: any[], queryParams?: Params, fragment?: string) {
function create(
segment: UrlSegment, startIndex: number, tree: UrlTree, commands: any[], queryParams?: Params,
fragment?: string) {
if (!segment) {
expect(segment).toBeDefined();
}
const s = new ActivatedRouteSnapshot([], <any>{}, PRIMARY_OUTLET, "someComponent", null, <any>segment, startIndex);
const a = new ActivatedRoute(new BehaviorSubject(null), new BehaviorSubject(null), PRIMARY_OUTLET, "someComponent", s);
const s = new ActivatedRouteSnapshot(
[], <any>{}, PRIMARY_OUTLET, 'someComponent', null, <any>segment, startIndex);
const a = new ActivatedRoute(
new BehaviorSubject(null), new BehaviorSubject(null), PRIMARY_OUTLET, 'someComponent', s);
advanceActivatedRoute(a);
return createUrlTree(a, tree, commands, queryParams, fragment);
}

View File

@ -1,412 +1,433 @@
import {DefaultUrlSerializer} from '../src/url_serializer';
import {UrlTree} from '../src/url_tree';
import {Params, PRIMARY_OUTLET} from '../src/shared';
import {ActivatedRouteSnapshot, RouterStateSnapshot} from '../src/router_state';
import {RouterConfig} from '../src/config';
import {recognize} from '../src/recognize';
import {ActivatedRouteSnapshot, RouterStateSnapshot} from '../src/router_state';
import {PRIMARY_OUTLET, Params} from '../src/shared';
import {DefaultUrlSerializer} from '../src/url_serializer';
import {UrlTree} from '../src/url_tree';
describe('recognize', () => {
it('should work', () => {
checkRecognize([
{
path: 'a', component: ComponentA
}
], "a", (s:RouterStateSnapshot) => {
checkActivatedRoute(s.root, "", {}, RootComponent);
checkActivatedRoute(s.firstChild(s.root), "a", {}, ComponentA);
checkRecognize([{path: 'a', component: ComponentA}], 'a', (s: RouterStateSnapshot) => {
checkActivatedRoute(s.root, '', {}, RootComponent);
checkActivatedRoute(s.firstChild(s.root), 'a', {}, ComponentA);
});
});
it('should support secondary routes', () => {
checkRecognize([
{ path: 'a', component: ComponentA },
{ path: 'b', component: ComponentB, outlet: 'left' },
{ path: 'c', component: ComponentC, outlet: 'right' }
], "a(left:b//right:c)", (s:RouterStateSnapshot) => {
const c = s.children(s.root);
checkActivatedRoute(c[0], "a", {}, ComponentA);
checkActivatedRoute(c[1], "b", {}, ComponentB, 'left');
checkActivatedRoute(c[2], "c", {}, ComponentC, 'right');
});
checkRecognize(
[
{path: 'a', component: ComponentA}, {path: 'b', component: ComponentB, outlet: 'left'},
{path: 'c', component: ComponentC, outlet: 'right'}
],
'a(left:b//right:c)', (s: RouterStateSnapshot) => {
const c = s.children(s.root);
checkActivatedRoute(c[0], 'a', {}, ComponentA);
checkActivatedRoute(c[1], 'b', {}, ComponentB, 'left');
checkActivatedRoute(c[2], 'c', {}, ComponentC, 'right');
});
});
it('should set url segment and index properly', () => {
const url = tree("a(left:b//right:c)");
recognize(RootComponent, [
{ path: 'a', component: ComponentA },
{ path: 'b', component: ComponentB, outlet: 'left' },
{ path: 'c', component: ComponentC, outlet: 'right' }
], url, "a(left:b//right:c)").subscribe((s) => {
expect(s.root._urlSegment).toBe(url.root);
expect(s.root._lastPathIndex).toBe(-1);
const url = tree('a(left:b//right:c)');
recognize(
RootComponent,
[
{path: 'a', component: ComponentA}, {path: 'b', component: ComponentB, outlet: 'left'},
{path: 'c', component: ComponentC, outlet: 'right'}
],
url, 'a(left:b//right:c)')
.subscribe((s) => {
expect(s.root._urlSegment).toBe(url.root);
expect(s.root._lastPathIndex).toBe(-1);
const c = s.children(s.root);
expect(c[0]._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]);
expect(c[0]._lastPathIndex).toBe(0);
const c = s.children(s.root);
expect(c[0]._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]);
expect(c[0]._lastPathIndex).toBe(0);
expect(c[1]._urlSegment).toBe(url.root.children["left"]);
expect(c[1]._lastPathIndex).toBe(0);
expect(c[1]._urlSegment).toBe(url.root.children['left']);
expect(c[1]._lastPathIndex).toBe(0);
expect(c[2]._urlSegment).toBe(url.root.children["right"]);
expect(c[2]._lastPathIndex).toBe(0);
});
expect(c[2]._urlSegment).toBe(url.root.children['right']);
expect(c[2]._lastPathIndex).toBe(0);
});
});
it('should set url segment and index properly (nested case)', () => {
const url = tree("a/b/c");
recognize(RootComponent, [
{ path: 'a/b', component: ComponentA, children: [
{path: 'c', component: ComponentC}
] },
], url, "a/b/c").subscribe((s:RouterStateSnapshot) => {
expect(s.root._urlSegment).toBe(url.root);
expect(s.root._lastPathIndex).toBe(-1);
const url = tree('a/b/c');
recognize(
RootComponent,
[
{path: 'a/b', component: ComponentA, children: [{path: 'c', component: ComponentC}]},
],
url, 'a/b/c')
.subscribe((s: RouterStateSnapshot) => {
expect(s.root._urlSegment).toBe(url.root);
expect(s.root._lastPathIndex).toBe(-1);
const compA = s.firstChild(s.root);
expect(compA._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]);
expect(compA._lastPathIndex).toBe(1);
const compA = s.firstChild(s.root);
expect(compA._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]);
expect(compA._lastPathIndex).toBe(1);
const compC = s.firstChild(<any>compA);
expect(compC._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]);
expect(compC._lastPathIndex).toBe(2);
});
const compC = s.firstChild(<any>compA);
expect(compC._urlSegment).toBe(url.root.children[PRIMARY_OUTLET]);
expect(compC._lastPathIndex).toBe(2);
});
});
it('should match routes in the depth first order', () => {
checkRecognize([
{path: 'a', component: ComponentA, children: [{path: ':id', component: ComponentB}]},
{path: 'a/:id', component: ComponentC}
], "a/paramA", (s:RouterStateSnapshot) => {
checkActivatedRoute(s.root, "", {}, RootComponent);
checkActivatedRoute(s.firstChild(s.root), "a", {}, ComponentA);
checkActivatedRoute(s.firstChild(<any>s.firstChild(s.root)), "paramA", {id: 'paramA'}, ComponentB);
});
checkRecognize(
[
{path: 'a', component: ComponentA, children: [{path: ':id', component: ComponentB}]},
{path: 'a/:id', component: ComponentC}
],
'a/paramA', (s: RouterStateSnapshot) => {
checkActivatedRoute(s.root, '', {}, RootComponent);
checkActivatedRoute(s.firstChild(s.root), 'a', {}, ComponentA);
checkActivatedRoute(
s.firstChild(<any>s.firstChild(s.root)), 'paramA', {id: 'paramA'}, ComponentB);
});
checkRecognize([
{path: 'a', component: ComponentA},
{path: 'a/:id', component: ComponentC}
], "a/paramA", (s:RouterStateSnapshot) => {
checkActivatedRoute(s.root, "", {}, RootComponent);
checkActivatedRoute(s.firstChild(s.root), "a/paramA", {id: 'paramA'}, ComponentC);
});
checkRecognize(
[{path: 'a', component: ComponentA}, {path: 'a/:id', component: ComponentC}], 'a/paramA',
(s: RouterStateSnapshot) => {
checkActivatedRoute(s.root, '', {}, RootComponent);
checkActivatedRoute(s.firstChild(s.root), 'a/paramA', {id: 'paramA'}, ComponentC);
});
});
it('should use outlet name when matching secondary routes', () => {
checkRecognize([
{ path: 'a', component: ComponentA },
{ path: 'b', component: ComponentB, outlet: 'left' },
{ path: 'b', component: ComponentC, outlet: 'right' }
], "a(right:b)", (s:RouterStateSnapshot) => {
const c = s.children(s.root);
checkActivatedRoute(c[0], "a", {}, ComponentA);
checkActivatedRoute(c[1], "b", {}, ComponentC, 'right');
});
checkRecognize(
[
{path: 'a', component: ComponentA}, {path: 'b', component: ComponentB, outlet: 'left'},
{path: 'b', component: ComponentC, outlet: 'right'}
],
'a(right:b)', (s: RouterStateSnapshot) => {
const c = s.children(s.root);
checkActivatedRoute(c[0], 'a', {}, ComponentA);
checkActivatedRoute(c[1], 'b', {}, ComponentC, 'right');
});
});
xit('should handle nested secondary routes', () => {
checkRecognize([
{ path: 'a', component: ComponentA },
{ path: 'b', component: ComponentB, outlet: 'left' },
{ path: 'c', component: ComponentC, outlet: 'right' }
], "a(left:b(right:c))", (s:RouterStateSnapshot) => {
const c = s.children(s.root);
checkActivatedRoute(c[0], "a", {}, ComponentA);
checkActivatedRoute(c[1], "b", {}, ComponentB, 'left');
checkActivatedRoute(c[2], "c", {}, ComponentC, 'right');
});
checkRecognize(
[
{path: 'a', component: ComponentA}, {path: 'b', component: ComponentB, outlet: 'left'},
{path: 'c', component: ComponentC, outlet: 'right'}
],
'a(left:b(right:c))', (s: RouterStateSnapshot) => {
const c = s.children(s.root);
checkActivatedRoute(c[0], 'a', {}, ComponentA);
checkActivatedRoute(c[1], 'b', {}, ComponentB, 'left');
checkActivatedRoute(c[2], 'c', {}, ComponentC, 'right');
});
});
it('should handle non top-level secondary routes', () => {
checkRecognize([
{ path: 'a', component: ComponentA, children: [
{ path: 'b', component: ComponentB },
{ path: 'c', component: ComponentC, outlet: 'left' }
] },
], "a/(b//left:c)", (s:RouterStateSnapshot) => {
const c = s.children(<any>s.firstChild(s.root));
checkActivatedRoute(c[0], "b", {}, ComponentB, PRIMARY_OUTLET);
checkActivatedRoute(c[1], "c", {}, ComponentC, 'left');
});
checkRecognize(
[
{
path: 'a',
component: ComponentA,
children: [
{path: 'b', component: ComponentB},
{path: 'c', component: ComponentC, outlet: 'left'}
]
},
],
'a/(b//left:c)', (s: RouterStateSnapshot) => {
const c = s.children(<any>s.firstChild(s.root));
checkActivatedRoute(c[0], 'b', {}, ComponentB, PRIMARY_OUTLET);
checkActivatedRoute(c[1], 'c', {}, ComponentC, 'left');
});
});
it('should sort routes by outlet name', () => {
checkRecognize([
{ path: 'a', component: ComponentA },
{ path: 'c', component: ComponentC, outlet: 'c' },
{ path: 'b', component: ComponentB, outlet: 'b' }
], "a(c:c//b:b)", (s:RouterStateSnapshot) => {
const c = s.children(s.root);
checkActivatedRoute(c[0], "a", {}, ComponentA);
checkActivatedRoute(c[1], "b", {}, ComponentB, 'b');
checkActivatedRoute(c[2], "c", {}, ComponentC, 'c');
});
checkRecognize(
[
{path: 'a', component: ComponentA}, {path: 'c', component: ComponentC, outlet: 'c'},
{path: 'b', component: ComponentB, outlet: 'b'}
],
'a(c:c//b:b)', (s: RouterStateSnapshot) => {
const c = s.children(s.root);
checkActivatedRoute(c[0], 'a', {}, ComponentA);
checkActivatedRoute(c[1], 'b', {}, ComponentB, 'b');
checkActivatedRoute(c[2], 'c', {}, ComponentC, 'c');
});
});
it('should support matrix parameters', () => {
checkRecognize([
{
path: 'a', component: ComponentA, children: [
{ path: 'b', component: ComponentB }
]
},
{ path: 'c', component: ComponentC, outlet: 'left' }
], "a;a1=11;a2=22/b;b1=111;b2=222(left:c;c1=1111;c2=2222)", (s:RouterStateSnapshot) => {
const c = s.children(s.root);
checkActivatedRoute(c[0], "a", {a1: '11', a2: '22'}, ComponentA);
checkActivatedRoute(s.firstChild(<any>c[0]), "b", {b1: '111', b2: '222'}, ComponentB);
checkActivatedRoute(c[1], "c", {c1: '1111', c2: '2222'}, ComponentC, 'left');
});
checkRecognize(
[
{path: 'a', component: ComponentA, children: [{path: 'b', component: ComponentB}]},
{path: 'c', component: ComponentC, outlet: 'left'}
],
'a;a1=11;a2=22/b;b1=111;b2=222(left:c;c1=1111;c2=2222)', (s: RouterStateSnapshot) => {
const c = s.children(s.root);
checkActivatedRoute(c[0], 'a', {a1: '11', a2: '22'}, ComponentA);
checkActivatedRoute(s.firstChild(<any>c[0]), 'b', {b1: '111', b2: '222'}, ComponentB);
checkActivatedRoute(c[1], 'c', {c1: '1111', c2: '2222'}, ComponentC, 'left');
});
});
describe("matching empty url", () => {
it("should support root index routes", () => {
recognize(RootComponent, [
{path: '', component: ComponentA}
], tree(""), "").forEach((s:RouterStateSnapshot) => {
checkActivatedRoute(s.firstChild(s.root), "", {}, ComponentA);
});
describe('matching empty url', () => {
it('should support root index routes', () => {
recognize(RootComponent, [{path: '', component: ComponentA}], tree(''), '')
.forEach((s: RouterStateSnapshot) => {
checkActivatedRoute(s.firstChild(s.root), '', {}, ComponentA);
});
});
it("should support nested root index routes", () => {
recognize(RootComponent, [
{path: '', component: ComponentA, children: [{path: '', component: ComponentB}]}
], tree(""), "").forEach((s:RouterStateSnapshot) => {
checkActivatedRoute(s.firstChild(s.root), "", {}, ComponentA);
checkActivatedRoute(s.firstChild(<any>s.firstChild(s.root)), "", {}, ComponentB);
});
it('should support nested root index routes', () => {
recognize(
RootComponent,
[{path: '', component: ComponentA, children: [{path: '', component: ComponentB}]}],
tree(''), '')
.forEach((s: RouterStateSnapshot) => {
checkActivatedRoute(s.firstChild(s.root), '', {}, ComponentA);
checkActivatedRoute(s.firstChild(<any>s.firstChild(s.root)), '', {}, ComponentB);
});
});
it('should set url segment and index properly', () => {
const url = tree("");
recognize(RootComponent, [
{path: '', component: ComponentA, children: [{path: '', component: ComponentB}]}
], url, "").forEach((s:RouterStateSnapshot) => {
expect(s.root._urlSegment).toBe(url.root);
expect(s.root._lastPathIndex).toBe(-1);
const url = tree('');
recognize(
RootComponent,
[{path: '', component: ComponentA, children: [{path: '', component: ComponentB}]}], url,
'')
.forEach((s: RouterStateSnapshot) => {
expect(s.root._urlSegment).toBe(url.root);
expect(s.root._lastPathIndex).toBe(-1);
const c = s.firstChild(s.root);
expect(c._urlSegment).toBe(url.root);
expect(c._lastPathIndex).toBe(-1);
const c = s.firstChild(s.root);
expect(c._urlSegment).toBe(url.root);
expect(c._lastPathIndex).toBe(-1);
const c2 = s.firstChild(<any>s.firstChild(s.root));
expect(c2._urlSegment).toBe(url.root);
expect(c2._lastPathIndex).toBe(-1);
});
const c2 = s.firstChild(<any>s.firstChild(s.root));
expect(c2._urlSegment).toBe(url.root);
expect(c2._lastPathIndex).toBe(-1);
});
});
it("should support index routes", () => {
recognize(RootComponent, [
{path: 'a', component: ComponentA, children: [
{path: '', component: ComponentB}
]}
], tree("a"), "a").forEach((s:RouterStateSnapshot) => {
checkActivatedRoute(s.firstChild(s.root), "a", {}, ComponentA);
checkActivatedRoute(s.firstChild(<any>s.firstChild(s.root)), "", {}, ComponentB);
});
it('should support index routes', () => {
recognize(
RootComponent,
[{path: 'a', component: ComponentA, children: [{path: '', component: ComponentB}]}],
tree('a'), 'a')
.forEach((s: RouterStateSnapshot) => {
checkActivatedRoute(s.firstChild(s.root), 'a', {}, ComponentA);
checkActivatedRoute(s.firstChild(<any>s.firstChild(s.root)), '', {}, ComponentB);
});
});
it("should support index routes with children", () => {
recognize(RootComponent, [
{
path: '', component: ComponentA, children: [
{ path: '', component: ComponentB, children: [
{path: 'c/:id', component: ComponentC}
]
}
]
}
], tree("c/10"), "c/10").forEach((s:RouterStateSnapshot) => {
checkActivatedRoute(s.firstChild(s.root), "", {}, ComponentA);
checkActivatedRoute(s.firstChild(<any>s.firstChild(s.root)), "", {}, ComponentB);
checkActivatedRoute(
s.firstChild(<any>s.firstChild(<any>s.firstChild(s.root))), "c/10", {id: '10'}, ComponentC);
});
it('should support index routes with children', () => {
recognize(
RootComponent, [{
path: '',
component: ComponentA,
children: [{
path: '',
component: ComponentB,
children: [{path: 'c/:id', component: ComponentC}]
}]
}],
tree('c/10'), 'c/10')
.forEach((s: RouterStateSnapshot) => {
checkActivatedRoute(s.firstChild(s.root), '', {}, ComponentA);
checkActivatedRoute(s.firstChild(<any>s.firstChild(s.root)), '', {}, ComponentB);
checkActivatedRoute(
s.firstChild(<any>s.firstChild(<any>s.firstChild(s.root))), 'c/10', {id: '10'},
ComponentC);
});
});
xit("should pass parameters to every nested index route (case with non-index route)", () => {
recognize(RootComponent, [
{path: 'a', component: ComponentA, children: [{path: '', component: ComponentB}]}
], tree("/a;a=1"), "/a;a=1").forEach((s:RouterStateSnapshot) => {
checkActivatedRoute(s.firstChild(s.root), "a", {a: '1'}, ComponentA);
checkActivatedRoute(s.firstChild(<any>s.firstChild(s.root)), "", {a: '1'}, ComponentB);
});
xit('should pass parameters to every nested index route (case with non-index route)', () => {
recognize(
RootComponent,
[{path: 'a', component: ComponentA, children: [{path: '', component: ComponentB}]}],
tree('/a;a=1'), '/a;a=1')
.forEach((s: RouterStateSnapshot) => {
checkActivatedRoute(s.firstChild(s.root), 'a', {a: '1'}, ComponentA);
checkActivatedRoute(s.firstChild(<any>s.firstChild(s.root)), '', {a: '1'}, ComponentB);
});
});
});
describe("wildcards", () => {
it("should support simple wildcards", () => {
checkRecognize([
{path: '**', component: ComponentA}
], "a/b/c/d;a1=11", (s:RouterStateSnapshot) => {
checkActivatedRoute(s.firstChild(s.root), "a/b/c/d", {a1:'11'}, ComponentA);
});
describe('wildcards', () => {
it('should support simple wildcards', () => {
checkRecognize(
[{path: '**', component: ComponentA}], 'a/b/c/d;a1=11', (s: RouterStateSnapshot) => {
checkActivatedRoute(s.firstChild(s.root), 'a/b/c/d', {a1: '11'}, ComponentA);
});
});
});
describe("componentless routes", () => {
it("should work", () => {
checkRecognize([
{
path: 'p/:id',
children: [
{path: 'a', component: ComponentA},
{path: 'b', component: ComponentB, outlet: 'aux'}
]
}
], "p/11;pp=22/(a;pa=33//aux:b;pb=44)", (s:RouterStateSnapshot) => {
const p = s.firstChild(s.root);
checkActivatedRoute(p, "p/11", {id: '11', pp: '22'}, undefined);
describe('componentless routes', () => {
it('should work', () => {
checkRecognize(
[{
path: 'p/:id',
children: [
{path: 'a', component: ComponentA},
{path: 'b', component: ComponentB, outlet: 'aux'}
]
}],
'p/11;pp=22/(a;pa=33//aux:b;pb=44)', (s: RouterStateSnapshot) => {
const p = s.firstChild(s.root);
checkActivatedRoute(p, 'p/11', {id: '11', pp: '22'}, undefined);
const c = s.children(p);
checkActivatedRoute(c[0], "a", {id: '11', pp: '22', pa: '33'}, ComponentA);
checkActivatedRoute(c[1], "b", {id: '11', pp: '22', pb: '44'}, ComponentB, "aux");
});
const c = s.children(p);
checkActivatedRoute(c[0], 'a', {id: '11', pp: '22', pa: '33'}, ComponentA);
checkActivatedRoute(c[1], 'b', {id: '11', pp: '22', pb: '44'}, ComponentB, 'aux');
});
});
it("should merge params until encounters a normal route", () => {
checkRecognize([
{
path: 'p/:id',
children: [
{path: 'a/:name', children: [
{path: 'b', component: ComponentB, children: [
{path: 'c', component: ComponentC}
]}
]}
]
}
], "p/11/a/victor/b/c", (s:RouterStateSnapshot) => {
const p = s.firstChild(s.root);
checkActivatedRoute(p, "p/11", {id: '11'}, undefined);
it('should merge params until encounters a normal route', () => {
checkRecognize(
[{
path: 'p/:id',
children: [{
path: 'a/:name',
children: [{
path: 'b',
component: ComponentB,
children: [{path: 'c', component: ComponentC}]
}]
}]
}],
'p/11/a/victor/b/c', (s: RouterStateSnapshot) => {
const p = s.firstChild(s.root);
checkActivatedRoute(p, 'p/11', {id: '11'}, undefined);
const a = s.firstChild(p);
checkActivatedRoute(a, "a/victor", {id: '11', name: 'victor'}, undefined);
const a = s.firstChild(p);
checkActivatedRoute(a, 'a/victor', {id: '11', name: 'victor'}, undefined);
const b = s.firstChild(a);
checkActivatedRoute(b, "b", {id: '11', name: 'victor'}, ComponentB);
const b = s.firstChild(a);
checkActivatedRoute(b, 'b', {id: '11', name: 'victor'}, ComponentB);
const c = s.firstChild(b);
checkActivatedRoute(c, "c", {}, ComponentC);
});
const c = s.firstChild(b);
checkActivatedRoute(c, 'c', {}, ComponentC);
});
});
xit("should work with empty paths", () => {
checkRecognize([
{
path: 'p/:id',
children: [
{path: '', component: ComponentA},
{path: '', component: ComponentB, outlet: 'aux'}
]
}
], "p/11", (s:RouterStateSnapshot) => {
const p = s.firstChild(s.root);
checkActivatedRoute(p, "p/11", {id: '11'}, undefined);
xit('should work with empty paths', () => {
checkRecognize(
[{
path: 'p/:id',
children: [
{path: '', component: ComponentA},
{path: '', component: ComponentB, outlet: 'aux'}
]
}],
'p/11', (s: RouterStateSnapshot) => {
const p = s.firstChild(s.root);
checkActivatedRoute(p, 'p/11', {id: '11'}, undefined);
const c = s.children(p);
console.log("lsfs", c);
checkActivatedRoute(c[0], "", {}, ComponentA);
checkActivatedRoute(c[1], "", {}, ComponentB, "aux");
});
const c = s.children(p);
console.log('lsfs', c);
checkActivatedRoute(c[0], '', {}, ComponentA);
checkActivatedRoute(c[1], '', {}, ComponentB, 'aux');
});
});
xit("should work with empty paths and params", () => {
checkRecognize([
{
path: 'p/:id',
children: [
{path: '', component: ComponentA},
{path: '', component: ComponentB, outlet: 'aux'}
]
}
], "p/11/(;pa=33//aux:;pb=44)", (s:RouterStateSnapshot) => {
const p = s.firstChild(s.root);
checkActivatedRoute(p, "p/11", {id: '11'}, undefined);
xit('should work with empty paths and params', () => {
checkRecognize(
[{
path: 'p/:id',
children: [
{path: '', component: ComponentA},
{path: '', component: ComponentB, outlet: 'aux'}
]
}],
'p/11/(;pa=33//aux:;pb=44)', (s: RouterStateSnapshot) => {
const p = s.firstChild(s.root);
checkActivatedRoute(p, 'p/11', {id: '11'}, undefined);
const c = s.children(p);
checkActivatedRoute(c[0], "", {pa: '33'}, ComponentA);
checkActivatedRoute(c[1], "", {pb: '44'}, ComponentB, "aux");
});
const c = s.children(p);
checkActivatedRoute(c[0], '', {pa: '33'}, ComponentA);
checkActivatedRoute(c[1], '', {pb: '44'}, ComponentB, 'aux');
});
});
xit("should work with only aux path", () => {
checkRecognize([
{
path: 'p/:id',
children: [
{path: '', component: ComponentA},
{path: '', component: ComponentB, outlet: 'aux'}
]
}
], "p/11", (s:RouterStateSnapshot) => {
const p = s.firstChild(s.root);
checkActivatedRoute(p, "p/11(aux:;pb=44)", {id: '11'}, undefined);
xit('should work with only aux path', () => {
checkRecognize(
[{
path: 'p/:id',
children: [
{path: '', component: ComponentA},
{path: '', component: ComponentB, outlet: 'aux'}
]
}],
'p/11', (s: RouterStateSnapshot) => {
const p = s.firstChild(s.root);
checkActivatedRoute(p, 'p/11(aux:;pb=44)', {id: '11'}, undefined);
const c = s.children(p);
checkActivatedRoute(c[0], "", {}, ComponentA);
checkActivatedRoute(c[1], "", {pb: '44'}, ComponentB, "aux");
});
const c = s.children(p);
checkActivatedRoute(c[0], '', {}, ComponentA);
checkActivatedRoute(c[1], '', {pb: '44'}, ComponentB, 'aux');
});
});
});
describe("query parameters", () => {
it("should support query params", () => {
describe('query parameters', () => {
it('should support query params', () => {
const config = [{path: 'a', component: ComponentA}];
checkRecognize(config, "a?q=11", (s:RouterStateSnapshot) => {
checkRecognize(config, 'a?q=11', (s: RouterStateSnapshot) => {
expect(s.queryParams).toEqual({q: '11'});
});
});
});
describe("fragment", () => {
it("should support fragment", () => {
describe('fragment', () => {
it('should support fragment', () => {
const config = [{path: 'a', component: ComponentA}];
checkRecognize(config, "a#f1", (s:RouterStateSnapshot) => {
expect(s.fragment).toEqual("f1");
});
checkRecognize(
config, 'a#f1', (s: RouterStateSnapshot) => { expect(s.fragment).toEqual('f1'); });
});
});
describe("error handling", () => {
describe('error handling', () => {
it('should error when two routes with the same outlet name got matched', () => {
recognize(RootComponent, [
{ path: 'a', component: ComponentA },
{ path: 'b', component: ComponentB, outlet: 'aux' },
{ path: 'c', component: ComponentC, outlet: 'aux' }
], tree("a(aux:b//aux:c)"), "a(aux:b//aux:c)").subscribe((_) => {}, (s:RouterStateSnapshot) => {
expect(s.toString()).toContain("Two segments cannot have the same outlet name: 'aux:b' and 'aux:c'.");
});
recognize(
RootComponent,
[
{path: 'a', component: ComponentA}, {path: 'b', component: ComponentB, outlet: 'aux'},
{path: 'c', component: ComponentC, outlet: 'aux'}
],
tree('a(aux:b//aux:c)'), 'a(aux:b//aux:c)')
.subscribe((_) => {}, (s: RouterStateSnapshot) => {
expect(s.toString())
.toContain(
'Two segments cannot have the same outlet name: \'aux:b\' and \'aux:c\'.');
});
});
it("should error when no matching routes", () => {
recognize(RootComponent, [
{ path: 'a', component: ComponentA }
], tree("invalid"), "invalid").subscribe((_) => {}, (s:RouterStateSnapshot) => {
expect(s.toString()).toContain("Cannot match any routes");
});
it('should error when no matching routes', () => {
recognize(RootComponent, [{path: 'a', component: ComponentA}], tree('invalid'), 'invalid')
.subscribe((_) => {}, (s: RouterStateSnapshot) => {
expect(s.toString()).toContain('Cannot match any routes');
});
});
it("should error when no matching routes (too short)", () => {
recognize(RootComponent, [
{ path: 'a/:id', component: ComponentA }
], tree("a"), "a").subscribe((_) => {}, (s:RouterStateSnapshot) => {
expect(s.toString()).toContain("Cannot match any routes");
});
it('should error when no matching routes (too short)', () => {
recognize(RootComponent, [{path: 'a/:id', component: ComponentA}], tree('a'), 'a')
.subscribe((_) => {}, (s: RouterStateSnapshot) => {
expect(s.toString()).toContain('Cannot match any routes');
});
});
});
});
function checkRecognize(config: RouterConfig, url: string, callback: any): void {
recognize(RootComponent, config, tree(url), url).subscribe(callback, e => {
throw e;
});
recognize(RootComponent, config, tree(url), url).subscribe(callback, e => { throw e; });
}
function checkActivatedRoute(actual: ActivatedRouteSnapshot, url: string, params: Params, cmp: Function, outlet: string = PRIMARY_OUTLET):void {
function checkActivatedRoute(
actual: ActivatedRouteSnapshot, url: string, params: Params, cmp: Function,
outlet: string = PRIMARY_OUTLET): void {
if (actual === null) {
expect(actual).not.toBeNull();
} else {
expect(actual.url.map(s => s.path).join("/")).toEqual(url);
expect(actual.url.map(s => s.path).join('/')).toEqual(url);
expect(actual.params).toEqual(params);
expect(actual.component).toBe(cmp);
expect(actual.outlet).toEqual(outlet);

View File

@ -1,42 +1,42 @@
import {DefaultUrlSerializer} from '../src/url_serializer';
import {UrlTree, UrlSegment} from '../src/url_tree';
import {RouterStateSnapshot} from '../src/router_state';
import {RouterConfig} from '../src/config';
import {recognize} from '../src/recognize';
import {resolve} from '../src/resolve';
import {RouterConfig} from '../src/config';
import {RouterStateSnapshot} from '../src/router_state';
import {DefaultUrlSerializer} from '../src/url_serializer';
import {UrlSegment, UrlTree} from '../src/url_tree';
describe('resolve', () => {
it('should resolve components', () => {
checkResolve([
{path: 'a', component: "ComponentA"}
], "a", {ComponentA: 'ResolvedComponentA'}, (resolved:RouterStateSnapshot) => {
expect(resolved.firstChild(resolved.root)._resolvedComponentFactory).toEqual('ResolvedComponentA');
});
checkResolve(
[{path: 'a', component: 'ComponentA'}], 'a', {ComponentA: 'ResolvedComponentA'},
(resolved: RouterStateSnapshot) => {
expect(resolved.firstChild(resolved.root)._resolvedComponentFactory)
.toEqual('ResolvedComponentA');
});
});
it('should not resolve componentless routes', () => {
checkResolve([
{path: 'a', children: []}
], "a", {}, (resolved:RouterStateSnapshot) => {
checkResolve([{path: 'a', children: []}], 'a', {}, (resolved: RouterStateSnapshot) => {
expect(resolved.firstChild(resolved.root)._resolvedComponentFactory).toEqual(null);
});
});
});
function checkResolve(config: RouterConfig, url: string, resolved: {[k:string]:string}, callback: any): void {
function checkResolve(
config: RouterConfig, url: string, resolved: {[k: string]: string}, callback: any): void {
const resolver = {
resolveComponent: (component:string):Promise<any> => {
resolveComponent: (component: string): Promise<any> => {
if (resolved[component]) {
return Promise.resolve(resolved[component]);
} else {
return Promise.reject("unknown component");
return Promise.reject('unknown component');
}
}
};
recognize(RootComponent, config, tree(url), url).mergeMap(s => resolve(<any>resolver, s)).subscribe(callback, e => {
throw e;
});
recognize(RootComponent, config, tree(url), url)
.mergeMap(s => resolve(<any>resolver, s))
.subscribe(callback, e => { throw e; });
}
function tree(url: string): UrlTree {

File diff suppressed because it is too large Load Diff

View File

@ -1,38 +1,38 @@
import {PRIMARY_OUTLET} from '../src/shared';
import {DefaultUrlSerializer, serializePath} from '../src/url_serializer';
import {UrlSegment} from '../src/url_tree';
import {PRIMARY_OUTLET} from '../src/shared';
describe('url serializer', () => {
const url = new DefaultUrlSerializer();
it('should parse the root url', () => {
const tree = url.parse("/");
expectSegment(tree.root, "");
expect(url.serialize(tree)).toEqual("/");
const tree = url.parse('/');
expectSegment(tree.root, '');
expect(url.serialize(tree)).toEqual('/');
});
it('should parse non-empty urls', () => {
const tree = url.parse("one/two");
expectSegment(tree.root.children[PRIMARY_OUTLET], "one/two");
expect(url.serialize(tree)).toEqual("/one/two");
const tree = url.parse('one/two');
expectSegment(tree.root.children[PRIMARY_OUTLET], 'one/two');
expect(url.serialize(tree)).toEqual('/one/two');
});
it("should parse multiple secondary segments", () => {
const tree = url.parse("/one/two(left:three//right:four)");
it('should parse multiple secondary segments', () => {
const tree = url.parse('/one/two(left:three//right:four)');
expectSegment(tree.root.children[PRIMARY_OUTLET], "one/two");
expectSegment(tree.root.children['left'], "three");
expectSegment(tree.root.children['right'], "four");
expectSegment(tree.root.children[PRIMARY_OUTLET], 'one/two');
expectSegment(tree.root.children['left'], 'three');
expectSegment(tree.root.children['right'], 'four');
expect(url.serialize(tree)).toEqual("/one/two(left:three//right:four)");
expect(url.serialize(tree)).toEqual('/one/two(left:three//right:four)');
});
it("should parse segments with empty paths", () => {
const tree = url.parse("/one/two/(;a=1//right:;b=2)");
it('should parse segments with empty paths', () => {
const tree = url.parse('/one/two/(;a=1//right:;b=2)');
const c = tree.root.children[PRIMARY_OUTLET];
expectSegment(tree.root.children[PRIMARY_OUTLET], "one/two", true);
expectSegment(tree.root.children[PRIMARY_OUTLET], 'one/two', true);
expect(c.children[PRIMARY_OUTLET].pathsWithParams[0].path).toEqual('');
expect(c.children[PRIMARY_OUTLET].pathsWithParams[0].parameters).toEqual({a: '1'});
@ -40,115 +40,115 @@ describe('url serializer', () => {
expect(c.children['right'].pathsWithParams[0].path).toEqual('');
expect(c.children['right'].pathsWithParams[0].parameters).toEqual({b: '2'});
expect(url.serialize(tree)).toEqual("/one/two/(;a=1//right:;b=2)");
expect(url.serialize(tree)).toEqual('/one/two/(;a=1//right:;b=2)');
});
it("should parse segments with empty paths (only aux)", () => {
const tree = url.parse("/one/two/(right:;b=2)");
it('should parse segments with empty paths (only aux)', () => {
const tree = url.parse('/one/two/(right:;b=2)');
const c = tree.root.children[PRIMARY_OUTLET];
expectSegment(tree.root.children[PRIMARY_OUTLET], "one/two", true);
expectSegment(tree.root.children[PRIMARY_OUTLET], 'one/two', true);
expect(c.children['right'].pathsWithParams[0].path).toEqual('');
expect(c.children['right'].pathsWithParams[0].parameters).toEqual({b: '2'});
expect(url.serialize(tree)).toEqual("/one/two/(right:;b=2)");
expect(url.serialize(tree)).toEqual('/one/two/(right:;b=2)');
});
it("should parse scoped secondary segments", () => {
const tree = url.parse("/one/(two//left:three)");
it('should parse scoped secondary segments', () => {
const tree = url.parse('/one/(two//left:three)');
const primary = tree.root.children[PRIMARY_OUTLET];
expectSegment(primary, "one", true);
expectSegment(primary, 'one', true);
expectSegment(primary.children[PRIMARY_OUTLET], "two");
expectSegment(primary.children["left"], "three");
expectSegment(primary.children[PRIMARY_OUTLET], 'two');
expectSegment(primary.children['left'], 'three');
expect(url.serialize(tree)).toEqual("/one/(two//left:three)");
expect(url.serialize(tree)).toEqual('/one/(two//left:three)');
});
it("should parse scoped secondary segments with unscoped ones", () => {
const tree = url.parse("/one/(two//left:three)(right:four)");
it('should parse scoped secondary segments with unscoped ones', () => {
const tree = url.parse('/one/(two//left:three)(right:four)');
const primary = tree.root.children[PRIMARY_OUTLET];
expectSegment(primary, "one", true);
expectSegment(primary.children[PRIMARY_OUTLET], "two");
expectSegment(primary.children["left"], "three");
expectSegment(tree.root.children["right"], "four");
expectSegment(primary, 'one', true);
expectSegment(primary.children[PRIMARY_OUTLET], 'two');
expectSegment(primary.children['left'], 'three');
expectSegment(tree.root.children['right'], 'four');
expect(url.serialize(tree)).toEqual("/one/(two//left:three)(right:four)");
expect(url.serialize(tree)).toEqual('/one/(two//left:three)(right:four)');
});
it("should parse secondary segments that have children", () => {
const tree = url.parse("/one(left:two/three)");
it('should parse secondary segments that have children', () => {
const tree = url.parse('/one(left:two/three)');
expectSegment(tree.root.children[PRIMARY_OUTLET], "one");
expectSegment(tree.root.children['left'], "two/three");
expectSegment(tree.root.children[PRIMARY_OUTLET], 'one');
expectSegment(tree.root.children['left'], 'two/three');
expect(url.serialize(tree)).toEqual("/one(left:two/three)");
expect(url.serialize(tree)).toEqual('/one(left:two/three)');
});
it("should parse an empty secondary segment group", () => {
const tree = url.parse("/one()");
it('should parse an empty secondary segment group', () => {
const tree = url.parse('/one()');
expectSegment(tree.root.children[PRIMARY_OUTLET], "one");
expectSegment(tree.root.children[PRIMARY_OUTLET], 'one');
expect(url.serialize(tree)).toEqual("/one");
expect(url.serialize(tree)).toEqual('/one');
});
it("should parse key-value matrix params", () => {
const tree = url.parse("/one;a=11a;b=11b(left:two;c=22//right:three;d=33)");
it('should parse key-value matrix params', () => {
const tree = url.parse('/one;a=11a;b=11b(left:two;c=22//right:three;d=33)');
expectSegment(tree.root.children[PRIMARY_OUTLET], "one;a=11a;b=11b");
expectSegment(tree.root.children["left"], "two;c=22");
expectSegment(tree.root.children["right"], "three;d=33");
expectSegment(tree.root.children[PRIMARY_OUTLET], 'one;a=11a;b=11b');
expectSegment(tree.root.children['left'], 'two;c=22');
expectSegment(tree.root.children['right'], 'three;d=33');
expect(url.serialize(tree)).toEqual("/one;a=11a;b=11b(left:two;c=22//right:three;d=33)");
expect(url.serialize(tree)).toEqual('/one;a=11a;b=11b(left:two;c=22//right:three;d=33)');
});
it("should parse key only matrix params", () => {
const tree = url.parse("/one;a");
it('should parse key only matrix params', () => {
const tree = url.parse('/one;a');
expectSegment(tree.root.children[PRIMARY_OUTLET], "one;a=true");
expectSegment(tree.root.children[PRIMARY_OUTLET], 'one;a=true');
expect(url.serialize(tree)).toEqual("/one;a=true");
expect(url.serialize(tree)).toEqual('/one;a=true');
});
it("should parse query params", () => {
const tree = url.parse("/one?a=1&b=2");
it('should parse query params', () => {
const tree = url.parse('/one?a=1&b=2');
expect(tree.queryParams).toEqual({a: '1', b: '2'});
});
it("should parse query params when with parenthesis", () => {
const tree = url.parse("/one?a=(11)&b=(22)");
it('should parse query params when with parenthesis', () => {
const tree = url.parse('/one?a=(11)&b=(22)');
expect(tree.queryParams).toEqual({a: '(11)', b: '(22)'});
});
it("should parse key only query params", () => {
const tree = url.parse("/one?a");
it('should parse key only query params', () => {
const tree = url.parse('/one?a');
expect(tree.queryParams).toEqual({a: 'true'});
});
it("should serializer query params", () => {
const tree = url.parse("/one?a");
expect(url.serialize(tree)).toEqual("/one?a=true");
it('should serializer query params', () => {
const tree = url.parse('/one?a');
expect(url.serialize(tree)).toEqual('/one?a=true');
});
it("should parse fragment", () => {
const tree = url.parse("/one#two");
expect(tree.fragment).toEqual("two");
expect(url.serialize(tree)).toEqual("/one#two");
it('should parse fragment', () => {
const tree = url.parse('/one#two');
expect(tree.fragment).toEqual('two');
expect(url.serialize(tree)).toEqual('/one#two');
});
it("should parse empty fragment", () => {
const tree = url.parse("/one#");
expect(tree.fragment).toEqual("");
expect(url.serialize(tree)).toEqual("/one#");
it('should parse empty fragment', () => {
const tree = url.parse('/one#');
expect(tree.fragment).toEqual('');
expect(url.serialize(tree)).toEqual('/one#');
});
});
function expectSegment(segment:UrlSegment, expected:string, hasChildren: boolean = false):void {
const p = segment.pathsWithParams.map(p => serializePath(p)).join("/");
function expectSegment(segment: UrlSegment, expected: string, hasChildren: boolean = false): void {
const p = segment.pathsWithParams.map(p => serializePath(p)).join('/');
expect(p).toEqual(expected);
expect(Object.keys(segment.children).length > 0).toEqual(hasChildren);
}

View File

@ -4,63 +4,63 @@ import {UrlTree, containsTree} from '../src/url_tree';
describe('UrlTree', () => {
const serializer = new DefaultUrlSerializer();
describe("containsTree", () => {
describe("exact = true", () => {
it("should return true when two tree are the same", () => {
const url = "/one/(one//left:three)(right:four)";
describe('containsTree', () => {
describe('exact = true', () => {
it('should return true when two tree are the same', () => {
const url = '/one/(one//left:three)(right:four)';
const t1 = serializer.parse(url);
const t2 = serializer.parse(url);
expect(containsTree(t1, t2, true)).toBe(true);
expect(containsTree(t2, t1, true)).toBe(true);
});
it("should return false when paths are not the same", () => {
const t1 = serializer.parse("/one/two(right:three)");
const t2 = serializer.parse("/one/two2(right:three)");
it('should return false when paths are not the same', () => {
const t1 = serializer.parse('/one/two(right:three)');
const t2 = serializer.parse('/one/two2(right:three)');
expect(containsTree(t1, t2, true)).toBe(false);
});
it("should return false when container has an extra child", () => {
const t1 = serializer.parse("/one/two(right:three)");
const t2 = serializer.parse("/one/two");
it('should return false when container has an extra child', () => {
const t1 = serializer.parse('/one/two(right:three)');
const t2 = serializer.parse('/one/two');
expect(containsTree(t1, t2, true)).toBe(false);
});
it("should return false when containee has an extra child", () => {
const t1 = serializer.parse("/one/two");
const t2 = serializer.parse("/one/two(right:three)");
it('should return false when containee has an extra child', () => {
const t1 = serializer.parse('/one/two');
const t2 = serializer.parse('/one/two(right:three)');
expect(containsTree(t1, t2, true)).toBe(false);
});
});
describe("exact = false", () => {
it("should return true when containee is missing a segment", () => {
const t1 = serializer.parse("/one/(two//left:three)(right:four)");
const t2 = serializer.parse("/one/(two//left:three)");
describe('exact = false', () => {
it('should return true when containee is missing a segment', () => {
const t1 = serializer.parse('/one/(two//left:three)(right:four)');
const t2 = serializer.parse('/one/(two//left:three)');
expect(containsTree(t1, t2, false)).toBe(true);
});
it("should return true when containee is missing some paths", () => {
const t1 = serializer.parse("/one/two/three");
const t2 = serializer.parse("/one/two");
it('should return true when containee is missing some paths', () => {
const t1 = serializer.parse('/one/two/three');
const t2 = serializer.parse('/one/two');
expect(containsTree(t1, t2, false)).toBe(true);
});
it("should return true container has its paths splitted into multiple segments", () => {
const t1 = serializer.parse("/one/(two//left:three)");
const t2 = serializer.parse("/one/two");
it('should return true container has its paths splitted into multiple segments', () => {
const t1 = serializer.parse('/one/(two//left:three)');
const t2 = serializer.parse('/one/two');
expect(containsTree(t1, t2, false)).toBe(true);
});
it("should return false when containee has extra segments", () => {
const t1 = serializer.parse("/one/two");
const t2 = serializer.parse("/one/(two//left:three)");
it('should return false when containee has extra segments', () => {
const t1 = serializer.parse('/one/two');
const t2 = serializer.parse('/one/(two//left:three)');
expect(containsTree(t1, t2, false)).toBe(false);
});
it("should return containee has segments that the container does not have", () => {
const t1 = serializer.parse("/one/(two//left:three)");
const t2 = serializer.parse("/one/(two//right:four)");
it('should return containee has segments that the container does not have', () => {
const t1 = serializer.parse('/one/(two//left:three)');
const t2 = serializer.parse('/one/(two//right:four)');
expect(containsTree(t1, t2, false)).toBe(false);
});
});

View File

@ -1,50 +1,51 @@
import {Tree, TreeNode} from '../../src/utils/tree';
describe('tree', () => {
it("should return the root of the tree", () => {
it('should return the root of the tree', () => {
const t = new Tree<any>(new TreeNode<number>(1, []));
expect(t.root).toEqual(1);
});
it("should return the parent of a node", () => {
it('should return the parent of a node', () => {
const t = new Tree<any>(new TreeNode<number>(1, [new TreeNode<number>(2, [])]));
expect(t.parent(1)).toEqual(null);
expect(t.parent(2)).toEqual(1);
});
it("should return the children of a node", () => {
it('should return the children of a node', () => {
const t = new Tree<any>(new TreeNode<number>(1, [new TreeNode<number>(2, [])]));
expect(t.children(1)).toEqual([2]);
expect(t.children(2)).toEqual([]);
});
it("should return the first child of a node", () => {
it('should return the first child of a node', () => {
const t = new Tree<any>(new TreeNode<number>(1, [new TreeNode<number>(2, [])]));
expect(t.firstChild(1)).toEqual(2);
expect(t.firstChild(2)).toEqual(null);
});
it("should return the siblings of a node", () => {
const t = new Tree<any>(new TreeNode<number>(1, [new TreeNode<number>(2, []), new TreeNode<number>(3, [])]));
it('should return the siblings of a node', () => {
const t = new Tree<any>(
new TreeNode<number>(1, [new TreeNode<number>(2, []), new TreeNode<number>(3, [])]));
expect(t.siblings(2)).toEqual([3]);
expect(t.siblings(1)).toEqual([]);
});
it("should return the path to the root", () => {
it('should return the path to the root', () => {
const t = new Tree<any>(new TreeNode<number>(1, [new TreeNode<number>(2, [])]));
expect(t.pathFromRoot(2)).toEqual([1, 2]);
});
describe("contains", () => {
it("should work", () => {
describe('contains', () => {
it('should work', () => {
const tree = new Tree<any>(
new TreeNode<number>(1, [new TreeNode<number>(2, []), new TreeNode<number>(3, [])]));
new TreeNode<number>(1, [new TreeNode<number>(2, []), new TreeNode<number>(3, [])]));
const subtree1 = new Tree<any>(new TreeNode<number>(1, []));
const subtree2 = new Tree<any>(new TreeNode<number>(1, [new TreeNode<number>(2, [])]));
const subtree3 = new Tree<any>(new TreeNode<number>(1, [new TreeNode<number>(3, [])]));
const notSubtree1 = new Tree<any>(new TreeNode<number>(1, [new TreeNode<number>(4, [])]));
const notSubtree2 = new Tree<any>(
new TreeNode<number>(1, [new TreeNode<number>(2, [new TreeNode<number>(4, [])])]));
new TreeNode<number>(1, [new TreeNode<number>(2, [new TreeNode<number>(4, [])])]));
expect(tree.contains(subtree1)).toEqual(true);
expect(tree.contains(subtree2)).toEqual(true);