[FIX] router: better support for hash mode

This commit is contained in:
Géry Debongnie
2019-08-31 09:46:20 +02:00
parent 6ff4dd74bf
commit 55be6437f1
2 changed files with 80 additions and 25 deletions
+5 -1
View File
@@ -164,7 +164,8 @@ export class Router {
parts[i] = <string>params[key]; parts[i] = <string>params[key];
} }
} }
return parts.join("/"); const prefix = this.mode === "hash" ? "#" : "";
return prefix + parts.join("/");
} }
private currentPath(): string { private currentPath(): string {
@@ -223,6 +224,9 @@ export class Router {
if (route.path === "*") { if (route.path === "*") {
return {}; return {};
} }
if (path.startsWith("#")) {
path = path.slice(1);
}
const descrParts = route.path.split("/"); const descrParts = route.path.split("/");
const targetParts = path.split("/"); const targetParts = path.split("/");
const l = descrParts.length; const l = descrParts.length;
+70 -19
View File
@@ -1,4 +1,4 @@
import { Destination, Router, RouterEnv, Route } from "../../src/router/Router"; import { Destination, RouterEnv, Route } from "../../src/router/Router";
import { makeTestEnv } from "../helpers"; import { makeTestEnv } from "../helpers";
import { TestRouter } from "./TestRouter"; import { TestRouter } from "./TestRouter";
@@ -28,15 +28,28 @@ describe("router miscellaneous", () => {
}); });
describe("routeToPath", () => { describe("routeToPath", () => {
const routeToPath = Router.prototype["routeToPath"];
test("simple non parameterized path", () => { test("simple non parameterized path", () => {
expect(routeToPath({path: "/abc"} as Route, {})).toBe("/abc"); router = new TestRouter(env, []);
expect(routeToPath({path: "/abc/def"} as Route, {})).toBe("/abc/def"); expect(router["routeToPath"]({ path: "/abc" } as Route, {})).toBe("/abc");
expect(routeToPath({path: "/abc"} as Route, { val: 12 })).toBe("/abc"); expect(router["routeToPath"]({ path: "/abc/def" } as Route, {})).toBe("/abc/def");
expect(router["routeToPath"]({ path: "/abc" } as Route, { val: 12 })).toBe("/abc");
}); });
test("simple parameterized path", () => { test("simple parameterized path", () => {
expect(routeToPath({path: "/abc/{{def}}"} as Route, { def: 34 })).toBe("/abc/34"); router = new TestRouter(env, []);
expect(router["routeToPath"]({ path: "/abc/{{def}}" } as Route, { def: 34 })).toBe("/abc/34");
});
test("simple non parameterized path, mode = hash", () => {
router = new TestRouter(env, [], { mode: "hash" });
expect(router["routeToPath"]({ path: "/abc" } as Route, {})).toBe("#/abc");
expect(router["routeToPath"]({ path: "/abc/def" } as Route, {})).toBe("#/abc/def");
expect(router["routeToPath"]({ path: "/abc" } as Route, { val: 12 })).toBe("#/abc");
});
test("simple parameterized path, mode=hash", () => {
router = new TestRouter(env, [], { mode: "hash" });
expect(router["routeToPath"]({ path: "/abc/{{def}}" } as Route, { def: 34 })).toBe("#/abc/34");
}); });
}); });
@@ -58,26 +71,60 @@ describe("destToPath", () => {
}); });
describe("getRouteParams", () => { describe("getRouteParams", () => {
const getRouteParams = Router.prototype["getRouteParams"];
test("properly match simple routes", () => { test("properly match simple routes", () => {
router = new TestRouter(env, []);
// simple route // simple route
expect(getRouteParams({path: "/home"} as Route, "/home")).toEqual({}); expect(router["getRouteParams"]({ path: "/home" } as Route, "/home")).toEqual({});
// no match // no match
expect(getRouteParams({path: "/home"} as Route, "/otherpath")).toEqual(false); expect(router["getRouteParams"]({ path: "/home" } as Route, "/otherpath")).toEqual(false);
// fallback route // fallback route
expect(getRouteParams({path: "*"} as Route, "somepath")).toEqual({}); expect(router["getRouteParams"]({ path: "*" } as Route, "somepath")).toEqual({});
});
test("properly match simple routes, mode hash", () => {
router = new TestRouter(env, [], { mode: "hash" });
// simple route
expect(router["getRouteParams"]({ path: "/home" } as Route, "#/home")).toEqual({});
// no match
expect(router["getRouteParams"]({ path: "/home" } as Route, "#/otherpath")).toEqual(false);
// fallback route
expect(router["getRouteParams"]({ path: "*" } as Route, "#/somepath")).toEqual({});
}); });
test("match some parameterized routes", () => { test("match some parameterized routes", () => {
expect(getRouteParams({path: "/invoices/{{id}}"} as Route, "/invoices/3")).toEqual({ router = new TestRouter(env, []);
expect(router["getRouteParams"]({ path: "/invoices/{{id}}" } as Route, "/invoices/3")).toEqual({
id: "3" id: "3"
}); });
}); });
test("match some parameterized routes, mode hash", () => {
router = new TestRouter(env, [], { mode: "hash" });
expect(router["getRouteParams"]({ path: "/invoices/{{id}}" } as Route, "#/invoices/3")).toEqual(
{
id: "3"
}
);
});
test("can convert to number if needed", () => { test("can convert to number if needed", () => {
expect(getRouteParams({path: "/invoices/{{id.number}}"} as Route, "/invoices/3")).toEqual({ router = new TestRouter(env, []);
expect(
router["getRouteParams"]({ path: "/invoices/{{id.number}}" } as Route, "/invoices/3")
).toEqual({
id: 3
});
});
test("can convert to number if needed, mode: hash", () => {
router = new TestRouter(env, [], { mode: "hash" });
expect(
router["getRouteParams"]({ path: "/invoices/{{id.number}}" } as Route, "#/invoices/3")
).toEqual({
id: 3 id: 3
}); });
}); });
@@ -131,7 +178,7 @@ describe("beforeRouteEnter", () => {
expect(window.location.pathname).toBe("/"); expect(window.location.pathname).toBe("/");
const guard = jest.fn(() => false); const guard = jest.fn(() => false);
router = new TestRouter(env, [ router = new TestRouter(env, [
{ name: "routea", path: "/some/patha"}, { name: "routea", path: "/some/patha" },
{ name: "routeb", path: "/some/pathb", beforeRouteEnter: guard } { name: "routeb", path: "/some/pathb", beforeRouteEnter: guard }
]); ]);
@@ -147,11 +194,13 @@ describe("beforeRouteEnter", () => {
test("navigation is redirected if guard decides so", async () => { test("navigation is redirected if guard decides so", async () => {
expect(window.location.pathname).toBe("/"); expect(window.location.pathname).toBe("/");
const guard = jest.fn(() => {return {to: "routec"}}); const guard = jest.fn(() => {
return { to: "routec" };
});
router = new TestRouter(env, [ router = new TestRouter(env, [
{ name: "routea", path: "/some/patha"}, { name: "routea", path: "/some/patha" },
{ name: "routeb", path: "/some/pathb", beforeRouteEnter: guard }, { name: "routeb", path: "/some/pathb", beforeRouteEnter: guard },
{ name: "routec", path: "/some/pathc"}, { name: "routec", path: "/some/pathc" }
]); ]);
await router.start(); await router.start();
@@ -166,10 +215,12 @@ describe("beforeRouteEnter", () => {
test("navigation is initially redirected if guard decides so", async () => { test("navigation is initially redirected if guard decides so", async () => {
expect(window.location.pathname).toBe("/"); expect(window.location.pathname).toBe("/");
const guard = jest.fn(() => {return {to: "otherroute"}}); const guard = jest.fn(() => {
return { to: "otherroute" };
});
router = new TestRouter(env, [ router = new TestRouter(env, [
{ name: "landing", path: "/", beforeRouteEnter: guard}, { name: "landing", path: "/", beforeRouteEnter: guard },
{ name: "otherroute", path: "/some/other/route"} { name: "otherroute", path: "/some/other/route" }
]); ]);
expect(window.location.pathname).toBe("/"); expect(window.location.pathname).toBe("/");