Last active
May 8, 2018 16:23
-
-
Save christo8989/772234acdfeae92a26b92bb568417203 to your computer and use it in GitHub Desktop.
This does not work with lazy loading modules (with routes) but I wanted to keep.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { TestBed, inject } from "@angular/core/testing"; | |
import { RouterTestingModule } from "@angular/router/testing"; | |
import { routes } from "../../../../test/mock.routes"; | |
import { LinkService } from "./link.service"; | |
describe("LinkService", () => { | |
beforeEach(() => { | |
TestBed.configureTestingModule({ | |
imports: [RouterTestingModule.withRoutes([ | |
{ | |
path: "", component: Object, children: [ | |
{ path: "", component: Object }, | |
{ | |
path: "foo", component: Object, children: [ | |
{ path: "zoo", component: Object }, | |
{ path: ":name", component: Object }, | |
], | |
}, | |
{ path: "roo/moo", component: Object }, | |
], | |
}, | |
{ path: "boo", component: Object }, | |
{ path: "this/is/a/long/one/:id", component: Object }, | |
{ path: "this/:name/is/a/weird/:adjective/one", component: Object }, | |
{ path: "redirect", redirectTo: "foo/zoo" }, | |
{ path: "**", redirectTo: "" }, | |
])], | |
providers: [LinkService], | |
}); | |
}); | |
it("should be created", inject([LinkService], (service: LinkService) => { | |
expect(service).toBeTruthy(); | |
})); | |
it("has path '/'", inject([LinkService], (service: LinkService) => { | |
expect(service.home()).toEqual("/"); | |
expect(service.home.toArray()).toEqual(["/"]); | |
})); | |
it("has path '/boo'", inject([LinkService], (service: LinkService) => { | |
expect(service.boo()).toEqual("/boo"); | |
expect(service.boo.toArray()).toEqual(["boo"]); | |
})); | |
it("has path '/roo/moo'", inject([LinkService], (service: LinkService) => { | |
expect(service.roo_moo()).toEqual("/roo/moo"); | |
expect(service.roo_moo.toArray()).toEqual(["roo", "moo"]); | |
})); | |
it("has path '/foo/zoo'", inject([LinkService], (service: LinkService) => { | |
expect(service.foo_zoo()).toEqual("/foo/zoo"); | |
expect(service.foo_zoo.toArray()).toEqual(["foo", "zoo"]); | |
})); | |
it("has path '/foo/:name'", inject([LinkService], (service: LinkService) => { | |
const name = 12345; | |
expect(service.foo_name(name)).toEqual("/foo/12345"); | |
expect(service.foo_name.toArray(name)).toEqual(["foo", "12345"]); | |
})); | |
it("has path '/this/is/a/long/one/:id'", inject([LinkService], (service: LinkService) => { | |
const id = 12345; | |
expect(service.this_is_a_long_one_id(id)) | |
.toEqual("/this/is/a/long/one/12345"); | |
expect(service.this_is_a_long_one_id.toArray(id)) | |
.toEqual(["this", "is", "a", "long", "one", "12345"]); | |
})); | |
it("has path '/this/:name/is/a/weird/:adjective/one'", inject([LinkService], (service: LinkService) => { | |
expect(service.this_name_is_a_weird_adjective_one("chris", "test")) | |
.toEqual("/this/chris/is/a/weird/test/one"); | |
expect(service.this_name_is_a_weird_adjective_one.toArray("chris", "test")) | |
.toEqual(["this", "chris", "is", "a", "weird", "test", "one"]); | |
})); | |
it("removed path '/redirect'", inject([LinkService], (service: LinkService) => { | |
expect(service.redirect).toBeFalsy(); | |
})); | |
it("removed path '**'", inject([LinkService], (service: LinkService) => { | |
expect(service["**"]).toBeFalsy(); | |
})); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Injectable } from "@angular/core"; | |
import { ChildActivationEnd, Route, Router, Routes } from "@angular/router"; | |
@Injectable() | |
export class LinkService { | |
[key: string]: any; | |
constructor(private router: Router) { | |
this.parseRoutes(router.config); | |
} | |
private parseRoutes(routes: Routes, url = ""): void { | |
routes.forEach(route => this.parseRoute(route, url)); | |
} | |
private parseRoute(route: Route, url = ""): void { | |
if (this.skip(route)) { | |
return; // do nothing | |
} | |
const newUrl = this.buildUrl(url, route); | |
if (this.hasChildren(route)) { | |
this.parseRoutes(route.children, newUrl); | |
} else { | |
this.createMethods(newUrl); | |
} | |
} | |
private skip(route: Route): boolean { | |
const isRedirect = route.redirectTo != null; | |
const hasWildcard = route.path.includes("*"); | |
const isSkip = isRedirect || hasWildcard; | |
return isSkip; | |
} | |
private buildUrl(url: string, route: Route): string { | |
const cleanUrl = this.cleanUrl(url); | |
const cleanPath = this.cleanUrl(route.path); | |
if (cleanPath === "") { | |
return cleanUrl; | |
} | |
const newUrl = `${cleanUrl}/${cleanPath}`; | |
return newUrl; | |
} | |
private cleanUrl(url: string): string { | |
let cleanUrl = url.trim(); | |
if (cleanUrl.startsWith("/")) { | |
cleanUrl = cleanUrl.substr(1); | |
} | |
if (cleanUrl.endsWith("/")) { | |
cleanUrl = cleanUrl.substr(0, cleanUrl.length - 1); | |
} | |
return cleanUrl; | |
} | |
private hasChildren(route: Route): boolean { | |
const children = route.children; | |
const isArray = Array.isArray(children); | |
if (!isArray) { | |
return false; | |
} | |
const hasItems = children.length > 0; | |
return hasItems; | |
} | |
private createMethods(url: string): void { | |
const cleanUrl = this.cleanUrl(url); | |
const name = this.createName(cleanUrl); | |
const parameters = this.getParameters(cleanUrl); | |
this.createStringMethod(name, cleanUrl, parameters); | |
this.createArrayMethod(name, cleanUrl, parameters); | |
} | |
private createName(url: string): string { | |
let name = url === "" ? "home" : this.replaceAll(url, "/", "_"); | |
name = this.replaceAll(name, ":", ""); | |
return name; | |
} | |
private getParameters(url: string): string[] { | |
const parameters = url | |
.split("/") | |
.filter(item => item.startsWith(":")) | |
.map(item => this.replaceAll(item, ":", "")); | |
return parameters; | |
} | |
private createStringMethod(name: string, url: string, parameters: string[]): void { | |
const actualUrl = `/${url}`; | |
this[name] = (...args) => { | |
const finalUrl = parameters.reduce(this.replaceUrlWithParameterValues(args), actualUrl); | |
return finalUrl; | |
}; | |
} | |
private createArrayMethod(name: string, url: string, parameters: string[]): void { | |
if (parameters.length < 1) { | |
const urlArray = url.split("/"); | |
if (name === "home") { | |
urlArray[0] = "/"; | |
} | |
this[name].toArray = () => urlArray; | |
} else { | |
this[name].toArray = (...args) => { | |
const urlArray = parameters | |
.reduce(this.replaceUrlWithParameterValues(args), url) | |
.split("/"); | |
return urlArray; | |
}; | |
} | |
} | |
private replaceUrlWithParameterValues(args: any[]): (a, b, c) => any { | |
return (url, parameterName, index) => { | |
const urlParameterName = `:${parameterName}`; | |
const value = args[index]; | |
const newUrl = url.replace(urlParameterName, value); | |
return newUrl; | |
}; | |
} | |
private replaceAll = (str: string, search: string, replacement: string): string => { | |
return str.split(search).join(replacement); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment