Jeff
Jeff

Reputation: 1879

Cypress or Puppeteer: How to test page with a react select popup/popover?

Request: Either with Cypress (preferably) or using extending Cypress with Puppeteer via cy.task(), being able to perform a test on a system-generated popup menu?

This popup menu element cannot be inspected by Chrome Devtools and is thereby not navigatable by either CSS selectors or XPath.

Details: I am using Cypress for UX testing and extend in limited cases with custom cy.task() with Puppeteer.

The web page under test has a dropdown selection that generates a popup menu, source is this npm module: npm react-select-async-paginate

popup menu

Under inspections, the popup menu is generated from an and it has these two attributes:

 element generating popup

Appreciate assistance, thank you


22 Feb, Updated

This is the generated react-select-async-paginate:

<div>
  <div class="***-singleValue">Offer Letter w/ Signature</div>
  <div class=" css-ackcql" data-value="">
    <input 
        id="react-select-2-input" 
        aria-autocomplete="list" 
        aria-expanded="false" 
        aria-haspopup="true"
        aria-controls="react-select-2-listbox" 
        aria-owns="react-select-2-listbox" 
        role="combobox">
  </div>
</div>

This is the attempt for selecting an option, but it does not loads selected option into <div class="***-singleValue">.

This Cypress script selects an option:

  cy.get(`${selectorReactSelectPaginate}`)
    .find('input[role="combobox"]')
    .focus()
    .type($valueSelect, { force: true })
    .then(() => {
      cy.wrap(true);
    });

As would able to validated using this Cypress script:

  cy.get(selectorReactSelectPaginate)
    .find('div[class*="-singleValue"]')
    .contains($valueSelectContains)
    .then(() => {
      cy.wrap(true);
    });

Upvotes: 4

Views: 1763

Answers (2)

Fody
Fody

Reputation: 32034

Yes, the option list is tricky to get at in devtools because of the blur event (which comes from the library itself). One approach is open devtools and watch carefully as you click open the select.

Using react-select-async-paginate - Simple Example, when I click open the select I can see this div appearing and disappearing

<div id="react-select-2-listbox">

So I can use Cypress to get a look inside that

cy.get('[role="combobox"]').click()

cy.get('#react-select-2-listbox')
  .then($listbox => {
    console.log($listbox)
  })

Now in devtools console, check out children property (has one child), then the child's children - these look like the options to be tested.

The common selector is an id starting with react-select-2-option, so I can test like so

cy.get('[role="combobox"]').click()

cy.get('#react-select-2-listbox')
  .find('[id^="react-select-2-option"]')   // all div's with id starting react-select-2-option
  .should('have.length', 10)
  .eq(3)                      // check out the 4th option
  .invoke('text')
  .should('eq', 'Option 4')   // passes

Selecting an option by typing into the box

Two things affect this method of selecting

  • the dropdown list changes (reloads) as you type characters
  • the element 'div[class*="-singleValue"]' only appears after you confirm the typed value (either enter key or blur(), I'm not sure which).

This worked for me

// Type in the option
cy.get(selectorReactSelectPaginate)
  .find('[role="combobox"]')
  .type(valueToSelect)

// Wait for the listbox to respond
cy.get('#react-select-2-listbox')
  .should('contain', valueToSelect)  

// Blur or enter will set the value
cy.get(selectorReactSelectPaginate)
  .find('[role="combobox"]')
  .type('{enter}')
  .blur()

// Check the value
cy.get(selectorReactSelectPaginate)
  .find('div[class*="-singleValue"]')
  .should('contain', valueToSelect)

Upvotes: 4

jjhelguero
jjhelguero

Reputation: 2555

A neat trick with test runner is to add a .wait() after the dropdown selection appears. A snapshot of the DOM will be created and you can click on the .wait() to view the snapshot and use dev tools to inspect the dropdown selection.

Upvotes: 2

Related Questions