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
};
}