@butternutbox/pawprint-native 1.6.3 → 2.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.
- package/.turbo/turbo-build.log +9 -9
- package/CHANGELOG.md +52 -0
- package/COMPONENT_GUIDELINES.md +57 -1
- package/dist/index.cjs +1459 -1380
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +81 -117
- package/dist/index.d.ts +81 -117
- package/dist/index.js +1206 -1125
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/__mocks__/react-native.tsx +33 -5
- package/src/__mocks__/rn-primitives/portal.tsx +71 -0
- package/src/components/atoms/Input/InputField.tsx +12 -2
- package/src/components/molecules/Drawer/Drawer.test.tsx +54 -2
- package/src/components/molecules/Drawer/DrawerBody.tsx +2 -17
- package/src/components/molecules/Drawer/DrawerContent.tsx +49 -2
- package/src/components/molecules/Drawer/DrawerOverlay.tsx +28 -16
- package/src/components/molecules/SelectField/AsyncSearch.test.tsx +373 -0
- package/src/components/molecules/SelectField/SelectDrawerField.stories.tsx +192 -0
- package/src/components/molecules/SelectField/SelectDrawerField.test.tsx +210 -0
- package/src/components/molecules/SelectField/SelectDrawerField.tsx +245 -0
- package/src/components/molecules/SelectField/SelectField.stories.tsx +221 -421
- package/src/components/molecules/SelectField/SelectField.test.tsx +214 -662
- package/src/components/molecules/SelectField/SelectField.tsx +269 -539
- package/src/components/molecules/SelectField/SelectFieldDropdown.tsx +90 -0
- package/src/components/molecules/SelectField/SelectFieldList.tsx +88 -0
- package/src/components/molecules/SelectField/SelectFieldOption.tsx +90 -0
- package/src/components/molecules/SelectField/core/index.ts +8 -0
- package/src/components/molecules/SelectField/core/listHeight.test.ts +22 -0
- package/src/components/molecules/SelectField/core/listHeight.ts +8 -0
- package/src/components/molecules/SelectField/core/options.ts +35 -0
- package/src/components/molecules/SelectField/core/useSelectOptions.ts +116 -0
- package/src/components/molecules/SelectField/index.ts +12 -9
- package/src/index.ts +0 -1
- package/src/test-utils.tsx +5 -1
- package/vitest.config.ts +7 -0
- package/src/components/molecules/SelectField/SelectFieldContent.tsx +0 -81
- package/src/components/molecules/SelectField/SelectFieldItem.tsx +0 -133
- package/src/components/molecules/SelectField/SelectFieldTrigger.tsx +0 -188
- package/src/components/molecules/SelectField/SelectFieldValue.tsx +0 -33
- package/src/components/molecules/SelectField/hooks/index.ts +0 -2
- package/src/components/molecules/SelectField/hooks/useSelectField.ts +0 -84
- package/src/hooks/index.ts +0 -1
- package/src/hooks/useDrawerKeyboardAvoidance.ts +0 -29
|
@@ -1,777 +1,329 @@
|
|
|
1
1
|
import React from "react"
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"
|
|
5
|
-
import { MEASURED_TRIGGER } from "../../../__mocks__/react-native"
|
|
2
|
+
import { screen, fireEvent, waitFor } from "@testing-library/react"
|
|
3
|
+
import { describe, it, expect, vi } from "vitest"
|
|
6
4
|
import { renderWithTheme } from "../../../test-utils"
|
|
7
5
|
import { SelectField } from "./SelectField"
|
|
6
|
+
import type { SelectFieldOptionData } from "./SelectField"
|
|
7
|
+
|
|
8
|
+
const COUNTRIES: SelectFieldOptionData[] = [
|
|
9
|
+
{ value: "uk", label: "United Kingdom" },
|
|
10
|
+
{ value: "us", label: "United States" },
|
|
11
|
+
{ value: "ca", label: "Canada" },
|
|
12
|
+
{ value: "au", label: "Australia" }
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
const renderField = (
|
|
16
|
+
props: Partial<React.ComponentProps<typeof SelectField>> = {}
|
|
17
|
+
) => {
|
|
18
|
+
renderWithTheme(
|
|
19
|
+
<SelectField
|
|
20
|
+
label="Country"
|
|
21
|
+
placeholder="Select a country"
|
|
22
|
+
options={COUNTRIES}
|
|
23
|
+
{...props}
|
|
24
|
+
/>
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
return screen.getByRole("combobox") as HTMLInputElement
|
|
28
|
+
}
|
|
8
29
|
|
|
9
30
|
describe("SelectField", () => {
|
|
10
|
-
describe("
|
|
11
|
-
it("renders label
|
|
12
|
-
|
|
13
|
-
<SelectField label="Country" placeholder="Select a country">
|
|
14
|
-
<SelectField.Item value="uk">United Kingdom</SelectField.Item>
|
|
15
|
-
</SelectField>
|
|
16
|
-
)
|
|
31
|
+
describe("field chrome", () => {
|
|
32
|
+
it("renders the label, description and optional text", () => {
|
|
33
|
+
renderField({ description: "Pick one", optionalText: "(optional)" })
|
|
17
34
|
|
|
18
35
|
expect(screen.getByText("Country")).toBeInTheDocument()
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
it("renders description when provided", () => {
|
|
22
|
-
renderWithTheme(
|
|
23
|
-
<SelectField
|
|
24
|
-
label="Country"
|
|
25
|
-
placeholder="Select a country"
|
|
26
|
-
description="Choose your country"
|
|
27
|
-
>
|
|
28
|
-
<SelectField.Item value="uk">United Kingdom</SelectField.Item>
|
|
29
|
-
</SelectField>
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
expect(screen.getByText("Choose your country")).toBeInTheDocument()
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
it("renders error message when error prop and state='error' are provided", () => {
|
|
36
|
-
renderWithTheme(
|
|
37
|
-
<SelectField
|
|
38
|
-
label="Country"
|
|
39
|
-
placeholder="Select a country"
|
|
40
|
-
state="error"
|
|
41
|
-
error="Country is required"
|
|
42
|
-
>
|
|
43
|
-
<SelectField.Item value="uk">United Kingdom</SelectField.Item>
|
|
44
|
-
</SelectField>
|
|
45
|
-
)
|
|
46
|
-
|
|
47
|
-
expect(screen.getByText("Country is required")).toBeInTheDocument()
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
it("does not render error message when error prop is provided without state='error'", () => {
|
|
51
|
-
renderWithTheme(
|
|
52
|
-
<SelectField
|
|
53
|
-
label="Country"
|
|
54
|
-
placeholder="Select a country"
|
|
55
|
-
error="Country is required"
|
|
56
|
-
>
|
|
57
|
-
<SelectField.Item value="uk">United Kingdom</SelectField.Item>
|
|
58
|
-
</SelectField>
|
|
59
|
-
)
|
|
60
|
-
|
|
61
|
-
expect(screen.queryByText("Country is required")).not.toBeInTheDocument()
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
it("shows (optional) when optionalText is provided", () => {
|
|
65
|
-
renderWithTheme(
|
|
66
|
-
<SelectField
|
|
67
|
-
label="Country"
|
|
68
|
-
placeholder="Select a country"
|
|
69
|
-
optionalText="(optional)"
|
|
70
|
-
>
|
|
71
|
-
<SelectField.Item value="uk">United Kingdom</SelectField.Item>
|
|
72
|
-
</SelectField>
|
|
73
|
-
)
|
|
74
|
-
|
|
36
|
+
expect(screen.getByText("Pick one")).toBeInTheDocument()
|
|
75
37
|
expect(screen.getByText("(optional)")).toBeInTheDocument()
|
|
76
38
|
})
|
|
77
39
|
|
|
78
|
-
it("renders the
|
|
79
|
-
|
|
80
|
-
<SelectField label="Country" placeholder="Select a country">
|
|
81
|
-
<SelectField.Item value="uk">United Kingdom</SelectField.Item>
|
|
82
|
-
</SelectField>
|
|
83
|
-
)
|
|
40
|
+
it("renders the error message whenever error is set", () => {
|
|
41
|
+
renderField({ error: "Please choose a country" })
|
|
84
42
|
|
|
85
|
-
expect(screen.getByText("
|
|
43
|
+
expect(screen.getByText("Please choose a country")).toBeInTheDocument()
|
|
86
44
|
})
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
describe("when using controlled mode", () => {
|
|
90
|
-
it("renders with controlled value", () => {
|
|
91
|
-
const onValueChange = vi.fn()
|
|
92
45
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
label="Country"
|
|
96
|
-
value="uk"
|
|
97
|
-
onValueChange={onValueChange}
|
|
98
|
-
placeholder="Select a country"
|
|
99
|
-
>
|
|
100
|
-
<SelectField.Item value="uk">United Kingdom</SelectField.Item>
|
|
101
|
-
<SelectField.Item value="us">United States</SelectField.Item>
|
|
102
|
-
</SelectField>
|
|
103
|
-
)
|
|
46
|
+
it("is not editable when disabled", () => {
|
|
47
|
+
const input = renderField({ disabled: true })
|
|
104
48
|
|
|
105
|
-
expect(
|
|
49
|
+
expect(input).toBeDisabled()
|
|
106
50
|
})
|
|
107
51
|
})
|
|
108
52
|
|
|
109
|
-
describe("
|
|
110
|
-
it("
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
<SelectField.Item value="uk">United Kingdom</SelectField.Item>
|
|
114
|
-
</SelectField>
|
|
115
|
-
)
|
|
53
|
+
describe("opening and closing", () => {
|
|
54
|
+
it("shows every option on focus", () => {
|
|
55
|
+
const input = renderField()
|
|
56
|
+
fireEvent.focus(input)
|
|
116
57
|
|
|
117
|
-
|
|
58
|
+
COUNTRIES.forEach((option) => {
|
|
59
|
+
expect(screen.getByText(option.label)).toBeInTheDocument()
|
|
60
|
+
})
|
|
118
61
|
})
|
|
119
|
-
})
|
|
120
62
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
renderWithTheme(
|
|
124
|
-
<SelectField
|
|
125
|
-
label="Country"
|
|
126
|
-
placeholder="Select a country"
|
|
127
|
-
state="error"
|
|
128
|
-
error="Country is required"
|
|
129
|
-
>
|
|
130
|
-
<SelectField.Item value="uk">United Kingdom</SelectField.Item>
|
|
131
|
-
</SelectField>
|
|
132
|
-
)
|
|
63
|
+
it("stays closed until the field is focused", () => {
|
|
64
|
+
renderField()
|
|
133
65
|
|
|
134
|
-
expect(screen.
|
|
66
|
+
expect(screen.queryByText("United Kingdom")).not.toBeInTheDocument()
|
|
135
67
|
})
|
|
136
68
|
|
|
137
|
-
it("
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
placeholder="Select a country"
|
|
142
|
-
state="success"
|
|
143
|
-
>
|
|
144
|
-
<SelectField.Item value="uk">United Kingdom</SelectField.Item>
|
|
145
|
-
</SelectField>
|
|
146
|
-
)
|
|
147
|
-
|
|
148
|
-
expect(screen.getByText("Country")).toBeInTheDocument()
|
|
149
|
-
})
|
|
150
|
-
})
|
|
69
|
+
it("closes on blur", async () => {
|
|
70
|
+
const input = renderField()
|
|
71
|
+
fireEvent.focus(input)
|
|
72
|
+
fireEvent.blur(input)
|
|
151
73
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
renderWithTheme(
|
|
155
|
-
<SelectField.Root>
|
|
156
|
-
<SelectField.Label>Country</SelectField.Label>
|
|
157
|
-
<SelectField.Trigger>
|
|
158
|
-
<SelectField.Value placeholder="Select a country" />
|
|
159
|
-
</SelectField.Trigger>
|
|
160
|
-
<SelectField.Content>
|
|
161
|
-
<SelectField.Item value="uk">United Kingdom</SelectField.Item>
|
|
162
|
-
</SelectField.Content>
|
|
163
|
-
<SelectField.Description>Choose your country</SelectField.Description>
|
|
164
|
-
</SelectField.Root>
|
|
74
|
+
await waitFor(() =>
|
|
75
|
+
expect(screen.queryByText("United Kingdom")).not.toBeInTheDocument()
|
|
165
76
|
)
|
|
166
|
-
|
|
167
|
-
expect(screen.getByText("Country")).toBeInTheDocument()
|
|
168
|
-
expect(screen.getByText("Choose your country")).toBeInTheDocument()
|
|
169
77
|
})
|
|
170
78
|
|
|
171
|
-
it("
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
<SelectField.Label state="error">Country</SelectField.Label>
|
|
175
|
-
<SelectField.Trigger state="error">
|
|
176
|
-
<SelectField.Value placeholder="Select a country" />
|
|
177
|
-
</SelectField.Trigger>
|
|
178
|
-
<SelectField.Content>
|
|
179
|
-
<SelectField.Item value="uk">United Kingdom</SelectField.Item>
|
|
180
|
-
</SelectField.Content>
|
|
181
|
-
<SelectField.Error>Country is required</SelectField.Error>
|
|
182
|
-
</SelectField.Root>
|
|
183
|
-
)
|
|
184
|
-
|
|
185
|
-
expect(screen.getByText("Country is required")).toBeInTheDocument()
|
|
186
|
-
})
|
|
187
|
-
})
|
|
79
|
+
it("does not open when disabled", () => {
|
|
80
|
+
const input = renderField({ disabled: true })
|
|
81
|
+
fireEvent.focus(input)
|
|
188
82
|
|
|
189
|
-
|
|
190
|
-
it("forwards ref to root element", () => {
|
|
191
|
-
const ref = React.createRef<View>()
|
|
192
|
-
renderWithTheme(<SelectField ref={ref} label="Test" />)
|
|
193
|
-
expect(ref.current).toBeTruthy()
|
|
83
|
+
expect(screen.queryByText("United Kingdom")).not.toBeInTheDocument()
|
|
194
84
|
})
|
|
195
85
|
})
|
|
196
86
|
|
|
197
|
-
describe("
|
|
198
|
-
it("renders
|
|
87
|
+
describe("portal", () => {
|
|
88
|
+
it("renders the dropdown outside the field's own subtree", () => {
|
|
199
89
|
renderWithTheme(
|
|
200
90
|
<SelectField
|
|
201
91
|
label="Country"
|
|
202
92
|
placeholder="Select a country"
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
<SelectField.Item value="uk">United Kingdom</SelectField.Item>
|
|
206
|
-
<SelectField.Item value="us">United States</SelectField.Item>
|
|
207
|
-
</SelectField>
|
|
93
|
+
options={COUNTRIES}
|
|
94
|
+
/>
|
|
208
95
|
)
|
|
209
96
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
})
|
|
213
|
-
})
|
|
214
|
-
|
|
215
|
-
describe("when searchable", () => {
|
|
216
|
-
const openDropdown = () => {
|
|
217
|
-
fireEvent.click(screen.getAllByRole("button")[0])
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
const openDropdownWithContent = () => {
|
|
221
|
-
vi.useFakeTimers()
|
|
222
|
-
fireEvent.click(screen.getAllByRole("button")[0])
|
|
223
|
-
act(() => vi.advanceTimersByTime(500))
|
|
224
|
-
vi.useRealTimers()
|
|
225
|
-
}
|
|
97
|
+
const input = screen.getByRole("combobox") as HTMLInputElement
|
|
98
|
+
fireEvent.focus(input)
|
|
226
99
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
<SelectField label="Country" placeholder="Select a country" searchable>
|
|
230
|
-
<SelectField.Item value="uk">United Kingdom</SelectField.Item>
|
|
231
|
-
<SelectField.Item value="us">United States</SelectField.Item>
|
|
232
|
-
</SelectField>
|
|
233
|
-
)
|
|
100
|
+
const row = screen.getByText("Canada")
|
|
101
|
+
const fieldRoot = input.closest("div")
|
|
234
102
|
|
|
235
|
-
expect(
|
|
236
|
-
|
|
237
|
-
expect(screen.getByPlaceholderText("Search...")).toBeInTheDocument()
|
|
103
|
+
expect(row).toBeInTheDocument()
|
|
104
|
+
expect(fieldRoot?.contains(row)).toBe(false)
|
|
238
105
|
})
|
|
239
106
|
|
|
240
|
-
it("
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
<SelectField.Item value="us">United States</SelectField.Item>
|
|
245
|
-
</SelectField>
|
|
246
|
-
)
|
|
247
|
-
|
|
248
|
-
openDropdown()
|
|
249
|
-
expect(screen.queryByPlaceholderText("Search...")).not.toBeInTheDocument()
|
|
250
|
-
})
|
|
107
|
+
it("removes the dropdown from the host when it closes", async () => {
|
|
108
|
+
const input = renderField()
|
|
109
|
+
fireEvent.focus(input)
|
|
110
|
+
expect(screen.getByText("Canada")).toBeInTheDocument()
|
|
251
111
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
label="Country"
|
|
256
|
-
placeholder="Select a country"
|
|
257
|
-
searchable
|
|
258
|
-
searchPlaceholder="Find a country..."
|
|
259
|
-
>
|
|
260
|
-
<SelectField.Item value="uk">United Kingdom</SelectField.Item>
|
|
261
|
-
</SelectField>
|
|
112
|
+
fireEvent.blur(input)
|
|
113
|
+
await waitFor(() =>
|
|
114
|
+
expect(screen.queryByText("Canada")).not.toBeInTheDocument()
|
|
262
115
|
)
|
|
263
|
-
|
|
264
|
-
openDropdown()
|
|
265
|
-
expect(
|
|
266
|
-
screen.getByPlaceholderText("Find a country...")
|
|
267
|
-
).toBeInTheDocument()
|
|
268
116
|
})
|
|
117
|
+
})
|
|
269
118
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
<SelectField.Item value="ca">Canada</SelectField.Item>
|
|
276
|
-
</SelectField>
|
|
277
|
-
)
|
|
278
|
-
|
|
279
|
-
openDropdownWithContent()
|
|
280
|
-
fireEvent.change(screen.getByPlaceholderText("Search..."), {
|
|
281
|
-
target: { value: "united" }
|
|
282
|
-
})
|
|
119
|
+
describe("filtering", () => {
|
|
120
|
+
it("matches on a substring, case-insensitively", () => {
|
|
121
|
+
const input = renderField()
|
|
122
|
+
fireEvent.focus(input)
|
|
123
|
+
fireEvent.change(input, { target: { value: " united" } })
|
|
283
124
|
|
|
284
125
|
expect(screen.getByText("United Kingdom")).toBeInTheDocument()
|
|
285
126
|
expect(screen.getByText("United States")).toBeInTheDocument()
|
|
286
127
|
expect(screen.queryByText("Canada")).not.toBeInTheDocument()
|
|
287
128
|
})
|
|
288
129
|
|
|
289
|
-
it("
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
openDropdownWithContent()
|
|
298
|
-
fireEvent.change(screen.getByPlaceholderText("Search..."), {
|
|
299
|
-
target: { value: "CANADA" }
|
|
130
|
+
it("orders starts-with matches ahead of contains matches", () => {
|
|
131
|
+
const input = renderField({
|
|
132
|
+
options: [
|
|
133
|
+
{ value: "scan", label: "Canine scan" },
|
|
134
|
+
{ value: "ca", label: "Canada" },
|
|
135
|
+
{ value: "af", label: "Africa" }
|
|
136
|
+
]
|
|
300
137
|
})
|
|
138
|
+
fireEvent.focus(input)
|
|
139
|
+
fireEvent.change(input, { target: { value: "ca" } })
|
|
301
140
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
141
|
+
const rendered = screen
|
|
142
|
+
.getAllByRole("button")
|
|
143
|
+
.map((row) => row.textContent)
|
|
144
|
+
.filter((text) => text && text.length > 0)
|
|
305
145
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
<SelectField label="Country" placeholder="Select a country" searchable>
|
|
309
|
-
<SelectField.Item value="uk">United Kingdom</SelectField.Item>
|
|
310
|
-
<SelectField.Item value="us">United States</SelectField.Item>
|
|
311
|
-
</SelectField>
|
|
146
|
+
expect(rendered.indexOf("Canine scan")).toBeLessThan(
|
|
147
|
+
rendered.indexOf("Africa")
|
|
312
148
|
)
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
fireEvent.change(screen.getByPlaceholderText("Search..."), {
|
|
316
|
-
target: { value: "xyz" }
|
|
317
|
-
})
|
|
318
|
-
|
|
319
|
-
expect(screen.getByText("No results found")).toBeInTheDocument()
|
|
320
|
-
})
|
|
321
|
-
|
|
322
|
-
it("shows custom noResultsText when provided", () => {
|
|
323
|
-
renderWithTheme(
|
|
324
|
-
<SelectField
|
|
325
|
-
label="Country"
|
|
326
|
-
placeholder="Select a country"
|
|
327
|
-
searchable
|
|
328
|
-
noResultsText="No countries match your search"
|
|
329
|
-
>
|
|
330
|
-
<SelectField.Item value="uk">United Kingdom</SelectField.Item>
|
|
331
|
-
</SelectField>
|
|
149
|
+
expect(rendered.indexOf("Canada")).toBeLessThan(
|
|
150
|
+
rendered.indexOf("Africa")
|
|
332
151
|
)
|
|
333
|
-
|
|
334
|
-
openDropdownWithContent()
|
|
335
|
-
fireEvent.change(screen.getByPlaceholderText("Search..."), {
|
|
336
|
-
target: { value: "xyz" }
|
|
337
|
-
})
|
|
338
|
-
|
|
339
|
-
expect(
|
|
340
|
-
screen.getByText("No countries match your search")
|
|
341
|
-
).toBeInTheDocument()
|
|
342
152
|
})
|
|
343
153
|
|
|
344
|
-
it("shows
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
<SelectField.Item value="ca">Canada</SelectField.Item>
|
|
349
|
-
</SelectField>
|
|
350
|
-
)
|
|
351
|
-
|
|
352
|
-
openDropdownWithContent()
|
|
353
|
-
const input = screen.getByPlaceholderText("Search...")
|
|
354
|
-
fireEvent.change(input, { target: { value: "canada" } })
|
|
355
|
-
expect(screen.queryByText("United Kingdom")).not.toBeInTheDocument()
|
|
154
|
+
it("shows the no-results row when nothing matches", () => {
|
|
155
|
+
const input = renderField({ noResultsText: "No countries found" })
|
|
156
|
+
fireEvent.focus(input)
|
|
157
|
+
fireEvent.change(input, { target: { value: "zzzz" } })
|
|
356
158
|
|
|
357
|
-
|
|
358
|
-
expect(screen.
|
|
359
|
-
expect(screen.getByText("Canada")).toBeInTheDocument()
|
|
360
|
-
})
|
|
361
|
-
|
|
362
|
-
it("closes the dropdown and clears the search when closed", () => {
|
|
363
|
-
renderWithTheme(
|
|
364
|
-
<SelectField label="Country" placeholder="Select a country" searchable>
|
|
365
|
-
<SelectField.Item value="uk">United Kingdom</SelectField.Item>
|
|
366
|
-
<SelectField.Item value="ca">Canada</SelectField.Item>
|
|
367
|
-
</SelectField>
|
|
368
|
-
)
|
|
369
|
-
|
|
370
|
-
openDropdownWithContent()
|
|
371
|
-
fireEvent.change(screen.getByPlaceholderText("Search..."), {
|
|
372
|
-
target: { value: "canada" }
|
|
373
|
-
})
|
|
374
|
-
expect(screen.queryByText("United Kingdom")).not.toBeInTheDocument()
|
|
375
|
-
|
|
376
|
-
fireEvent.click(screen.getByTestId("select-overlay"))
|
|
377
|
-
expect(screen.queryByPlaceholderText("Search...")).not.toBeInTheDocument()
|
|
159
|
+
expect(screen.getByText("No countries found")).toBeInTheDocument()
|
|
160
|
+
expect(screen.queryByText("Canada")).not.toBeInTheDocument()
|
|
378
161
|
})
|
|
379
162
|
|
|
380
|
-
it("
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
)
|
|
163
|
+
it("resets the filter on refocus so the full list shows again", () => {
|
|
164
|
+
const input = renderField()
|
|
165
|
+
fireEvent.focus(input)
|
|
166
|
+
fireEvent.change(input, { target: { value: "united" } })
|
|
167
|
+
fireEvent.blur(input)
|
|
168
|
+
fireEvent.focus(input)
|
|
386
169
|
|
|
387
|
-
|
|
388
|
-
const input = screen.getByPlaceholderText("Search...")
|
|
389
|
-
vi.useFakeTimers()
|
|
390
|
-
input.blur()
|
|
391
|
-
expect(input).not.toHaveFocus()
|
|
392
|
-
|
|
393
|
-
act(() => vi.advanceTimersByTime(50))
|
|
394
|
-
vi.useRealTimers()
|
|
395
|
-
expect(input).toHaveFocus()
|
|
170
|
+
expect(screen.getByText("Canada")).toBeInTheDocument()
|
|
396
171
|
})
|
|
397
172
|
})
|
|
398
173
|
|
|
399
|
-
describe("
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
fireEvent.
|
|
404
|
-
|
|
405
|
-
fireEvent.change(input, { target: { value: query } })
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
it("shows children as the default list before the user types", async () => {
|
|
409
|
-
const onSearchQuery = vi.fn(async (): Promise<Result[]> => [])
|
|
410
|
-
|
|
411
|
-
renderWithTheme(
|
|
412
|
-
<SelectField
|
|
413
|
-
label="Breed"
|
|
414
|
-
placeholder="Select a breed"
|
|
415
|
-
searchable
|
|
416
|
-
debounceMs={0}
|
|
417
|
-
onSearchQuery={onSearchQuery}
|
|
418
|
-
>
|
|
419
|
-
<SelectField.Item value="popular">Most popular</SelectField.Item>
|
|
420
|
-
</SelectField>
|
|
421
|
-
)
|
|
422
|
-
|
|
423
|
-
fireEvent.click(screen.getAllByRole("button")[0])
|
|
424
|
-
|
|
425
|
-
expect(await screen.findByText("Most popular")).toBeInTheDocument()
|
|
426
|
-
expect(onSearchQuery).not.toHaveBeenCalled()
|
|
427
|
-
})
|
|
428
|
-
|
|
429
|
-
it("does not open an empty dropdown in query mode before the user types", () => {
|
|
430
|
-
const onSearchQuery = vi.fn(async (): Promise<Result[]> => [])
|
|
431
|
-
|
|
432
|
-
renderWithTheme(
|
|
433
|
-
<SelectField
|
|
434
|
-
label="Breed"
|
|
435
|
-
placeholder="Select a breed"
|
|
436
|
-
searchable
|
|
437
|
-
debounceMs={0}
|
|
438
|
-
onSearchQuery={onSearchQuery}
|
|
439
|
-
/>
|
|
440
|
-
)
|
|
441
|
-
|
|
442
|
-
vi.useFakeTimers()
|
|
443
|
-
fireEvent.click(screen.getAllByRole("button")[0])
|
|
444
|
-
act(() => vi.advanceTimersByTime(500))
|
|
445
|
-
vi.useRealTimers()
|
|
446
|
-
|
|
447
|
-
// Trigger is open (search input shown) but no content container is
|
|
448
|
-
// rendered: an empty dropdown crashes the real Select.Content on web.
|
|
449
|
-
expect(screen.getByPlaceholderText("Search...")).toBeInTheDocument()
|
|
450
|
-
expect(screen.queryByTestId("select-overlay")).not.toBeInTheDocument()
|
|
451
|
-
expect(onSearchQuery).not.toHaveBeenCalled()
|
|
452
|
-
})
|
|
453
|
-
|
|
454
|
-
it("calls onSearchQuery with the typed query and renders the results", async () => {
|
|
455
|
-
const onSearchQuery = vi.fn(
|
|
456
|
-
async (): Promise<Result[]> => [
|
|
457
|
-
{ value: "labrador", label: "Labrador Retriever" }
|
|
458
|
-
]
|
|
459
|
-
)
|
|
460
|
-
|
|
461
|
-
renderWithTheme(
|
|
462
|
-
<SelectField
|
|
463
|
-
label="Breed"
|
|
464
|
-
placeholder="Select a breed"
|
|
465
|
-
searchable
|
|
466
|
-
debounceMs={0}
|
|
467
|
-
onSearchQuery={onSearchQuery}
|
|
468
|
-
/>
|
|
469
|
-
)
|
|
470
|
-
|
|
471
|
-
openAndType("lab")
|
|
174
|
+
describe("selecting", () => {
|
|
175
|
+
it("sets the input text to the option label and emits its value", () => {
|
|
176
|
+
const onValueChange = vi.fn()
|
|
177
|
+
const input = renderField({ onValueChange })
|
|
178
|
+
fireEvent.focus(input)
|
|
179
|
+
fireEvent.click(screen.getByText("Canada"))
|
|
472
180
|
|
|
473
|
-
expect(
|
|
474
|
-
expect(
|
|
181
|
+
expect(onValueChange).toHaveBeenCalledWith("ca")
|
|
182
|
+
expect(input).toHaveValue("Canada")
|
|
475
183
|
})
|
|
476
184
|
|
|
477
|
-
it("
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
resolveQuery = resolve
|
|
483
|
-
})
|
|
484
|
-
)
|
|
485
|
-
|
|
486
|
-
renderWithTheme(
|
|
487
|
-
<SelectField
|
|
488
|
-
label="Breed"
|
|
489
|
-
placeholder="Select a breed"
|
|
490
|
-
searchable
|
|
491
|
-
debounceMs={0}
|
|
492
|
-
onSearchQuery={onSearchQuery}
|
|
493
|
-
/>
|
|
494
|
-
)
|
|
495
|
-
|
|
496
|
-
openAndType("lab")
|
|
497
|
-
|
|
498
|
-
expect(await screen.findByRole("progressbar")).toBeInTheDocument()
|
|
185
|
+
it("closes the dropdown after selecting", () => {
|
|
186
|
+
const input = renderField()
|
|
187
|
+
fireEvent.focus(input)
|
|
188
|
+
fireEvent.click(screen.getByText("Canada"))
|
|
189
|
+
fireEvent.blur(input)
|
|
499
190
|
|
|
500
|
-
|
|
501
|
-
act(() => resolveQuery([{ value: "labrador", label: "Labrador" }]))
|
|
502
|
-
|
|
503
|
-
expect(await screen.findByText("Labrador")).toBeInTheDocument()
|
|
504
|
-
expect(screen.queryByRole("progressbar")).not.toBeInTheDocument()
|
|
191
|
+
expect(screen.queryByText("Australia")).not.toBeInTheDocument()
|
|
505
192
|
})
|
|
506
193
|
|
|
507
|
-
it("
|
|
508
|
-
const
|
|
509
|
-
|
|
194
|
+
it("does not emit for a disabled option", () => {
|
|
195
|
+
const onValueChange = vi.fn()
|
|
196
|
+
const input = renderField({
|
|
197
|
+
onValueChange,
|
|
198
|
+
options: [{ value: "uk", label: "United Kingdom", disabled: true }]
|
|
510
199
|
})
|
|
200
|
+
fireEvent.focus(input)
|
|
201
|
+
fireEvent.click(screen.getByText("United Kingdom"))
|
|
511
202
|
|
|
512
|
-
|
|
513
|
-
<SelectField
|
|
514
|
-
label="Breed"
|
|
515
|
-
placeholder="Select a breed"
|
|
516
|
-
searchable
|
|
517
|
-
debounceMs={0}
|
|
518
|
-
errorText="Couldn't load breeds"
|
|
519
|
-
onSearchQuery={onSearchQuery}
|
|
520
|
-
/>
|
|
521
|
-
)
|
|
522
|
-
|
|
523
|
-
openAndType("lab")
|
|
524
|
-
|
|
525
|
-
expect(
|
|
526
|
-
await screen.findByText("Couldn't load breeds")
|
|
527
|
-
).toBeInTheDocument()
|
|
203
|
+
expect(onValueChange).not.toHaveBeenCalled()
|
|
528
204
|
})
|
|
529
205
|
|
|
530
|
-
it("
|
|
531
|
-
const
|
|
206
|
+
it("marks the committed option as selected", () => {
|
|
207
|
+
const input = renderField({ defaultValue: "ca" })
|
|
208
|
+
fireEvent.focus(input)
|
|
532
209
|
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
placeholder="Select a breed"
|
|
537
|
-
searchable
|
|
538
|
-
debounceMs={0}
|
|
539
|
-
noResultsText="No breeds found"
|
|
540
|
-
onSearchQuery={onSearchQuery}
|
|
541
|
-
/>
|
|
542
|
-
)
|
|
210
|
+
const selected = screen
|
|
211
|
+
.getAllByRole("button")
|
|
212
|
+
.find((row) => row.textContent === "Canada")
|
|
543
213
|
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
expect(await screen.findByText("No breeds found")).toBeInTheDocument()
|
|
214
|
+
expect(selected).toHaveAttribute("aria-selected", "true")
|
|
547
215
|
})
|
|
216
|
+
})
|
|
548
217
|
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
)
|
|
555
|
-
|
|
556
|
-
renderWithTheme(
|
|
557
|
-
<SelectField
|
|
558
|
-
label="Breed"
|
|
559
|
-
placeholder="Select a breed"
|
|
560
|
-
searchable
|
|
561
|
-
debounceMs={0}
|
|
562
|
-
onSearchQuery={onSearchQuery}
|
|
563
|
-
>
|
|
564
|
-
<SelectField.Item value="uk">United Kingdom</SelectField.Item>
|
|
565
|
-
</SelectField>
|
|
566
|
-
)
|
|
567
|
-
|
|
568
|
-
openAndType("lab")
|
|
569
|
-
|
|
570
|
-
expect(await screen.findByText("Labrador Retriever")).toBeInTheDocument()
|
|
571
|
-
expect(screen.queryByText("United Kingdom")).not.toBeInTheDocument()
|
|
572
|
-
})
|
|
573
|
-
|
|
574
|
-
it("debounces the query, firing once after the last keystroke", () => {
|
|
575
|
-
const onSearchQuery = vi.fn(
|
|
576
|
-
async (): Promise<Result[]> => [
|
|
577
|
-
{ value: "labrador", label: "Labrador Retriever" }
|
|
578
|
-
]
|
|
579
|
-
)
|
|
580
|
-
|
|
581
|
-
renderWithTheme(
|
|
582
|
-
<SelectField
|
|
583
|
-
label="Breed"
|
|
584
|
-
placeholder="Select a breed"
|
|
585
|
-
searchable
|
|
586
|
-
debounceMs={300}
|
|
587
|
-
onSearchQuery={onSearchQuery}
|
|
588
|
-
/>
|
|
589
|
-
)
|
|
590
|
-
|
|
591
|
-
vi.useFakeTimers()
|
|
592
|
-
fireEvent.click(screen.getAllByRole("button")[0])
|
|
593
|
-
const input = screen.getByPlaceholderText("Search...")
|
|
594
|
-
|
|
595
|
-
fireEvent.change(input, { target: { value: "l" } })
|
|
596
|
-
act(() => vi.advanceTimersByTime(200))
|
|
597
|
-
fireEvent.change(input, { target: { value: "la" } })
|
|
598
|
-
act(() => vi.advanceTimersByTime(200))
|
|
599
|
-
fireEvent.change(input, { target: { value: "lab" } })
|
|
600
|
-
|
|
601
|
-
// Each keystroke restarted the timer, so nothing has fired yet even
|
|
602
|
-
// though 400ms of typing has elapsed.
|
|
603
|
-
expect(onSearchQuery).not.toHaveBeenCalled()
|
|
218
|
+
describe("selection vs blur", () => {
|
|
219
|
+
it("selects even when the row press also blurs the field", async () => {
|
|
220
|
+
const onValueChange = vi.fn()
|
|
221
|
+
const input = renderField({ onValueChange })
|
|
222
|
+
fireEvent.focus(input)
|
|
604
223
|
|
|
605
|
-
|
|
606
|
-
|
|
224
|
+
const row = screen.getByText("Canada")
|
|
225
|
+
fireEvent.blur(input)
|
|
226
|
+
fireEvent.click(row)
|
|
607
227
|
|
|
608
|
-
expect(
|
|
609
|
-
expect(
|
|
228
|
+
await waitFor(() => expect(input).toHaveValue("Canada"))
|
|
229
|
+
expect(onValueChange).toHaveBeenLastCalledWith("ca")
|
|
610
230
|
})
|
|
611
231
|
|
|
612
|
-
it("
|
|
613
|
-
const
|
|
614
|
-
const
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
resolvers.push(resolve)
|
|
618
|
-
})
|
|
619
|
-
)
|
|
620
|
-
|
|
621
|
-
renderWithTheme(
|
|
622
|
-
<SelectField
|
|
623
|
-
label="Breed"
|
|
624
|
-
placeholder="Select a breed"
|
|
625
|
-
searchable
|
|
626
|
-
debounceMs={0}
|
|
627
|
-
onSearchQuery={onSearchQuery}
|
|
628
|
-
/>
|
|
629
|
-
)
|
|
630
|
-
|
|
631
|
-
fireEvent.click(screen.getAllByRole("button")[0])
|
|
632
|
-
const input = screen.getByPlaceholderText("Search...")
|
|
633
|
-
|
|
634
|
-
fireEvent.change(input, { target: { value: "lab" } })
|
|
635
|
-
await waitFor(() => expect(resolvers).toHaveLength(1))
|
|
636
|
-
|
|
637
|
-
fireEvent.change(input, { target: { value: "labr" } })
|
|
638
|
-
await waitFor(() => expect(resolvers).toHaveLength(2))
|
|
639
|
-
|
|
640
|
-
// The newer query lands first, then the superseded one resolves late.
|
|
641
|
-
await act(async () => {
|
|
642
|
-
resolvers[1]([{ value: "labrador", label: "Labrador Retriever" }])
|
|
643
|
-
})
|
|
644
|
-
expect(screen.getByText("Labrador Retriever")).toBeInTheDocument()
|
|
232
|
+
it("does not overwrite the selection with a blur commit", async () => {
|
|
233
|
+
const onValueChange = vi.fn()
|
|
234
|
+
const input = renderField({ onValueChange })
|
|
235
|
+
fireEvent.focus(input)
|
|
236
|
+
fireEvent.change(input, { target: { value: "can" } })
|
|
645
237
|
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
238
|
+
const row = screen.getByText("Canada")
|
|
239
|
+
fireEvent.blur(input)
|
|
240
|
+
fireEvent.click(row)
|
|
649
241
|
|
|
650
|
-
expect(
|
|
651
|
-
expect(
|
|
242
|
+
await waitFor(() => expect(input).toHaveValue("Canada"))
|
|
243
|
+
expect(onValueChange).not.toHaveBeenCalledWith(null)
|
|
652
244
|
})
|
|
653
245
|
})
|
|
654
246
|
|
|
655
|
-
describe("
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
value="uk"
|
|
663
|
-
leadingIcon={<div data-testid="icon">🇬🇧</div>}
|
|
664
|
-
>
|
|
665
|
-
United Kingdom
|
|
666
|
-
</SelectField.Item>
|
|
667
|
-
</SelectField>
|
|
668
|
-
)
|
|
669
|
-
|
|
670
|
-
openDropdown()
|
|
671
|
-
expect(screen.getByTestId("icon")).toBeInTheDocument()
|
|
672
|
-
})
|
|
673
|
-
|
|
674
|
-
it("renders items with hintText", () => {
|
|
675
|
-
renderWithTheme(
|
|
676
|
-
<SelectField label="Country" placeholder="Select a country">
|
|
677
|
-
<SelectField.Item value="uk" hintText="Europe">
|
|
678
|
-
United Kingdom
|
|
679
|
-
</SelectField.Item>
|
|
680
|
-
</SelectField>
|
|
681
|
-
)
|
|
247
|
+
describe("free text", () => {
|
|
248
|
+
it("keeps the typed text and emits null when nothing matches", async () => {
|
|
249
|
+
const onValueChange = vi.fn()
|
|
250
|
+
const input = renderField({ onValueChange, defaultValue: "ca" })
|
|
251
|
+
fireEvent.focus(input)
|
|
252
|
+
fireEvent.change(input, { target: { value: "xyz" } })
|
|
253
|
+
fireEvent.blur(input)
|
|
682
254
|
|
|
683
|
-
|
|
684
|
-
|
|
255
|
+
expect(input).toHaveValue("xyz")
|
|
256
|
+
await waitFor(() => expect(onValueChange).toHaveBeenLastCalledWith(null))
|
|
685
257
|
})
|
|
686
258
|
|
|
687
|
-
it("
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
</SelectField>
|
|
694
|
-
)
|
|
259
|
+
it("commits an exactly typed label without selecting from the list", async () => {
|
|
260
|
+
const onValueChange = vi.fn()
|
|
261
|
+
const input = renderField({ onValueChange })
|
|
262
|
+
fireEvent.focus(input)
|
|
263
|
+
fireEvent.change(input, { target: { value: "canada" } })
|
|
264
|
+
fireEvent.blur(input)
|
|
695
265
|
|
|
696
|
-
|
|
697
|
-
const item = screen.getByText("United Kingdom")
|
|
698
|
-
expect(item).toBeInTheDocument()
|
|
266
|
+
await waitFor(() => expect(onValueChange).toHaveBeenLastCalledWith("ca"))
|
|
699
267
|
})
|
|
700
268
|
})
|
|
701
|
-
describe("when the field moves while the dropdown is open", () => {
|
|
702
|
-
const restingPageY = MEASURED_TRIGGER.pageY
|
|
703
269
|
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
270
|
+
describe("clearing", () => {
|
|
271
|
+
it("is hidden while the field is empty", () => {
|
|
272
|
+
renderField()
|
|
707
273
|
|
|
708
|
-
|
|
709
|
-
MEASURED_TRIGGER.pageY = restingPageY
|
|
710
|
-
vi.useRealTimers()
|
|
274
|
+
expect(screen.queryByLabelText("Clear selection")).not.toBeInTheDocument()
|
|
711
275
|
})
|
|
712
276
|
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
<SelectField.Item value="lab">Labrador</SelectField.Item>
|
|
717
|
-
<SelectField.Item value="pug">Pug</SelectField.Item>
|
|
718
|
-
</SelectField>
|
|
719
|
-
)
|
|
720
|
-
|
|
721
|
-
const triggerPositionOf = (container: HTMLElement) =>
|
|
722
|
-
container
|
|
723
|
-
.querySelector("[data-trigger-position]")
|
|
724
|
-
?.getAttribute("data-trigger-position")
|
|
725
|
-
|
|
726
|
-
const advanceFrames = (count: number) =>
|
|
727
|
-
act(() => vi.advanceTimersByTime(count * 16))
|
|
728
|
-
|
|
729
|
-
it("anchors the dropdown to the field once it has opened", () => {
|
|
730
|
-
const { container } = renderSearchable()
|
|
277
|
+
it("appears once there is text and empties the field", () => {
|
|
278
|
+
const onValueChange = vi.fn()
|
|
279
|
+
const input = renderField({ onValueChange, defaultValue: "ca" })
|
|
731
280
|
|
|
732
|
-
fireEvent.click(screen.
|
|
733
|
-
advanceFrames(3)
|
|
281
|
+
fireEvent.click(screen.getByLabelText("Clear selection"))
|
|
734
282
|
|
|
735
|
-
expect(
|
|
736
|
-
|
|
737
|
-
)
|
|
283
|
+
expect(input).toHaveValue("")
|
|
284
|
+
expect(onValueChange).toHaveBeenCalledWith(null)
|
|
738
285
|
})
|
|
739
286
|
|
|
740
|
-
it("
|
|
741
|
-
const {
|
|
287
|
+
it("shows the full list again after clearing", () => {
|
|
288
|
+
const input = renderField({ defaultValue: "ca" })
|
|
289
|
+
fireEvent.focus(input)
|
|
290
|
+
fireEvent.click(screen.getByLabelText("Clear selection"))
|
|
742
291
|
|
|
743
|
-
|
|
744
|
-
advanceFrames(3)
|
|
745
|
-
MEASURED_TRIGGER.pageY = 380
|
|
746
|
-
advanceFrames(3)
|
|
747
|
-
|
|
748
|
-
expect(triggerPositionOf(container)).toBe(
|
|
749
|
-
JSON.stringify({ ...MEASURED_TRIGGER, pageY: 380 })
|
|
750
|
-
)
|
|
292
|
+
expect(screen.getByText("Australia")).toBeInTheDocument()
|
|
751
293
|
})
|
|
294
|
+
})
|
|
752
295
|
|
|
753
|
-
|
|
754
|
-
|
|
296
|
+
describe("controlled mode", () => {
|
|
297
|
+
it("shows the label for the controlled value", () => {
|
|
298
|
+
const input = renderField({ value: "au" })
|
|
755
299
|
|
|
756
|
-
|
|
757
|
-
|
|
300
|
+
expect(input).toHaveValue("Australia")
|
|
301
|
+
})
|
|
758
302
|
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
303
|
+
it("does not change its own value when controlled", () => {
|
|
304
|
+
const input = renderField({ value: "au", onValueChange: vi.fn() })
|
|
305
|
+
fireEvent.focus(input)
|
|
306
|
+
fireEvent.click(screen.getByText("Canada"))
|
|
307
|
+
fireEvent.blur(input)
|
|
763
308
|
|
|
764
|
-
expect(
|
|
765
|
-
JSON.stringify({ ...MEASURED_TRIGGER, pageY: restingPageY })
|
|
766
|
-
)
|
|
309
|
+
expect(input).toHaveValue("Australia")
|
|
767
310
|
})
|
|
311
|
+
})
|
|
312
|
+
|
|
313
|
+
describe("regression", () => {
|
|
314
|
+
it("keeps focus on the input while the filtered list changes", () => {
|
|
315
|
+
const input = renderField()
|
|
316
|
+
fireEvent.focus(input)
|
|
317
|
+
input.focus()
|
|
768
318
|
|
|
769
|
-
|
|
770
|
-
|
|
319
|
+
fireEvent.change(input, { target: { value: "u" } })
|
|
320
|
+
expect(document.activeElement).toBe(input)
|
|
771
321
|
|
|
772
|
-
|
|
322
|
+
fireEvent.change(input, { target: { value: "un" } })
|
|
323
|
+
expect(document.activeElement).toBe(input)
|
|
773
324
|
|
|
774
|
-
|
|
325
|
+
fireEvent.change(input, { target: { value: "zzz" } })
|
|
326
|
+
expect(document.activeElement).toBe(input)
|
|
775
327
|
})
|
|
776
328
|
})
|
|
777
329
|
})
|