@@ -156,44 +156,86 @@ describe('select2', () => {
156
156
} )
157
157
158
158
context ( 'ajax data source' , ( ) => {
159
- it ( 'selects a value' , ( ) => {
160
- // https://select2.org/data-sources/ajax
161
-
162
- // Approach 1 (doesn't work): click on the container to
163
- // populate the values, and then select the value
164
- // cy.get('#select2-user-container').click()
165
- // cy.get('.select2-results__option').contains('Leanne Graham').click()
166
- // cy.get('#user').should('have.value', '1')
167
-
168
- // Approach 2 (doesn't work): using wait for xhr
169
- // cy.server()
170
- // cy.route('https://jsonplaceholder.cypress.io/users?_type=query').as('users')
171
- // cy.get('#select2-user-container').click()
172
- // cy.wait('@users')
173
- // cy.get('.select2-results__option').contains('Leanne Graham').click()
174
- // cy.get('#user').should('have.value', '1')
175
-
176
- // Approach 3: using .should to wait (works inconsistently)
177
- cy . server ( )
178
- cy . route ( 'https://jsonplaceholder.cypress.io/users*' ) . as ( 'users' )
159
+ // Select2 Ajax data fetch docs at https://select2.org/data-sources/ajax
179
160
180
- // click on the select2 container, which makes the ajax call
161
+ // NOTE: test shows what will NOT work
162
+ it . skip ( 'selects a value - WILL NOT WORK, JUST A DEMO' , ( ) => {
163
+ // clicking on the container starts Ajax call
181
164
cy . get ( '#select2-user-container' ) . click ( )
182
- cy . wait ( '@users' )
183
165
184
- // select a value
185
- cy . get ( '.select2-results__option' ) . contains ( 'Leanne Graham' ) . should ( 'be.visible' ) . click ( )
166
+ // we know the choice elements have this class
167
+ cy . get ( '.select2-results__option' )
168
+ // so let's try finding the element with the text
169
+ // WILL NOT WORK because our search is limited
170
+ // to the initial empty set of results
171
+ // from the previous ".get" command
172
+ . contains ( 'Leanne Graham' ) . click ( )
186
173
187
- // confirm the value of the selected element
174
+ // confirm the right user is found
188
175
cy . get ( '#user' ) . should ( 'have.value' , '1' )
176
+ cy . get ( '#select2-user-container' ) . should ( 'have.text' , 'Leanne Graham' )
177
+ } )
189
178
190
- // confirm Select2 widget renders the name
179
+ it ( 'selects a value by waiting for loading class to go away' , ( ) => {
180
+ // clicking on the container starts Ajax call
181
+ cy . get ( '#select2-user-container' ) . click ( )
182
+
183
+ cy . get ( '.select2-results__option' )
184
+ . should ( 'not.have.class' , 'loading-results' )
185
+ // great, now the results are shown in the DOM
186
+ . contains ( 'Leanne Graham' ) . click ( )
187
+
188
+ // confirm the right user is found
189
+ cy . get ( '#user' ) . should ( 'have.value' , '1' )
191
190
cy . get ( '#select2-user-container' ) . should ( 'have.text' , 'Leanne Graham' )
192
191
} )
193
192
194
- it ( 'selects a value by typing and selecting' , ( ) => {
195
- // https://select2.org/data-sources/ajax
193
+ it ( 'selects a value by retrying' , ( ) => {
194
+ // clicking on the container starts Ajax call
195
+ cy . get ( '#select2-user-container' ) . click ( )
196
+
197
+ // we need to retry getting the option until it is found
198
+ // then we can click it. To retry finding the element with text
199
+ // we should use https://on.cypress.io/contains
200
+ cy . contains ( '.select2-results__option' , 'Leanne Graham' ) . click ( )
201
+
202
+ // confirm the right user is found
203
+ cy . get ( '#user' ) . should ( 'have.value' , '1' )
204
+ cy . get ( '#select2-user-container' ) . should ( 'have.text' , 'Leanne Graham' )
205
+ } )
206
+
207
+ it ( 'selects a value after the list has been is populated' , ( ) => {
208
+ // clicking on the container starts Ajax call
209
+ cy . get ( '#select2-user-container' ) . click ( )
210
+
211
+ // let's wait for the list of options to be populated
212
+ // before trying to find a specific item
213
+ cy . get ( '.select2-results__option' ) . should ( 'have.length.gt' , 3 )
214
+ // and now we can find the user among the results
215
+ . contains ( 'Leanne Graham' ) . click ( )
216
+
217
+ // confirm the right user is found
218
+ cy . get ( '#user' ) . should ( 'have.value' , '1' )
219
+ cy . get ( '#select2-user-container' ) . should ( 'have.text' , 'Leanne Graham' )
220
+ } )
196
221
222
+ it ( 'selects a value after Ajax completes' , ( ) => {
223
+ cy . server ( )
224
+ cy . route ( 'https://jsonplaceholder.cypress.io/users?_type=query' ) . as ( 'users' )
225
+ cy . get ( '#select2-user-container' ) . click ( )
226
+ cy . wait ( '@users' )
227
+
228
+ // The Ajax call has completed - but that does not mean the widget
229
+ // has populated the DOM elements. Thus we need to use the same
230
+ // retry mechanism until an option with expected text exists
231
+ cy . contains ( '.select2-results__option' , 'Leanne Graham' ) . click ( )
232
+
233
+ // confirm the right user is found
234
+ cy . get ( '#user' ) . should ( 'have.value' , '1' )
235
+ cy . get ( '#select2-user-container' ) . should ( 'have.text' , 'Leanne Graham' )
236
+ } )
237
+
238
+ it ( 'selects a value by typing and selecting' , ( ) => {
197
239
cy . server ( )
198
240
cy . route ( 'https://jsonplaceholder.cypress.io/users?term=clem&_type=query&q=clem' ) . as ( 'user_search' )
199
241
@@ -204,15 +246,62 @@ describe('select2', () => {
204
246
cy . get ( 'input[aria-controls="select2-user-results"]' ) . type ( 'clem{enter}' )
205
247
cy . wait ( '@user_search' )
206
248
207
- // select a value
208
- cy . get ( '.select2-results__option' ) . contains ( 'Clementine Bauch' ) . should ( 'be.visible' ) . click ( )
249
+ // select a value, again by retrying command
250
+ // https://on.cypress.io/retry-ability
251
+ cy . contains ( '.select2-results__option' , 'Clementine Bauch' ) . should ( 'be.visible' ) . click ( )
209
252
210
253
// confirm the value of the selected element
211
254
cy . get ( '#user' ) . should ( 'have.value' , '3' )
212
255
213
256
// confirm Select2 widget renders the name
214
257
cy . get ( '#select2-user-container' ) . should ( 'have.text' , 'Clementine Bauch' )
215
258
} )
259
+
260
+ it ( 'selects the user returned by the Ajax call' , ( ) => {
261
+ // instead of hard-coding the user id and name, let's
262
+ // select the user using the Ajax response data
263
+ cy . server ( )
264
+ cy . route ( 'https://jsonplaceholder.cypress.io/users?_type=query' ) . as ( 'users' )
265
+ cy . get ( '#select2-user-container' ) . click ( )
266
+ cy . wait ( '@users' ) . its ( 'responseBody' ) . should ( 'have.length' , 10 )
267
+ // let's take user #5
268
+ . its ( '5' )
269
+ . then ( ( user ) => {
270
+ expect ( user ) . to . have . property ( 'name' )
271
+ expect ( user ) . to . have . property ( 'id' )
272
+
273
+ cy . contains ( '.select2-results__option' , user . name ) . click ( )
274
+ // the Select2 widget picks the right user
275
+ cy . get ( '#user' ) . should ( 'have.value' , user . id )
276
+ cy . get ( '#select2-user-container' ) . should ( 'have.text' , user . name )
277
+ } )
278
+ } )
279
+
280
+ it ( 'selects the user from stubbed Ajax call' , ( ) => {
281
+ cy . server ( )
282
+ // do not go to the server, mock the response instead
283
+ // but return the response after a delay
284
+ cy . route ( {
285
+ url : 'https://jsonplaceholder.cypress.io/users?_type=query' ,
286
+ response : [ {
287
+ id : 101 ,
288
+ name : 'Joe Smith' ,
289
+ } , {
290
+ id : 201 ,
291
+ name : 'Mary Jane' ,
292
+ } ] ,
293
+ delay : 2000 ,
294
+ } )
295
+
296
+ cy . get ( '#select2-user-container' ) . click ( )
297
+
298
+ // keep retrying finding the element until it is present
299
+ cy . contains ( '.select2-results__option' , 'Mary Jane' , { timeout : 2500 } ) . click ( )
300
+
301
+ // confirm the user was selected
302
+ cy . get ( '#user' ) . should ( 'have.value' , 201 )
303
+ cy . get ( '#select2-user-container' ) . should ( 'have.text' , 'Mary Jane' )
304
+ } )
216
305
} )
217
306
218
307
context ( 'programmatic control' , ( ) => {
0 commit comments