Files
Jyotisha/frontend/tests/home-bootstrap-screens.test.tsx
T
jesse-ux da35b3e4af refactor(home): split bootstrap, recovery polling, and shells
Move the home startup sequence and consultation recovery poll into
plain functions, and the error and onboarding screens into components.
Landing rules, the 20s fatal screen, retry, and the chart settings
deep link stay the same.
2026-09-25 02:59:11 +08:00

153 lines
6.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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(
<HomeBootstrapError accountError={accountError} onRetry={() => 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(<HomeBootstrapError accountError={accountError} onRetry={() => { 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, /<HomeBootstrapError[\s\S]*onRetry=\{\(\) => 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(
<HomeOnboardingShell
profileComplete={false}
profileDraft={emptyProfile}
setProfileDraft={() => 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(
<HomeOnboardingShell
profileComplete={false}
profileDraft={{ ...emptyProfile, name: "林遥" }}
setProfileDraft={() => 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, />继续</);
const placeMarkup = renderToStaticMarkup(
<HomeOnboardingShell
profileComplete={false}
profileDraft={{ ...emptyProfile, name: "林遥" }}
setProfileDraft={() => 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, />确定</);
const retryMarkup = renderToStaticMarkup(
<HomeOnboardingShell
profileComplete={false}
profileDraft={{ ...emptyProfile, name: "林遥" }}
setProfileDraft={() => 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, />重新评估</);
});