Files
TJWaterFrontend_Refine/src/components/threeDimensional/ThreeDimensionalControls.test.tsx
T
jiang a9b25b94d8
Generic Container CI/CD / test-build-publish (push) Successful in 2m20s
Frontend CI/CD v2 / build-test-publish-and-deploy (push) Successful in 2m20s
feat(3d): refine scene controls and camera views
Keep the control panel geometry stable when toggling building context, and use accessible switch controls to prevent focus-driven movement. Add browser coverage for camera framing, opacity, responsive layout, and the default 6x pipe scale.
2026-09-14 15:41:44 +08:00

193 lines
5.3 KiB
TypeScript

import { fireEvent, render, screen } from "@testing-library/react";
import { ThreeDimensionalControls } from "./ThreeDimensionalControls";
import type { SceneRuntimeState } from "./sceneProtocol";
const state: SceneRuntimeState = {
mode: "network",
status: "管网实体模型",
contextVisible: true,
roofVisible: true,
displayMode: "global",
style: {
scale: 6,
mode: "uniform",
color: "#098ed0",
missingColor: "#89949d",
lowColor: "#2b83ba",
highColor: "#e66c37",
opacity: 1,
roughness: 0.3,
metalness: 0.22,
nodes: true,
direction: "none",
arrowColor: "#f2b447",
autoRange: true,
min: 0,
max: 3,
},
styleSummary: {},
appearance: {
preset: "day",
exposure: 0.95,
contextOpacity: 0.4,
shadows: true,
effects: true,
quality: "standard",
},
camera: {
active: "overview",
note: "供水总览",
views: [
{
id: "overview",
label: "供水总览",
mode: "network",
saved: false,
},
],
},
};
describe("ThreeDimensionalControls", () => {
it("toggles the active toolbar panel and opens a different panel", () => {
const onOpenChange = jest.fn();
const onTabChange = jest.fn();
const { rerender } = render(
<ThreeDimensionalControls
open
activeTab="scene"
ready
state={state}
selection={null}
timelineOpen
onOpenChange={onOpenChange}
onTimelineOpenChange={jest.fn()}
onTabChange={onTabChange}
onCommand={jest.fn()}
/>,
);
fireEvent.click(screen.getByRole("button", { name: "场景与视角" }));
expect(onOpenChange).toHaveBeenLastCalledWith(false);
expect(onTabChange).not.toHaveBeenCalled();
rerender(
<ThreeDimensionalControls
open={false}
activeTab="scene"
ready
state={state}
selection={null}
timelineOpen
onOpenChange={onOpenChange}
onTimelineOpenChange={jest.fn()}
onTabChange={onTabChange}
onCommand={jest.fn()}
/>,
);
fireEvent.click(screen.getByRole("button", { name: "管网样式" }));
expect(onTabChange).toHaveBeenLastCalledWith("style");
expect(onOpenChange).toHaveBeenLastCalledWith(true);
});
it("sends typed scene commands from platform controls", () => {
const onCommand = jest.fn();
const onTimelineOpenChange = jest.fn();
render(
<ThreeDimensionalControls
open
activeTab="scene"
ready
state={state}
selection={null}
timelineOpen
onOpenChange={jest.fn()}
onTimelineOpenChange={onTimelineOpenChange}
onTabChange={jest.fn()}
onCommand={onCommand}
/>,
);
fireEvent.click(screen.getByRole("button", { name: "站房精细版" }));
expect(onCommand).toHaveBeenCalledWith({ name: "set-mode", mode: "detail" });
fireEvent.change(screen.getByRole("slider", { name: "建筑背景透明度 60%" }), {
target: { value: "0.35" },
});
expect(onCommand).toHaveBeenCalledWith({
name: "set-appearance",
patch: { contextOpacity: 0.65 },
});
fireEvent.click(screen.getByRole("switch", { name: "建筑背景" }));
expect(onCommand).toHaveBeenCalledWith({ name: "toggle-context" });
fireEvent.click(screen.getByRole("button", { name: "时间轴" }));
expect(onTimelineOpenChange).toHaveBeenCalledWith(false);
});
it("uses the glass listbox instead of a native select", () => {
const onCommand = jest.fn();
render(
<ThreeDimensionalControls
open
activeTab="scene"
ready
state={state}
selection={null}
timelineOpen
onOpenChange={jest.fn()}
onTimelineOpenChange={jest.fn()}
onTabChange={jest.fn()}
onCommand={onCommand}
/>,
);
const displayMode = screen.getByRole("combobox", {
name: "管网展示比例",
});
expect(displayMode.tagName).not.toBe("SELECT");
fireEvent.mouseDown(displayMode);
fireEvent.click(screen.getByRole("option", { name: "泵房协调比例" }));
expect(onCommand).toHaveBeenCalledWith({
name: "set-display-mode",
mode: "coordinated",
});
});
it("shows selected asset fields and linked assets in the property tab", () => {
const onCommand = jest.fn();
render(
<ThreeDimensionalControls
open
activeTab="properties"
ready
state={state}
selection={{
assetId: "inp:node:J-1",
elementId: "J-1",
kind: "节点",
title: "节点 · J-1",
sections: [
{
title: "运行结果",
fields: [{ label: "压力", value: "31.200 mH₂O" }],
},
],
neighbors: [{ id: "P-1", label: "P-1" }],
}}
timelineOpen
onOpenChange={jest.fn()}
onTimelineOpenChange={jest.fn()}
onTabChange={jest.fn()}
onCommand={onCommand}
/>,
);
expect(screen.getByText("节点 · J-1")).toBeInTheDocument();
expect(screen.getByText("31.200 mH₂O")).toBeInTheDocument();
fireEvent.click(screen.getByRole("button", { name: "P-1" }));
expect(onCommand).toHaveBeenCalledWith({ name: "select-asset", assetId: "P-1" });
});
});