1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
|
import { describe, it, beforeEach, afterEach } from "node:test";
import assert from "node:assert";
import "../test-setup.ts";
import { createRoot, type Root } from "react-dom/client";
import { act } from "@testing-library/react";
import { CameraSelector } from "./CameraSelector.tsx";
import { useStore } from "../store/store.ts";
describe("CameraSelector", () => {
let container: HTMLDivElement;
let root: Root;
beforeEach(() => {
container = document.createElement("div");
document.body.appendChild(container);
root = createRoot(container);
useStore.setState({
models: [],
selectedModelId: null,
cameraView: "perspective",
backdropUrl: null,
availableModels: [],
});
});
afterEach(() => {
act(() => {
root.unmount();
});
container.remove();
});
it("should render a dropdown", async () => {
await act(async () => {
root.render(<CameraSelector />);
});
const select = container.querySelector("select.camera-selector");
assert.ok(select, "Should render a select dropdown");
});
it("should have perspective as default option", async () => {
await act(async () => {
root.render(<CameraSelector />);
});
const select = container.querySelector(
"select.camera-selector",
) as HTMLSelectElement;
assert.strictEqual(select?.value, "perspective");
});
it("should have all camera view options", async () => {
await act(async () => {
root.render(<CameraSelector />);
});
const options = container.querySelectorAll("select.camera-selector option");
const values = Array.from(options).map(
(opt) => (opt as HTMLOptionElement).value,
);
assert.ok(values.includes("perspective"), "Should have perspective option");
assert.ok(values.includes("ortho-top"), "Should have ortho-top option");
assert.ok(values.includes("ortho-front"), "Should have ortho-front option");
assert.ok(values.includes("ortho-side"), "Should have ortho-side option");
});
it("should update store when selection changes", async () => {
await act(async () => {
root.render(<CameraSelector />);
});
const select = container.querySelector(
"select.camera-selector",
) as HTMLSelectElement;
await act(async () => {
select.value = "ortho-top";
select.dispatchEvent(new Event("change", { bubbles: true }));
});
assert.strictEqual(useStore.getState().cameraView, "ortho-top");
});
it("should be positioned as overlay", async () => {
await act(async () => {
root.render(<CameraSelector />);
});
const wrapper = container.querySelector(".camera-selector-wrapper");
assert.ok(wrapper, "Should have wrapper for positioning");
});
it("should reflect store camera view state", async () => {
useStore.setState({ cameraView: "ortho-front" });
await act(async () => {
root.render(<CameraSelector />);
});
const select = container.querySelector(
"select.camera-selector",
) as HTMLSelectElement;
assert.strictEqual(select?.value, "ortho-front");
});
});
|