mirror of
https://github.com/odoo/owl.git
synced 2025-10-06 19:59:41 +07:00
[IMP] router: add validation for destinations
This commit is contained in:
+12
-5
@@ -19,7 +19,7 @@ export interface RouterEnv extends Env {
|
|||||||
|
|
||||||
export interface Destination {
|
export interface Destination {
|
||||||
path?: string;
|
path?: string;
|
||||||
name?: string;
|
to?: string;
|
||||||
params?: RouteParams;
|
params?: RouteParams;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,6 +53,9 @@ export class Router {
|
|||||||
if (partialRoute.component) {
|
if (partialRoute.component) {
|
||||||
QWeb.register("__component__" + partialRoute.name, partialRoute.component);
|
QWeb.register("__component__" + partialRoute.name, partialRoute.component);
|
||||||
}
|
}
|
||||||
|
if (partialRoute.redirect) {
|
||||||
|
this.validateDestination(partialRoute.redirect);
|
||||||
|
}
|
||||||
partialRoute.params = partialRoute.path ? findParams(partialRoute.path) : [];
|
partialRoute.params = partialRoute.path ? findParams(partialRoute.path) : [];
|
||||||
this.routes[partialRoute.name] = partialRoute as Route;
|
this.routes[partialRoute.name] = partialRoute as Route;
|
||||||
this.routeIds.push(partialRoute.name);
|
this.routeIds.push(partialRoute.name);
|
||||||
@@ -75,16 +78,20 @@ export class Router {
|
|||||||
}
|
}
|
||||||
|
|
||||||
destToUrl(dest: Destination): string {
|
destToUrl(dest: Destination): string {
|
||||||
if ((!dest.path && !dest.name) || (dest.path && dest.name)) {
|
this.validateDestination(dest);
|
||||||
throw new Error(`Invalid destination: ${JSON.stringify(dest)}`);
|
return dest.path || this.routeToURL(this.routes[dest.to!].path, dest.params!);
|
||||||
}
|
|
||||||
return dest.path || this.routeToURL(this.routes[dest.name!].path, dest.params!);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
get currentRouteName(): string | null {
|
get currentRouteName(): string | null {
|
||||||
return this.currentRoute && this.currentRoute.name;
|
return this.currentRoute && this.currentRoute.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private validateDestination(dest: Destination) {
|
||||||
|
if ((!dest.path && !dest.to) || (dest.path && dest.to)) {
|
||||||
|
throw new Error(`Invalid destination: ${JSON.stringify(dest)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private routeToURL(path: string, params: RouteParams): string {
|
private routeToURL(path: string, params: RouteParams): string {
|
||||||
const parts = path.split("/");
|
const parts = path.split("/");
|
||||||
const l = parts.length;
|
const l = parts.length;
|
||||||
|
|||||||
@@ -43,12 +43,12 @@ describe("router directive t-routecomponent", () => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
router = new TestRouter(env, routes, { mode: "history" });
|
router = new TestRouter(env, routes, { mode: "history" });
|
||||||
router.navigate({ name: "about" });
|
router.navigate({ to: "about" });
|
||||||
const app = new App(env);
|
const app = new App(env);
|
||||||
await app.mount(fixture);
|
await app.mount(fixture);
|
||||||
expect(fixture.innerHTML).toBe("<div><span>About</span></div>");
|
expect(fixture.innerHTML).toBe("<div><span>About</span></div>");
|
||||||
|
|
||||||
router.navigate({ name: "users" });
|
router.navigate({ to: "users" });
|
||||||
await nextTick();
|
await nextTick();
|
||||||
expect(fixture.innerHTML).toBe("<div><span>Users</span></div>");
|
expect(fixture.innerHTML).toBe("<div><span>Users</span></div>");
|
||||||
expect(env.qweb.templates.App.fn.toString()).toMatchSnapshot();
|
expect(env.qweb.templates.App.fn.toString()).toMatchSnapshot();
|
||||||
@@ -70,7 +70,7 @@ describe("router directive t-routecomponent", () => {
|
|||||||
|
|
||||||
const routes = [{ name: "book", path: "/book/{{title}}", component: Book }];
|
const routes = [{ name: "book", path: "/book/{{title}}", component: Book }];
|
||||||
router = new TestRouter(env, routes, { mode: "history" });
|
router = new TestRouter(env, routes, { mode: "history" });
|
||||||
router.navigate({ name: "book", params: { title: "1984" } });
|
router.navigate({ to: "book", params: { title: "1984" } });
|
||||||
const app = new App(env);
|
const app = new App(env);
|
||||||
await app.mount(fixture);
|
await app.mount(fixture);
|
||||||
expect(fixture.innerHTML).toBe("<div><span>Book 1984</span></div>");
|
expect(fixture.innerHTML).toBe("<div><span>Book 1984</span></div>");
|
||||||
@@ -97,7 +97,7 @@ describe("router directive t-routecomponent", () => {
|
|||||||
|
|
||||||
const routes = [{ name: "book", path: "/book/{{title}}/{{val.number}}", component: Book }];
|
const routes = [{ name: "book", path: "/book/{{title}}/{{val.number}}", component: Book }];
|
||||||
router = new TestRouter(env, routes, { mode: "history" });
|
router = new TestRouter(env, routes, { mode: "history" });
|
||||||
router.navigate({ name: "book", params: { title: "1984", val: "123" } });
|
router.navigate({ to: "book", params: { title: "1984", val: "123" } });
|
||||||
const app = new App(env);
|
const app = new App(env);
|
||||||
await app.mount(fixture);
|
await app.mount(fixture);
|
||||||
expect(fixture.innerHTML).toBe("<div><span>Book 1984|124</span></div>");
|
expect(fixture.innerHTML).toBe("<div><span>Book 1984|124</span></div>");
|
||||||
|
|||||||
@@ -16,6 +16,16 @@ afterEach(() => {
|
|||||||
router = null;
|
router = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("router miscellaneous", () => {
|
||||||
|
test("validate routes shape", () => {
|
||||||
|
expect(() => {
|
||||||
|
router = new TestRouter(env, [
|
||||||
|
{ name: "someroute", path: "/some/path", redirect: { abc: "hey" } as Destination }
|
||||||
|
]);
|
||||||
|
}).toThrow(`Invalid destination: {"abc":"hey"}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("routeToURL", () => {
|
describe("routeToURL", () => {
|
||||||
const routeToURL = Router.prototype["routeToURL"];
|
const routeToURL = Router.prototype["routeToURL"];
|
||||||
test("simple non parameterized path", () => {
|
test("simple non parameterized path", () => {
|
||||||
@@ -37,11 +47,11 @@ describe("destToURL", () => {
|
|||||||
}).toThrow('Invalid destination: {"abc":123}');
|
}).toThrow('Invalid destination: {"abc":123}');
|
||||||
|
|
||||||
expect(() => {
|
expect(() => {
|
||||||
router!.destToUrl({ name: "someroute" } as Destination);
|
router!.destToUrl({ to: "someroute" } as Destination);
|
||||||
}).not.toThrow();
|
}).not.toThrow();
|
||||||
|
|
||||||
expect(() => {
|
expect(() => {
|
||||||
router!.destToUrl({ path: "/someroute", name: "otherroute" } as Destination);
|
router!.destToUrl({ path: "/someroute", to: "otherroute" } as Destination);
|
||||||
}).toThrow();
|
}).toThrow();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -76,10 +86,10 @@ describe("redirect", () => {
|
|||||||
test("can redirect to other route", () => {
|
test("can redirect to other route", () => {
|
||||||
router = new TestRouter(env, [
|
router = new TestRouter(env, [
|
||||||
{ name: "routea", path: "/some/path" },
|
{ name: "routea", path: "/some/path" },
|
||||||
{ name: "routeb", path: "/some/other/path", redirect: { name: "routea" } }
|
{ name: "routeb", path: "/some/other/path", redirect: { to: "routea" } }
|
||||||
]);
|
]);
|
||||||
|
|
||||||
router.navigate({ name: "routeb" });
|
router.navigate({ to: "routeb" });
|
||||||
expect(window.location.pathname).toBe("/some/path");
|
expect(window.location.pathname).toBe("/some/path");
|
||||||
expect(router.currentRouteName).toBe("routea");
|
expect(router.currentRouteName).toBe("routea");
|
||||||
});
|
});
|
||||||
@@ -90,7 +100,7 @@ describe("redirect", () => {
|
|||||||
{ name: "routeb", path: "/some/other/path", redirect: { path: "/some/path" } }
|
{ name: "routeb", path: "/some/other/path", redirect: { path: "/some/path" } }
|
||||||
]);
|
]);
|
||||||
|
|
||||||
router.navigate({ name: "routeb" });
|
router.navigate({ to: "routeb" });
|
||||||
expect(window.location.pathname).toBe("/some/path");
|
expect(window.location.pathname).toBe("/some/path");
|
||||||
expect(router.currentRouteName).toBe("routea");
|
expect(router.currentRouteName).toBe("routea");
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user