Files
cloudflare__vinext/tests/pregenerated-concrete-paths.test.ts
T
Nathan Nguyen 49b45b9891 feat(ppr): add encodePrerenderRouteParams and match kind exact payload tests (#1714)
* feat(ppr): add fallback shell payload identity

* refactor(ppr): address review feedback on payload identity helpers

- normalizePregeneratedPathname: document the deliberate non-strict vs
  strict normalization choice so it isn't "fixed" into a build-time throw
- addPregeneratedConcretePath: normalize the pathname internally as the
  single source of truth, removing the caller pre-normalize footgun
- export PrerenderRouteParamsRouteMatch for #1716 consumers
- cover direct un-normalized recording with a test

* fix(ppr): mark PrerenderRouteParamsRouteMatch @public for knip

The type is exported for #1716's serving consumers but has no in-repo
reference yet, so knip's no-unused-exports gate flags it. Knip excludes
exports tagged @public from that report; this keeps the reviewer-requested
export without failing CI.

* docs(ppr): document live-Set and dedup contracts on concrete-path registry

Address bonk review notes:
- getRenderedConcreteUrlPathsForRoute returns the live backing Set for
  allocation-free hot-path lookups; document that callers must not retain
  the reference across a re-seed (clear empties the map, stranding it).
- parsePregeneratedConcretePaths intentionally does not dedupe repeated
  route patterns; document that they merge additively and value-dedup in
  addPregeneratedConcretePath makes the result equivalent.

---------

Co-authored-by: James <james@eli.cx>
2026-06-03 12:20:32 +01:00

90 lines
3.4 KiB
TypeScript

import { describe, it, expect, afterEach } from "vite-plus/test";
import {
clearPregeneratedConcretePaths,
addPregeneratedConcretePath,
getRenderedConcreteUrlPathsForRoute,
initPregeneratedPathsFromGlobals,
normalizePregeneratedPathname,
} from "../packages/vinext/src/server/pregenerated-concrete-paths.js";
describe("pregenerated concrete paths", () => {
afterEach(() => {
clearPregeneratedConcretePaths();
});
it("returns undefined for an unknown route pattern", () => {
expect(getRenderedConcreteUrlPathsForRoute("/en/blog/[slug]")).toBeUndefined();
});
it("stores and retrieves pathnames for a route pattern", () => {
addPregeneratedConcretePath("/:locale/blog/:slug", "/en/blog/hello");
addPregeneratedConcretePath("/:locale/blog/:slug", "/fr/blog/bonjour");
const paths = getRenderedConcreteUrlPathsForRoute("/:locale/blog/:slug");
expect(paths).toBeDefined();
expect([...paths!]).toEqual(["/en/blog/hello", "/fr/blog/bonjour"]);
});
it("supports independent route patterns", () => {
addPregeneratedConcretePath("/:locale/blog/:slug", "/en/blog/hello");
addPregeneratedConcretePath("/products/:id", "/products/42");
expect([...getRenderedConcreteUrlPathsForRoute("/:locale/blog/:slug")!]).toEqual([
"/en/blog/hello",
]);
expect([...getRenderedConcreteUrlPathsForRoute("/products/:id")!]).toEqual(["/products/42"]);
});
it("returns an empty state after clear", () => {
addPregeneratedConcretePath("/en/blog/[slug]", "/en/blog/persistent");
expect(getRenderedConcreteUrlPathsForRoute("/en/blog/[slug]")).toBeDefined();
clearPregeneratedConcretePaths();
expect(getRenderedConcreteUrlPathsForRoute("/en/blog/[slug]")).toBeUndefined();
});
it("clears stale paths from a previous build on re-population (issue 3)", () => {
// Build A
addPregeneratedConcretePath("/en/blog/[slug]", "/en/blog/old");
addPregeneratedConcretePath("/en/blog/[slug]", "/en/blog/also-old");
expect(getRenderedConcreteUrlPathsForRoute("/en/blog/[slug]")!.size).toBe(2);
// Build B — clear and re-seed without the old paths
clearPregeneratedConcretePaths();
addPregeneratedConcretePath("/en/blog/[slug]", "/en/blog/new");
const paths = getRenderedConcreteUrlPathsForRoute("/en/blog/[slug]")!;
expect(paths.has("/en/blog/old")).toBe(false);
expect(paths.has("/en/blog/also-old")).toBe(false);
expect(paths.has("/en/blog/new")).toBe(true);
expect(paths.size).toBe(1);
});
it("normalizes percent-encoded pathnames", () => {
expect(normalizePregeneratedPathname("/en/blog/hello%20world")).toBe("/en/blog/hello world");
});
it("normalizes un-normalized pathnames recorded directly", () => {
addPregeneratedConcretePath("/:locale/blog/:slug", "/en/blog/hello%20world");
addPregeneratedConcretePath("/:locale/blog/:slug", "//en/./blog/world");
expect([...getRenderedConcreteUrlPathsForRoute("/:locale/blog/:slug")!]).toEqual([
"/en/blog/hello world",
"/en/blog/world",
]);
});
it("initializes from the Worker global concrete-path table", () => {
globalThis.__VINEXT_PREGENERATED_CONCRETE_PATHS = [
["/:locale/blog/:slug", ["/en/blog/hello%20world"]],
];
initPregeneratedPathsFromGlobals();
delete globalThis.__VINEXT_PREGENERATED_CONCRETE_PATHS;
expect([...getRenderedConcreteUrlPathsForRoute("/:locale/blog/:slug")!]).toEqual([
"/en/blog/hello world",
]);
});
});