@balby/booking-search 1.0.0

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,358 @@
1
+ import { test, expect, describe, beforeEach } from "bun:test"
2
+ import React from "react"
3
+ import { render, screen, fireEvent, waitFor } from "@testing-library/react"
4
+ import { GuestSelector } from "../guest-selector"
5
+ import type { GuestData } from "../../../types/booking"
6
+
7
+ describe("GuestSelector", () => {
8
+ const mockValue: GuestData = {
9
+ adults: 2,
10
+ children: 0,
11
+ }
12
+
13
+ const mockOnChange = (guests: GuestData) => {}
14
+
15
+ beforeEach(() => {
16
+ // Reset any state between tests if needed
17
+ })
18
+
19
+ test("renders with default guest count", () => {
20
+ render(<GuestSelector value={mockValue} onChange={mockOnChange} />)
21
+
22
+ expect(screen.getByText("Guests")).toBeDefined()
23
+ expect(screen.getByText("2 adulti")).toBeDefined()
24
+ })
25
+
26
+ test("displays singular form for one adult", () => {
27
+ render(
28
+ <GuestSelector
29
+ value={{ adults: 1, children: 0 }}
30
+ onChange={mockOnChange}
31
+ />
32
+ )
33
+
34
+ expect(screen.getByText("1 adulto")).toBeDefined()
35
+ })
36
+
37
+ test("displays children count when children > 0", () => {
38
+ render(
39
+ <GuestSelector
40
+ value={{ adults: 2, children: 1 }}
41
+ onChange={mockOnChange}
42
+ />
43
+ )
44
+
45
+ expect(screen.getByText("2 adulti, 1 bambino")).toBeDefined()
46
+ })
47
+
48
+ test("displays plural form for multiple children", () => {
49
+ render(
50
+ <GuestSelector
51
+ value={{ adults: 2, children: 3 }}
52
+ onChange={mockOnChange}
53
+ />
54
+ )
55
+
56
+ expect(screen.getByText("2 adulti, 3 bambini")).toBeDefined()
57
+ })
58
+
59
+ test("opens popover when button is clicked", async () => {
60
+ render(<GuestSelector value={mockValue} onChange={mockOnChange} />)
61
+
62
+ const button = screen.getByRole("button", { name: "Select guests" })
63
+ fireEvent.click(button)
64
+
65
+ await waitFor(() => {
66
+ expect(screen.getByText("Adulti")).toBeDefined()
67
+ expect(screen.getByText("Bambini")).toBeDefined()
68
+ })
69
+ })
70
+
71
+ test("displays guest steppers in popover", async () => {
72
+ render(<GuestSelector value={mockValue} onChange={mockOnChange} />)
73
+
74
+ const button = screen.getByRole("button", { name: "Select guests" })
75
+ fireEvent.click(button)
76
+
77
+ await waitFor(() => {
78
+ expect(screen.getByText("Adulti")).toBeDefined()
79
+ expect(screen.getByText("Età 18+")).toBeDefined()
80
+ expect(screen.getByText("Bambini")).toBeDefined()
81
+ expect(screen.getByText("Età 0-17")).toBeDefined()
82
+ })
83
+ })
84
+
85
+ test("increments adults when plus button is clicked", async () => {
86
+ let currentValue = { adults: 2, children: 0 }
87
+ const handleChange = (guests: GuestData) => {
88
+ currentValue = guests
89
+ }
90
+
91
+ render(<GuestSelector value={currentValue} onChange={handleChange} />)
92
+
93
+ const button = screen.getByRole("button", { name: "Select guests" })
94
+ fireEvent.click(button)
95
+
96
+ await waitFor(() => {
97
+ const incrementButton = screen.getByLabelText("Increase adulti")
98
+ fireEvent.click(incrementButton)
99
+ })
100
+
101
+ const confirmButton = screen.getByText("Conferma")
102
+ fireEvent.click(confirmButton)
103
+
104
+ await waitFor(() => {
105
+ expect(currentValue.adults).toBe(3)
106
+ })
107
+ })
108
+
109
+ test("decrements adults when minus button is clicked", async () => {
110
+ let currentValue = { adults: 2, children: 0 }
111
+ const handleChange = (guests: GuestData) => {
112
+ currentValue = guests
113
+ }
114
+
115
+ render(<GuestSelector value={currentValue} onChange={handleChange} />)
116
+
117
+ const button = screen.getByRole("button", { name: "Select guests" })
118
+ fireEvent.click(button)
119
+
120
+ await waitFor(() => {
121
+ const decrementButton = screen.getByLabelText("Decrease adulti")
122
+ fireEvent.click(decrementButton)
123
+ })
124
+
125
+ const confirmButton = screen.getByText("Conferma")
126
+ fireEvent.click(confirmButton)
127
+
128
+ await waitFor(() => {
129
+ expect(currentValue.adults).toBe(1)
130
+ })
131
+ })
132
+
133
+ test("increments children when plus button is clicked", async () => {
134
+ let currentValue = { adults: 2, children: 0 }
135
+ const handleChange = (guests: GuestData) => {
136
+ currentValue = guests
137
+ }
138
+
139
+ render(<GuestSelector value={currentValue} onChange={handleChange} />)
140
+
141
+ const button = screen.getByRole("button", { name: "Select guests" })
142
+ fireEvent.click(button)
143
+
144
+ await waitFor(() => {
145
+ const incrementButton = screen.getByLabelText("Increase bambini")
146
+ fireEvent.click(incrementButton)
147
+ })
148
+
149
+ const confirmButton = screen.getByText("Conferma")
150
+ fireEvent.click(confirmButton)
151
+
152
+ await waitFor(() => {
153
+ expect(currentValue.children).toBe(1)
154
+ })
155
+ })
156
+
157
+ test("decrements children when minus button is clicked", async () => {
158
+ let currentValue = { adults: 2, children: 2 }
159
+ const handleChange = (guests: GuestData) => {
160
+ currentValue = guests
161
+ }
162
+
163
+ render(<GuestSelector value={currentValue} onChange={handleChange} />)
164
+
165
+ const button = screen.getByRole("button", { name: "Select guests" })
166
+ fireEvent.click(button)
167
+
168
+ await waitFor(() => {
169
+ const decrementButton = screen.getByLabelText("Decrease bambini")
170
+ fireEvent.click(decrementButton)
171
+ })
172
+
173
+ const confirmButton = screen.getByText("Conferma")
174
+ fireEvent.click(confirmButton)
175
+
176
+ await waitFor(() => {
177
+ expect(currentValue.children).toBe(1)
178
+ })
179
+ })
180
+
181
+ test("prevents decrementing adults below 1", async () => {
182
+ render(
183
+ <GuestSelector
184
+ value={{ adults: 1, children: 0 }}
185
+ onChange={mockOnChange}
186
+ />
187
+ )
188
+
189
+ const button = screen.getByRole("button", { name: "Select guests" })
190
+ fireEvent.click(button)
191
+
192
+ await waitFor(() => {
193
+ const decrementButton = screen.getByLabelText("Decrease adulti")
194
+ expect(decrementButton.hasAttribute("disabled")).toBe(true)
195
+ })
196
+ })
197
+
198
+ test("prevents decrementing children below 0", async () => {
199
+ render(
200
+ <GuestSelector
201
+ value={{ adults: 2, children: 0 }}
202
+ onChange={mockOnChange}
203
+ />
204
+ )
205
+
206
+ const button = screen.getByRole("button", { name: "Select guests" })
207
+ fireEvent.click(button)
208
+
209
+ await waitFor(() => {
210
+ const decrementButton = screen.getByLabelText("Decrease bambini")
211
+ expect(decrementButton.hasAttribute("disabled")).toBe(true)
212
+ })
213
+ })
214
+
215
+ test("prevents incrementing adults above maxAdults", async () => {
216
+ render(
217
+ <GuestSelector
218
+ value={{ adults: 5, children: 0 }}
219
+ onChange={mockOnChange}
220
+ maxAdults={5}
221
+ />
222
+ )
223
+
224
+ const button = screen.getByRole("button", { name: "Select guests" })
225
+ fireEvent.click(button)
226
+
227
+ await waitFor(() => {
228
+ const incrementButton = screen.getByLabelText("Increase adulti")
229
+ expect(incrementButton.hasAttribute("disabled")).toBe(true)
230
+ })
231
+ })
232
+
233
+ test("prevents incrementing children above maxChildren", async () => {
234
+ render(
235
+ <GuestSelector
236
+ value={{ adults: 2, children: 3 }}
237
+ onChange={mockOnChange}
238
+ maxChildren={3}
239
+ />
240
+ )
241
+
242
+ const button = screen.getByRole("button", { name: "Select guests" })
243
+ fireEvent.click(button)
244
+
245
+ await waitFor(() => {
246
+ const incrementButton = screen.getByLabelText("Increase bambini")
247
+ expect(incrementButton.hasAttribute("disabled")).toBe(true)
248
+ })
249
+ })
250
+
251
+ test("does not call onChange until confirm is clicked", async () => {
252
+ let changeCallCount = 0
253
+ const handleChange = (guests: GuestData) => {
254
+ changeCallCount++
255
+ }
256
+
257
+ render(
258
+ <GuestSelector
259
+ value={{ adults: 2, children: 0 }}
260
+ onChange={handleChange}
261
+ />
262
+ )
263
+
264
+ const button = screen.getByRole("button", { name: "Select guests" })
265
+ fireEvent.click(button)
266
+
267
+ await waitFor(() => {
268
+ const incrementButton = screen.getByLabelText("Increase adulti")
269
+ fireEvent.click(incrementButton)
270
+ fireEvent.click(incrementButton)
271
+ })
272
+
273
+ // onChange should not have been called yet
274
+ expect(changeCallCount).toBe(0)
275
+
276
+ const confirmButton = screen.getByText("Conferma")
277
+ fireEvent.click(confirmButton)
278
+
279
+ // Now onChange should be called
280
+ await waitFor(() => {
281
+ expect(changeCallCount).toBe(1)
282
+ })
283
+ })
284
+
285
+ test("resets to original value when popover is closed without confirming", async () => {
286
+ const { rerender } = render(
287
+ <GuestSelector
288
+ value={{ adults: 2, children: 0 }}
289
+ onChange={mockOnChange}
290
+ />
291
+ )
292
+
293
+ const button = screen.getByRole("button", { name: "Select guests" })
294
+ fireEvent.click(button)
295
+
296
+ await waitFor(() => {
297
+ const incrementButton = screen.getByLabelText("Increase adulti")
298
+ fireEvent.click(incrementButton)
299
+ })
300
+
301
+ // Close popover without confirming (click outside)
302
+ fireEvent.keyDown(document, { key: "Escape" })
303
+
304
+ // Re-open and verify value is still 2
305
+ await waitFor(() => {
306
+ fireEvent.click(button)
307
+ })
308
+
309
+ await waitFor(() => {
310
+ const adultsValue = screen.getAllByText("2")[0]
311
+ expect(adultsValue).toBeDefined()
312
+ })
313
+ })
314
+
315
+ test("disables the button when disabled prop is true", () => {
316
+ render(
317
+ <GuestSelector
318
+ value={mockValue}
319
+ onChange={mockOnChange}
320
+ disabled={true}
321
+ />
322
+ )
323
+
324
+ const button = screen.getByRole("button", { name: "Select guests" })
325
+ expect(button.hasAttribute("disabled")).toBe(true)
326
+ })
327
+
328
+ test("applies custom className", () => {
329
+ const { container } = render(
330
+ <GuestSelector
331
+ value={mockValue}
332
+ onChange={mockOnChange}
333
+ className="custom-class"
334
+ />
335
+ )
336
+
337
+ const button = container.querySelector("button")
338
+ expect(button?.classList.contains("custom-class")).toBe(true)
339
+ })
340
+
341
+ test("closes popover after confirming selection", async () => {
342
+ render(<GuestSelector value={mockValue} onChange={mockOnChange} />)
343
+
344
+ const button = screen.getByRole("button", { name: "Select guests" })
345
+ fireEvent.click(button)
346
+
347
+ await waitFor(() => {
348
+ expect(screen.getByText("Conferma")).toBeDefined()
349
+ })
350
+
351
+ const confirmButton = screen.getByText("Conferma")
352
+ fireEvent.click(confirmButton)
353
+
354
+ await waitFor(() => {
355
+ expect(screen.queryByText("Conferma")).toBeNull()
356
+ })
357
+ })
358
+ })