feat(router): implement RouterLinkActive

This commit is contained in:
vsavkin
2016-06-15 09:01:05 -07:00
parent 2aa19fd078
commit 25560ed048
8 changed files with 296 additions and 4 deletions

View File

@ -658,6 +658,90 @@ describe("Integration", () => {
})));
});
});
describe("routerActiveLink", () => {
it("should set the class when the link is active (exact = true)",
fakeAsync(inject([Router, TestComponentBuilder, Location], (router, tcb, location) => {
const fixture = tcb.createFakeAsync(RootCmp);
advance(fixture);
router.resetConfig([
{ path: 'team/:id', component: TeamCmp, children: [
{ path: 'link', component: DummyLinkCmp, children: [
{path: 'simple', component: SimpleCmp},
{path: '', component: BlankCmp}
] }
] }
]);
router.navigateByUrl('/team/22/link');
advance(fixture);
expect(location.path()).toEqual('/team/22/link');
const native = fixture.debugElement.nativeElement.querySelector("a");
expect(native.className).toEqual("active");
router.navigateByUrl('/team/22/link/simple');
advance(fixture);
expect(location.path()).toEqual('/team/22/link/simple');
expect(native.className).toEqual("");
})));
it("should set the class on a parent element when the link is active (exact = true)",
fakeAsync(inject([Router, TestComponentBuilder, Location], (router, tcb, location) => {
const fixture = tcb.createFakeAsync(RootCmp);
advance(fixture);
router.resetConfig([
{ path: 'team/:id', component: TeamCmp, children: [
{ path: 'link', component: DummyLinkWithParentCmp, children: [
{path: 'simple', component: SimpleCmp},
{path: '', component: BlankCmp}
] }
] }
]);
router.navigateByUrl('/team/22/link');
advance(fixture);
expect(location.path()).toEqual('/team/22/link');
const native = fixture.debugElement.nativeElement.querySelector("link-parent");
expect(native.className).toEqual("active");
router.navigateByUrl('/team/22/link/simple');
advance(fixture);
expect(location.path()).toEqual('/team/22/link/simple');
expect(native.className).toEqual("");
})));
it("should set the class when the link is active (exact = false)",
fakeAsync(inject([Router, TestComponentBuilder, Location], (router, tcb, location) => {
const fixture = tcb.createFakeAsync(RootCmp);
advance(fixture);
router.resetConfig([
{ path: 'team/:id', component: TeamCmp, children: [
{ path: 'link', component: DummyLinkCmp, children: [
{path: 'simple', component: SimpleCmp},
{path: '', component: BlankCmp}
] }
] }
]);
router.navigateByUrl('/team/22/link;exact=false');
advance(fixture);
expect(location.path()).toEqual('/team/22/link;exact=false');
const native = fixture.debugElement.nativeElement.querySelector("a");
expect(native.className).toEqual("active");
router.navigateByUrl('/team/22/link/simple');
advance(fixture);
expect(location.path()).toEqual('/team/22/link/simple');
expect(native.className).toEqual("active");
})));
});
});
function expectEvents(events:Event[], pairs: any[]) {
@ -681,6 +765,27 @@ class StringLinkCmp {}
})
class AbsoluteLinkCmp {}
@Component({
selector: 'link-cmp',
template: `<router-outlet></router-outlet><a routerLinkActive="active" [routerLinkActiveOptions]="{exact: exact}" [routerLink]="['./']">link</a>`,
directives: ROUTER_DIRECTIVES
})
class DummyLinkCmp {
private exact: boolean;
constructor(route: ActivatedRoute) {
// convert 'false' into false
this.exact = (<any>route.snapshot.params).exact !== 'false';
}
}
@Component({
selector: 'link-cmp',
template: `<router-outlet></router-outlet><link-parent routerLinkActive="active"><a [routerLink]="['./']">link</a></link-parent>`,
directives: ROUTER_DIRECTIVES
})
class DummyLinkWithParentCmp {
}
@Component({
selector: 'link-cmp',
template: `<a [routerLink]="['../simple']">link</a>`,

View File

@ -0,0 +1,68 @@
import {DefaultUrlSerializer} from '../src/url_serializer';
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)";
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)");
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");
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)");
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)");
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");
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");
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)");
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)");
expect(containsTree(t1, t2, false)).toBe(false);
});
});
});
});