Files
Jyotisha/frontend/tests/admin-antd-ssr-contract.test.ts
T
Jesse_Chen 9c296f1e3f
Independent Staging Quality Gate / validate (push) Successful in 12m8s
Independent Staging Quality Gate / publish (push) Successful in 14m29s
fix(ux): surface hidden notices, bound report waits, add root boundaries
Framework-level UX fixes found while auditing staging (BUG-216..220).

- chat: route 44 previously discarded composer notices to sonner with
  dedupe, so recovery, cancel and archive feedback is actually visible
  (BUG-216)
- chat: anchor stream auto-scroll to bottom proximity and add a
  jump-to-latest control, so reading history is no longer interrupted
  on every token (BUG-218)
- reports: replace the silent 120s poll cutoff with an explicit
  timed-out state, an 8m budget, stepped backoff and an elapsed
  counter (BUG-217)
- reports: pause polling while the tab is hidden, via a shared hook
- app: add root error, global-error and not-found boundaries (BUG-219)
- admin: add antd SSR style extraction and the React 19 render adapter,
  and move admin-only css out of the global stylesheet (BUG-220)
- membership: run bootstrap fetches concurrently and pause payment
  polling while hidden
- build: configure optimizePackageImports

Verified on top of 2d370f2e: tsc, eslint, next build, and the related
frontend contract suites.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-17 13:14:15 +08:00

70 lines
3.9 KiB
TypeScript

import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import test from "node:test";
const registry = readFileSync(new URL("../src/components/admin/admin-antd-registry.tsx", import.meta.url), "utf8");
const adminLayout = readFileSync(new URL("../src/app/admin/layout.tsx", import.meta.url), "utf8");
const rootLayout = readFileSync(new URL("../src/app/layout.tsx", import.meta.url), "utf8");
const globalsCss = readFileSync(new URL("../src/app/globals.css", import.meta.url), "utf8");
const adminCss = readFileSync(new URL("../src/app/admin/admin.css", import.meta.url), "utf8");
const nextConfig = readFileSync(new URL("../next.config.ts", import.meta.url), "utf8");
const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")) as {
dependencies: Record<string, string>;
};
test("admin antd styles are extracted during server rendering", () => {
assert.match(registry, /^"use client";/);
assert.match(registry, /import \{ StyleProvider, createCache, extractStyle \} from "@ant-design\/cssinjs";/);
assert.match(registry, /useServerInsertedHTML\(\(\) => \{/);
assert.match(registry, /extractStyle\(cache, \{ plain: true, once: true \}\)/);
assert.match(registry, /<StyleProvider cache=\{cache\}>\{children\}<\/StyleProvider>/);
assert.match(registry, /id="antd-cssinjs"/);
assert.match(registry, /data-rc-order="prepend"/);
assert.ok("@ant-design/cssinjs" in packageJson.dependencies, "cssinjs must be a declared dependency");
});
test("the antd registry wraps the admin subtree only", () => {
assert.match(adminLayout, /import \{ AdminAntdRegistry \} from "@\/components\/admin\/admin-antd-registry";/);
assert.match(adminLayout, /<AdminAntdRegistry>\s*<AdminApp>\{children\}<\/AdminApp>\s*<\/AdminAntdRegistry>/);
assert.doesNotMatch(rootLayout, /AdminAntdRegistry|cssinjs|antd/);
});
test("antd runs with the React 19 render patch inside admin", () => {
assert.match(registry, /import \{ unstableSetRender \} from "antd";/);
assert.match(registry, /import \{ createRoot, type Root \} from "react-dom\/client";/);
assert.match(registry, /unstableSetRender\(\(node, container\) => \{/);
assert.match(registry, /target\._reactRoot \?\?= createRoot\(target\);/);
assert.match(registry, /root\.render\(node\);/);
assert.match(registry, /root\.unmount\(\);/);
});
test("admin antd overrides ship only on admin routes", () => {
assert.doesNotMatch(globalsCss, /\.admin-app-shell \.ant-layout-content/);
assert.doesNotMatch(globalsCss, /\.admin-app-shell \.ant-table-wrapper/);
assert.doesNotMatch(globalsCss, /\.admin-text-list|\.admin-loading/);
assert.match(adminCss, /\.admin-app-shell \.ant-layout-content \{ padding: 22px; \}/);
assert.match(adminCss, /\.admin-app-shell \.ant-table-wrapper \.ant-table \{ background: #fbfaf7; \}/);
assert.match(adminCss, /\.admin-text-list \{ max-width: 680px;/);
assert.match(adminCss, /\.admin-loading \{ min-height: 100dvh;/);
assert.match(adminLayout, /import "\.\/admin\.css";/);
assert.doesNotMatch(rootLayout, /admin\.css/);
});
test("the admin shell keeps one antd reset stylesheet", () => {
assert.match(adminLayout, /import "antd\/dist\/reset\.css";/);
assert.doesNotMatch(adminLayout, /@refinedev\/antd\/dist\/reset\.css/);
});
test("barrel-heavy packages are optimized at build time", () => {
assert.match(nextConfig, /optimizePackageImports: \[/);
for (const pkg of ["@ant-design/icons", "@refinedev/antd", "@refinedev/core", "antd", "date-fns", "lucide-react"]) {
assert.ok(nextConfig.includes(`"${pkg}"`), `${pkg} must be listed in optimizePackageImports`);
assert.ok(pkg in packageJson.dependencies, `${pkg} must be a declared dependency`);
}
assert.match(nextConfig, /authInterrupts: true/);
assert.match(nextConfig, /outputFileTracingIncludes: \{/);
assert.match(nextConfig, /"\/api\/consult": \[/);
assert.match(nextConfig, /turbopack: \{ root: repositoryRoot \}/);
assert.match(nextConfig, /output: "standalone"/);
});