feat(housekeeping): validate preview route runtime

This commit is contained in:
Simo committed 2026-08-31 18:45:45 +02:00
1 parent d868c990bf
commit 543607a80e
17 files changed
+466 -6

No files matched your search

@@ -0,0 +1,95 @@
import { describe, expect, it } from "vitest";
import { PERMS } from "@/lib/permission-slugs";
import { anyCapability, type HousekeepingDomainManifest } from "../contracts";
import { createHousekeepingRegistry } from "../registry";
import { matchHousekeepingRoute } from "./match-route";
const peopleManifest = {
id: "people",
labelKey: "pages.housekeeping.domains.people.title",
descriptionKey: "pages.housekeeping.domains.people.description",
iconId: "users",
previewHref: "/ase-next/people",
capability: anyCapability(PERMS.USERS_VIEW),
landingRouteId: "people.users",
routes: [
{
id: "people.users",
labelKey: "pages.housekeeping.people.users.title",
href: "/ase-next/people/users",
capability: anyCapability(PERMS.USERS_VIEW),
},
{
id: "people.user-settings",
labelKey: "pages.housekeeping.people.userSettings.title",
href: "/ase-next/people/users/settings",
capability: anyCapability(PERMS.USERS_VIEW),
},
{
id: "people.user-detail",
labelKey: "pages.housekeeping.people.userDetail.title",
href: "/ase-next/people/users/:id",
capability: anyCapability(PERMS.USERS_VIEW),
},
],
searchProviders: [],
inboxSources: [],
widgets: [],
} satisfies HousekeepingDomainManifest;
const registry = createHousekeepingRegistry([peopleManifest]);
describe("matchHousekeepingRoute", () => {
it("matches concrete and dynamic preview routes", () => {
expect(matchHousekeepingRoute(registry, "/ase-next/people/users")).toEqual({
routeId: "people.users",
domain: "people",
params: {},
canonicalHref: "/ase-next/people/users",
});
expect(
matchHousekeepingRoute(registry, "/ase-next/people/users/42"),
).toEqual({
routeId: "people.user-detail",
domain: "people",
params: { id: "42" },
canonicalHref: "/ase-next/people/users/42",
});
});
it("prefers a literal route over a dynamic route", () => {
expect(
matchHousekeepingRoute(registry, "/ase-next/people/users/settings"),
).toMatchObject({
routeId: "people.user-settings",
params: {},
});
});
it("decodes a parameter exactly once", () => {
expect(
matchHousekeepingRoute(registry, "/ase-next/people/users/%34%32"),
).toMatchObject({
routeId: "people.user-detail",
params: { id: "42" },
canonicalHref: "/ase-next/people/users/42",
});
});
it.each([
"/ase-next/people",
"/ase-next/people/unknown",
"/ase-next/people/users/",
"/ase-next/people/users?rank=7",
"/ase-next/people/users#active",
"/ase-next/people\\users",
"/ase-next/people//users",
"/ase-next/people/./users",
"/ase-next/people/users/..",
"/ase-next/people/users/%2F",
"/ase-next/people/users/%252F",
"/ase-next/people/users/%00",
])("rejects an unregistered canonical path: %s", (pathname) => {
expect(matchHousekeepingRoute(registry, pathname)).toBeNull();
});
});