import { describe, expect, it } from "vitest"; import { createInvestigationDevCase, investigationDevCases } from "./investigation-dev-cases"; import { parseInvestigationDevJsonl } from "./investigation-dev-preview"; describe("switchable investigation Dev cases", () => { it.each(investigationDevCases.filter((item) => !item.id.startsWith("invalid_")))( "$label produces a valid, nonempty batch within the existing presentation contract", ({ id }) => { const input = createInvestigationDevCase(id); const preview = parseInvestigationDevJsonl(input); const records = input.split("\n").map((line) => JSON.parse(line)); expect(records.every((record) => typeof record.record_type === "string")).toBe(true); expect( records .filter((record) => record.record_type === "presentation") .every((record) => !record.name && !record.params && record.command.action) ).toBe(true); expect(preview.blocks.every((block) => block.phase === "final")).toBe(true); expect( preview.commands.length + preview.blocks.length + preview.records.length ).toBeGreaterThan(0); } ); it.each(investigationDevCases.filter((item) => item.id.startsWith("invalid_")))( "$label cannot produce an executable batch", ({ id }) => { expect(() => parseInvestigationDevJsonl(createInvestigationDevCase(id))).toThrow( id === "invalid_json" ? "第 2 行不是合法 JSON" : "第 1 行展示指令不合法" ); } ); it("keeps feature locating and highlighting in map debugging rather than running another path from a synthetic case", () => { expect(investigationDevCases.some((item) => String(item.id) === "map_targets")).toBe(false); for (const item of investigationDevCases.filter((item) => !item.id.startsWith("invalid_"))) { const preview = parseInvestigationDevJsonl(createInvestigationDevCase(item.id)); expect(preview.commands.some((command) => ["locate_features", "highlight_features"].includes(command.action))).toBe(false); } }); it("provides dense tables and full-day series without exceeding publication limits", () => { const tables = parseInvestigationDevJsonl(createInvestigationDevCase("complex_tables")); const nodes = tables.blocks.map((block) => Object.values(block.spec.elements)[0]); expect(nodes[0].props.columns).toHaveLength(8); expect(nodes[0].props.rows).toHaveLength(50); expect(nodes[1].props.rows).toEqual([]); const charts = parseInvestigationDevJsonl(createInvestigationDevCase("complex_charts")); const pressure = Object.values(charts.blocks[0].spec.elements)[0].props; expect(pressure.x_data).toHaveLength(96); expect(pressure.series).toHaveLength(8); }); it.each(["data_only", "candidates_table", "valves_table"] as const)( "%s never turns synthetic asset IDs or embedded action fields into map queries or writes", (id) => { const preview = parseInvestigationDevJsonl(createInvestigationDevCase(id)); expect(preview.commands).toEqual([]); expect(preview.records).toHaveLength(2); expect(preview.records.every((record) => record.origin === "synthetic")).toBe(true); } ); it("keeps every spatial fixture inside the verified tjwater_v2 network bounds", () => { const visit = (value: unknown) => { if (!Array.isArray(value)) return; if (typeof value[0] === "number" && typeof value[1] === "number") { expect(value[0]).toBeGreaterThanOrEqual(121.3516324392188); expect(value[0]).toBeLessThanOrEqual(121.77248154882845); expect(value[1]).toBeGreaterThanOrEqual(30.810500094449143); expect(value[1]).toBeLessThanOrEqual(31.00720694600021); } else value.forEach(visit); }; for (const id of ["combined", "complex_investigation", "impact_area", "complaint_heatmap"] as const) { const preview = parseInvestigationDevJsonl(createInvestigationDevCase(id)); for (const command of preview.commands) if (command.action === "set_overlay") { for (const feature of command.data.features) visit(feature.geometry.coordinates); } } }); });