只做启程(一):同一笔预扣覆盖已公布的标准档,更贵的只扣差价;引导状态与人物关系只加列。tsc 与 lint 通过。test:db 91 项,失败 14,其中 13 条为 Windows 已知失败;校正遥测单独重跑通过。 Co-Authored-By: Grok (agent loop)
83 lines
3.8 KiB
TypeScript
83 lines
3.8 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { readFileSync } from "node:fs";
|
|
import test from "node:test";
|
|
|
|
import { parseChartSubjectWrite, libraryProfileFromSubjectRow } from "../src/lib/chart-subject-write.ts";
|
|
import { readProfile } from "../src/lib/home-profile.ts";
|
|
import { parseOnboardingPatch, parseOnboardingState } from "../src/lib/onboarding-state.ts";
|
|
import { parsePersonRelation, personRelationLabel } from "../src/lib/person-relation.ts";
|
|
|
|
const route = readFileSync(new URL("../src/app/api/onboarding-state/route.ts", import.meta.url), "utf8");
|
|
const account = readFileSync(new URL("../src/app/api/account/route.ts", import.meta.url), "utf8");
|
|
|
|
test("person relation accepts only the five household values", () => {
|
|
assert.equal(parsePersonRelation("child"), "child");
|
|
assert.equal(parsePersonRelation("family"), null);
|
|
assert.equal(parsePersonRelation(null), null);
|
|
assert.equal(personRelationLabel(null), "其他");
|
|
assert.equal(personRelationLabel("parent"), "父母");
|
|
assert.equal(personRelationLabel("other"), "其他");
|
|
});
|
|
|
|
test("a chart write omits relation unless the client sent the key", () => {
|
|
const omitted = parseChartSubjectWrite({ name: "示例乙", date: "1992-03-12" });
|
|
assert.equal(omitted.ok, true);
|
|
if (!omitted.ok) return;
|
|
assert.equal("relation" in omitted.write.columns, false);
|
|
|
|
const child = parseChartSubjectWrite({ name: "示例乙", date: "1992-03-12", relation: "child" });
|
|
assert.equal(child.ok, true);
|
|
if (!child.ok) return;
|
|
assert.equal(child.write.columns.relation, "child");
|
|
|
|
const cleared = parseChartSubjectWrite({ name: "示例乙", date: "1992-03-12", relation: null });
|
|
assert.equal(cleared.ok, true);
|
|
if (!cleared.ok) return;
|
|
assert.equal(cleared.write.columns.relation, null);
|
|
|
|
const illegal = parseChartSubjectWrite({ name: "示例乙", date: "1992-03-12", relation: "client" });
|
|
assert.equal(illegal.ok, false);
|
|
});
|
|
|
|
test("an old chart row with a null relation still reads", () => {
|
|
const profile = libraryProfileFromSubjectRow({ name: "示例乙", relation: null, profile: {} });
|
|
assert.equal(profile.relation, null);
|
|
assert.equal(readProfile(profile).relation, null);
|
|
assert.equal("relation" in readProfile({ name: "示例乙" }), false);
|
|
});
|
|
|
|
test("onboarding state keeps only the three keys and the hint list", () => {
|
|
const saved = parseOnboardingPatch({
|
|
chartVisitedAt: "2026-10-22T00:00:00Z",
|
|
hintsSeen: ["follow-up", "tab-chart"],
|
|
});
|
|
assert.equal(saved.ok, true);
|
|
assert.equal(parseOnboardingPatch({ userId: "someone-else" }).ok, false);
|
|
assert.equal(parseOnboardingPatch({ hintsSeen: ["not-a-hint"] }).ok, false);
|
|
assert.equal(parseOnboardingPatch({ checklistDismissedAt: "tomorrow" }).ok, false);
|
|
assert.deepEqual(parseOnboardingState({
|
|
chartVisitedAt: "2026-10-22T00:00:00Z",
|
|
hintsSeen: ["follow-up"],
|
|
extra: true,
|
|
}), {
|
|
chartVisitedAt: "2026-10-22T00:00:00Z",
|
|
hintsSeen: ["follow-up"],
|
|
});
|
|
});
|
|
|
|
test("the onboarding route is login-only and writes the session user", () => {
|
|
assert.match(route, /请先登录/);
|
|
assert.match(route, /status: 401/);
|
|
assert.match(route, /p_user_id: user\.id/);
|
|
assert.doesNotMatch(route, /userId|body\.id|p_user_id: parsed/);
|
|
});
|
|
|
|
test("account GET exposes firstConsultFree from the column, and a missing column is not free", () => {
|
|
assert.match(account, /first_consult_free_used_at/);
|
|
assert.match(account, /firstConsultFree: firstConsultFreeFromProfile\(profile\)/);
|
|
assert.match(account, /hasOwnProperty\.call\(profile, "first_consult_free_used_at"\)/);
|
|
const getSource = account.slice(account.indexOf("export async function GET"), account.indexOf("export async function PATCH"));
|
|
const fallbacks = getSource.slice(getSource.indexOf("isMissingProfileColumn"));
|
|
assert.equal(fallbacks.includes("first_consult_free_used_at"), false);
|
|
});
|