import { describe, expect, it } from "vitest"; import { createTechLogServingContract } from "../../scripts/lib/tech-log-serving-contract.ts"; import { TECH_LOG_ROUTE_REGISTRY } from "../../src/features/tech-log/contracts/tech-log-route-contract.ts"; const publicRoutePaths = Object.values(TECH_LOG_ROUTE_REGISTRY) .filter((route) => route.layoutGroup === "PUBLIC") .map((route) => route.path); describe("TechLog production serving contract", () => { it("derives one pattern per registered Public route", () => { const contract = createTechLogServingContract({ publicRoutePaths }); expect(contract.schemaVersion).toBe(2); expect(contract.publicSpaPathPatterns).toEqual([ "^/$", "^/cases/[^/]+$", "^/explore$", "^/explore/[^/]+$", "^/profile$", "^/projects$", "^/projects/[^/]+$", "^/projects/[^/]+/activity$", "^/projects/[^/]+/decisions$", "^/projects/[^/]+/records$", "^/questions/[^/]+$", "^/references/[^/]+$", "^/releases$", "^/releases/[^/]+$", "^/search$", "^/topics/[^/]+$", ]); expect(contract.studioPathPrefix).toBe("/studio"); expect(contract.studioSpaPathPatterns).toEqual([ "^/studio$", "^/studio/assets$", "^/studio/documents$", "^/studio/documents/new$", "^/studio/documents/[^/]+/(edit|validation|preview|publish)$", "^/studio/publications$", "^/studio/publications/[^/]+/preview$", ]); expect(contract.notFound).toEqual({ status: 404, contentType: "text/plain;charset=UTF-8", body: "Not Found", }); }); /** * The reason this migration happened: a slug that did not exist at build time * used to be 404ed by the web server before the SPA was asked. A published * record must be served whatever its slug. */ it("serves a slug the build never saw", () => { const { publicSpaPathPatterns } = createTechLogServingContract({ publicRoutePaths }); const matches = (pathname: string) => publicSpaPathPatterns.some((pattern) => new RegExp(pattern).test(pathname)); expect(matches("/cases/a-record-published-yesterday")).toBe(true); expect(matches("/projects/a-new-project/decisions")).toBe(true); expect(matches("/topics/a-new-topic")).toBe(true); }); /** A parameter is one segment. Extra depth is a 404, not a soft 200. */ it("does not let a parameter swallow a slash", () => { const { publicSpaPathPatterns } = createTechLogServingContract({ publicRoutePaths }); const matches = (pathname: string) => publicSpaPathPatterns.some((pattern) => new RegExp(pattern).test(pathname)); expect(matches("/cases/a/b")).toBe(false); expect(matches("/projects/one/two/three")).toBe(false); expect(matches("/nope")).toBe(false); }); /** * The catch-all belongs to the SPA, not to the edge. Serving index.html for * every unmatched URL would turn a 404 into a soft 200 and hide broken links. */ it("drops the catch-all route", () => { const { publicSpaPathPatterns } = createTechLogServingContract({ publicRoutePaths: ["/", "*"], }); expect(publicSpaPathPatterns).toEqual(["^/$"]); }); });