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 { HomeBootstrapError } from "../src/components/home-bootstrap-error.tsx"; import { HomeOnboardingShell } from "../src/components/home-onboarding-shell.tsx"; import type { BirthTimeGuidedController } from "../src/hooks/use-birth-time-guided-journey.ts"; import { emptyProfile, presetOnboardingMessage } from "../src/lib/home-types.ts"; import { createClientLifecycleHarness } from "./react-client-lifecycle-test-support.ts"; Object.assign(globalThis, { React }); const page = readFileSync(new URL("../src/app/(app)/page.tsx", import.meta.url), "utf8"); test("the fatal screen keeps its copy and retries through retryHomeBootstrap", async () => { const accountError = "连接云端服务超时。请检查网络后重试,或返回登录页重新建立会话。"; const markup = renderToStaticMarkup( undefined} />, ); assert.match(markup, /暂时无法进入 Jyotisha/); assert.match(markup, /连接云端服务超时。请检查网络后重试,或返回登录页重新建立会话。/); assert.match(markup, /重试/); assert.match(markup, /返回登录/); assert.match(markup, /app-loading app-loading-error/); assert.match(markup, /role="alert"/); const harness = createClientLifecycleHarness(); let retried = 0; try { await harness.render( { retried += 1; }} />); const retry = harness.elements().find((node) => node.tagName === "BUTTON" && node.text.includes("重试")); assert.ok(retry); await harness.event(retry); assert.equal(retried, 1); } finally { await harness.close(); } // 原值:错误屏按钮内联在 page.tsx,onClick 直接调用 retryHomeBootstrap。 // 新值:按钮在 HomeBootstrapError,page.tsx 把 onRetry 接到同一个 retryHomeBootstrap(...reloadSessionList)。 // 原因:错误屏抽成组件后,重试仍局部重跑,不整页刷新。 assert.match(page, / retryHomeBootstrap\([\s\S]*reloadSessionList,[\s\S]*\)\}/); assert.doesNotMatch(page, /window\.location\.reload\(\)/); }); test("onboarding keeps the name prompt, birth card, place card, and retry card", () => { const guided = {} as BirthTimeGuidedController; const nameMarkup = renderToStaticMarkup( undefined} onboardingStep="name" presetMessageLength={presetOnboardingMessage.length} currentOnboardingMessage={presetOnboardingMessage} onboardingJustCompleted={false} onboardingCardReady={false} presetMessageFinished birthTimeJourney={null} birthTimeAssessmentPhase={null} birthTimeError="" birthTimeGuided={guided} accountError="" profileSaving={false} saveOnboardingBirth={() => undefined} saveOnboardingPlace={() => undefined} retryBirthTimeAssessment={() => undefined} />, ); assert.match(nameMarkup, /你好,我是 Jyotisha/); assert.match(nameMarkup, /请问我该怎么称呼你/); assert.doesNotMatch(nameMarkup, /出生日期与时间/); const birthMarkup = renderToStaticMarkup( undefined} onboardingStep="birth" presetMessageLength={80} currentOnboardingMessage="出生时间" onboardingJustCompleted={false} onboardingCardReady presetMessageFinished birthTimeJourney={null} birthTimeAssessmentPhase={null} birthTimeError="" birthTimeGuided={guided} accountError="" profileSaving={false} saveOnboardingBirth={() => undefined} saveOnboardingPlace={() => undefined} retryBirthTimeAssessment={() => undefined} />, ); assert.match(birthMarkup, /出生日期与时间/); assert.match(birthMarkup, />继续 undefined} onboardingStep="place" presetMessageLength={80} currentOnboardingMessage="出生地点" onboardingJustCompleted={false} onboardingCardReady presetMessageFinished birthTimeJourney={null} birthTimeAssessmentPhase={null} birthTimeError="" birthTimeGuided={guided} accountError="" profileSaving={false} saveOnboardingBirth={() => undefined} saveOnboardingPlace={() => undefined} retryBirthTimeAssessment={() => undefined} />, ); assert.match(placeMarkup, /出生地点/); assert.match(placeMarkup, /搜索全球城市或区县,系统会匹配出生当日的时区。/); assert.match(placeMarkup, />确定 undefined} onboardingStep="rectification" presetMessageLength={80} currentOnboardingMessage="校正" onboardingJustCompleted={false} onboardingCardReady presetMessageFinished birthTimeJourney={null} birthTimeAssessmentPhase={null} birthTimeError="" birthTimeGuided={guided} accountError="" profileSaving={false} saveOnboardingBirth={() => undefined} saveOnboardingPlace={() => undefined} retryBirthTimeAssessment={() => undefined} />, ); assert.match(retryMarkup, /出生时间尚未完成评估/); assert.match(retryMarkup, /资料已经保留,但暂时无法恢复校正进度。系统不会应用未经验证的具体时间。/); assert.match(retryMarkup, />重新评估