-1

I'm attempting to select an item which renders a drop-down list of items that match a search.

I select the correct item once the drop-down list has been opened. The id values changes so they cannot be used.

This is the script in Cypress:

cy.get('input[placeholder="Search Something"]').type('Your search query').type('{enter}');
cy.contains('div span', 'XXXXX XXX').click();

or 

cy.get('div[role="listbox"]')
  .contains('span', 'XXX XXX')
  .should('exist')
  .click();

Below is the inspection from the page:

<div 
  class="w-full" 
  id="headlessui-combobox-button-137" 
  tabindex="-1" 
  aria-haspopup="listbox" 
  aria-expanded="true" 
  data-headlessui-state="open" 
  aria-controls="headlessui-combobox-options-139"
>
    <input 
      placeholder="Search Subscribers"  
      class="w-full inputFocus px-4 rounded-3xl text-ever-green  font-beatrice font-normal transition-colors focus:border-cornflower-blue focus:outline-none outline-none placeholder:text-slate-gray h-smButtonHeight text-sm border-2 border-duck-egg-blue"  
      id="headlessui-combobox-input-138"  
      role="combobox"  
      type="text"  
      aria-expanded="true"  
      aria-autocomplete="list"  
      data-headlessui-state="open"  
      value="Prod"  
      aria-controls="headlessui-combobox-options-139"  
      aria-activedescendant="headlessui-combobox-option-156"
    >
</div>

Below is the extract from the page the drop down:

<div 
  class="absolute z-10 w-full mt-2 overflow-auto text-base bg-white rounded-md shadow-dropdown max-h-60 focus:outline-none sm:text-sm left-0 right-0 mx-auto p-0"  
  aria-labelledby="headlessui-combobox-button-137"  
  role="listbox"  
  aria-multiselectable="true"  
  id="headlessui-combobox-options-139"  
  data-headlessui-state="open"
>
    <div  
      class="relative h-full max-h-60 p-2 overflow-y-auto"   
      role="none"
    >
        <div   
          class="relative"    
          style="height: 32px;"    
          role="none"   
        >   
        <div    
          class="absolute top-0 left-0 w-full"     
          id="headlessui-combobox-option-156"     
          role="option"     
          tabindex="-1"     
          aria-selected="true"     
          data-headlessui-state="active selected"     
          style="transform: translateY(0px);"    
        >    
          <span     
            class="cursor-pointer flex items-center gap-x-2 py-1.5 px-4.5 font-medium text-sm transition-colors lg:truncate text-cornflower-blue bg-ice-blue"   
          >   
              <span    
                class="w-1/2 xl:w-1/3 inline-block text-xs">+1 251 230 8828   
              </span>   
              <span    
                class="w-1/2 xl:w-1/3 inline-block text-xs"   
              >   
                  <div class="text-ever-green">Prod 701</div>
              </span>
              <span class="w-1/3 hidden xl:inline-block text-xs"> 
                  <div> 

Any solutions welcomed.

Lola Ichingbola
  • 3,035
  • 3
  • 16
Nobody
  • 549
  • 1
  • 10
  • 24
  • To clarify, are you having issues with 1) selecting the item which then renders the drop-down list, or 2) selecting an item once the drop-down list has been opened? – Stitt Jun 12 '23 at 11:03
  • 2. selecting an item once the drop-down list has been opened? – Nobody Jun 12 '23 at 11:36
  • I haven't used this on a span with role=option, but have you tried to use cy.select()? https://docs.cypress.io/api/commands/select – agoff Jun 12 '23 at 13:54

2 Answers2

2

This is a HeadlessUi component that constructs components from divs, as shown in the code sample.

Avoiding changing ids
To access the parts needed for testing, you can use [role="listbox"] and [role="option"], which would be the equivalent to <select> and <option> in plain HTML5.

Using the correct command sequence
The relationship between listbox and options is parent-child, so instead of get().contains() I recommend get().find().

The way you have done it, the "subject" (the queried element) is the listbox instead of the option, and click the parent listbox doesn't make an option selection.

cy.get('[role="listbox"]')
  .find('[role="option"]:contains("XXX XXX")')  // be careful with brackets and quote marks
  .click();
Lola Ichingbola
  • 3,035
  • 3
  • 16
0

Here is a function which I have adapted from my own for Mantine dropdown boxes. It should be able to be called simply as a function within your test specs.

Cypress.Commands.add('selecter', (selectSelector, value) => {
  cy.get(selectSelector).scrollIntoView();
  cy.get(selectSelector).click({ force: true });

  const options = () =>
    cy.get('listbox').find('option');
  if (typeof value === 'string') {
    // If the given value is a string, select the option with that label
    return options()
      .contains(value, { matchCase: false })
      .click({ force: true });
  }
  if (typeof value === 'number') {
    // Else if it's a number, select the option at that index
    return options()
      .eq(value)
      .click({ force: true });
  }
  throw new Error(
    `value should be a string or number, but was '${value}' (${typeof value}).`,
  );
});
Stitt
  • 406
  • 2
  • 8