import { cleanup, render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { afterEach, describe, expect, it, vi } from "vitest"; import type { WorkbenchMapCommands, WorkbenchMapControllerState } from "../map/workbench-map-controller"; import { MapDevPanel } from "./map-dev-panel"; afterEach(cleanup); describe("MapDevPanel", () => { it("deduplicates pasted IDs for every location action and prevents oversized batches", async () => { const user = userEvent.setup(); const commands = createCommands(); render(); const input = screen.getByLabelText("要素 ID(可多个)"); await user.clear(input); await user.paste("P-1,P-2\nP-1 P-3;P-4"); const target = { sourceId: "pipes", featureIds: ["P-1", "P-2", "P-3", "P-4"] }; await user.click(screen.getByRole("button", { name: "仅高亮" })); expect(commands.highlight).toHaveBeenCalledWith(target); await user.click(screen.getByRole("button", { name: "缩放到要素" })); expect(commands.zoomToFeature).toHaveBeenCalledWith(target); await user.click(screen.getByRole("button", { name: "定位并高亮" })); expect(commands.locateAndHighlight).toHaveBeenCalledWith(target); await user.clear(input); expect(screen.getByRole("button", { name: "定位并高亮" })).toBeDisabled(); await user.paste(Array.from({ length: 101 }, (_, i) => `P-${i}`).join(",")); expect(screen.getByRole("alert")).toHaveTextContent("单次最多 100 个"); expect(screen.getByRole("button", { name: "定位并高亮" })).toBeDisabled(); }); it("defaults to following investigations and allows disabling it", async () => { const user = userEvent.setup(); const onFollowChange = vi.fn(); render( ); const follow = screen.getByRole("checkbox", { name: "跟随所选调查" }); expect(follow).toBeChecked(); await user.click(follow); expect(onFollowChange).toHaveBeenCalledWith(false); }); it("keeps map inputs when switching between investigation and map tools", async () => { const user = userEvent.setup(); const commands = createCommands(); render(); expect(screen.getByRole("tab", { name: "调查测试" })).toHaveAttribute("aria-selected", "true"); expect(screen.queryByRole("button", { name: "定位并高亮" })).not.toBeInTheDocument(); await user.click(screen.getByRole("tab", { name: "地图调试" })); const featureId = screen.getByLabelText("要素 ID(可多个)"); await user.clear(featureId); await user.type(featureId, "DEMO-PIPE-03"); await user.click(screen.getByRole("tab", { name: "调查测试" })); expect(screen.queryByRole("button", { name: "重置地图调试效果" })).not.toBeInTheDocument(); await user.click(screen.getByRole("tab", { name: "地图调试" })); expect(screen.getByLabelText("要素 ID(可多个)")).toHaveValue("DEMO-PIPE-03"); expect(commands.resetAll).not.toHaveBeenCalled(); }); it("updates a pipe with its signed velocity", async () => { const user = userEvent.setup(); const commands = createCommands(); render( ); await user.click(screen.getByText("水流调试")); const pipeId = screen.getByLabelText("管道 ID"); const velocity = screen.getByLabelText("有符号流速"); await user.clear(pipeId); await user.type(pipeId, "P-9"); await user.clear(velocity); await user.type(velocity, "-2.75"); await user.click(screen.getByRole("button", { name: "更新该管道方向" })); expect(commands.updatePipeFlowCalculation).toHaveBeenCalledWith({ pipeId: "P-9", velocity: -2.75 }); }); it("shows the current flow direction counts", async () => { const user = userEvent.setup(); render( ); await user.click(screen.getByText("水流调试")); expect( screen.getByRole("status", { name: "" }) ).toHaveTextContent("已赋值 4 · 正向 2 · 反向 1 · 停止 1"); }); }); function createCommands() { return { zoomToFeature: vi.fn(), locateAndHighlight: vi.fn(), highlight: vi.fn(), clearHighlight: vi.fn(), setFlowVisible: vi.fn(), replacePipeFlowCalculations: vi.fn(), updatePipeFlowCalculation: vi.fn(), clearPipeFlowCalculations: vi.fn(), showValueLabel: vi.fn(), clearValueLabel: vi.fn(), applyLayerGroupStyle: vi.fn(), resetLayerGroupStyle: vi.fn(), resetAll: vi.fn() } satisfies WorkbenchMapCommands; } function createControllerState( patch: Partial = {} ): WorkbenchMapControllerState { return { target: null, targets: [], targetResult: null, valueLabels: {}, pending: false, errorCode: null, flowVisible: false, flowSummary: { total: 0, forward: 0, reverse: 0, stopped: 0, invalid: 0 }, styledGroups: [], ...patch }; }