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.
153 lines
6.0 KiB
TypeScript
153 lines
6.0 KiB
TypeScript
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, />重新评估</);
|
||
});
|