From bf705fcd99720558412d3a89ff460ab9e047ab93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A9ry=20Debongnie?= Date: Thu, 25 Jul 2019 23:17:34 +0200 Subject: [PATCH] [REF] router: add TestRouter and improve tests --- src/router/Router.ts | 12 +++++++---- tests/router/TestRouter.ts | 17 +++++++++++++++ tests/router/directive.test.ts | 26 +++++++++++------------ tests/router/router.test.ts | 39 +++++++++++++++++++++++++++++++--- 4 files changed, 74 insertions(+), 20 deletions(-) create mode 100644 tests/router/TestRouter.ts diff --git a/src/router/Router.ts b/src/router/Router.ts index 2bc64a52..74e5717d 100644 --- a/src/router/Router.ts +++ b/src/router/Router.ts @@ -60,7 +60,8 @@ export class Router { this.checkRoute(); - window.addEventListener("popstate", () => this.checkAndUpdateRoute()); + this.checkAndUpdateRoute = this.checkAndUpdateRoute.bind(this); + window.addEventListener("popstate", this.checkAndUpdateRoute); // setup link and directive env.qweb.addTemplate(LINK_TEMPLATE_NAME, LINK_TEMPLATE); @@ -74,11 +75,14 @@ export class Router { } destToUrl(dest: Destination): string { + if ((!dest.path && !dest.name) || (dest.path && dest.name)) { + throw new Error(`Invalid destination: ${JSON.stringify(dest)}`); + } return dest.path || this.routeToURL(this.routes[dest.name!].path, dest.params!); } - get currentRouteName(): string | null{ - return this.currentRoute && this.currentRoute.name; + get currentRouteName(): string | null { + return this.currentRoute && this.currentRoute.name; } private routeToURL(path: string, params: RouteParams): string { @@ -112,7 +116,7 @@ export class Router { this.currentParams = {}; } - private checkAndUpdateRoute(): void { + protected checkAndUpdateRoute(): void { const initialName = this.currentRoute ? this.currentRoute.name : null; this.checkRoute(); const currentName = this.currentRoute ? this.currentRoute.name : null; diff --git a/tests/router/TestRouter.ts b/tests/router/TestRouter.ts new file mode 100644 index 00000000..77b0b61e --- /dev/null +++ b/tests/router/TestRouter.ts @@ -0,0 +1,17 @@ +import { Router } from "../../src/router/Router"; +import { QWeb } from "../../src/qweb/index"; + +export class TestRouter extends Router { + destroy() { + window.removeEventListener("popstate", this.checkAndUpdateRoute); + delete QWeb.DIRECTIVE_NAMES.routecomponent; + QWeb.DIRECTIVES = QWeb.DIRECTIVES.filter(d => d.name !== "routecomponent"); + + // remove component defined inroutes + for (let key in QWeb.components) { + if (key.startsWith("__component__")) { + delete QWeb.components[key]; + } + } + } +} diff --git a/tests/router/directive.test.ts b/tests/router/directive.test.ts index b8bf3274..a6be0beb 100644 --- a/tests/router/directive.test.ts +++ b/tests/router/directive.test.ts @@ -1,24 +1,24 @@ import { Component } from "../../src/component/component"; -import { QWeb } from "../../src/qweb/index"; -import { Router, RouterEnv } from "../../src/router/Router"; +import { RouterEnv } from "../../src/router/Router"; import { makeTestEnv, makeTestFixture, nextTick } from "../helpers"; +import { TestRouter } from "./TestRouter"; describe("router directive t-routecomponent", () => { let fixture: HTMLElement; let env: RouterEnv; + let router: TestRouter | null = null; beforeEach(() => { fixture = makeTestFixture(); env = makeTestEnv(); - delete QWeb.DIRECTIVE_NAMES.routecomponent; - QWeb.DIRECTIVES = QWeb.DIRECTIVES.filter(d => d.name !== "routecomponent"); - for (let key in QWeb.components) { - delete QWeb.components[key]; - } }); afterEach(() => { fixture.remove(); + if (router) { + router.destroy(); + } + router = null; }); test("can render simple cases", async () => { @@ -42,7 +42,7 @@ describe("router directive t-routecomponent", () => { { name: "users", path: "/users", component: Users } ]; - const router = new Router(env,routes, {mode: 'history'}) + router = new TestRouter(env, routes, { mode: "history" }); router.navigate({ name: "about" }); const app = new App(env); await app.mount(fixture); @@ -69,7 +69,7 @@ describe("router directive t-routecomponent", () => { } const routes = [{ name: "book", path: "/book/{{title}}", component: Book }]; - const router = new Router(env,routes, {mode: 'history'}) + router = new TestRouter(env, routes, { mode: "history" }); router.navigate({ name: "book", params: { title: "1984" } }); const app = new App(env); await app.mount(fixture); @@ -87,16 +87,16 @@ describe("router directive t-routecomponent", () => { `); class Book extends Component { - get incVal() { - return this.props.val + 1; - } + get incVal() { + return this.props.val + 1; + } } class App extends Component { components = { Book }; } const routes = [{ name: "book", path: "/book/{{title}}/{{val.number}}", component: Book }]; - const router = new Router(env,routes, {mode: 'history'}) + router = new TestRouter(env, routes, { mode: "history" }); router.navigate({ name: "book", params: { title: "1984", val: "123" } }); const app = new App(env); await app.mount(fixture); diff --git a/tests/router/router.test.ts b/tests/router/router.test.ts index 8235ff84..b7545593 100644 --- a/tests/router/router.test.ts +++ b/tests/router/router.test.ts @@ -1,7 +1,23 @@ -import { Router } from "../../src/router/Router"; +import { Destination, Router, RouterEnv } from "../../src/router/Router"; +import { makeTestEnv } from "../helpers"; +import { TestRouter } from "./TestRouter"; + +let env: RouterEnv; +let router: TestRouter | null = null; + +beforeEach(() => { + env = makeTestEnv(); +}); + +afterEach(() => { + if (router) { + router.destroy(); + } + router = null; +}); describe("routeToURL", () => { - const routeToURL = Router.prototype.routeToURL; + const routeToURL = Router.prototype["routeToURL"]; test("simple non parameterized path", () => { expect(routeToURL("/abc", {})).toBe("/abc"); expect(routeToURL("/abc/def", {})).toBe("/abc/def"); @@ -13,8 +29,25 @@ describe("routeToURL", () => { }); }); +describe("destToURL", () => { + test("validate destination shape", () => { + router = new TestRouter(env, [{ name: "someroute", path: "/some/path" }]); + expect(() => { + router!.destToUrl({ abc: 123 } as Destination); + }).toThrow('Invalid destination: {"abc":123}'); + + expect(() => { + router!.destToUrl({ name: "someroute" } as Destination); + }).not.toThrow(); + + expect(() => { + router!.destToUrl({ path: "/someroute", name: "otherroute" } as Destination); + }).toThrow(); + }); +}); + describe("match routes", () => { - const matchRoute = Router.prototype.matchRoute; + const matchRoute = Router.prototype["matchRoute"]; test("properly match simple routes", () => { // simple route expect(matchRoute("/home", "/home")).toEqual({});