import assert from "node:assert/strict"; import test from "node:test"; import { copyResultText, resultScope, resultDisplay, queryPath, compactAnalysisPath, } from "./result-presentation.js"; import type { AssistantResult } from "../../../shared/assets/assistant.js"; const result: AssistantResult = { plan: { kind: "assets", category: "available", groupBy: "region", view: "table", filters: { type: ["4.5T"] }, }, title: "可运营库存 · 按区域统计", summary: "当前范围共有135台可运营库存。", source: "资产台账", fetchedAt: "2026-09-23T08:00:00Z", groups: [], rows: [], metrics: [{ label: "可运营库存", value: 135, unit: "台" }], scope: { company: "演示公司", permission: "当前账号可见车辆", filters: ["4.5T", "可运营库存"], grouping: "区域", period: "当前资产台账", definitions: ["车型按吨位汇总,4.5T包含普货与冷链"], sourceUpdatedAt: null, }, }; test("copy preserves facts, scope, definitions and distinguishes unknown source update from query time", () => { const text = copyResultText(result, null); for (const expected of [ "135台", "公司:演示公司", "权限范围:当前账号可见车辆", "筛选条件:4.5T;可运营库存", "分组:区域", "4.5T包含普货与冷链", "源数据更新时间:未提供", "查询时间:", ]) assert.ok(text.includes(expected), expected); }); test("partial briefing copies missing answers and inventory evidence without inventing a source timestamp", () => { const partial: AssistantResult = { ...result, outcome: "partial", unanswered: [ { question: "闲置损失多少钱", reason: "未接入成本数据,不估算金额。" }, ], inventoryBreakdown: { title: "库存集中情况", summary: "4.5T冷链库存最多。", groups: [ { name: "4.5T冷链", count: 155, operating: 0, rate: 0, share: 53.3 }, ], }, }; const text = copyResultText(partial, null); assert.match(text, /4.5T冷链:155台,占库存53.3%/); assert.match(text, /尚未回答:[\s\S]*未接入成本数据,不估算金额/); assert.match(text, /源数据更新时间:未提供/); }); test("copying a revoked result keeps the revocation explicit", () => { const text = copyResultText( result, null, "上一条回答的是待运营,不能用于判断待交车。", ); assert.match( text, /【此回答已撤回】上一条回答的是待运营,不能用于判断待交车/, ); }); test("fallback scope keeps exclusion and selected vehicle filters", () => { const fallback = resultScope( { ...result, scope: undefined, plan: { ...result.plan, excludeFilters: { city: ["嘉兴市"] }, vehicleIds: ["example-1"], exception: "overdue", }, }, "演示公司", ); assert.deepEqual(fallback.filters, [ "可运营库存", "车型:4.5T", "排除城市:嘉兴市", "指定车辆:1台", "已超过预计完成时间", ]); assert.equal(fallback.sourceUpdatedAt, null); }); test("copy includes regional facts and daily flow without duplicating groups or copying vehicle details", () => { const regional: AssistantResult = { ...result, groups: [ { name: "华东", count: 99, operating: 0, rate: 0, share: 73.3, abnormal: 1, pending: 0, }, ], insights: ["华东占当前可运营库存73.3%。"], rows: [ { id: "private-vehicle", plate: "测试车牌不应复制", vehicleClass: "4.5T普货", type: "4.5T", model: "演示型号", region: "华东", city: "嘉兴市", department: "演示部门", status: "可运营", }, ], }; const regionalText = copyResultText(regional, null); assert.match(regionalText, /华东:99台,占比73.3%/); assert.match(regionalText, /异动1台,待交车0台/); assert.match(regionalText, /分析发现:[\s\S]*华东占当前可运营库存73.3%/); assert.ok(!regionalText.includes("测试车牌不应复制")); const flowText = copyResultText( { ...regional, plan: { ...regional.plan, kind: "flow", start: "2026-09-23", end: "2026-09-23", }, daily: [ { date: "2026-09-23", delivered: 5, returned: 2, replaced: 1, total: 7, }, ], }, null, ); assert.match( flowText, /2026-09-23:交车5车次,还车2车次,其中替换交车1车次,合计7车次/, ); assert.match(flowText, /替换交车包含在交车中,不重复相加/); assert.ok(!flowText.includes("华东:99台")); assert.ok(!flowText.includes("测试车牌不应复制")); }); test("single totals use metric cards while comparisons, trends and explicit records retain their display", () => { const total = { ...result.plan, groupBy: "none" as const, view: "chart" as const, }; assert.equal(resultDisplay(total), "metrics"); assert.equal(resultDisplay({ ...total, groupBy: "region" }), "chart"); assert.equal(resultDisplay({ ...total, secondaryGroupBy: "type" }), "chart"); assert.equal(resultDisplay({ ...total, kind: "flow" }), "chart"); assert.equal(resultDisplay({ ...total, view: "list" }), "list"); assert.equal(resultDisplay({ ...total, view: "table" }), "table"); }); test("current path retains every active slice and highlights the current grouping", () => { const path = queryPath({ ...result.plan, filters: { region: ["华东"], city: ["嘉兴市"] }, excludeFilters: { model: ["演示型号"] }, groupBy: "vehicleClass", exception: "overdue", }); assert.deepEqual(path, [ "可运营库存", "区域:华东", "城市:嘉兴市", "排除型号:演示型号", "已超期", "按车型细分统计", ]); }); test("analysis path collapses display-only steps and preserves the latest node of each scope", () => { const path = compactAnalysisPath([ { resultId: "all", label: "全部库存" }, { resultId: "east-chart", label: "库存 · 华东" }, { resultId: "east-table", label: "库存 · 华东" }, { resultId: "jiaxing", label: "库存 · 华东 / 嘉兴" }, ]); assert.deepEqual( path.map((crumb) => crumb.resultId), ["all", "east-table", "jiaxing"], ); assert.equal(path.at(-2)?.label, "库存 · 华东"); }); test("vehicle status navigation identifies a vehicle answer instead of a total", () => { const path = queryPath({ kind: "assets", category: "all", groupBy: "none", view: "list", filters: {}, vehicleIds: ["v1"], responseMode: "vehicle-status" }); assert.ok(path.includes("车辆状态")); assert.ok(!path.includes("总量")); });