@seed-design/react 2.0.5 → 2.1.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.
Files changed (76) hide show
  1. package/lib/components/ContentDialog/ContentDialog.cjs +105 -0
  2. package/lib/components/ContentDialog/ContentDialog.d.ts +50 -0
  3. package/lib/components/ContentDialog/ContentDialog.d.ts.map +1 -0
  4. package/lib/components/ContentDialog/ContentDialog.js +91 -0
  5. package/lib/components/ContentDialog/ContentDialog.namespace.cjs +24 -0
  6. package/lib/components/ContentDialog/ContentDialog.namespace.d.ts +2 -0
  7. package/lib/components/ContentDialog/ContentDialog.namespace.d.ts.map +1 -0
  8. package/lib/components/ContentDialog/ContentDialog.namespace.js +19 -0
  9. package/lib/components/ContentDialog/index.cjs +21 -0
  10. package/lib/components/ContentDialog/index.d.ts +3 -0
  11. package/lib/components/ContentDialog/index.d.ts.map +1 -0
  12. package/lib/components/ContentDialog/index.js +3 -0
  13. package/lib/components/Dialog/index.d.ts.map +1 -1
  14. package/lib/components/QuantityPicker/QuantityPicker.cjs +120 -0
  15. package/lib/components/QuantityPicker/QuantityPicker.d.ts +25 -0
  16. package/lib/components/QuantityPicker/QuantityPicker.d.ts.map +1 -0
  17. package/lib/components/QuantityPicker/QuantityPicker.js +113 -0
  18. package/lib/components/QuantityPicker/QuantityPicker.namespace.cjs +17 -0
  19. package/lib/components/QuantityPicker/QuantityPicker.namespace.d.ts +2 -0
  20. package/lib/components/QuantityPicker/QuantityPicker.namespace.d.ts.map +1 -0
  21. package/lib/components/QuantityPicker/QuantityPicker.namespace.js +12 -0
  22. package/lib/components/QuantityPicker/QuantityPicker.test.d.ts +2 -0
  23. package/lib/components/QuantityPicker/QuantityPicker.test.d.ts.map +1 -0
  24. package/lib/components/QuantityPicker/index.cjs +14 -0
  25. package/lib/components/QuantityPicker/index.d.ts +3 -0
  26. package/lib/components/QuantityPicker/index.d.ts.map +1 -0
  27. package/lib/components/QuantityPicker/index.js +3 -0
  28. package/lib/components/ResponsiveDialog/ResponsiveDialog.cjs +196 -0
  29. package/lib/components/ResponsiveDialog/ResponsiveDialog.d.ts +72 -0
  30. package/lib/components/ResponsiveDialog/ResponsiveDialog.d.ts.map +1 -0
  31. package/lib/components/ResponsiveDialog/ResponsiveDialog.js +181 -0
  32. package/lib/components/ResponsiveDialog/ResponsiveDialog.namespace.cjs +25 -0
  33. package/lib/components/ResponsiveDialog/ResponsiveDialog.namespace.d.ts +2 -0
  34. package/lib/components/ResponsiveDialog/ResponsiveDialog.namespace.d.ts.map +1 -0
  35. package/lib/components/ResponsiveDialog/ResponsiveDialog.namespace.js +20 -0
  36. package/lib/components/ResponsiveDialog/index.cjs +23 -0
  37. package/lib/components/ResponsiveDialog/index.d.ts +3 -0
  38. package/lib/components/ResponsiveDialog/index.d.ts.map +1 -0
  39. package/lib/components/ResponsiveDialog/index.js +3 -0
  40. package/lib/components/Select/Select.cjs +191 -0
  41. package/lib/components/Select/Select.d.ts +89 -0
  42. package/lib/components/Select/Select.d.ts.map +1 -0
  43. package/lib/components/Select/Select.js +171 -0
  44. package/lib/components/Select/Select.namespace.cjs +30 -0
  45. package/lib/components/Select/Select.namespace.d.ts +2 -0
  46. package/lib/components/Select/Select.namespace.d.ts.map +1 -0
  47. package/lib/components/Select/Select.namespace.js +25 -0
  48. package/lib/components/Select/Select.test.d.ts +2 -0
  49. package/lib/components/Select/Select.test.d.ts.map +1 -0
  50. package/lib/components/Select/index.cjs +27 -0
  51. package/lib/components/Select/index.d.ts +3 -0
  52. package/lib/components/Select/index.d.ts.map +1 -0
  53. package/lib/components/Select/index.js +3 -0
  54. package/lib/components/index.cjs +81 -0
  55. package/lib/components/index.d.ts +4 -0
  56. package/lib/components/index.d.ts.map +1 -1
  57. package/lib/components/index.js +9 -1
  58. package/lib/index.cjs +82 -1
  59. package/lib/index.js +10 -2
  60. package/package.json +8 -6
  61. package/src/components/ContentDialog/ContentDialog.namespace.ts +26 -0
  62. package/src/components/ContentDialog/ContentDialog.tsx +222 -0
  63. package/src/components/ContentDialog/index.ts +33 -0
  64. package/src/components/Dialog/index.ts +5 -0
  65. package/src/components/QuantityPicker/QuantityPicker.namespace.ts +12 -0
  66. package/src/components/QuantityPicker/QuantityPicker.test.tsx +108 -0
  67. package/src/components/QuantityPicker/QuantityPicker.tsx +214 -0
  68. package/src/components/QuantityPicker/index.ts +14 -0
  69. package/src/components/ResponsiveDialog/ResponsiveDialog.namespace.ts +28 -0
  70. package/src/components/ResponsiveDialog/ResponsiveDialog.tsx +327 -0
  71. package/src/components/ResponsiveDialog/index.ts +31 -0
  72. package/src/components/Select/Select.namespace.ts +38 -0
  73. package/src/components/Select/Select.test.tsx +451 -0
  74. package/src/components/Select/Select.tsx +443 -0
  75. package/src/components/Select/index.ts +40 -0
  76. package/src/components/index.ts +4 -0
@@ -0,0 +1,451 @@
1
+ import { render, act } from "@testing-library/react";
2
+ import { describe, expect, it, jest } from "bun:test";
3
+ import type * as React from "react";
4
+
5
+ import {
6
+ SelectRoot,
7
+ SelectTrigger,
8
+ SelectValue,
9
+ SelectPlaceholder,
10
+ SelectPrefixIcon,
11
+ SelectPositioner,
12
+ SelectContent,
13
+ SelectScrollArea,
14
+ SelectItem,
15
+ SelectItemPrefixIcon,
16
+ SelectItemBody,
17
+ SelectItemLabel,
18
+ SelectItemIndicator,
19
+ SelectHiddenSelect,
20
+ type SelectRootProps,
21
+ } from "./Select";
22
+ import { FieldRoot, FieldLabel } from "../Field/Field";
23
+
24
+ const waitForPositioning = () => act(async () => {});
25
+
26
+ function TestSelect({ staticIcon, ...props }: SelectRootProps & { staticIcon?: React.ReactNode }) {
27
+ return (
28
+ <SelectRoot {...props}>
29
+ <SelectTrigger aria-label="Fruit">
30
+ <SelectPrefixIcon fallback={staticIcon} />
31
+ <SelectValue />
32
+ <SelectPlaceholder>Choose a fruit</SelectPlaceholder>
33
+ </SelectTrigger>
34
+ <SelectPositioner>
35
+ <SelectContent>
36
+ <SelectScrollArea>
37
+ <SelectItem value="apple" label="Apple" prefixIcon={<svg data-testid="apple-icon" />}>
38
+ <SelectItemBody>
39
+ <SelectItemLabel>Apple</SelectItemLabel>
40
+ </SelectItemBody>
41
+ </SelectItem>
42
+ <SelectItem value="banana" label="Banana">
43
+ <SelectItemBody>
44
+ <SelectItemLabel>Banana</SelectItemLabel>
45
+ </SelectItemBody>
46
+ </SelectItem>
47
+ <SelectItem
48
+ value="cherry"
49
+ label="Cherry"
50
+ prefixIcon={<svg data-testid="cherry-icon" />}
51
+ >
52
+ <SelectItemBody>
53
+ <SelectItemLabel>Cherry</SelectItemLabel>
54
+ </SelectItemBody>
55
+ </SelectItem>
56
+ </SelectScrollArea>
57
+ </SelectContent>
58
+ </SelectPositioner>
59
+ </SelectRoot>
60
+ );
61
+ }
62
+
63
+ describe("Select", () => {
64
+ describe("SelectPrefixIcon (selected-item mirroring)", () => {
65
+ it("renders the static svg while nothing is selected", async () => {
66
+ const { queryByTestId } = render(
67
+ <TestSelect staticIcon={<svg data-testid="static-icon" />} />,
68
+ );
69
+ await waitForPositioning();
70
+ expect(queryByTestId("static-icon")).toBeInTheDocument();
71
+ });
72
+
73
+ it("renders nothing while nothing is selected and no static svg is given", async () => {
74
+ const { getByRole } = render(<TestSelect />);
75
+ await waitForPositioning();
76
+ expect(getByRole("combobox").querySelector("svg")).toBeNull();
77
+ });
78
+
79
+ it("renders the selected item's icon over the static svg with exactly one selection", async () => {
80
+ const { queryByTestId } = render(
81
+ <TestSelect staticIcon={<svg data-testid="static-icon" />} defaultValue={["apple"]} />,
82
+ );
83
+ await waitForPositioning();
84
+ expect(queryByTestId("apple-icon")).toBeInTheDocument();
85
+ expect(queryByTestId("static-icon")).not.toBeInTheDocument();
86
+ });
87
+
88
+ it("renders the selected item's icon with exactly one selection and no static svg", async () => {
89
+ const { queryByTestId } = render(<TestSelect defaultValue={["apple"]} />);
90
+ await waitForPositioning();
91
+ expect(queryByTestId("apple-icon")).toBeInTheDocument();
92
+ });
93
+
94
+ it("falls back to the static svg when the single selected item has no icon", async () => {
95
+ const { queryByTestId } = render(
96
+ <TestSelect staticIcon={<svg data-testid="static-icon" />} defaultValue={["banana"]} />,
97
+ );
98
+ await waitForPositioning();
99
+ expect(queryByTestId("static-icon")).toBeInTheDocument();
100
+ });
101
+
102
+ it("renders nothing when the single selected item has no icon and no static svg is given", async () => {
103
+ const { getByRole } = render(<TestSelect defaultValue={["banana"]} />);
104
+ await waitForPositioning();
105
+ expect(getByRole("combobox").querySelector("svg")).toBeNull();
106
+ });
107
+
108
+ it("falls back to the static svg when the single selected value has no rendered option", async () => {
109
+ const { queryByTestId } = render(
110
+ <TestSelect staticIcon={<svg data-testid="static-icon" />} defaultValue={["ghost"]} />,
111
+ );
112
+ await waitForPositioning();
113
+ expect(queryByTestId("static-icon")).toBeInTheDocument();
114
+ });
115
+
116
+ it("renders the static svg with two or more selections", async () => {
117
+ const { queryByTestId } = render(
118
+ <TestSelect
119
+ multiple
120
+ staticIcon={<svg data-testid="static-icon" />}
121
+ defaultValue={["apple", "cherry"]}
122
+ />,
123
+ );
124
+ await waitForPositioning();
125
+ expect(queryByTestId("static-icon")).toBeInTheDocument();
126
+ expect(queryByTestId("apple-icon")).not.toBeInTheDocument();
127
+ expect(queryByTestId("cherry-icon")).not.toBeInTheDocument();
128
+ });
129
+
130
+ it("mirrors the item icon when a multi-select has exactly one selection", async () => {
131
+ const { queryByTestId } = render(
132
+ <TestSelect
133
+ multiple
134
+ staticIcon={<svg data-testid="static-icon" />}
135
+ defaultValue={["cherry"]}
136
+ />,
137
+ );
138
+ await waitForPositioning();
139
+ expect(queryByTestId("cherry-icon")).toBeInTheDocument();
140
+ expect(queryByTestId("static-icon")).not.toBeInTheDocument();
141
+ });
142
+
143
+ it("keeps the mirrored icon aria-hidden and the trigger accessible name unchanged", async () => {
144
+ const { getByRole, getByTestId } = render(
145
+ <TestSelect staticIcon={<svg data-testid="static-icon" />} defaultValue={["apple"]} />,
146
+ );
147
+ await waitForPositioning();
148
+ expect(getByTestId("apple-icon")).toHaveAttribute("aria-hidden", "true");
149
+ expect(getByRole("combobox", { name: "Fruit" })).toBeInTheDocument();
150
+ });
151
+
152
+ it("returns to the static svg when the selection is cleared", async () => {
153
+ const { queryByTestId, rerender } = render(
154
+ <TestSelect staticIcon={<svg data-testid="static-icon" />} value={["apple"]} />,
155
+ );
156
+ await waitForPositioning();
157
+ expect(queryByTestId("apple-icon")).toBeInTheDocument();
158
+ expect(queryByTestId("static-icon")).not.toBeInTheDocument();
159
+
160
+ rerender(<TestSelect staticIcon={<svg data-testid="static-icon" />} value={[]} />);
161
+ expect(queryByTestId("apple-icon")).not.toBeInTheDocument();
162
+ expect(queryByTestId("static-icon")).toBeInTheDocument();
163
+ });
164
+
165
+ it("renders nothing with two or more selections and no static svg", async () => {
166
+ const { getByRole } = render(<TestSelect multiple defaultValue={["apple", "cherry"]} />);
167
+ await waitForPositioning();
168
+ // neither item icon mirrors (only exactly-one mirrors) and there is no
169
+ // fallback, so the prefix slot renders nothing
170
+ expect(getByRole("combobox").querySelector("svg")).toBeNull();
171
+ });
172
+
173
+ it("forwards the disabled state to the prefix icon", async () => {
174
+ const { getByTestId } = render(
175
+ <TestSelect disabled staticIcon={<svg data-testid="static-icon" />} />,
176
+ );
177
+ await waitForPositioning();
178
+ expect(getByTestId("static-icon")).toHaveAttribute("data-disabled");
179
+ });
180
+ });
181
+
182
+ describe("item row: context-driven label & prefix", () => {
183
+ function RowSelect(props: SelectRootProps) {
184
+ return (
185
+ <SelectRoot defaultOpen {...props}>
186
+ <SelectTrigger aria-label="Fruit">
187
+ <SelectValue />
188
+ </SelectTrigger>
189
+ <SelectPositioner>
190
+ <SelectContent>
191
+ <SelectScrollArea>
192
+ <SelectItem
193
+ value="apple"
194
+ label="Apple"
195
+ prefixIcon={<svg data-testid="apple-row-icon" />}
196
+ >
197
+ <SelectItemPrefixIcon />
198
+ <SelectItemBody>
199
+ <SelectItemLabel />
200
+ </SelectItemBody>
201
+ </SelectItem>
202
+ <SelectItem value="banana" label="Banana">
203
+ <SelectItemPrefixIcon />
204
+ <SelectItemBody>
205
+ <SelectItemLabel />
206
+ </SelectItemBody>
207
+ </SelectItem>
208
+ <SelectItem value="cherry" label={<em>Cherry</em>} textValue="Cherry">
209
+ <SelectItemBody>
210
+ <SelectItemLabel>Override</SelectItemLabel>
211
+ </SelectItemBody>
212
+ </SelectItem>
213
+ </SelectScrollArea>
214
+ </SelectContent>
215
+ </SelectPositioner>
216
+ </SelectRoot>
217
+ );
218
+ }
219
+
220
+ it("renders the item's context label when SelectItemLabel has no children", async () => {
221
+ const { getByRole } = render(<RowSelect />);
222
+ await waitForPositioning();
223
+ expect(getByRole("option", { name: "Apple" })).toBeInTheDocument();
224
+ expect(getByRole("option", { name: "Banana" })).toBeInTheDocument();
225
+ });
226
+
227
+ it("lets explicit SelectItemLabel children win over the context label", async () => {
228
+ const { getByRole } = render(<RowSelect />);
229
+ await waitForPositioning();
230
+ expect(getByRole("option", { name: "Override" })).toBeInTheDocument();
231
+ });
232
+
233
+ it("renders the item's context prefixIcon in the row, kept aria-hidden", async () => {
234
+ const { getByTestId } = render(<RowSelect />);
235
+ await waitForPositioning();
236
+ expect(getByTestId("apple-row-icon")).toHaveAttribute("aria-hidden", "true");
237
+ });
238
+
239
+ it("renders no row prefix icon when the item has no prefixIcon", async () => {
240
+ const { getByRole } = render(<RowSelect />);
241
+ await waitForPositioning();
242
+ expect(getByRole("option", { name: "Banana" }).querySelector("svg")).toBeNull();
243
+ });
244
+
245
+ it("lets an explicit svg prop override the item's context prefixIcon", async () => {
246
+ const { getByTestId, queryByTestId } = render(
247
+ <SelectRoot defaultOpen>
248
+ <SelectTrigger aria-label="Fruit">
249
+ <SelectValue />
250
+ </SelectTrigger>
251
+ <SelectPositioner>
252
+ <SelectContent>
253
+ <SelectScrollArea>
254
+ <SelectItem value="apple" label="Apple" prefixIcon={<svg data-testid="ctx-icon" />}>
255
+ <SelectItemPrefixIcon svg={<svg data-testid="override-icon" />} />
256
+ <SelectItemBody>
257
+ <SelectItemLabel />
258
+ </SelectItemBody>
259
+ </SelectItem>
260
+ </SelectScrollArea>
261
+ </SelectContent>
262
+ </SelectPositioner>
263
+ </SelectRoot>,
264
+ );
265
+ await waitForPositioning();
266
+ expect(getByTestId("override-icon")).toBeInTheDocument();
267
+ expect(queryByTestId("ctx-icon")).not.toBeInTheDocument();
268
+ });
269
+
270
+ // Every item slot carries its own `[data-disabled]` selector, so the disabled
271
+ // color only lands if the state reaches each element — the prefix icon included.
272
+ it("forwards the disabled item state to the item prefix icon, body and label", async () => {
273
+ const { getByTestId, getByText } = render(
274
+ <SelectRoot defaultOpen>
275
+ <SelectTrigger aria-label="Fruit">
276
+ <SelectValue />
277
+ </SelectTrigger>
278
+ <SelectPositioner>
279
+ <SelectContent>
280
+ <SelectScrollArea>
281
+ <SelectItem
282
+ value="apple"
283
+ label="Apple"
284
+ prefixIcon={<svg data-testid="apple-row-icon" />}
285
+ disabled
286
+ >
287
+ <SelectItemPrefixIcon />
288
+ <SelectItemBody data-testid="apple-body">
289
+ <SelectItemLabel />
290
+ </SelectItemBody>
291
+ </SelectItem>
292
+ </SelectScrollArea>
293
+ </SelectContent>
294
+ </SelectPositioner>
295
+ </SelectRoot>,
296
+ );
297
+ await waitForPositioning();
298
+ expect(getByTestId("apple-row-icon")).toHaveAttribute("data-disabled");
299
+ expect(getByTestId("apple-body")).toHaveAttribute("data-disabled");
300
+ expect(getByText("Apple")).toHaveAttribute("data-disabled");
301
+ });
302
+ });
303
+
304
+ describe("Field composition", () => {
305
+ function FieldSelect() {
306
+ return (
307
+ <FieldRoot>
308
+ <FieldLabel>Fruit</FieldLabel>
309
+ <SelectRoot>
310
+ <SelectTrigger>
311
+ <SelectValue />
312
+ </SelectTrigger>
313
+ <SelectPositioner>
314
+ <SelectContent>
315
+ <SelectScrollArea>
316
+ <SelectItem value="apple" label="Apple">
317
+ <SelectItemBody>
318
+ <SelectItemLabel>Apple</SelectItemLabel>
319
+ </SelectItemBody>
320
+ </SelectItem>
321
+ </SelectScrollArea>
322
+ </SelectContent>
323
+ </SelectPositioner>
324
+ <SelectHiddenSelect />
325
+ </SelectRoot>
326
+ </FieldRoot>
327
+ );
328
+ }
329
+
330
+ it("associates the field label with the hidden select, not the trigger", async () => {
331
+ const { container } = render(<FieldSelect />);
332
+ await waitForPositioning();
333
+
334
+ const label = container.querySelector("label");
335
+ const hidden = container.querySelector("select");
336
+ if (!label || !hidden) throw new Error("label or hidden select not rendered");
337
+
338
+ // Label activation on the trigger button would open the listbox; targeting
339
+ // the hidden select instead forwards only focus (via its onFocus redirect).
340
+ expect(hidden.id).toBe(label.htmlFor);
341
+ expect(container.querySelector("button")?.id).not.toBe(label.htmlFor);
342
+ });
343
+
344
+ it("labels the trigger via the field label id", async () => {
345
+ const { container, getByRole } = render(<FieldSelect />);
346
+ await waitForPositioning();
347
+
348
+ const label = container.querySelector("label");
349
+ expect(getByRole("combobox")).toHaveAttribute("aria-labelledby", label?.id);
350
+ });
351
+
352
+ // APG combobox pattern: the listbox popup carries the same field label so
353
+ // screen readers announce the group name when focus enters the options.
354
+ it("labels the listbox popup via the field label id", async () => {
355
+ const { container, getByRole } = render(<FieldSelect />);
356
+ await waitForPositioning();
357
+
358
+ const label = container.querySelector("label");
359
+ expect(getByRole("listbox")).toHaveAttribute("aria-labelledby", label?.id);
360
+ });
361
+ });
362
+
363
+ describe("SelectItemIndicator", () => {
364
+ function IndicatorSelect(props: SelectRootProps) {
365
+ return (
366
+ <SelectRoot defaultOpen {...props}>
367
+ <SelectTrigger aria-label="Fruit">
368
+ <SelectValue />
369
+ </SelectTrigger>
370
+ <SelectPositioner>
371
+ <SelectContent>
372
+ <SelectScrollArea>
373
+ <SelectItem value="apple" label="Apple">
374
+ <SelectItemBody>
375
+ <SelectItemLabel />
376
+ </SelectItemBody>
377
+ <SelectItemIndicator
378
+ selected={<svg data-testid="apple-selected" />}
379
+ unselected={<svg data-testid="apple-unselected" />}
380
+ />
381
+ </SelectItem>
382
+ <SelectItem value="banana" label="Banana">
383
+ <SelectItemBody>
384
+ <SelectItemLabel />
385
+ </SelectItemBody>
386
+ <SelectItemIndicator selected={<svg data-testid="banana-selected" />} />
387
+ </SelectItem>
388
+ </SelectScrollArea>
389
+ </SelectContent>
390
+ </SelectPositioner>
391
+ </SelectRoot>
392
+ );
393
+ }
394
+
395
+ it("shows the selected icon on the selected item, kept aria-hidden", async () => {
396
+ const { getByTestId, queryByTestId } = render(<IndicatorSelect defaultValue={["apple"]} />);
397
+ await waitForPositioning();
398
+
399
+ expect(getByTestId("apple-selected")).toBeInTheDocument();
400
+ expect(getByTestId("apple-selected")).toHaveAttribute("aria-hidden", "true");
401
+ expect(queryByTestId("apple-unselected")).not.toBeInTheDocument();
402
+ });
403
+
404
+ it("shows the unselected icon while the item is not selected", async () => {
405
+ const { getByTestId, queryByTestId } = render(<IndicatorSelect />);
406
+ await waitForPositioning();
407
+
408
+ expect(getByTestId("apple-unselected")).toBeInTheDocument();
409
+ expect(queryByTestId("apple-selected")).not.toBeInTheDocument();
410
+ });
411
+
412
+ it("renders nothing for an unselected item that has no unselected icon", async () => {
413
+ const { queryByTestId } = render(<IndicatorSelect defaultValue={["apple"]} />);
414
+ await waitForPositioning();
415
+
416
+ // banana is unselected and provides no `unselected` icon
417
+ expect(queryByTestId("banana-selected")).not.toBeInTheDocument();
418
+ });
419
+ });
420
+
421
+ describe("SelectTrigger accessibility warning", () => {
422
+ it("warns when there is no Field and no aria-label", async () => {
423
+ const warn = jest.spyOn(console, "warn").mockImplementation(() => {});
424
+ render(
425
+ <SelectRoot>
426
+ <SelectTrigger>
427
+ <SelectValue />
428
+ </SelectTrigger>
429
+ <SelectPositioner>
430
+ <SelectContent>
431
+ <SelectScrollArea />
432
+ </SelectContent>
433
+ </SelectPositioner>
434
+ </SelectRoot>,
435
+ );
436
+ await waitForPositioning();
437
+
438
+ expect(warn).toHaveBeenCalledWith(expect.stringContaining("SelectTrigger"));
439
+ warn.mockRestore();
440
+ });
441
+
442
+ it("stays silent when an aria-label is provided", async () => {
443
+ const warn = jest.spyOn(console, "warn").mockImplementation(() => {});
444
+ render(<TestSelect />);
445
+ await waitForPositioning();
446
+
447
+ expect(warn).not.toHaveBeenCalled();
448
+ warn.mockRestore();
449
+ });
450
+ });
451
+ });