import { describe, expect, it } from "vitest"; import type { Spec } from "@json-render/core"; import { getAnswerTaskLayout } from "./answer-task-layout"; describe("answer task composition", () => { const nodes: Spec["elements"] = { root: { type: "Stack", props: { columns: "one" }, children: ["comparison", "data", "evidence", "mixed", "form"] }, comparison: { type: "Stack", props: { columns: "two" }, children: ["metric-a", "metric-b"] }, "metric-a": { type: "Metric", props: {} }, "metric-b": { type: "Metric", props: {} }, data: { type: "Section", props: { title: "趋势" }, children: ["chart", "table"] }, chart: { type: "Chart", props: {} }, table: { type: "Table", props: {} }, evidence: { type: "Evidence", props: {} }, mixed: { type: "Section", props: { title: "判断与依据" }, children: ["note", "basis"] }, note: { type: "Text", props: {} }, basis: { type: "Evidence", props: {} }, form: { type: "FollowUpForm", props: {} } }; it("composes independent content while keeping authored comparisons and mixed sections together", () => { expect(getAnswerTaskLayout({ root: "root", elements: nodes })).toEqual({ overview: ["comparison", "mixed"], analysis: ["data"], evidence: ["evidence"], followUp: ["form"] }); }); it("preserves an explicitly authored comparison as the root", () => { expect(getAnswerTaskLayout({ root: "comparison", elements: nodes })).toBeNull(); }); it("keeps explicit content roles and comparison intent instead of guessing from component types", () => { const elements: Spec["elements"] = { ...nodes, data: { ...nodes.data, props: { title: "读数依据", role: "evidence" } }, mixed: { ...nodes.mixed, props: { title: "处理结果", role: "result" } } }; expect(getAnswerTaskLayout({ root: "root", elements })).toEqual({ overview: ["comparison", "mixed"], analysis: [], evidence: ["data", "evidence"], followUp: ["form"] }); expect(getAnswerTaskLayout({ root: "root", elements: { ...elements, root: { ...elements.root, props: { ...elements.root.props, intent: "comparison" } } } })).toBeNull(); }); });