Files
Jyotisha/frontend/tests/consultation-domain-registry.test.ts
T
jesse-ux 8144fca27d
Independent Staging Quality Gate / validate (push) Failing after 9m47s
Independent Staging Quality Gate / publish (push) Skipped
fix(chat): fold natal reports and drop homepage topic cards
Homepage no longer waits on /api/onboarding for six starter questions.
Natal answers show the spoken layer first; the Level 2 skeleton sits in a
collapsed 完整分析 block. Wide tables scroll sideways on a phone. Form
inputs are 16px so iOS does not zoom on focus.
2026-09-15 12:27:16 +08:00

106 lines
6.3 KiB
TypeScript

import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import test from "node:test";
import {
consultationDomainIds,
consultationDomainRegistry,
normalizeConsultationDomain,
validateConsultationDomainPlan,
} from "../src/lib/consultation-domain-registry.ts";
import { consultationInputSchema } from "../src/mastra/consultation-workflow.ts";
import { chatSessionWriteSchema } from "../src/lib/chat-session-write-contract.ts";
import {
defaultGuidedJyotishTopics,
generalGuidedJyotishTopics,
} from "../src/lib/guided-jyotish-topics.ts";
const expected = ["career", "marriage", "wealth", "health", "education", "migration", "family", "annual", "timing", "general"];
test("domain registry is the complete allowlist used by UI and workflow input", () => {
assert.deepEqual([...consultationDomainIds], expected);
assert.deepEqual(consultationDomainRegistry.map((domain) => domain.id), expected);
assert.deepEqual(defaultGuidedJyotishTopics.map((topic) => topic.id), expected);
for (const theme of expected) {
assert.equal(consultationInputSchema.safeParse({ year: 2000, month: 1, day: 1, hour: 0, minute: 0, lat: 0, lon: 0, tz: 0, city: "Test", question: "test", theme }).success, true);
}
});
test("aliases normalize to stable persisted domain ids", () => {
assert.equal(normalizeConsultationDomain("relationship"), "marriage");
assert.equal(normalizeConsultationDomain("finance"), "wealth");
assert.equal(normalizeConsultationDomain("health-pressure"), "health");
assert.equal(normalizeConsultationDomain("home"), "migration");
assert.equal(normalizeConsultationDomain("unknown"), null);
});
test("server domain plans are allowlisted, ordered and deduplicated", () => {
assert.deepEqual(validateConsultationDomainPlan(["career", "finance", "career", "home"]), ["career", "wealth", "migration"]);
assert.throws(() => validateConsultationDomainPlan([]), /invalid_consultation_domain_plan/);
assert.throws(() => validateConsultationDomainPlan(["career", "prashna"]), /unsupported_consultation_domain/);
});
test("default guided topics derive every canonical domain with evidence and claim boundaries", () => {
// Moved from starter-questions.test.ts when homepage theme cards were removed.
const guidedTopicsSource = readFileSync(new URL("../src/lib/guided-jyotish-topics.ts", import.meta.url), "utf8");
assert.equal(consultationDomainIds.length, 10);
assert.deepEqual(consultationDomainRegistry.map((domain) => domain.id), [...consultationDomainIds]);
assert.match(guidedTopicsSource, /consultationDomainRegistry\.map/);
assert.deepEqual(defaultGuidedJyotishTopics.map((topic) => topic.id), [...consultationDomainIds]);
assert.equal(defaultGuidedJyotishTopics.length, consultationDomainRegistry.length);
for (const [index, topic] of defaultGuidedJyotishTopics.entries()) {
const domain = consultationDomainRegistry[index];
assert.equal(topic.id, domain.id);
assert.equal(topic.label, domain.label);
assert.equal(topic.prompt, domain.prompt);
assert.equal(topic.strictWorkflowRoute, domain.strictWorkflowRoute);
assert.deepEqual(topic.evidencePreview, [...domain.evidencePreview]);
assert.equal(topic.confidenceCap, domain.confidenceCap);
assert.equal(topic.claimBoundary, domain.claimBoundary);
}
const domainById = new Map(consultationDomainRegistry.map((domain) => [domain.id, domain]));
assert.match(domainById.get("career")?.requiredLayers.join(" ") ?? "", /D10/);
assert.match(domainById.get("marriage")?.requiredLayers.join(" ") ?? "", /D9/);
assert.match(domainById.get("wealth")?.requiredLayers.join(" ") ?? "", /Ashtakavarga/);
assert.match(domainById.get("timing")?.requiredLayers.join(" ") ?? "", /negative holdout gate/);
});
test("general guided topics keep user-centered prompts and the same claim boundaries", () => {
// Moved from starter-questions.test.ts. Homepage no longer renders these cards;
// the registry remains the contract for personal-report and no-minute copy.
assert.deepEqual(generalGuidedJyotishTopics.map((topic) => topic.id), [...consultationDomainIds]);
assert.deepEqual(generalGuidedJyotishTopics.map((topic) => topic.prompt), [
"请帮我梳理目前的事业方向和下一步重点。",
"请帮我看看我在关系中容易重复什么模式。",
"请帮我分析目前的财富重点、风险和更稳妥的选择。",
"请从非医疗诊断的角度,帮我看看近期的身心压力和调整重点。",
"请帮我看看我更适合怎样学习,以及如何安排下一步。",
"请帮我分析现阶段是否适合迁居、置业或考虑海外发展。",
"请帮我看看家庭关系中最需要处理的问题和责任边界。",
"请帮我看看未来一年的主要趋势、机会和需要留意的阶段。",
"请帮我看看目前适合推进什么,哪些事情需要再等等。",
"请结合我的情况,帮我找出现在最值得优先处理的三个问题。",
]);
for (const topic of generalGuidedJyotishTopics) {
const personalTopic = defaultGuidedJyotishTopics.find((candidate) => candidate.id === topic.id);
assert.ok(personalTopic);
assert.equal(topic.label, personalTopic.label);
assert.equal(topic.strictWorkflowRoute, personalTopic.strictWorkflowRoute);
assert.deepEqual(topic.evidencePreview, personalTopic.evidencePreview);
assert.equal(topic.confidenceCap, personalTopic.confidenceCap);
assert.equal(topic.claimBoundary, personalTopic.claimBoundary);
assert.notEqual(topic.prompt, personalTopic.prompt);
}
assert.ok(generalGuidedJyotishTopics.every((topic) => /我/.test(topic.prompt)));
assert.ok(generalGuidedJyotishTopics.every((topic) => !/印度占星|一般如何|通常|哪些因素|证据层/.test(topic.prompt)));
});
test("session persistence accepts every canonical domain and rejects product routes", () => {
for (const theme of expected) {
const parsed = chatSessionWriteSchema.safeParse({ title: "Test", theme, model_id: "test", messages: [], session_type: "consultation", rectification_case_id: null, updated_at: "2026-08-14T00:00:00.000Z" });
assert.equal(parsed.success, true, theme);
}
assert.equal(chatSessionWriteSchema.safeParse({ title: "Test", theme: "muhurta", model_id: "test", messages: [], session_type: "consultation", rectification_case_id: null, updated_at: "2026-08-14T00:00:00.000Z" }).success, false);
});