Files
TJWaterFrontend_Refine/src/components/olmap/MonitoringPlaceOptimization/SchemeEditor.test.tsx
T

277 lines
6.9 KiB
TypeScript

import { act, fireEvent, render, screen, waitFor } from "@testing-library/react";
import SchemeEditor from "./SchemeEditor";
import { getSensorPlacementCandidate } from "./schemeApi";
import type { SensorPlacementScheme } from "./types";
import { handleMapClickSelectFeatures } from "@/utils/mapQueryService";
const mockOpen = jest.fn();
let mockSingleClickHandler: ((event: unknown) => void) | undefined;
let mockGridColumns: Array<{
field: string;
headerName?: string;
valueFormatter?: (value: unknown) => string;
}> = [];
const mockMap = {
addLayer: jest.fn(),
removeLayer: jest.fn(),
on: jest.fn((eventName: string, handler: (event: unknown) => void) => {
if (eventName === "singleclick") {
mockSingleClickHandler = handler;
}
}),
un: jest.fn(),
forEachFeatureAtPixel: jest.fn(() => undefined),
getView: jest.fn(() => ({
animate: jest.fn(),
getZoom: jest.fn(() => 16),
getResolution: jest.fn(() => 1),
})),
};
jest.mock("@refinedev/core", () => ({
useNotification: () => ({ open: mockOpen }),
}));
jest.mock("@components/olmap/core/MapComponent", () => ({
useMap: () => mockMap,
}));
jest.mock("@mui/x-data-grid", () => ({
DataGrid: (props: {
columns: typeof mockGridColumns;
density?: string;
initialState?: { density?: string };
rowHeight?: number;
columnHeaderHeight?: number;
}) => {
mockGridColumns = props.columns;
return (
<div
data-testid="scheme-grid"
data-density={props.density ?? "uncontrolled"}
data-initial-density={props.initialState?.density ?? ""}
data-row-height={props.rowHeight ?? "automatic"}
data-column-header-height={props.columnHeaderHeight ?? "automatic"}
/>
);
},
GridToolbar: () => null,
}));
jest.mock("@mui/x-data-grid/locales", () => ({
zhCN: {
components: {
MuiDataGrid: {
defaultProps: {
localeText: {},
},
},
},
},
}));
jest.mock("ol/Feature", () => ({
__esModule: true,
default: class {
private values: Record<string, unknown>;
constructor(values: Record<string, unknown>) {
this.values = values;
}
get(key: string) {
return this.values[key];
}
setId() {}
},
}));
jest.mock("ol/geom/Point", () => ({
__esModule: true,
default: class {
constructor(_coordinates: number[]) {}
},
}));
jest.mock("ol/source/Vector", () => ({
__esModule: true,
default: class {
clear() {}
addFeature() {}
},
}));
jest.mock("ol/layer/Vector", () => ({
__esModule: true,
default: class {
private source: { clear: () => void; addFeature: () => void };
constructor(options: {
source: { clear: () => void; addFeature: () => void };
}) {
this.source = options.source;
}
getSource() {
return this.source;
}
setVisible() {}
},
}));
jest.mock("ol/style", () => ({
Circle: class {},
Fill: class {},
Stroke: class {},
Style: class {},
Text: class {},
}));
jest.mock("@/utils/mapQueryService", () => ({
handleMapClickSelectFeatures: jest.fn(),
}));
jest.mock("./SchemeDrawingDialog", () => ({
__esModule: true,
default: () => null,
}));
jest.mock("./schemeApi", () => ({
exportSensorPlacementExcel: jest.fn(),
getSensorPlacementCandidate: jest.fn(),
overwriteSensorPlacementScheme: jest.fn(),
}));
const scheme: SensorPlacementScheme = {
id: 1,
scheme_name: "测试方案",
sensor_number: 1,
min_diameter: 300,
username: "operator",
create_time: "2026-07-30T08:00:00+08:00",
sensor_location: ["J1"],
sensor_points: [
{
node_id: "J1",
max_pipe_diameter: 400,
project_x: 10,
project_y: 20,
map_x: 13500010,
map_y: 3600020,
longitude: 121,
latitude: 31,
elevation: 5,
},
],
can_edit: true,
};
const mockGetSensorPlacementCandidate = jest.mocked(
getSensorPlacementCandidate,
);
const mockHandleMapClickSelectFeatures = jest.mocked(
handleMapClickSelectFeatures,
);
describe("SchemeEditor notifications", () => {
beforeEach(() => {
jest.clearAllMocks();
mockSingleClickHandler = undefined;
mockGridColumns = [];
});
it("uses the same error notification contract as scheme query when replace starts outside an existing sensor", async () => {
render(<SchemeEditor scheme={scheme} network="fengyang" />);
fireEvent.click(screen.getByRole("button", { name: "替换" }));
await waitFor(() => expect(mockSingleClickHandler).toBeDefined());
act(() => {
mockSingleClickHandler?.({
pixel: [0, 0],
coordinate: [13500000, 3600000],
stopPropagation: jest.fn(),
});
});
expect(mockOpen).toHaveBeenCalledWith({
type: "error",
message: "请先点击要替换的监测点",
});
});
it("loads authoritative point details when adding a map-selected node", async () => {
mockHandleMapClickSelectFeatures.mockResolvedValue({
get: (key: string) => (key === "id" ? "J2" : undefined),
getId: () => "J2",
} as never);
mockGetSensorPlacementCandidate.mockResolvedValue({
node_id: "J2",
max_pipe_diameter: 500,
project_x: 30,
project_y: 40,
map_x: 13500030,
map_y: 3600040,
longitude: 121.1,
latitude: 31.1,
elevation: 6,
});
render(<SchemeEditor scheme={scheme} network="fengyang" />);
fireEvent.click(screen.getByRole("button", { name: "添加" }));
await waitFor(() => expect(mockSingleClickHandler).toBeDefined());
await act(async () => {
mockSingleClickHandler?.({
pixel: [0, 0],
coordinate: [13500030, 3600040],
stopPropagation: jest.fn(),
});
await Promise.resolve();
});
expect(mockGetSensorPlacementCandidate).toHaveBeenCalledWith("J2");
});
it("lets the Data Grid density selector control row sizing", () => {
render(<SchemeEditor scheme={scheme} network="fengyang" />);
expect(screen.getByTestId("scheme-grid")).toHaveAttribute(
"data-density",
"uncontrolled",
);
expect(screen.getByTestId("scheme-grid")).toHaveAttribute(
"data-initial-density",
"compact",
);
expect(screen.getByTestId("scheme-grid")).toHaveAttribute(
"data-row-height",
"automatic",
);
expect(screen.getByTestId("scheme-grid")).toHaveAttribute(
"data-column-header-height",
"automatic",
);
});
it("places actions and status first and displays the selected pipe diameter", () => {
render(<SchemeEditor scheme={scheme} network="fengyang" />);
expect(mockGridColumns.slice(0, 5).map((column) => column.field)).toEqual([
"actions",
"adjustment_status",
"sequence",
"node_id",
"max_pipe_diameter",
]);
const diameterColumn = mockGridColumns.find(
(column) => column.field === "max_pipe_diameter",
);
expect(diameterColumn?.headerName).toBe("最大管径 (mm)");
expect(diameterColumn?.valueFormatter?.(400)).toBe("400");
expect(diameterColumn?.valueFormatter?.(null)).toBe("无");
});
});