Files
Jyotisha/frontend/tests/birth-time-journey-turn.test.ts
2026-07-18 18:40:23 +08:00

123 lines
4.5 KiB
TypeScript

import assert from "node:assert/strict";
import test from "node:test";
import {
createInitialJourneyTurn,
deriveNextAction,
projectJourneyTurn,
} from "../src/lib/birth-time-journey-turn.ts";
import type { CandidateResult } from "../src/lib/birth-time-evidence.ts";
import type { QuestionSpec } from "../src/lib/birth-time-question-planner.ts";
function question(domain: QuestionSpec["domain"]): QuestionSpec {
return {
questionId: `baseline_${domain}_1`,
phase: "baseline",
domain,
requestedPrecision: ["year", "month"],
allowUnknown: true,
purposeCode: `candidate_difference_${domain}`,
plannerVersion: "candidate-difference-v1",
};
}
const lowResult: CandidateResult = {
resultId: "1d8ee348-61a3-433d-8907-ff6d281b9992",
confidence: "low",
canApply: false,
winningSegment: null,
eventCount: 3,
domainCount: 3,
topScore: 8,
secondScore: 7,
marginPercent: 12.5,
reasons: ["Candidate scores remain close."],
evidence: [],
algorithmVersion: "birth-time-event-scoring-v1",
};
test("a fresh rectification turn asks exactly one baseline evidence question", () => {
const turn = createInitialJourneyTurn(question("career"));
assert.equal(turn.nextAction.kind, "ask_baseline_evidence");
assert.equal(turn.progress.confirmedEvidenceCount, 0);
assert.equal(turn.progress.maxAdaptiveRounds, 3);
assert.equal(turn.permissions.canConfirmCandidate, false);
});
test("the third low adaptive result becomes terminal", () => {
const next = deriveNextAction({
progress: {
phase: "adaptive",
baselineDomainCount: 3,
confirmedEvidenceCount: 6,
adaptiveRound: 3,
maxAdaptiveRounds: 3,
},
candidateResult: lowResult,
nextQuestion: question("health_pressure"),
confirmedTime: null,
});
assert.equal(next.kind, "present_low_result");
});
test("projection skips confirmed evidence domains when planning the next baseline question", () => {
const careerEvents = [
{ id: "5cb071d6-6d99-46be-85dc-a9bf59ef6ac5", domain: "career", date: "2011", precision: "year" },
{ id: "0790866c-ad5e-4a45-b2b4-a5c73f6be6ea", domain: "career", date: "2019", precision: "year" },
{ id: "0ef52e51-ab5f-453b-81e5-adb44a929224", domain: "career", date: "2021", precision: "year" },
] as const;
const turn = projectJourneyTurn({
turnVersion: 0,
snapshot: {
state: "rectifying", assistantIntent: "continue_rectification_questions", input: "rectification_questions",
route: "rectification", confidence: null, canApply: false, activeTime: null,
reportedRange: { label: "14:00—15:00", startTime: "14:00", endTime: "15:00" },
},
questionnaire: { samples: [
{ d4Sign: "Aries", d9Sign: "Aries", d10Sign: "Aries", d24Sign: "Aries", d30Sign: "Aries" },
{ d4Sign: "Aries", d9Sign: "Aries", d10Sign: "Taurus", d24Sign: "Aries", d30Sign: "Aries" },
{ d4Sign: "Aries", d9Sign: "Aries", d10Sign: "Gemini", d24Sign: "Aries", d30Sign: "Aries" },
] },
persistedProgress: { adaptiveRound: 0, askedDomains: [] },
candidateResult: null,
lifeEvents: careerEvents,
});
assert.equal(turn.nextAction.kind, "ask_baseline_evidence");
assert.equal(turn.nextAction.question.domain, "education");
});
test("a low result becomes terminal when adaptive question planning is exhausted early", () => {
const next = deriveNextAction({
progress: {
phase: "adaptive", baselineDomainCount: 3, confirmedEvidenceCount: 6, adaptiveRound: 1, maxAdaptiveRounds: 3,
},
candidateResult: lowResult,
nextQuestion: null,
});
assert.deepEqual(next, { kind: "present_low_result", resultId: lowResult.resultId });
});
test("projection pauses completed legacy evidence without fabricating a draft", () => {
const turn = projectJourneyTurn({
turnVersion: 0,
snapshot: {
state: "rectifying", assistantIntent: "continue_rectification_questions", input: "rectification_questions",
route: "rectification", confidence: null, canApply: false, activeTime: null,
reportedRange: { label: "14:00—15:00", startTime: "14:00", endTime: "15:00" },
},
questionnaire: { samples: [] },
candidateResult: null,
lifeEvents: [
{ id: "5cb071d6-6d99-46be-85dc-a9bf59ef6ac5", domain: "education", date: "2011", precision: "year" },
{ id: "0790866c-ad5e-4a45-b2b4-a5c73f6be6ea", domain: "career", date: "2019", precision: "year" },
{ id: "0ef52e51-ab5f-453b-81e5-adb44a929224", domain: "relationship", date: "2021", precision: "year" },
],
});
assert.equal(turn.nextAction.kind, "paused");
assert.equal(turn.evidenceDraft, null);
});