mirror of
https://github.com/cloudflare/vinext.git
synced 2026-09-14 19:04:59 +08:00
dd1dfae3c6
* fix(app-router): scope layout params and propagate layout head errors Layouts received full route params, layout generateMetadata failures were swallowed, and layout-thrown forbidden()/unauthorized() fell back through the not-found boundary path. Those diverge from Next.js when nested layouts depend on segment params, when head generation fails before page render, or when HTTP access APIs are thrown from a layout. The generated RSC entry now delegates param slicing, head resolution, and parent access-boundary selection to typed runtime helpers. The helpers keep route-specific imports in the entry while moving the behavioral core into unit-tested modules. Tests port Next.js layout params, global-error, forbidden, and unauthorized coverage into focused helper and integration regressions. * test(app-router): cover layout viewport error boundaries Layout generateViewport() failures now intentionally share the same boundary path as layout generateMetadata() failures. Copilot flagged that this behavior change needed direct coverage. Add dev and production-preview compat assertions for co-located error.tsx handling and global-error escalation, with fixtures that throw from layout generateViewport(). * chore(app-router): address head review nits
48 lines
2.2 KiB
TypeScript
48 lines
2.2 KiB
TypeScript
import { describe, expect, it } from "vite-plus/test";
|
|
import { resolveAppPageSegmentParams } from "../packages/vinext/src/server/app-page-params.js";
|
|
|
|
describe("app page params helpers", () => {
|
|
it("passes only params that apply to each layout", () => {
|
|
// Ported from Next.js: test/e2e/app-dir/layout-params/layout-params.test.ts
|
|
// https://github.com/vercel/next.js/blob/canary/test/e2e/app-dir/layout-params/layout-params.test.ts
|
|
const routeSegments = ["base", "[param1]", "[param2]"];
|
|
const matchedParams = { param1: "something", param2: "another" };
|
|
|
|
expect(resolveAppPageSegmentParams(routeSegments, 0, matchedParams)).toEqual({});
|
|
expect(resolveAppPageSegmentParams(routeSegments, 1, matchedParams)).toEqual({});
|
|
expect(resolveAppPageSegmentParams(routeSegments, 2, matchedParams)).toEqual({
|
|
param1: "something",
|
|
});
|
|
expect(resolveAppPageSegmentParams(routeSegments, 3, matchedParams)).toEqual({
|
|
param1: "something",
|
|
param2: "another",
|
|
});
|
|
});
|
|
|
|
it("scopes catch-all params to the catch-all layout", () => {
|
|
// Ported from Next.js: test/e2e/app-dir/layout-params/layout-params.test.ts
|
|
// https://github.com/vercel/next.js/blob/canary/test/e2e/app-dir/layout-params/layout-params.test.ts
|
|
const routeSegments = ["catchall", "[...params]"];
|
|
const matchedParams = { params: ["something", "another"] };
|
|
|
|
expect(resolveAppPageSegmentParams(routeSegments, 1, matchedParams)).toEqual({});
|
|
expect(resolveAppPageSegmentParams(routeSegments, 2, matchedParams)).toEqual({
|
|
params: ["something", "another"],
|
|
});
|
|
});
|
|
|
|
it("omits empty optional catch-all params from layouts", () => {
|
|
// Ported from Next.js: test/e2e/app-dir/layout-params/layout-params.test.ts
|
|
// https://github.com/vercel/next.js/blob/canary/test/e2e/app-dir/layout-params/layout-params.test.ts
|
|
const routeSegments = ["optional-catchall", "[[...params]]"];
|
|
|
|
expect(resolveAppPageSegmentParams(routeSegments, 1, { params: [] })).toEqual({});
|
|
expect(resolveAppPageSegmentParams(routeSegments, 2, { params: [] })).toEqual({});
|
|
expect(
|
|
resolveAppPageSegmentParams(routeSegments, 2, { params: ["something", "another"] }),
|
|
).toEqual({
|
|
params: ["something", "another"],
|
|
});
|
|
});
|
|
});
|