135 lines
4.2 KiB
TypeScript
135 lines
4.2 KiB
TypeScript
import assert from "node:assert/strict";
|
||
import test from "node:test";
|
||
import {
|
||
assistantIntentCopy,
|
||
birthTimeDisplayState,
|
||
birthTimePersistenceValues,
|
||
describeBirthTimeDraft,
|
||
formatBirthDate,
|
||
isBirthTimeReadyForConsultation,
|
||
isBirthTimeDraftReady,
|
||
parseBirthDate,
|
||
type BirthTimeDraft,
|
||
} from "../src/lib/birth-time-intake-model.ts";
|
||
|
||
const emptyDraft: BirthTimeDraft = {
|
||
date: "1993-04-17",
|
||
time: "",
|
||
reportedTime: "",
|
||
birthTimeSource: "",
|
||
birthTimePeriod: "",
|
||
birthTimeClue: "",
|
||
uncertaintyBeforeMinutes: null,
|
||
uncertaintyAfterMinutes: null,
|
||
birthTimeStatus: "",
|
||
};
|
||
|
||
test("birth time intake requires only the fields selected by the source", () => {
|
||
const hospital = {
|
||
...emptyDraft,
|
||
birthTimeSource: "hospital_record",
|
||
reportedTime: "08:16",
|
||
} satisfies BirthTimeDraft;
|
||
const period = {
|
||
...emptyDraft,
|
||
birthTimeSource: "period_only",
|
||
birthTimePeriod: "evening",
|
||
} satisfies BirthTimeDraft;
|
||
const incompleteApproximate = {
|
||
...emptyDraft,
|
||
birthTimeSource: "approximate",
|
||
reportedTime: "14:30",
|
||
} satisfies BirthTimeDraft;
|
||
|
||
assert.equal(isBirthTimeDraftReady(hospital), true);
|
||
assert.equal(isBirthTimeDraftReady(period), true);
|
||
assert.equal(isBirthTimeDraftReady(incompleteApproximate), false);
|
||
assert.equal(isBirthTimeDraftReady({ ...emptyDraft, birthTimeSource: "unknown" }), true);
|
||
});
|
||
|
||
test("a persisted candidate working time can leave rectification onboarding", () => {
|
||
const candidate = {
|
||
...emptyDraft,
|
||
time: "04:53",
|
||
birthTimeStatus: "candidate",
|
||
} satisfies BirthTimeDraft;
|
||
|
||
assert.equal(isBirthTimeReadyForConsultation(candidate), true);
|
||
assert.equal(isBirthTimeReadyForConsultation({ ...candidate, time: "" }), false);
|
||
assert.equal(isBirthTimeReadyForConsultation({ ...candidate, birthTimeStatus: "rectifying" }), false);
|
||
});
|
||
|
||
test("a persisted candidate working time takes precedence over the reported range", () => {
|
||
// Given: rectification saved a candidate minute while preserving the user's original period.
|
||
const candidate = {
|
||
...emptyDraft,
|
||
time: "04:53",
|
||
birthTimeSource: "period_only",
|
||
birthTimePeriod: "early_morning",
|
||
birthTimeStatus: "candidate",
|
||
} satisfies BirthTimeDraft;
|
||
|
||
// When: a profile surface asks what birth-time state to display.
|
||
const display = birthTimeDisplayState(candidate);
|
||
|
||
// Then: the candidate minute is primary and the original period remains secondary.
|
||
assert.deepEqual(display, {
|
||
kind: "candidate",
|
||
activeTime: "04:53",
|
||
reportedLabel: "凌晨 / 清晨(04:00—07:59)",
|
||
});
|
||
});
|
||
|
||
test("birth time declaration payload cannot write deterministic application fields", () => {
|
||
const draft = {
|
||
...emptyDraft,
|
||
time: "14:24",
|
||
reportedTime: "14:30",
|
||
birthTimeSource: "approximate",
|
||
uncertaintyBeforeMinutes: 30,
|
||
uncertaintyAfterMinutes: 30,
|
||
birthTimeStatus: "confirmed",
|
||
} satisfies BirthTimeDraft;
|
||
|
||
assert.deepEqual(birthTimePersistenceValues(draft), {
|
||
reported_birth_time: "14:30",
|
||
birth_time_source: "approximate",
|
||
birth_time_period: null,
|
||
birth_time_clue: null,
|
||
uncertainty_before_minutes: 30,
|
||
uncertainty_after_minutes: 30,
|
||
});
|
||
});
|
||
|
||
test("birth time intake describes uncertainty without claiming false precision", () => {
|
||
const approximate = {
|
||
...emptyDraft,
|
||
birthTimeSource: "approximate",
|
||
reportedTime: "14:30",
|
||
uncertaintyBeforeMinutes: 30,
|
||
uncertaintyAfterMinutes: 30,
|
||
} satisfies BirthTimeDraft;
|
||
|
||
assert.equal(describeBirthTimeDraft(approximate), "1993年4月17日,约 14:30(前后 30 分钟)");
|
||
assert.equal(
|
||
assistantIntentCopy("present_saved_candidate_range"),
|
||
"目前只能保存候选范围,还没有足够证据应用到具体分钟。",
|
||
);
|
||
});
|
||
|
||
test("birth date parsing preserves the local calendar day", () => {
|
||
const parsed = parseBirthDate("1993-04-17");
|
||
|
||
assert.equal(parsed?.getFullYear(), 1993);
|
||
assert.equal(parsed?.getMonth(), 3);
|
||
assert.equal(parsed?.getDate(), 17);
|
||
});
|
||
|
||
test("birth date values round trip leap days and reject invalid input", () => {
|
||
const leapDay = parseBirthDate("2000-02-29");
|
||
|
||
assert.equal(leapDay === undefined ? undefined : formatBirthDate(leapDay), "2000-02-29");
|
||
assert.equal(parseBirthDate(""), undefined);
|
||
assert.equal(parseBirthDate("2001-02-29"), undefined);
|
||
});
|