- 建档重读人物名单时保留旧名单,失败也不卡在加载画面(BUG-1455) - 对话右栏改用自己的拖宽把手,侧栏与右栏都能用方向键(BUG-1456/1457) - 启程清单胶囊和首页一起出来,读状态时用上次的样子占位(BUG-1458) - 起步第一问与别人的天空过场读一次已算好的星盘取星座,上升只在不会换座时用(BUG-1459,产品 10-27 同意) - 补回删减的断言与三栏说明;登录代码改回原样,替身放进测试;删旧校正画面的无用样式 - 首屏 +7.54% 产品已接受,写进 DESIGN Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LutgzyJqNhPpZy1nFsJtN3
93 lines
3.6 KiB
TypeScript
93 lines
3.6 KiB
TypeScript
import "./install-test-document";
|
|
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
|
|
import { OnboardingMotionHost } from "../src/components/onboarding-motion-host.tsx";
|
|
import { onboardingMotionEnabled } from "../src/lib/onboarding-hints.ts";
|
|
import { OnboardingJourneyContext, type OnboardingJourney } from "../src/lib/onboarding-journey.tsx";
|
|
import { claimOnboardingPlay, resetOnboardingPlays } from "../src/lib/motion/onboarding-play.ts";
|
|
import { playOnboardingEnter, setOnboardingMotionLoader } from "../src/lib/motion/onboarding-run.ts";
|
|
import { createClientLifecycleHarness } from "./react-client-lifecycle-test-support.ts";
|
|
|
|
function closedJourney(): OnboardingJourney {
|
|
return {
|
|
showChecklist: false,
|
|
checklistPending: false,
|
|
userId: "",
|
|
items: [],
|
|
label: "",
|
|
celebration: false,
|
|
activeHint: null,
|
|
hintText: "",
|
|
showChartDot: false,
|
|
tabHasDot: () => false,
|
|
dismissChecklist: () => {},
|
|
dismissHint: async () => true,
|
|
go: () => {},
|
|
setChartTab: () => {},
|
|
markChartVisited: () => {},
|
|
setChecklistOpen: () => {},
|
|
setLive: () => {},
|
|
registerHome: () => {},
|
|
hintWatch: false,
|
|
motionEnabled: onboardingMotionEnabled({
|
|
checklistDismissed: true,
|
|
checklistOpen: false,
|
|
unfinishedItem: true,
|
|
beforeFirstQuestion: true,
|
|
}),
|
|
};
|
|
}
|
|
|
|
test("a closed checklist plays none of the four onboarding beats", async () => {
|
|
const journey = closedJourney();
|
|
assert.equal(journey.motionEnabled, false);
|
|
resetOnboardingPlays();
|
|
const harness = createClientLifecycleHarness();
|
|
try {
|
|
await harness.render(
|
|
<OnboardingJourneyContext.Provider value={journey}>
|
|
<OnboardingMotionHost />
|
|
<button type="button" data-onboarding-enter="follow-up">追问</button>
|
|
<article data-onboarding-enter="archive">档案</article>
|
|
<svg data-onboarding-draw="vedic" data-onboarding-draw-key="vedic" />
|
|
<article data-onboarding-synastry="00000000-0000-4000-8000-000000001447">合盘</article>
|
|
</OnboardingJourneyContext.Provider>,
|
|
);
|
|
await harness.idle();
|
|
assert.equal(claimOnboardingPlay("enter:follow-up"), true);
|
|
assert.equal(claimOnboardingPlay("enter:archive"), true);
|
|
assert.equal(claimOnboardingPlay("draw:vedic"), true);
|
|
assert.equal(claimOnboardingPlay("syn:00000000-0000-4000-8000-000000001447"), true);
|
|
assert.equal(harness.errors.length, 0, harness.errors.map(String).join("\n"));
|
|
} finally {
|
|
await harness.close();
|
|
}
|
|
});
|
|
|
|
test("a failed or slow Motion load leaves the element visible", async () => {
|
|
const harness = createClientLifecycleHarness();
|
|
try {
|
|
resetOnboardingPlays();
|
|
setOnboardingMotionLoader(() => Promise.reject(new Error("motion failed")));
|
|
const failed = harness.document.createElement("div");
|
|
failed.setAttribute("data-onboarding-enter", "follow-up");
|
|
(failed.style as { opacity?: string }).opacity = "1";
|
|
await playOnboardingEnter(failed as unknown as HTMLElement);
|
|
assert.notEqual((failed.style as { opacity?: string }).opacity, "0");
|
|
|
|
resetOnboardingPlays();
|
|
setOnboardingMotionLoader(() => new Promise(() => {}));
|
|
const slow = harness.document.createElement("div");
|
|
slow.setAttribute("data-onboarding-enter", "archive");
|
|
(slow.style as { opacity?: string }).opacity = "1";
|
|
const started = Date.now();
|
|
await playOnboardingEnter(slow as unknown as HTMLElement);
|
|
assert.ok(Date.now() - started >= 250);
|
|
assert.notEqual((slow.style as { opacity?: string }).opacity, "0");
|
|
} finally {
|
|
setOnboardingMotionLoader(null);
|
|
await harness.close();
|
|
}
|
|
});
|