aboutsummaryrefslogtreecommitdiff
path: root/src/components/CameraSelector.test.tsx
blob: 90968b7792226d916cf910c8f39c21bf8689e28f (plain)
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");
  });
});