import { render, screen } from "@testing-library/react";
import { describe, expect, it } from "vitest";
import { MemoryRouter } from "react-router-dom";
import { CommandPalette } from "../design/components/primitives/CommandPalette";
import { ROUTE_ELEMENTS } from "./App";
import {
WORKBENCH_ROUTES,
PALETTE_ROUTES,
LANDING_ROUTE_IDS,
ROUTE_DIGIT_MAP,
ROUTE_SECTIONS,
leftNavSections,
} from "./routes";
/**
* B3.5-a — the route registry is the single source of truth. These guards
* fail loudly if a route is added to App without the registry, if a registry
* route loses an element, or if a navigable route falls out of the command
* palette (the prior Demos/Calibration drift).
*/
describe("route registry ↔ App element map", () => {
it("every route has exactly one element, and no element is orphaned", () => {
const routeIds = WORKBENCH_ROUTES.map((r) => r.id).sort();
const elementIds = Object.keys(ROUTE_ELEMENTS).sort();
expect(elementIds).toEqual(routeIds);
});
it("no route element is undefined (a registry route without an element)", () => {
for (const route of WORKBENCH_ROUTES) {
expect(ROUTE_ELEMENTS[route.id]).toBeDefined();
}
});
it("route ids and paths are unique", () => {
const ids = WORKBENCH_ROUTES.map((r) => r.id);
const paths = WORKBENCH_ROUTES.map((r) => r.path);
expect(new Set(ids).size).toBe(ids.length);
expect(new Set(paths).size).toBe(paths.length);
});
});
describe("keyboard-digit assignment is honest", () => {
it("digits are unique and within 0–9", () => {
const digits = WORKBENCH_ROUTES.map((r) => r.keyboardDigit).filter(
(d): d is string => d !== null,
);
expect(new Set(digits).size).toBe(digits.length);
for (const d of digits) expect(d).toMatch(/^[0-9]$/);
});
it("ROUTE_DIGIT_MAP maps each pinned digit to its route path", () => {
for (const route of WORKBENCH_ROUTES) {
if (route.keyboardDigit === null) continue;
expect(ROUTE_DIGIT_MAP[route.keyboardDigit]).toBe(route.path);
}
const pinned = WORKBENCH_ROUTES.filter((r) => r.keyboardDigit !== null);
expect(Object.keys(ROUTE_DIGIT_MAP)).toHaveLength(pinned.length);
});
it("more routes than digits — at least one route is palette-only (honest model)", () => {
const paletteOnly = WORKBENCH_ROUTES.filter((r) => r.keyboardDigit === null);
expect(paletteOnly.length).toBeGreaterThan(0);
});
});
describe("landing routes derive from the registry", () => {
it("includes Replay and Calibration (the prior drift)", () => {
expect(LANDING_ROUTE_IDS).toContain("replay");
expect(LANDING_ROUTE_IDS).toContain("calibration");
});
});
describe("leftNavSections", () => {
it("covers every LeftNav route exactly once, in section order", () => {
const flattened = leftNavSections().flatMap((g) => g.routes.map((r) => r.id));
const expected = WORKBENCH_ROUTES.filter((r) => r.leftNavVisible).map((r) => r.id);
expect(flattened).toEqual(expected);
});
it("only emits known sections", () => {
for (const group of leftNavSections()) {
expect(ROUTE_SECTIONS).toContain(group.section);
}
});
});
describe("command palette reachability", () => {
it("every palette-visible route is reachable as a Navigate command", () => {
render(
{}} />
,
);
for (const route of PALETTE_ROUTES) {
expect(
screen.getByRole("button", { name: `Open ${route.label}` }),
).toBeInTheDocument();
}
});
it("Demos and Calibration are present (the regression they fell out of)", () => {
render(
{}} />
,
);
expect(screen.getByRole("button", { name: "Open Demos" })).toBeInTheDocument();
expect(
screen.getByRole("button", { name: "Open Calibration" }),
).toBeInTheDocument();
});
});