test/shared/admin-surface.test.ts
Rama main · réplica de lectura del repositorio original.
import { expect } from "@std/expect";
import { describe, it as test } from "@std/testing/bdd";
import type { AdminDestinationId } from "#shared/admin-surface/ids.ts";
import {
ADMIN_SURFACE,
adminDestination,
adminDestinationAllowed,
adminDestinationAt,
adminPath,
adminPattern,
adminRecordPath,
afterSavePath,
} from "#shared/admin-surface.ts";
describe("the pattern a route declares", () => {
test("is the one the surface holds, for every route", () => {
// adminPattern names the literal its declaration wrote, which the fold
// cannot carry through as a type. This reads all of them back, so the
// name and the value can never drift apart unnoticed.
const wrong = Object.entries(ADMIN_SURFACE.destinations)
.filter(
([id, destination]) =>
adminPattern(id as AdminDestinationId) !== destination.pattern,
)
.map(([id]) => id);
expect(wrong).toEqual([]);
});
test("says which id was never declared", () => {
// Reached only past the types, which is how a page definition naming a
// route that does not exist shows itself.
expect(() => adminPattern("nowhere" as AdminDestinationId)).toThrow(
'No admin route is declared as "nowhere"',
);
});
test("refuses to mint a record URL for a route taking two parameters", () => {
// An entity page names the route it serves, so a route that needs a
// second value cannot be one, and saying so at the page definition beats
// minting a URL with a parameter still in it.
expect(() => adminRecordPath("answerEdit", 7)).toThrow(
'Admin route "answerEdit" does not address one record',
);
});
test("refuses to mint a record URL for a route taking none", () => {
// A collection's own path names no record either, and quietly returning
// it would send every record to the same page.
expect(() => adminRecordPath("holidays", 7)).toThrow(
'Admin route "holidays" does not address one record',
);
});
test("mints a record URL whatever the route calls its parameter", () => {
expect(adminRecordPath("attendee", 7)).toBe("/admin/attendees/7");
expect(adminRecordPath("holiday", 7)).toBe("/admin/holidays/7");
});
test("says which path has no route", () => {
expect(() => adminDestinationAt("/admin/nowhere")).toThrow(
'No admin route is declared at "/admin/nowhere"',
);
});
test("keeps the parameters the route takes", () => {
expect(adminPattern("holiday")).toBe("/admin/holidays/:id");
expect(adminPattern("holidays")).toBe("/admin/holidays");
});
});
describe("admin surface paths", () => {
test("fills every named route parameter", () => {
expect(adminPath("answerEdit", { answerId: 9, id: 42 })).toBe(
"/admin/questions/42/answers/9/edit",
);
});
test("allows write forms only for their audience while writable", () => {
expect(adminDestinationAllowed("modifierEdit", "manager", false)).toBe(
true,
);
expect(adminDestinationAllowed("modifierEdit", "editor", false)).toBe(
false,
);
expect(adminDestinationAllowed("modifierEdit", "owner", true)).toBe(false);
});
test("allows view routes in read-only mode", () => {
expect(adminDestinationAllowed("modifiers", "manager", true)).toBe(true);
});
test("takes each route's intent from the group it is declared in", () => {
expect(adminDestination("modifiers").intent).toBe("view");
expect(adminDestination("modifierEdit").intent).toBe("write-form");
});
test("gives every route the audience its area declares", () => {
// holidayNew states no role of its own, so it takes the area's owner-only
// audience — the same one the handler enforces.
expect(adminDestination("holidayNew").audience).toEqual(["owner"]);
expect(adminDestination("holidays").audience).toEqual(["owner"]);
});
});
describe("generated CRUD save paths", () => {
test("uses the collection list when the POST route has no override", () => {
expect(afterSavePath(adminDestination("modifiers"), "modifiers", 3)).toBe(
"/admin/modifiers",
);
expect(
afterSavePath(adminDestination("modifierEdit"), "modifiers", 3),
).toBe("/admin/modifiers");
expect(afterSavePath(adminDestination("statuses"), "statuses", 3)).toBe(
"/admin/settings/statuses",
);
});
test("uses record overrides on the create and edit POST routes", () => {
expect(afterSavePath(adminDestination("groups"), "groups", 7)).toBe(
"/admin/groups/7",
);
expect(afterSavePath(adminDestination("groupEdit"), "groups", 7)).toBe(
"/admin/groups/7",
);
expect(afterSavePath(adminDestination("statusEdit"), "statuses", 9)).toBe(
"/admin/settings/statuses/9",
);
});
});