refactor(chat): extract profile onboarding and rectification surface hooks

Close the home-page split by moving account/onboarding and rectification glue out of page.tsx without relocating React state, keeping the route static and hook order intact.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-09-02 05:56:47 +08:00
parent fbb80fa376
commit bf6989eccf
15 changed files with 920 additions and 527 deletions
@@ -2,10 +2,12 @@ import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import test from "node:test";
import { homeSurface } from "./home-surface.ts";
test("onboarding keeps the current card visible while birth-time assessment is pending", () => {
// Given: saving the selected time can span profile persistence and assessment requests.
const source = [
readFileSync(new URL("../src/app/page.tsx", import.meta.url), "utf8"),
homeSurface,
readFileSync(new URL("../src/components/birth-time-assessment-overlay.tsx", import.meta.url), "utf8"),
].join("\n");
@@ -11,6 +11,7 @@ import { guidedTerminalPath } from "../src/lib/birth-time-guided-terminal.ts";
import { parseJourneyResponse } from "../src/lib/birth-time-journey-client.ts";
import { dynamicBirthTimePreview } from "../src/lib/birth-time-dynamic-preview.ts";
import { guidedBirthTimePreview } from "../src/lib/birth-time-guided-preview.ts";
import { homeSurface } from "./home-surface.ts";
test("draft revision publishes its new version before confirmation can fail", async () => {
const original = guidedBirthTimePreview("birth-time-rectification-draft");
@@ -147,7 +148,7 @@ test("unconfirmed terminal candidates preserve the range without offering direct
test("terminal CJK copy stays intact while homepage candidates remain unconfirmed in v3", () => {
const candidateResultSource = readFileSync(new URL("../src/components/birth-time-candidate-result.tsx", import.meta.url), "utf8");
const pageSource = readFileSync(new URL("../src/app/page.tsx", import.meta.url), "utf8");
const pageSource = homeSurface;
assert.match(candidateResultSource, /候选范围已保留,但当前证据不足以将具体分钟写入当前排盘时间。补充经历后可重新评估。/);
assert.match(pageSource, /`出生资料已保存。\$\{birthTimeConsultationOptionsCopy\(savedProfile\)\}`/);
@@ -69,7 +69,7 @@ test("auth redirects stay hard document loads so stale session state cannot surv
assert.doesNotMatch(pageSource, /router\.replace\("\/login"\)/);
// And: the login redirect after sign-out drops the whole React tree with the session.
const signOut = sourceBetween(pageSource, "async function signOut()", "function chooseSuggestedQuestion");
const signOut = sourceBetween(pageSource, "async function signOut()", "return {\n refreshAccount,");
assert.match(signOut, /await selfHostedOtpActions\.signOut\(\);\n\s*window\.location\.assign\("\/login"\)/);
// And: the sibling membership surface keeps the same precedent.
+2
View File
@@ -15,6 +15,8 @@ const homeSurfaceFiles = [
const optionalHomeHookFiles = [
"../src/hooks/use-session-management.ts",
"../src/hooks/use-consultation-run.ts",
"../src/hooks/use-profile-onboarding.ts",
"../src/hooks/use-rectification-surface.ts",
] as const;
export const homeSurface = [
+4 -2
View File
@@ -2,14 +2,16 @@ import assert from "node:assert/strict";
import { existsSync, readFileSync } from "node:fs";
import test from "node:test";
import { homeSurface } from "./home-surface.ts";
test("upserts a missing profile when saving account details", () => {
const source = readFileSync(new URL("../src/app/page.tsx", import.meta.url), "utf8");
const source = homeSurface;
assert.match(source, /fetch\("\/api\/account",[\s\S]*?\{[\s\S]*?method:\s*"PATCH"/);
assert.match(source, /credentials:\s*"same-origin"/);
});
test("every profile save adopts the birth-time truth the account write returned", () => {
const source = readFileSync(new URL("../src/app/page.tsx", import.meta.url), "utf8");
const source = homeSurface;
// Given: the account write derives birth-time status and active minute.
assert.match(source, /const savedProfile = applyPersistedBirthTime\(nextProfile, payload\?\.birthTime\)/);
+1 -3
View File
@@ -1,9 +1,7 @@
import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import test from "node:test";
import { preserveShallowEqual } from "../src/lib/preserve-shallow-equal.ts";
const pageSource = readFileSync(new URL("../src/app/page.tsx", import.meta.url), "utf8");
import { homeSurface as pageSource } from "./home-surface.ts";
test("preserves the current profile reference when refreshed values are unchanged", () => {
const current = {
@@ -128,7 +128,7 @@ test("server profile failures pause automatic rectification resume", () => {
);
const incompleteHandler = page.slice(
page.indexOf("function handleRectificationProfileIncomplete"),
page.indexOf("async function draftSynastryQuestionFromChart"),
page.indexOf("function handleRectificationMessagesChange"),
);
assert.match(resumeEffect, /\|\| rectificationError\) return/);
assert.match(incompleteHandler, /setRectificationError\("profile_incomplete"\)/);