Skip to content

Commit e308a6f

Browse files
committed
New UI tests
1 parent 797b4b1 commit e308a6f

18 files changed

+1072
-39
lines changed

chartlets.js/package-lock.json

Lines changed: 506 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

chartlets.js/packages/lib/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
"@typescript-eslint/parser": "^7.18.0",
8484
"@vitejs/plugin-react-swc": "^3.7.0",
8585
"@vitest/coverage-v8": "^2.1.1",
86+
"canvas": "^2.11.2",
8687
"eslint": "^8.57.1",
8788
"eslint-plugin-react-hooks": "^4.6.2",
8889
"eslint-plugin-react-refresh": "^0.4.12",

chartlets.js/packages/lib/src/hooks.test.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,30 @@ describe("useComponentChangeHandlers", () => {
9090
const { result } = renderHook(() =>
9191
useComponentChangeHandlers("panels", 3),
9292
);
93+
const [handleChange0, handleChange1, handleChange2] = result.current;
94+
expect(typeof handleChange0).toEqual("function");
95+
expect(typeof handleChange1).toEqual("function");
96+
expect(typeof handleChange2).toEqual("function");
9397
act(() =>
94-
result.current[0]({
98+
handleChange0({
9599
componentType: "button",
96-
id: "btn",
100+
id: "btn1",
101+
property: "clicked",
102+
value: true,
103+
}),
104+
);
105+
act(() =>
106+
handleChange1({
107+
componentType: "button",
108+
id: "btn2",
109+
property: "clicked",
110+
value: true,
111+
}),
112+
);
113+
act(() =>
114+
handleChange2({
115+
componentType: "button",
116+
id: "btn3",
97117
property: "clicked",
98118
value: true,
99119
}),

chartlets.js/packages/lib/src/plugins/mui/Box.test.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ describe("Box", () => {
99
render(
1010
<Box id="bx" type={"Box"} children={["Hallo!"]} onChange={onChange} />,
1111
);
12+
// to inspect rendered component, do:
13+
// expect(document.querySelector("#bx")).toEqual({});
1214
expect(screen.getByText("Hallo!")).not.toBeUndefined();
1315
});
1416
});
Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,20 @@
11
import { describe, it, expect } from "vitest";
22
import { render, screen, fireEvent } from "@testing-library/react";
3-
import type {
4-
ComponentChangeEvent,
5-
ComponentChangeHandler,
6-
} from "@/types/state/event";
3+
import { createChangeHandler } from "./common.test";
74
import { Button } from "./Button";
85

96
describe("Button", () => {
107
it("should render the Button component", () => {
11-
const onChange: ComponentChangeHandler = () => {};
128
render(
13-
<Button id="bt" type={"Button"} text={"Click!"} onChange={onChange} />,
9+
<Button id="bt" type={"Button"} text={"Click!"} onChange={() => {}} />,
1410
);
11+
// to inspect rendered component, do:
12+
// expect(document.querySelector("#bt")).toEqual({});
1513
expect(screen.getByText("Click!")).not.toBeUndefined();
1614
});
1715

18-
it("should fire the 'clicked'", () => {
19-
let recordedEvent: ComponentChangeEvent | undefined = undefined;
20-
const onChange: ComponentChangeHandler = (event) => {
21-
recordedEvent = event;
22-
};
16+
it("should fire the 'clicked' property", () => {
17+
const { recordedEvents, onChange } = createChangeHandler();
2318
render(
2419
<Button
2520
data-testid="bt"
@@ -30,6 +25,12 @@ describe("Button", () => {
3025
/>,
3126
);
3227
fireEvent.click(screen.getByText("Click!"));
33-
expect(recordedEvent).not.toBeUndefined();
28+
expect(recordedEvents.length).toEqual(1);
29+
expect(recordedEvents[0]).toEqual({
30+
componentType: "Button",
31+
id: "bt",
32+
property: "clicked",
33+
value: true,
34+
});
3435
});
3536
});
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { describe, it, expect } from "vitest";
2+
import { render, screen, fireEvent } from "@testing-library/react";
3+
import { createChangeHandler } from "./common.test";
4+
import { Checkbox } from "./Checkbox";
5+
6+
describe("Checkbox", () => {
7+
it("should render the Checkbox component", () => {
8+
render(
9+
<Checkbox
10+
id="cb"
11+
type={"Checkbox"}
12+
label={"Click!"}
13+
onChange={() => {}}
14+
/>,
15+
);
16+
// to inspect rendered component, do:
17+
// expect(document.querySelector("#cb")).toEqual({});
18+
expect(screen.getByText("Click!")).not.toBeUndefined();
19+
});
20+
21+
it("should fire 'value' property", () => {
22+
const { recordedEvents, onChange } = createChangeHandler();
23+
render(
24+
<Checkbox
25+
data-testid="bt"
26+
id="cb"
27+
type={"Checkbox"}
28+
label={"Click!"}
29+
value={false}
30+
onChange={onChange}
31+
/>,
32+
);
33+
fireEvent.click(screen.getByText("Click!"));
34+
expect(recordedEvents.length).toEqual(1);
35+
expect(recordedEvents[0]).toEqual({
36+
componentType: "Checkbox",
37+
id: "cb",
38+
property: "value",
39+
value: true,
40+
});
41+
});
42+
});
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { describe, it, expect } from "vitest";
2+
import { render, screen } from "@testing-library/react";
3+
import { CircularProgress } from "./CircularProgress";
4+
5+
describe("CircularProgress", () => {
6+
it("should render the CircularProgress component", () => {
7+
render(
8+
<CircularProgress
9+
type="CircularProgress"
10+
id="cp"
11+
size="small"
12+
onChange={() => {}}
13+
/>,
14+
);
15+
// to inspect rendered component, do:
16+
// expect(document.querySelector("#cp")).toEqual({});
17+
expect(screen.getByRole("progressbar")).not.toBeUndefined();
18+
});
19+
});
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { describe, it, expect } from "vitest";
2+
import { render, screen, fireEvent } from "@testing-library/react";
3+
import { IconButton } from "./IconButton";
4+
import { createChangeHandler } from "@/plugins/mui/common.test";
5+
6+
describe("IconButton", () => {
7+
it("should render the IconButton component", () => {
8+
render(
9+
<IconButton
10+
id="ibt"
11+
type={"IconButton"}
12+
icon={"arrow-left"}
13+
onChange={() => {}}
14+
/>,
15+
);
16+
// to inspect rendered component, do:
17+
// expect(document.querySelector("#ibt")).toEqual({});
18+
expect(screen.getByRole("button")).not.toBeUndefined();
19+
});
20+
21+
it("should fire the 'clicked' property", () => {
22+
const { recordedEvents, onChange } = createChangeHandler();
23+
render(
24+
<IconButton
25+
id="ibt"
26+
type={"IconButton"}
27+
icon={"arrow-left"}
28+
onChange={onChange}
29+
/>,
30+
);
31+
fireEvent.click(screen.getByRole("button"));
32+
expect(recordedEvents.length).toEqual(1);
33+
expect(recordedEvents[0]).toEqual({
34+
componentType: "IconButton",
35+
id: "ibt",
36+
property: "clicked",
37+
value: true,
38+
});
39+
});
40+
});
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
import { describe, it, expect } from "vitest";
2+
import { render, screen, fireEvent, within } from "@testing-library/react";
3+
import { createChangeHandler } from "./common.test";
4+
import { Select } from "./Select";
5+
6+
describe("Select", () => {
7+
it("should render the component", () => {
8+
render(
9+
<Select
10+
id="sel"
11+
type={"Select"}
12+
label={"Colors"}
13+
options={["red", "green", "blue"]}
14+
value={"red"}
15+
onChange={() => {}}
16+
/>,
17+
);
18+
// to inspect rendered component, do:
19+
// expect(document.querySelector("#sel")).toEqual({});
20+
expect(screen.getByRole("combobox")).not.toBeUndefined();
21+
});
22+
23+
it("should fire 'value' property with text options", () => {
24+
const { recordedEvents, onChange } = createChangeHandler();
25+
render(
26+
<Select
27+
id="sel"
28+
type={"Select"}
29+
label={"Colors"}
30+
options={["red", "green", "blue"]}
31+
value={"red"}
32+
onChange={onChange}
33+
/>,
34+
);
35+
// open the Select component's list box
36+
// note, we must use "mouseDown" as "click" doesn't work
37+
fireEvent.mouseDown(screen.getByRole("combobox"));
38+
// click item in the Select component's list box
39+
const listBox = within(screen.getByRole("listbox"));
40+
fireEvent.click(listBox.getByText(/green/i));
41+
expect(recordedEvents.length).toBe(1);
42+
expect(recordedEvents[0]).toEqual({
43+
componentType: "Select",
44+
id: "sel",
45+
property: "value",
46+
value: "green",
47+
});
48+
});
49+
50+
it("should fire 'value' property with numeric options", () => {
51+
const { recordedEvents, onChange } = createChangeHandler();
52+
render(
53+
<Select
54+
id="sel"
55+
type={"Select"}
56+
label={"Colors"}
57+
options={[10, 11, 12]}
58+
value={12}
59+
onChange={onChange}
60+
/>,
61+
);
62+
// open the Select component's list box
63+
// note, we must use "mouseDown" as "click" doesn't work
64+
fireEvent.mouseDown(screen.getByRole("combobox"));
65+
// click item in the Select component's list box
66+
const listBox = within(screen.getByRole("listbox"));
67+
fireEvent.click(listBox.getByText(/11/i));
68+
expect(recordedEvents.length).toBe(1);
69+
expect(recordedEvents[0]).toEqual({
70+
componentType: "Select",
71+
id: "sel",
72+
property: "value",
73+
value: 11,
74+
});
75+
});
76+
77+
it("should fire 'value' property with tuple options", () => {
78+
const { recordedEvents, onChange } = createChangeHandler();
79+
render(
80+
<Select
81+
id="sel"
82+
type={"Select"}
83+
label={"Colors"}
84+
options={[
85+
[10, "red"],
86+
[11, "yellow"],
87+
[12, "blue"],
88+
]}
89+
value={11}
90+
onChange={onChange}
91+
/>,
92+
);
93+
// open the Select component's list box
94+
// note, we must use "mouseDown" as "click" doesn't work
95+
fireEvent.mouseDown(screen.getByRole("combobox"));
96+
// click item in the Select component's list box
97+
const listBox = within(screen.getByRole("listbox"));
98+
fireEvent.click(listBox.getByText(/blue/i));
99+
expect(recordedEvents.length).toBe(1);
100+
expect(recordedEvents[0]).toEqual({
101+
componentType: "Select",
102+
id: "sel",
103+
property: "value",
104+
value: 12,
105+
});
106+
});
107+
108+
it("should fire 'value' property with object options", () => {
109+
const { recordedEvents, onChange } = createChangeHandler();
110+
render(
111+
<Select
112+
id="sel"
113+
type={"Select"}
114+
label={"Colors"}
115+
options={[
116+
{ value: 10, label: "Black" },
117+
{ value: 20 },
118+
{ value: 30, label: "Blue" },
119+
{ value: 40, label: "Yellow" },
120+
]}
121+
value={11}
122+
onChange={onChange}
123+
/>,
124+
);
125+
// open the Select component's list box
126+
// note, we must use "mouseDown" as "click" doesn't work
127+
fireEvent.mouseDown(screen.getByRole("combobox"));
128+
// click item in the Select component's list box
129+
const listBox = within(screen.getByRole("listbox"));
130+
fireEvent.click(listBox.getByText(/Yellow/i));
131+
expect(recordedEvents.length).toBe(1);
132+
expect(recordedEvents[0]).toEqual({
133+
componentType: "Select",
134+
id: "sel",
135+
property: "value",
136+
value: 40,
137+
});
138+
// value 20 has no label, so "20" will be displayed
139+
fireEvent.click(listBox.getByText(/20/i));
140+
expect(recordedEvents.length).toBe(2);
141+
expect(recordedEvents[1]).toEqual({
142+
componentType: "Select",
143+
id: "sel",
144+
property: "value",
145+
value: 20,
146+
});
147+
});
148+
});

chartlets.js/packages/lib/src/plugins/mui/Select.tsx

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,18 @@ export function Select({
3131
onChange,
3232
}: SelectProps) {
3333
const handleChange = (event: SelectChangeEvent) => {
34-
if (!id) {
35-
return;
34+
if (id) {
35+
let newValue: string | number = event.target.value;
36+
if (typeof value == "number") {
37+
newValue = Number.parseInt(newValue);
38+
}
39+
onChange({
40+
componentType: type,
41+
id: id,
42+
property: "value",
43+
value: newValue,
44+
});
3645
}
37-
let newValue: string | number = event.target.value;
38-
if (typeof value == "number") {
39-
newValue = Number.parseInt(newValue);
40-
}
41-
return onChange({
42-
componentType: type,
43-
id: id,
44-
property: "value",
45-
value: newValue,
46-
});
4746
};
4847
return (
4948
<MuiFormControl variant="filled" size="small" style={style}>

0 commit comments

Comments
 (0)