1
+ import { noop } from '@algolia/autocomplete-shared' ;
1
2
import userEvent from '@testing-library/user-event' ;
2
3
3
4
import { AutocompleteState } from '..' ;
4
- import { createPlayground , createSource , defer } from '../../../../test/utils' ;
5
+ import {
6
+ createPlayground ,
7
+ createSource ,
8
+ defer ,
9
+ runAllMicroTasks ,
10
+ } from '../../../../test/utils' ;
5
11
import { createAutocomplete } from '../createAutocomplete' ;
6
12
7
13
type Item = {
@@ -31,7 +37,7 @@ describe('concurrency', () => {
31
37
userEvent . type ( input , 'b' ) ;
32
38
userEvent . type ( input , 'c' ) ;
33
39
34
- await defer ( ( ) => { } , timeout ) ;
40
+ await defer ( noop , timeout ) ;
35
41
36
42
let stateHistory : Array <
37
43
AutocompleteState < Item >
@@ -57,7 +63,7 @@ describe('concurrency', () => {
57
63
58
64
userEvent . type ( input , '{backspace}' . repeat ( 3 ) ) ;
59
65
60
- await defer ( ( ) => { } , timeout ) ;
66
+ await defer ( noop , timeout ) ;
61
67
62
68
stateHistory = onStateChange . mock . calls . flatMap ( ( x ) => x [ 0 ] . state ) ;
63
69
@@ -88,19 +94,44 @@ describe('concurrency', () => {
88
94
getSources,
89
95
} ) ;
90
96
91
- userEvent . type ( inputElement , 'ab{esc} ' ) ;
97
+ userEvent . type ( inputElement , 'ab' ) ;
92
98
93
- await defer ( ( ) => { } , timeout ) ;
99
+ // The search request is triggered
100
+ expect ( onStateChange ) . toHaveBeenLastCalledWith (
101
+ expect . objectContaining ( {
102
+ state : expect . objectContaining ( {
103
+ status : 'loading' ,
104
+ query : 'ab' ,
105
+ } ) ,
106
+ } )
107
+ ) ;
94
108
109
+ userEvent . type ( inputElement , '{esc}' ) ;
110
+
111
+ // The status is immediately set to "idle" and the panel is closed
95
112
expect ( onStateChange ) . toHaveBeenLastCalledWith (
96
113
expect . objectContaining ( {
97
114
state : expect . objectContaining ( {
115
+ status : 'idle' ,
98
116
isOpen : false ,
117
+ query : '' ,
118
+ } ) ,
119
+ } )
120
+ ) ;
121
+
122
+ await defer ( noop , timeout ) ;
123
+
124
+ // Once the request is settled, the state remains unchanged
125
+ expect ( onStateChange ) . toHaveBeenLastCalledWith (
126
+ expect . objectContaining ( {
127
+ state : expect . objectContaining ( {
99
128
status : 'idle' ,
129
+ isOpen : false ,
100
130
} ) ,
101
131
} )
102
132
) ;
103
- expect ( getSources ) . toHaveBeenCalledTimes ( 2 ) ;
133
+
134
+ expect ( getSources ) . toHaveBeenCalledTimes ( 3 ) ;
104
135
} ) ;
105
136
106
137
test ( 'keeps the panel closed on blur' , async ( ) => {
@@ -115,19 +146,46 @@ describe('concurrency', () => {
115
146
getSources,
116
147
} ) ;
117
148
118
- userEvent . type ( inputElement , 'a{enter}' ) ;
149
+ userEvent . type ( inputElement , 'a' ) ;
150
+
151
+ await runAllMicroTasks ( ) ;
152
+
153
+ // The search request is triggered
154
+ expect ( onStateChange ) . toHaveBeenLastCalledWith (
155
+ expect . objectContaining ( {
156
+ state : expect . objectContaining ( {
157
+ status : 'loading' ,
158
+ query : 'a' ,
159
+ } ) ,
160
+ } )
161
+ ) ;
119
162
120
- await defer ( ( ) => { } , timeout ) ;
163
+ userEvent . type ( inputElement , '{enter}' ) ;
121
164
165
+ // The status is immediately set to "idle" and the panel is closed
122
166
expect ( onStateChange ) . toHaveBeenLastCalledWith (
123
167
expect . objectContaining ( {
124
168
state : expect . objectContaining ( {
169
+ status : 'idle' ,
125
170
isOpen : false ,
171
+ query : 'a' ,
172
+ } ) ,
173
+ } )
174
+ ) ;
175
+
176
+ await defer ( noop , timeout ) ;
177
+
178
+ // Once the request is settled, the state remains unchanged
179
+ expect ( onStateChange ) . toHaveBeenLastCalledWith (
180
+ expect . objectContaining ( {
181
+ state : expect . objectContaining ( {
126
182
status : 'idle' ,
183
+ isOpen : false ,
127
184
} ) ,
128
185
} )
129
186
) ;
130
- expect ( getSources ) . toHaveBeenCalledTimes ( 1 ) ;
187
+
188
+ expect ( getSources ) . toHaveBeenCalledTimes ( 2 ) ;
131
189
} ) ;
132
190
133
191
test ( 'keeps the panel closed on touchstart blur' , async ( ) => {
@@ -156,19 +214,45 @@ describe('concurrency', () => {
156
214
window . addEventListener ( 'touchstart' , onTouchStart ) ;
157
215
158
216
userEvent . type ( inputElement , 'a' ) ;
217
+
218
+ await runAllMicroTasks ( ) ;
219
+
220
+ // The search request is triggered
221
+ expect ( onStateChange ) . toHaveBeenLastCalledWith (
222
+ expect . objectContaining ( {
223
+ state : expect . objectContaining ( {
224
+ status : 'loading' ,
225
+ query : 'a' ,
226
+ } ) ,
227
+ } )
228
+ ) ;
229
+
159
230
const customEvent = new CustomEvent ( 'touchstart' , { bubbles : true } ) ;
160
231
window . document . dispatchEvent ( customEvent ) ;
161
232
162
- await defer ( ( ) => { } , timeout ) ;
163
-
233
+ // The status is immediately set to "idle" and the panel is closed
164
234
expect ( onStateChange ) . toHaveBeenLastCalledWith (
165
235
expect . objectContaining ( {
166
236
state : expect . objectContaining ( {
237
+ status : 'idle' ,
167
238
isOpen : false ,
239
+ query : 'a' ,
240
+ } ) ,
241
+ } )
242
+ ) ;
243
+
244
+ await defer ( noop , timeout ) ;
245
+
246
+ // Once the request is settled, the state remains unchanged
247
+ expect ( onStateChange ) . toHaveBeenLastCalledWith (
248
+ expect . objectContaining ( {
249
+ state : expect . objectContaining ( {
168
250
status : 'idle' ,
251
+ isOpen : false ,
169
252
} ) ,
170
253
} )
171
254
) ;
255
+
172
256
expect ( getSources ) . toHaveBeenCalledTimes ( 1 ) ;
173
257
174
258
window . removeEventListener ( 'touchstart' , onTouchStart ) ;
@@ -197,7 +281,7 @@ describe('concurrency', () => {
197
281
198
282
userEvent . type ( inputElement , 'a{esc}' ) ;
199
283
200
- await defer ( ( ) => { } , delay ) ;
284
+ await defer ( noop , delay ) ;
201
285
202
286
expect ( onStateChange ) . toHaveBeenLastCalledWith (
203
287
expect . objectContaining ( {
@@ -229,7 +313,7 @@ describe('concurrency', () => {
229
313
230
314
userEvent . type ( inputElement , 'a{enter}' ) ;
231
315
232
- await defer ( ( ) => { } , delay ) ;
316
+ await defer ( noop , delay ) ;
233
317
234
318
expect ( onStateChange ) . toHaveBeenLastCalledWith (
235
319
expect . objectContaining ( {
@@ -276,7 +360,7 @@ describe('concurrency', () => {
276
360
const customEvent = new CustomEvent ( 'touchstart' , { bubbles : true } ) ;
277
361
window . document . dispatchEvent ( customEvent ) ;
278
362
279
- await defer ( ( ) => { } , delay ) ;
363
+ await defer ( noop , delay ) ;
280
364
281
365
expect ( onStateChange ) . toHaveBeenLastCalledWith (
282
366
expect . objectContaining ( {
0 commit comments