@react-chess-tools/react-chess-puzzle 0.6.2 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,158 @@
1
+ import React from "react";
2
+ import { render, screen, fireEvent } from "@testing-library/react";
3
+ import "@testing-library/jest-dom";
4
+ import { ChessPuzzle } from "../..";
5
+ import { Hint } from "../Hint";
6
+ import { Puzzle } from "../../../../utils";
7
+
8
+ describe("ChessPuzzle.Hint", () => {
9
+ const mockPuzzle: Puzzle = {
10
+ fen: "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
11
+ moves: ["e4", "e5"],
12
+ };
13
+
14
+ it("should have correct displayName", () => {
15
+ expect(Hint.displayName).toBe("ChessPuzzle.Hint");
16
+ });
17
+
18
+ it("should forward ref to button element", () => {
19
+ const ref = React.createRef<HTMLElement>();
20
+
21
+ render(
22
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
23
+ <Hint ref={ref} />
24
+ </ChessPuzzle.Root>,
25
+ );
26
+
27
+ expect(ref.current).toBeInstanceOf(HTMLButtonElement);
28
+ });
29
+
30
+ it("should forward ref when using asChild", () => {
31
+ const ref = React.createRef<HTMLElement>();
32
+
33
+ render(
34
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
35
+ <Hint ref={ref} asChild>
36
+ <button>Custom Hint</button>
37
+ </Hint>
38
+ </ChessPuzzle.Root>,
39
+ );
40
+
41
+ expect(ref.current).toBeInstanceOf(HTMLButtonElement);
42
+ });
43
+
44
+ it("should be visible when status matches showOn", () => {
45
+ render(
46
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
47
+ <Hint showOn={["not-started"]}>Hint</Hint>
48
+ </ChessPuzzle.Root>,
49
+ );
50
+
51
+ expect(screen.getByRole("button")).toBeInTheDocument();
52
+ });
53
+
54
+ it("should be hidden when status does not match showOn", () => {
55
+ render(
56
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
57
+ <Hint showOn={["solved"]}>Hint</Hint>
58
+ </ChessPuzzle.Root>,
59
+ );
60
+
61
+ expect(screen.queryByRole("button")).not.toBeInTheDocument();
62
+ });
63
+
64
+ it("should default to showing on not-started and in-progress statuses", () => {
65
+ render(
66
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
67
+ <Hint>Hint</Hint>
68
+ </ChessPuzzle.Root>,
69
+ );
70
+
71
+ expect(screen.getByRole("button")).toBeInTheDocument();
72
+ });
73
+
74
+ it("should accept multiple statuses in showOn", () => {
75
+ render(
76
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
77
+ <Hint showOn={["not-started", "in-progress", "failed", "solved"]}>
78
+ Hint
79
+ </Hint>
80
+ </ChessPuzzle.Root>,
81
+ );
82
+
83
+ expect(screen.getByRole("button")).toBeInTheDocument();
84
+ });
85
+
86
+ it("should render custom element when asChild is true", () => {
87
+ render(
88
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
89
+ <Hint asChild>
90
+ <button className="custom-button">Custom Hint</button>
91
+ </Hint>
92
+ </ChessPuzzle.Root>,
93
+ );
94
+
95
+ const button = screen.getByRole("button");
96
+ expect(button).toHaveTextContent("Custom Hint");
97
+ expect(button).toHaveClass("custom-button");
98
+ });
99
+
100
+ it("should compose onClick handlers with asChild", () => {
101
+ const childOnClick = jest.fn();
102
+
103
+ render(
104
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
105
+ <Hint asChild>
106
+ <button onClick={childOnClick}>Hint</button>
107
+ </Hint>
108
+ </ChessPuzzle.Root>,
109
+ );
110
+
111
+ fireEvent.click(screen.getByRole("button"));
112
+ expect(childOnClick).toHaveBeenCalledTimes(1);
113
+ });
114
+
115
+ it("should throw error when used outside ChessPuzzle.Root", () => {
116
+ const consoleError = jest
117
+ .spyOn(console, "error")
118
+ .mockImplementation(() => {});
119
+
120
+ expect(() => {
121
+ render(<Hint>Hint</Hint>);
122
+ }).toThrow();
123
+
124
+ consoleError.mockRestore();
125
+ });
126
+
127
+ it("should render text children", () => {
128
+ render(
129
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
130
+ <Hint>Show Hint</Hint>
131
+ </ChessPuzzle.Root>,
132
+ );
133
+
134
+ expect(screen.getByRole("button")).toHaveTextContent("Show Hint");
135
+ });
136
+
137
+ it("should render element children", () => {
138
+ render(
139
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
140
+ <Hint>
141
+ <span data-testid="child">Hint Icon</span>
142
+ </Hint>
143
+ </ChessPuzzle.Root>,
144
+ );
145
+
146
+ expect(screen.getByTestId("child")).toBeInTheDocument();
147
+ });
148
+
149
+ it("should render without children", () => {
150
+ render(
151
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
152
+ <Hint aria-label="Show hint" />
153
+ </ChessPuzzle.Root>,
154
+ );
155
+
156
+ expect(screen.getByRole("button")).toBeInTheDocument();
157
+ });
158
+ });
@@ -0,0 +1,140 @@
1
+ import React from "react";
2
+ import { render, screen } from "@testing-library/react";
3
+ import "@testing-library/jest-dom";
4
+ import { ChessPuzzle } from "../..";
5
+ import { PuzzleBoard } from "../PuzzleBoard";
6
+ import { Puzzle } from "../../../../utils";
7
+ import { ChessGame } from "@react-chess-tools/react-chess-game";
8
+
9
+ describe("ChessPuzzle.PuzzleBoard", () => {
10
+ const mockPuzzle: Puzzle = {
11
+ fen: "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
12
+ moves: ["e4", "e5"],
13
+ };
14
+
15
+ it("should have correct displayName", () => {
16
+ expect(PuzzleBoard.displayName).toBe("ChessPuzzle.PuzzleBoard");
17
+ });
18
+
19
+ it("should forward ref to underlying Board component", () => {
20
+ const ref = React.createRef<HTMLDivElement>();
21
+
22
+ render(
23
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
24
+ <PuzzleBoard ref={ref} />
25
+ </ChessPuzzle.Root>,
26
+ );
27
+
28
+ expect(ref.current).toBeInstanceOf(HTMLDivElement);
29
+ });
30
+
31
+ it("should allow focusing via ref", () => {
32
+ const ref = React.createRef<HTMLDivElement>();
33
+
34
+ render(
35
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
36
+ <PuzzleBoard ref={ref} tabIndex={0} />
37
+ </ChessPuzzle.Root>,
38
+ );
39
+
40
+ expect(ref.current).toBeInstanceOf(HTMLDivElement);
41
+
42
+ // Note: focus() doesn't work in JSDOM, but we can verify the ref points to the element
43
+ // In a real browser, ref.current?.focus() would set document.activeElement to ref.current
44
+ });
45
+
46
+ it("should apply custom className", () => {
47
+ const { container } = render(
48
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
49
+ <PuzzleBoard className="custom-puzzle-board-class" />
50
+ </ChessPuzzle.Root>,
51
+ );
52
+
53
+ const board = container.querySelector('[style*="position: relative"]');
54
+ expect(board).toHaveClass("custom-puzzle-board-class");
55
+ });
56
+
57
+ it("should apply custom style", () => {
58
+ const customStyle = { border: "2px solid blue", margin: "15px" };
59
+
60
+ const { container } = render(
61
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
62
+ <PuzzleBoard style={customStyle} />
63
+ </ChessPuzzle.Root>,
64
+ );
65
+
66
+ const board = container.querySelector('[style*="position: relative"]');
67
+ expect(board).toHaveStyle({ border: "2px solid blue" });
68
+ expect(board).toHaveStyle({ margin: "15px" });
69
+ });
70
+
71
+ it("should apply custom id", () => {
72
+ const { container } = render(
73
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
74
+ <PuzzleBoard id="custom-puzzle-board-id" />
75
+ </ChessPuzzle.Root>,
76
+ );
77
+
78
+ const board = container.querySelector('[style*="position: relative"]');
79
+ expect(board).toHaveAttribute("id", "custom-puzzle-board-id");
80
+ });
81
+
82
+ it("should apply data-* attributes", () => {
83
+ render(
84
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
85
+ <PuzzleBoard data-testid="puzzle-board" data-custom="puzzle-value" />
86
+ </ChessPuzzle.Root>,
87
+ );
88
+
89
+ const board = screen.getByTestId("puzzle-board");
90
+ expect(board).toHaveAttribute("data-custom", "puzzle-value");
91
+ });
92
+
93
+ it("should apply aria-* attributes", () => {
94
+ const { container } = render(
95
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
96
+ <PuzzleBoard aria-label="Puzzle board" aria-describedby="puzzle-desc" />
97
+ </ChessPuzzle.Root>,
98
+ );
99
+
100
+ const board = container.querySelector('[style*="position: relative"]');
101
+ expect(board).toHaveAttribute("aria-label", "Puzzle board");
102
+ expect(board).toHaveAttribute("aria-describedby", "puzzle-desc");
103
+ });
104
+
105
+ it("should accept custom onClick handler", () => {
106
+ const handleClick = jest.fn();
107
+
108
+ const { container } = render(
109
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
110
+ <PuzzleBoard onClick={handleClick} />
111
+ </ChessPuzzle.Root>,
112
+ );
113
+
114
+ const board = container.querySelector(
115
+ '[style*="position: relative"]',
116
+ ) as HTMLElement;
117
+ board?.click();
118
+
119
+ expect(handleClick).toHaveBeenCalledTimes(1);
120
+ });
121
+
122
+ it("should throw error when used outside ChessPuzzle.Root", () => {
123
+ // Suppress console.error for this test
124
+ const consoleError = jest
125
+ .spyOn(console, "error")
126
+ .mockImplementation(() => {});
127
+
128
+ expect(() => {
129
+ render(
130
+ <ChessGame.Root>
131
+ <PuzzleBoard />
132
+ </ChessGame.Root>,
133
+ );
134
+ }).toThrow(
135
+ "useChessPuzzleContext must be used within a ChessPuzzle component",
136
+ );
137
+
138
+ consoleError.mockRestore();
139
+ });
140
+ });
@@ -0,0 +1,341 @@
1
+ import React from "react";
2
+ import { render, screen, fireEvent } from "@testing-library/react";
3
+ import "@testing-library/jest-dom";
4
+ import { ChessPuzzle } from "../..";
5
+ import { Reset } from "../Reset";
6
+ import { Puzzle } from "../../../../utils";
7
+
8
+ describe("ChessPuzzle.Reset", () => {
9
+ const mockPuzzle: Puzzle = {
10
+ fen: "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
11
+ moves: ["e4", "e5"],
12
+ };
13
+
14
+ describe("displayName", () => {
15
+ it("should have correct displayName", () => {
16
+ expect(Reset.displayName).toBe("ChessPuzzle.Reset");
17
+ });
18
+ });
19
+
20
+ describe("ref forwarding", () => {
21
+ it("should forward ref to button element", () => {
22
+ const ref = React.createRef<HTMLElement>();
23
+
24
+ render(
25
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
26
+ <Reset
27
+ ref={ref}
28
+ showOn={["not-started", "in-progress", "failed", "solved"]}
29
+ />
30
+ </ChessPuzzle.Root>,
31
+ );
32
+
33
+ expect(ref.current).toBeInstanceOf(HTMLButtonElement);
34
+ });
35
+
36
+ it("should forward ref when using asChild", () => {
37
+ const ref = React.createRef<HTMLElement>();
38
+
39
+ render(
40
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
41
+ <Reset
42
+ ref={ref}
43
+ asChild
44
+ showOn={["not-started", "in-progress", "failed", "solved"]}
45
+ >
46
+ <button>Custom Reset</button>
47
+ </Reset>
48
+ </ChessPuzzle.Root>,
49
+ );
50
+
51
+ expect(ref.current).toBeInstanceOf(HTMLButtonElement);
52
+ });
53
+
54
+ it("should support callback refs", () => {
55
+ let capturedRef: HTMLElement | null = null;
56
+ const callbackRef = (ref: HTMLElement | null) => {
57
+ capturedRef = ref;
58
+ };
59
+
60
+ render(
61
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
62
+ <Reset
63
+ ref={callbackRef}
64
+ showOn={["not-started", "in-progress", "failed", "solved"]}
65
+ />
66
+ </ChessPuzzle.Root>,
67
+ );
68
+
69
+ expect(capturedRef).toBeInstanceOf(HTMLButtonElement);
70
+ });
71
+ });
72
+
73
+ describe("visibility based on showOn prop", () => {
74
+ it("should be visible when status matches showOn", () => {
75
+ render(
76
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
77
+ <Reset showOn={["not-started"]}>Reset</Reset>
78
+ </ChessPuzzle.Root>,
79
+ );
80
+
81
+ expect(screen.getByRole("button")).toBeInTheDocument();
82
+ });
83
+
84
+ it("should be hidden when status does not match showOn", () => {
85
+ render(
86
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
87
+ <Reset showOn={["solved"]}>Reset</Reset>
88
+ </ChessPuzzle.Root>,
89
+ );
90
+
91
+ expect(screen.queryByRole("button")).not.toBeInTheDocument();
92
+ });
93
+
94
+ it("should default to showing on failed and solved statuses", () => {
95
+ // Default showOn is ["failed", "solved"], so it should be hidden at start
96
+ render(
97
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
98
+ <Reset>Reset</Reset>
99
+ </ChessPuzzle.Root>,
100
+ );
101
+
102
+ expect(screen.queryByRole("button")).not.toBeInTheDocument();
103
+ });
104
+
105
+ it("should accept multiple statuses in showOn", () => {
106
+ render(
107
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
108
+ <Reset showOn={["not-started", "in-progress", "failed", "solved"]}>
109
+ Reset
110
+ </Reset>
111
+ </ChessPuzzle.Root>,
112
+ );
113
+
114
+ expect(screen.getByRole("button")).toBeInTheDocument();
115
+ });
116
+ });
117
+
118
+ describe("prop spreading", () => {
119
+ it("should apply custom className", () => {
120
+ render(
121
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
122
+ <Reset className="custom-reset-class" showOn={["not-started"]}>
123
+ Reset
124
+ </Reset>
125
+ </ChessPuzzle.Root>,
126
+ );
127
+
128
+ expect(screen.getByRole("button")).toHaveClass("custom-reset-class");
129
+ });
130
+
131
+ it("should apply custom id", () => {
132
+ render(
133
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
134
+ <Reset id="reset-button" showOn={["not-started"]}>
135
+ Reset
136
+ </Reset>
137
+ </ChessPuzzle.Root>,
138
+ );
139
+
140
+ expect(screen.getByRole("button")).toHaveAttribute("id", "reset-button");
141
+ });
142
+
143
+ it("should apply data-* attributes", () => {
144
+ render(
145
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
146
+ <Reset
147
+ data-testid="reset"
148
+ data-custom="value"
149
+ showOn={["not-started"]}
150
+ >
151
+ Reset
152
+ </Reset>
153
+ </ChessPuzzle.Root>,
154
+ );
155
+
156
+ const button = screen.getByTestId("reset");
157
+ expect(button).toHaveAttribute("data-custom", "value");
158
+ });
159
+
160
+ it("should apply aria-* attributes", () => {
161
+ render(
162
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
163
+ <Reset aria-label="Reset puzzle" showOn={["not-started"]}>
164
+ Reset
165
+ </Reset>
166
+ </ChessPuzzle.Root>,
167
+ );
168
+
169
+ expect(screen.getByRole("button")).toHaveAttribute(
170
+ "aria-label",
171
+ "Reset puzzle",
172
+ );
173
+ });
174
+
175
+ it("should apply disabled attribute", () => {
176
+ render(
177
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
178
+ <Reset disabled showOn={["not-started"]}>
179
+ Reset
180
+ </Reset>
181
+ </ChessPuzzle.Root>,
182
+ );
183
+
184
+ expect(screen.getByRole("button")).toBeDisabled();
185
+ });
186
+ });
187
+
188
+ describe("asChild pattern", () => {
189
+ it("should render custom element when asChild is true", () => {
190
+ render(
191
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
192
+ <Reset asChild showOn={["not-started"]}>
193
+ <button className="custom-button">Custom Reset</button>
194
+ </Reset>
195
+ </ChessPuzzle.Root>,
196
+ );
197
+
198
+ const button = screen.getByRole("button");
199
+ expect(button).toHaveTextContent("Custom Reset");
200
+ expect(button).toHaveClass("custom-button");
201
+ });
202
+
203
+ it("should merge className with asChild element", () => {
204
+ render(
205
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
206
+ <Reset asChild className="reset-class" showOn={["not-started"]}>
207
+ <button className="child-class">Reset</button>
208
+ </Reset>
209
+ </ChessPuzzle.Root>,
210
+ );
211
+
212
+ const button = screen.getByRole("button");
213
+ expect(button).toHaveClass("reset-class");
214
+ expect(button).toHaveClass("child-class");
215
+ });
216
+
217
+ it("should compose onClick handlers with asChild", () => {
218
+ const childOnClick = jest.fn();
219
+
220
+ render(
221
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
222
+ <Reset asChild showOn={["not-started"]}>
223
+ <button onClick={childOnClick}>Reset</button>
224
+ </Reset>
225
+ </ChessPuzzle.Root>,
226
+ );
227
+
228
+ fireEvent.click(screen.getByRole("button"));
229
+ expect(childOnClick).toHaveBeenCalledTimes(1);
230
+ });
231
+ });
232
+
233
+ describe("functionality", () => {
234
+ it("should call onReset callback when clicked", () => {
235
+ const handleReset = jest.fn();
236
+
237
+ render(
238
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
239
+ <Reset onReset={handleReset} showOn={["not-started"]}>
240
+ Reset
241
+ </Reset>
242
+ </ChessPuzzle.Root>,
243
+ );
244
+
245
+ fireEvent.click(screen.getByRole("button"));
246
+ expect(handleReset).toHaveBeenCalledTimes(1);
247
+ });
248
+
249
+ it("should pass puzzle context to onReset callback", () => {
250
+ const handleReset = jest.fn();
251
+
252
+ render(
253
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
254
+ <Reset onReset={handleReset} showOn={["not-started"]}>
255
+ Reset
256
+ </Reset>
257
+ </ChessPuzzle.Root>,
258
+ );
259
+
260
+ fireEvent.click(screen.getByRole("button"));
261
+ expect(handleReset).toHaveBeenCalledWith(
262
+ expect.objectContaining({
263
+ puzzle: mockPuzzle,
264
+ status: expect.any(String),
265
+ changePuzzle: expect.any(Function),
266
+ }),
267
+ );
268
+ });
269
+
270
+ it("should have type button by default", () => {
271
+ render(
272
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
273
+ <Reset showOn={["not-started"]}>Reset</Reset>
274
+ </ChessPuzzle.Root>,
275
+ );
276
+
277
+ expect(screen.getByRole("button")).toHaveAttribute("type", "button");
278
+ });
279
+ });
280
+
281
+ describe("context validation", () => {
282
+ it("should throw error when used outside ChessPuzzle.Root", () => {
283
+ const consoleError = jest
284
+ .spyOn(console, "error")
285
+ .mockImplementation(() => {});
286
+
287
+ expect(() => {
288
+ render(<Reset showOn={["not-started"]}>Reset</Reset>);
289
+ }).toThrow();
290
+
291
+ consoleError.mockRestore();
292
+ });
293
+ });
294
+
295
+ describe("children", () => {
296
+ it("should render text children", () => {
297
+ render(
298
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
299
+ <Reset showOn={["not-started"]}>Reset Puzzle</Reset>
300
+ </ChessPuzzle.Root>,
301
+ );
302
+
303
+ expect(screen.getByRole("button")).toHaveTextContent("Reset Puzzle");
304
+ });
305
+
306
+ it("should render element children", () => {
307
+ render(
308
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
309
+ <Reset showOn={["not-started"]}>
310
+ <span data-testid="child">Reset Icon</span>
311
+ </Reset>
312
+ </ChessPuzzle.Root>,
313
+ );
314
+
315
+ expect(screen.getByTestId("child")).toBeInTheDocument();
316
+ });
317
+
318
+ it("should render without children", () => {
319
+ render(
320
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
321
+ <Reset showOn={["not-started"]} aria-label="Reset" />
322
+ </ChessPuzzle.Root>,
323
+ );
324
+
325
+ expect(screen.getByRole("button")).toBeInTheDocument();
326
+ });
327
+ });
328
+
329
+ describe("backward compatibility", () => {
330
+ it("should work with minimal props when status matches default showOn", () => {
331
+ // Since default showOn is ["failed", "solved"], we need to set showOn to see the button
332
+ render(
333
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
334
+ <Reset showOn={["not-started"]}>Reset</Reset>
335
+ </ChessPuzzle.Root>,
336
+ );
337
+
338
+ expect(screen.getByRole("button")).toBeInTheDocument();
339
+ });
340
+ });
341
+ });
@@ -0,0 +1,42 @@
1
+ import React from "react";
2
+ import { render, screen } from "@testing-library/react";
3
+ import "@testing-library/jest-dom";
4
+ import { ChessPuzzle } from "../..";
5
+ import { Root } from "../Root";
6
+ import { Puzzle } from "../../../../utils";
7
+
8
+ describe("ChessPuzzle.Root", () => {
9
+ const mockPuzzle: Puzzle = {
10
+ fen: "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
11
+ moves: ["e4", "e5"],
12
+ };
13
+
14
+ it("should have correct displayName", () => {
15
+ expect(Root.displayName).toBe("ChessPuzzle.Root");
16
+ });
17
+
18
+ it("should render children correctly", () => {
19
+ render(
20
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
21
+ <div data-testid="child">Child Component</div>
22
+ </ChessPuzzle.Root>,
23
+ );
24
+
25
+ expect(screen.getByTestId("child")).toBeInTheDocument();
26
+ expect(screen.getByText("Child Component")).toBeInTheDocument();
27
+ });
28
+
29
+ it("should render multiple children", () => {
30
+ render(
31
+ <ChessPuzzle.Root puzzle={mockPuzzle}>
32
+ <div data-testid="child-1">Child 1</div>
33
+ <div data-testid="child-2">Child 2</div>
34
+ <div data-testid="child-3">Child 3</div>
35
+ </ChessPuzzle.Root>,
36
+ );
37
+
38
+ expect(screen.getByTestId("child-1")).toBeInTheDocument();
39
+ expect(screen.getByTestId("child-2")).toBeInTheDocument();
40
+ expect(screen.getByTestId("child-3")).toBeInTheDocument();
41
+ });
42
+ });