// 2026-09-30 loading round: the chart wait lights houses up in order, the people // archive uses the shared orbit, and today's line enters softly (BUG-1125). import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import test from "node:test"; import React from "react"; import { renderToStaticMarkup } from "react-dom/server"; import { ChartPageSkeleton } from "../src/components/chart-page/chart-page-skeleton.tsx"; import { EMPTY_NORTH_INDIAN_CHART, VedicChartSvg } from "../src/components/personal-report/vedic-chart-svg.tsx"; import { StarterGreeting } from "../src/components/starter-home.tsx"; import { cssDeclarations } from "./css-contract-test-support.ts"; Object.assign(globalThis, { React }); const css = readFileSync(new URL("../src/app/globals.css", import.meta.url), "utf8"); const read = (path: string) => readFileSync(new URL(path, import.meta.url), "utf8"); test("the Vedic wait numbers its twelve houses in house order; the finished chart carries no index", () => { const waiting = renderToStaticMarkup(); const indexes = [...waiting.matchAll(/--house-index:\s*(\d+)/g)].map((match) => Number(match[1])); assert.deepEqual(indexes, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]); assert.doesNotMatch(waiting, /app-loading-orbit|app-loading-mark/, "no orbit logo over the chart"); assert.match(waiting, /role="status"/); assert.match(waiting, /虚构的等待句<\/span>/); const finished = renderToStaticMarkup(); assert.doesNotMatch(finished, /--house-index/); }); test("the western wait draws twelve sectors that light up around the wheel", () => { const waiting = renderToStaticMarkup(); assert.equal((waiting.match(/class="chart-skeleton-sector"/g) ?? []).length, 12); assert.deepEqual([...waiting.matchAll(/--house-index:\s*(\d+)/g)].map((match) => Number(match[1])), [...Array(12).keys()]); }); test("the house glow is a fill-only keyframe; lines stay still", () => { const start = css.indexOf("@keyframes chart-skeleton-house"); const keyframes = css.slice(start, css.indexOf("\n}", start) + 2); assert.match(keyframes, /fill-opacity: 0\.18/); assert.doesNotMatch(keyframes, /(^|[^-])opacity:|transform|stroke/); assert.match(cssDeclarations(".chart-page-skeleton .chart-page-western-spoke", css), /stroke-opacity: 0\.55/); }); test("people archive and the picker wait with the shared orbit, sentence for screen readers only", () => { const people = read("../src/components/people/people-page.tsx"); assert.match(people, //); assert.doesNotMatch(people, /

/); const picker = read("../src/components/subject-switcher.tsx"); assert.match(picker, //); }); test("today's line fades in (240ms, 4px) and is keyed on its text; reduced motion is instant (BUG-1125)", () => { const markup = renderToStaticMarkup(); assert.match(markup, /

虚构的一句。<\/p>/); assert.match(read("../src/components/starter-home.tsx"), /