Files
Jyotisha/frontend/tests/onboarding-presentation.test.ts
T
Jesse_ChenandCursor f6715ee4bf
Independent Staging Quality Gate / validate (push) Failing after 11m34s
Independent Staging Quality Gate / publish (push) Has been skipped
feat(home): write the daily card with the Agent and vary the starter heading
The daily starlanguage card claimed to be personal but was a four-card
rotation picked by hashing the date and birth place, with the same pool
duplicated as a client fallback. It now collects chart, Vimshottari and
Narayana dasha, D9/D10 and today's transits, hands that evidence to a
dedicated Agent, and keeps the result per account per day in process. A
failed generation says so instead of printing generic advice.

The starter heading is drawn from a pool on each visit, and the
rectification card drops its fine print.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-17 22:27:49 +08:00

55 lines
2.8 KiB
TypeScript

import assert from "node:assert/strict";
import test from "node:test";
import {
createOnboardingFallbackGreeting,
createStartGreeting,
isCurrentOnboardingRequest,
onboardingProfileFingerprint,
onboardingRequestIdentity,
} from "../src/lib/onboarding-client.ts";
import { createStarterPrompt, starterPromptVariants } from "../src/lib/starter-prompt.ts";
const completeProfile = {
name: "林遥", date: "1990-06-15", time: "12:30", reportedTime: "12:30",
birthTimeSource: "hospital_record", birthTimePeriod: "", birthTimeClue: "出生证明", birthTimeStatus: "confirmed",
uncertaintyBeforeMinutes: 0, uncertaintyAfterMinutes: 0, rectificationCaseId: "", countryCode: "CN", provinceCode: "110000", cityCode: "110000-city", districtCode: "110101",
} as const;
test("rejects stale A presentation and derives terminal and fallback greetings from profile B", () => {
// Given: one account starts onboarding for a complete persisted profile A.
const firstIdentity = onboardingRequestIdentity("account-1", onboardingProfileFingerprint(completeProfile));
// When: the name changes before that request completes and profile B is presented.
const changedProfile = { ...completeProfile, name: "周宁" };
const currentIdentity = onboardingRequestIdentity("account-1", onboardingProfileFingerprint(changedProfile));
const terminalGreeting = createStartGreeting(changedProfile.name, new Date("2026-07-19T08:00:00+08:00"), 0);
const fallbackGreeting = createOnboardingFallbackGreeting(changedProfile.name);
// Then: stale work is rejected and neither presentation path can retain A's name.
assert.notEqual(currentIdentity, firstIdentity);
assert.equal(isCurrentOnboardingRequest(currentIdentity, firstIdentity), false);
for (const greeting of [terminalGreeting, fallbackGreeting]) {
assert.match(greeting, /周宁/);
assert.doesNotMatch(greeting, /林遥/);
}
assert.equal(fallbackGreeting, "周宁,从你此刻最关心的问题开始吧。");
});
test("the starter heading varies per visit and stays inside the pool", () => {
// Given: a pool of distinct openings rather than one fixed line.
assert.ok(starterPromptVariants.length >= 5);
assert.equal(new Set(starterPromptVariants).size, starterPromptVariants.length);
// Then: every selection lands on a real variant, including the extremes.
assert.equal(createStarterPrompt(0), starterPromptVariants[0]);
assert.equal(createStarterPrompt(1), starterPromptVariants.at(-1));
assert.equal(createStarterPrompt(0.999999), starterPromptVariants.at(-1));
// And: the whole pool is reachable, so the heading is not one line in disguise.
const reached = new Set(
Array.from({ length: starterPromptVariants.length }, (_, index) =>
createStarterPrompt(index / starterPromptVariants.length)),
);
assert.equal(reached.size, starterPromptVariants.length);
});