feat: expand intelligent investigation workspace
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { render, screen, fireEvent, waitFor, within } from "@testing-library/react";
|
||||
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { AnswerUiView } from "./answer-ui-view";
|
||||
@@ -33,6 +33,29 @@ function taskBlock(includeData = true) {
|
||||
return parsed;
|
||||
}
|
||||
describe("local interactive answer renderer", () => {
|
||||
it("shows navigation for long answers while keeping short metric and evidence replies quiet", () => {
|
||||
const fixture = taskBlock(false);
|
||||
fixture.spec.elements.root.children = ["metric", "evidence"];
|
||||
delete fixture.spec.elements.form;
|
||||
const { rerender } = render(<AnswerUiView block={fixture} />);
|
||||
expect(screen.getByRole("group", { name: "当前压力" })).toBeVisible();
|
||||
expect(screen.queryByRole("navigation", { name: "回答内容导航" })).not.toBeInTheDocument();
|
||||
const longer = structuredClone(fixture);
|
||||
longer.spec.elements.evidence.props.summary = "待核对的监测资料。".repeat(150);
|
||||
rerender(<AnswerUiView block={longer} />);
|
||||
expect(screen.getByRole("navigation", { name: "回答内容导航" })).toBeVisible();
|
||||
});
|
||||
|
||||
it("uses a single form and evidence card's own headings without fixed wrapper instructions", () => {
|
||||
render(<AnswerUiView block={taskBlock()} onSubmit={vi.fn()} />);
|
||||
expect(screen.getByLabelText("现场记录(必填)")).toBeVisible();
|
||||
expect(screen.getByRole("button", { name: /读数依据/ })).toBeVisible();
|
||||
expect(screen.queryByRole("button", { name: "收起补充资料" })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: "收起核查依据" })).not.toBeInTheDocument();
|
||||
expect(screen.queryByText("直接探索已加载数据")).not.toBeInTheDocument();
|
||||
expect(screen.queryByText("区分记录、推断与用户资料")).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("adapts response and report composition without replacing a reader's form draft", async () => {
|
||||
const user = userEvent.setup();
|
||||
const fixture = taskBlock();
|
||||
@@ -68,38 +91,33 @@ describe("local interactive answer renderer", () => {
|
||||
expect(screen.getByRole("note")).toHaveTextContent("能力限制");
|
||||
expect(screen.getByRole("note")).not.toHaveTextContent("注意事项");
|
||||
});
|
||||
it("combines metrics, selected rows and evidence into one deliberate quote without sending", async () => {
|
||||
it("shows data and evidence without row selection, quoting or analysis controls", async () => {
|
||||
const user = userEvent.setup();
|
||||
const ask = vi.fn();
|
||||
const submit = vi.fn();
|
||||
render(<AnswerUiView block={taskBlock()} onAsk={ask} onSubmit={submit} />);
|
||||
await user.click(screen.getByRole("button", { name: "将当前压力加入分析" }));
|
||||
await user.click(screen.getByRole("checkbox", { name: "选择第 1 行" }));
|
||||
await user.click(screen.getByRole("button", { name: "将所选行加入分析" }));
|
||||
render(<AnswerUiView block={taskBlock()} onSubmit={submit} />);
|
||||
expect(screen.getByRole("group", { name: "当前压力" })).toHaveTextContent("0.2130MPa");
|
||||
expect(screen.getByRole("table")).toHaveTextContent("北区入口");
|
||||
expect(screen.getAllByRole("columnheader")).toHaveLength(2);
|
||||
await user.click(screen.getByRole("button", { name: /读数依据.*测试查询/ }));
|
||||
await user.click(screen.getByRole("button", { name: "将读数依据加入分析" }));
|
||||
const tray = screen.getByRole("region", { name: "分析内容篮" });
|
||||
expect(tray).toHaveTextContent("已选 3 项分析内容");
|
||||
expect(ask).not.toHaveBeenCalled();
|
||||
await user.type(within(tray).getByRole("textbox"), "比较差异并核查原因");
|
||||
await user.click(within(tray).getByRole("button", { name: "带入对话" }));
|
||||
expect(ask).toHaveBeenCalledWith({ title: "3 项内容的联合分析", text: expect.stringContaining("分析目标:比较差异并核查原因") });
|
||||
const quote = ask.mock.calls[0][0].text;
|
||||
for (const exact of ["0.2130MPa", "来源:监测快照", "对象:北区入口;压力(MPa):0.2130", "资料编号:DEMO-26", "引用内容块:task"]) expect(quote).toContain(exact);
|
||||
await waitFor(() => expect(screen.getByText("仅用于演练")).toBeVisible());
|
||||
expect(screen.getByText("DEMO-26")).toBeVisible();
|
||||
expect(screen.queryByRole("checkbox")).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: /加入分析|针对.*提问|取消选行/ })).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("region", { name: "分析内容篮" })).not.toBeInTheDocument();
|
||||
expect(submit).not.toHaveBeenCalled();
|
||||
await user.click(within(tray).getByRole("button", { name: "移除当前压力" }));
|
||||
expect(tray).toHaveTextContent("已选 2 项分析内容");
|
||||
expect(screen.getByRole("button", { name: "将当前压力加入分析" })).toHaveAttribute("aria-pressed", "false");
|
||||
});
|
||||
|
||||
it("keeps the same form and selected content when more data arrives and support sections collapse", async () => {
|
||||
it("keeps the same form when more data arrives and support sections collapse", async () => {
|
||||
const user = userEvent.setup();
|
||||
const ask = vi.fn();
|
||||
const { rerender } = render(<AnswerUiView block={taskBlock(false)} onAsk={ask} onSubmit={vi.fn()} />);
|
||||
const { rerender } = render(<AnswerUiView block={taskBlock(false)} onSubmit={vi.fn()} />);
|
||||
const editor = screen.getByLabelText("现场记录(必填)");
|
||||
await user.type(editor, "未发送的现场草稿");
|
||||
await user.click(screen.getByRole("button", { name: "将当前压力加入分析" }));
|
||||
rerender(<AnswerUiView block={taskBlock()} onAsk={ask} onSubmit={vi.fn()} />);
|
||||
const grouped = taskBlock();
|
||||
grouped.spec.elements.root.children = [...(grouped.spec.elements.root.children ?? []), "extra-form"];
|
||||
grouped.spec.elements["extra-form"] = { ...grouped.spec.elements.form, props: {
|
||||
title: "其他资料", description: "可选补充", fields: [{ name: "extra", label: "其他记录", kind: "text", required: false }]
|
||||
} };
|
||||
rerender(<AnswerUiView block={grouped} onSubmit={vi.fn()} />);
|
||||
expect(screen.getByLabelText("现场记录(必填)")).toBe(editor);
|
||||
expect(editor).toHaveValue("未发送的现场草稿");
|
||||
await user.click(screen.getByRole("button", { name: "收起补充资料" }));
|
||||
@@ -108,25 +126,22 @@ describe("local interactive answer renderer", () => {
|
||||
await user.click(screen.getByRole("button", { name: "展开补充资料" }));
|
||||
await waitFor(() => expect(editor).toBeVisible());
|
||||
expect(editor).toHaveValue("未发送的现场草稿");
|
||||
expect(screen.getByRole("region", { name: "分析内容篮" })).toHaveTextContent("已选 1 项分析内容");
|
||||
await user.click(screen.getByRole("button", { name: "收起补充资料" }));
|
||||
const updated = taskBlock();
|
||||
updated.spec.elements.table.props.rows = [["新增入口", "0.24"]];
|
||||
rerender(<AnswerUiView block={updated} onAsk={ask} onSubmit={vi.fn()} />);
|
||||
rerender(<AnswerUiView block={updated} onSubmit={vi.fn()} />);
|
||||
expect(screen.getByLabelText("现场记录(必填)")).toBe(editor);
|
||||
await waitFor(() => expect(editor).toBeVisible());
|
||||
expect(editor).toHaveValue("未发送的现场草稿");
|
||||
});
|
||||
|
||||
it("rejects oversized row quotes without truncating values or removing existing selections", async () => {
|
||||
const user = userEvent.setup();
|
||||
it("preserves long original cell values without requiring a selection or quote action", () => {
|
||||
const fixture = taskBlock();
|
||||
fixture.spec.elements.table.props.rows = Array.from({ length: 12 }, (_, index) => [String(index), "长".repeat(800)]);
|
||||
render(<AnswerUiView block={fixture} onAsk={vi.fn()} />);
|
||||
await user.click(screen.getByRole("button", { name: "将当前压力加入分析" }));
|
||||
await user.click(screen.getByRole("checkbox", { name: "选择入口记录的全部筛选结果" }));
|
||||
await user.click(screen.getByRole("button", { name: "将所选行加入分析" }));
|
||||
expect(screen.getByRole("status")).toHaveTextContent("8000 字");
|
||||
expect(screen.getByRole("region", { name: "分析内容篮" })).toHaveTextContent("已选 1 项分析内容");
|
||||
expect(screen.getByRole("checkbox", { name: "选择第 12 行" })).toBeChecked();
|
||||
render(<AnswerUiView block={fixture} />);
|
||||
expect(screen.getAllByText("长".repeat(800))).toHaveLength(12);
|
||||
expect(screen.queryByRole("checkbox")).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: /加入分析|针对.*提问/ })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("expresses supplied context and cautions as readable notes without announcing historical alerts", () => {
|
||||
@@ -143,16 +158,14 @@ describe("local interactive answer renderer", () => {
|
||||
expect(screen.queryByRole("note")).not.toBeInTheDocument();
|
||||
expect(screen.getByText("普通回答")).toBeInTheDocument();
|
||||
});
|
||||
it("offers a named metric quote action and retains the exact value, unit and source", async () => {
|
||||
const user = userEvent.setup();
|
||||
const ask = vi.fn();
|
||||
it("retains a metric's exact value, unit and source without action buttons", () => {
|
||||
render(<AnswerUiView block={block("Metric", {
|
||||
label: "当前压力", value: "0.3000", unit: "MPa", source: "已加载记录",
|
||||
})} onAsk={ask} />);
|
||||
await user.click(screen.getByRole("button", { name: "针对当前压力提问" }));
|
||||
expect(ask).toHaveBeenCalledWith({
|
||||
title: "当前压力", text: "当前压力:0.3000MPa\n来源:已加载记录\n引用内容块:test",
|
||||
});
|
||||
})} />);
|
||||
const metric = screen.getByRole("group", { name: "当前压力" });
|
||||
expect(metric).toHaveTextContent("0.3000MPa");
|
||||
expect(metric).toHaveTextContent("来源:已加载记录");
|
||||
expect(screen.queryByRole("button")).not.toBeInTheDocument();
|
||||
});
|
||||
it("renders through json-render and lets readers inspect exact chart data with keyboard tabs", async () => {
|
||||
const user = userEvent.setup();
|
||||
@@ -199,22 +212,21 @@ describe("local interactive answer renderer", () => {
|
||||
feature_ids: ["DEMO-P001", "DEMO-P002"]
|
||||
});
|
||||
});
|
||||
it("filters and sorts loaded rows, then quotes the selected original values without sending", async () => {
|
||||
it("filters and sorts loaded rows without selecting or sending content", async () => {
|
||||
const user = userEvent.setup();
|
||||
const ask = vi.fn();
|
||||
const submit = vi.fn();
|
||||
render(<AnswerUiView block={block("Table", {
|
||||
title: "监测记录", columns: ["监测点", "压力"],
|
||||
rows: [["南站", "0.32"], ["北站", "0.21"], ["南站二号", "0.26"]]
|
||||
})} onAsk={ask} onSubmit={submit} />);
|
||||
})} onSubmit={submit} />);
|
||||
await user.type(screen.getByRole("textbox", { name: "搜索监测记录" }), "南站");
|
||||
expect(screen.getByText("2 / 3 行")).toBeInTheDocument();
|
||||
await user.click(screen.getByRole("button", { name: "按压力排序" }));
|
||||
const rows = screen.getAllByRole("row");
|
||||
expect(rows[1]).toHaveTextContent("南站二号");
|
||||
await user.click(screen.getByRole("checkbox", { name: "选择第 3 行" }));
|
||||
await user.click(screen.getByRole("button", { name: "针对这部分提问" }));
|
||||
expect(ask).toHaveBeenCalledWith({ title: "监测记录", text: expect.stringContaining("监测点:南站二号;压力:0.26") });
|
||||
expect(rows[1]).toHaveTextContent("0.26");
|
||||
expect(screen.queryByRole("checkbox")).not.toBeInTheDocument();
|
||||
expect(screen.queryByRole("button", { name: /加入分析|针对.*提问/ })).not.toBeInTheDocument();
|
||||
expect(submit).not.toHaveBeenCalled();
|
||||
});
|
||||
it("keeps form values after a failed submission", async () => {
|
||||
|
||||
Reference in New Issue
Block a user