Skip to content

Commit eb5821e

Browse files
committed
Adding unit tests for Tank
1 parent 53069ba commit eb5821e

File tree

1 file changed

+240
-0
lines changed

1 file changed

+240
-0
lines changed

src/ui/widgets/Tank/tank.test.tsx

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
import React from "react";
2+
import { render, screen } from "@testing-library/react";
3+
import { describe, test, expect, beforeEach, vi } from "vitest";
4+
import { TankComponent } from "./tank";
5+
import { Font } from "../../../types/font";
6+
import { Color, DType } from "../../../types";
7+
8+
// Mock the MUI X-Charts components
9+
vi.mock("@mui/x-charts/BarChart", () => ({
10+
BarChart: vi.fn(({ series, xAxis, yAxis, sx }) => (
11+
<div
12+
data-testid="bar-chart"
13+
data-series={JSON.stringify(series)}
14+
data-xaxis={JSON.stringify(xAxis)}
15+
data-yaxis={JSON.stringify(yAxis)}
16+
style={sx}
17+
/>
18+
))
19+
}));
20+
21+
vi.mock("@mui/x-charts", () => ({
22+
XAxis: vi.fn(),
23+
YAxis: vi.fn()
24+
}));
25+
26+
vi.mock("@mui/material", () => ({
27+
Box: vi.fn(({ children }) => <div data-testid="mui-box">{children}</div>)
28+
}));
29+
30+
// Mock for font.css() function
31+
const mockFontCss = vi.fn().mockReturnValue({
32+
fontFamily: "Arial",
33+
fontSize: "12px"
34+
});
35+
36+
describe("TankComponent", () => {
37+
// Basic test setup
38+
const defaultProps = {
39+
value: {
40+
getDoubleValue: () => 50,
41+
display: {
42+
units: "mm",
43+
controlRange: { min: 0, max: 100 }
44+
}
45+
} as Partial<DType> as DType,
46+
connected: true,
47+
readonly: true,
48+
pvName: "TEST:PV",
49+
minimum: 0,
50+
maximum: 100,
51+
font: { css: mockFontCss } as Partial<Font> as Font
52+
};
53+
54+
beforeEach(() => {
55+
vi.clearAllMocks();
56+
});
57+
58+
describe("Rendering", () => {
59+
test("renders with default props", () => {
60+
render(<TankComponent {...defaultProps} />);
61+
62+
const barChart = screen.getByTestId("bar-chart");
63+
expect(barChart).toBeDefined();
64+
65+
// Check default orientation (vertical)
66+
const chartData = JSON.parse(barChart.getAttribute("data-yaxis") ?? "");
67+
expect(chartData[0].position).toBe("left"); // Default is vertical with scale on left
68+
});
69+
70+
test("renders with horizontal orientation", () => {
71+
render(<TankComponent {...defaultProps} horizontal={true} />);
72+
73+
const barChart = screen.getByTestId("bar-chart");
74+
const xAxisData = JSON.parse(barChart.getAttribute("data-xaxis") ?? "");
75+
76+
expect(xAxisData[0].position).toBe("top"); // Horizontal with scale on top
77+
});
78+
79+
test("renders with label when showLabel is true", () => {
80+
render(<TankComponent {...defaultProps} showLabel={true} />);
81+
82+
expect(screen.getByText("50")).toBeDefined();
83+
});
84+
85+
test("renders with custom precision", () => {
86+
render(
87+
<TankComponent {...defaultProps} showLabel={true} precision={2} />
88+
);
89+
90+
expect(screen.getByText("50.00")).toBeDefined();
91+
});
92+
93+
test("renders with warning when min > max", () => {
94+
render(
95+
<TankComponent
96+
{...defaultProps}
97+
showLabel={true}
98+
minimum={200}
99+
maximum={100}
100+
/>
101+
);
102+
103+
expect(screen.getByText("Check min and max values")).toBeDefined();
104+
});
105+
});
106+
107+
describe("PV limits", () => {
108+
test("uses PV limits when limitsFromPv is true", () => {
109+
const props = {
110+
...defaultProps,
111+
limitsFromPv: true,
112+
minimum: 10, // These should be overridden
113+
maximum: 90 // by the PV control range
114+
};
115+
116+
render(<TankComponent {...props} />);
117+
118+
const barChart = screen.getByTestId("bar-chart");
119+
const yAxisData = JSON.parse(barChart.getAttribute("data-yaxis") ?? "");
120+
121+
// Should use PV limits (0, 100) instead of props (10, 90)
122+
expect(yAxisData[0].min).toBe(0);
123+
expect(yAxisData[0].max).toBe(100);
124+
});
125+
126+
test("handles undefined PV value gracefully", () => {
127+
const props = {
128+
...defaultProps,
129+
value: undefined
130+
};
131+
132+
render(<TankComponent {...props} />);
133+
134+
const barChart = screen.getByTestId("bar-chart");
135+
const seriesData = JSON.parse(barChart.getAttribute("data-series") ?? "");
136+
137+
expect(seriesData[0].data[0]).toBe(0);
138+
});
139+
140+
test("handles edge case with value equal to maximum", () => {
141+
const props = {
142+
...defaultProps,
143+
value: {
144+
getDoubleValue: () => 100,
145+
display: {
146+
units: "mm",
147+
controlRange: { min: 0, max: 100 }
148+
}
149+
} as Partial<DType> as DType
150+
};
151+
152+
render(<TankComponent {...props} />);
153+
154+
const barChart = screen.getByTestId("bar-chart");
155+
const seriesData = JSON.parse(barChart.getAttribute("data-series") ?? "");
156+
157+
expect(seriesData[0].data[0]).toBe(100);
158+
expect(seriesData[1].data[0]).toBe(0); // Empty part should be 0
159+
});
160+
161+
test("handles edge case with value below minimum", () => {
162+
const props = {
163+
...defaultProps,
164+
value: {
165+
getDoubleValue: () => -10,
166+
display: {
167+
units: "mm",
168+
controlRange: { min: 0, max: 100 }
169+
}
170+
} as Partial<DType> as DType
171+
};
172+
173+
render(<TankComponent {...props} />);
174+
175+
const barChart = screen.getByTestId("bar-chart");
176+
const seriesData = JSON.parse(barChart.getAttribute("data-series") ?? "");
177+
178+
expect(seriesData[0].data[0]).toBe(-10);
179+
});
180+
});
181+
182+
describe("Styling", () => {
183+
test("applies custom colors", () => {
184+
const fillColor = Color.fromRgba(100, 150, 200);
185+
const emptyColor = Color.fromRgba(200, 200, 200);
186+
const backgroundColor = Color.fromRgba(240, 240, 240);
187+
188+
render(
189+
<TankComponent
190+
{...defaultProps}
191+
fillColor={fillColor}
192+
emptyColor={emptyColor}
193+
backgroundColor={backgroundColor}
194+
/>
195+
);
196+
197+
const barChart = screen.getByTestId("bar-chart");
198+
const seriesData = JSON.parse(barChart.getAttribute("data-series") ?? "");
199+
200+
expect(seriesData[0].color).toBe(fillColor.toString());
201+
expect(seriesData[1].color).toBe(emptyColor.toString());
202+
203+
// Check background color is applied
204+
expect(barChart.style.backgroundColor).toBe("rgb(240, 240, 240)");
205+
});
206+
207+
test("applies transparent background when transparent is true", () => {
208+
render(<TankComponent {...defaultProps} transparent={true} />);
209+
210+
const barChart = screen.getByTestId("bar-chart");
211+
expect(barChart.style.backgroundColor).toBe("transparent");
212+
});
213+
214+
test("hides scale when scaleVisible is false", () => {
215+
render(<TankComponent {...defaultProps} scaleVisible={false} />);
216+
217+
const barChart = screen.getByTestId("bar-chart");
218+
const yAxisData = JSON.parse(barChart.getAttribute("data-yaxis") ?? "");
219+
220+
expect(yAxisData[0].position).toBe("none");
221+
});
222+
223+
test("applies log scale when logScale is true", () => {
224+
render(<TankComponent {...defaultProps} logScale={true} />);
225+
226+
const barChart = screen.getByTestId("bar-chart");
227+
const yAxisData = JSON.parse(barChart.getAttribute("data-yaxis") ?? "");
228+
229+
expect(yAxisData[0].scaleType).toBe("symlog");
230+
});
231+
232+
test("applies font styling to label", () => {
233+
render(<TankComponent {...defaultProps} showLabel={true} />);
234+
235+
const labelContainer = screen.getByText("50");
236+
expect(labelContainer?.style.fontFamily).toBe("Arial");
237+
expect(labelContainer?.style.fontSize).toBe("12px");
238+
});
239+
});
240+
});

0 commit comments

Comments
 (0)