import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import test from "node:test"; const read = (relative: string) => readFileSync(new URL(relative, import.meta.url), "utf8"); const error = read("../src/app/error.tsx"); const globalError = read("../src/app/global-error.tsx"); const notFound = read("../src/app/not-found.tsx"); const chinese = /[\u4e00-\u9fff]/; test("the app root ships error, global-error and not-found boundaries", () => { for (const source of [error, globalError, notFound]) { assert.ok(source.length > 0); assert.match(source, /export default function \w+\(/); } }); test("root error boundary is a client component that can reset and route home", () => { assert.match(error, /^"use client";/); assert.match(error, /reset,\s*\}: \{[\s\S]*reset: \(\) => void;/); assert.match(error, /onClick=\{\(\) => reset\(\)\}/); assert.match(error, /href="\/"/); assert.match(error, /error\.digest/); assert.doesNotMatch(error, /error\.stack/); }); test("global error boundary replaces the root layout without external styling", () => { assert.match(globalError, /^"use client";/); assert.match(globalError, //); assert.match(globalError, //); assert.match(globalError, /<\/html>/); assert.doesNotMatch(globalError, /^import /m); assert.doesNotMatch(globalError, /className="[a-z-]*(flex|text-|bg-|min-h-)/); assert.match(globalError, /minHeight: "44px"/); assert.match(globalError, /onClick=\{\(\) => reset\(\)\}/); assert.match(globalError, /window\.location\.assign\("\/"\)/); }); test("root not found stays a server component and links back to the chat home", () => { assert.doesNotMatch(notFound, /"use client"/); assert.doesNotMatch(notFound, /useState|useEffect|onClick/); assert.match(notFound, /404/); assert.match(notFound, /render=\{\}/); }); test("every boundary announces itself accessibly with one heading", () => { for (const source of [error, globalError]) { assert.match(source, /role="alert"/); } for (const source of [error, globalError, notFound]) { assert.equal(source.match(/

{ for (const source of [error, globalError, notFound]) { const copy = source.match(/>\s*([^<>{}]*[\u4e00-\u9fff][^<>{}]*)\s*= 2); for (const line of copy) { assert.match(line, chinese); assert.doesNotMatch(line, /[!!]/); assert.doesNotMatch(line, /\p{Extended_Pictographic}/u); } } });