@@ -156,44 +156,86 @@ describe('select2', () => {
156156 } )
157157
158158 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
179160
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
181164 cy . get ( '#select2-user-container' ) . click ( )
182- cy . wait ( '@users' )
183165
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 ( )
186173
187- // confirm the value of the selected element
174+ // confirm the right user is found
188175 cy . get ( '#user' ) . should ( 'have.value' , '1' )
176+ cy . get ( '#select2-user-container' ) . should ( 'have.text' , 'Leanne Graham' )
177+ } )
189178
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' )
191190 cy . get ( '#select2-user-container' ) . should ( 'have.text' , 'Leanne Graham' )
192191 } )
193192
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+ } )
196221
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' , ( ) => {
197239 cy . server ( )
198240 cy . route ( 'https://jsonplaceholder.cypress.io/users?term=clem&_type=query&q=clem' ) . as ( 'user_search' )
199241
@@ -204,15 +246,62 @@ describe('select2', () => {
204246 cy . get ( 'input[aria-controls="select2-user-results"]' ) . type ( 'clem{enter}' )
205247 cy . wait ( '@user_search' )
206248
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 ( )
209252
210253 // confirm the value of the selected element
211254 cy . get ( '#user' ) . should ( 'have.value' , '3' )
212255
213256 // confirm Select2 widget renders the name
214257 cy . get ( '#select2-user-container' ) . should ( 'have.text' , 'Clementine Bauch' )
215258 } )
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+ } )
216305 } )
217306
218307 context ( 'programmatic control' , ( ) => {
0 commit comments