Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

select react-select dropdown list option using cypress

Tags:

Does anyone know how to select an option from a react-select dropdown list in a cypress test?

I have tried lots of stuff but to no avail.

Seems that react-select uses a hidden input. That cypress can not write into. And divs that cypress can also not write into either.

It also does not help that I do not know how to inspect the actual dropdown list in dev tools because it does not stay open.

I am using:

  • react-select v2.4.1
  • cypress v3.1.5

Edit 1:

@bkucera's answer works. The working Code I ended up was:

it('updates Person', () => {     cy.get('[data-id=bearbeiter]')       .find('.css-10nd86i')       .click()       .find('input')       .eq(1)       .focus()     cy.contains('Test Tester').click({ force: true })   }) 

I had to add an .eq(1) after find because there seem to be two inputs.

Edit 2:

Above solution ended up clicking on elements in the nav tree on my site that happened to contain the same text. So no cigar :-(

Edit 3:

I have also tried this solution:

Cypress.Commands.add('setSelectOption', ({ selector, option, value }) => {   cy.get(selector)     .find('.css-10nd86i input')     .eq(1)     .focus()     .type(value, { force: true }) }) 

...but even though force: true is used I get this error:

The element typed into was:    > <input name="aeId" type="hidden" value="862333db-31cf-444c-b8ea-021c640c7a44">  Cypress considers the 'body', 'textarea', any 'element' with a 'tabindex' or 'contenteditable' attribute, or any 'input' with a 'type' attribute of 'text', 'password', 'email', 'number', 'date', 'week', 'month', 'time', 'datetime', 'datetime-local', 'search', 'url', or 'tel' to be valid typeable elements. 

Edit 4:

So far this has worked best:

Cypress.Commands.add('setSelectOption', ({ selector, option, value }) => {   cy.get(selector)     .find('.css-10nd86i input:text')     .focus()     .type(option, { force: true, delay: 600, timeout: 330000 })     .type('{enter}', { force: true })   cy.get(selector)     .find('.css-10nd86i')     .find('input')     .eq(1)     .should('have.value', value) }) 

At least it works for short lists. Text is entered slowly. For our species list (7000 long) I added those delay and timeout options. Delay seems to help but I have not been able to understand exactly how these options influence behaviour. And sometimes cypress times out :-(

Edit 5:

Meanwhile (react-select v3.0.4, cypress v3.3.2) all tests fail because:

Expected to find element '.css-10nd86i' but never found it 

I guess the class has changed. Not surprising with such a brittle solution :-(

like image 228
Alex Avatar asked Mar 07 '19 14:03

Alex


People also ask

How do I select a drop down in react?

To create a dropdown select in React, use the react-select library. The react-select library has features dynamic search/filter, async option loading, accessibility, and fast render times. In addition, it has a flexible and beautiful Select Input control for ReactJS with multi-select, autocomplete, and ajax support.


2 Answers

On Cypress 4.2.0 and react-select 3.0.8 pressing enter twice is working for me:

cy.get('#react-select-component-id').type('Something{enter}{enter}'); 
like image 51
Mark Jackson Avatar answered Oct 28 '22 03:10

Mark Jackson


Unfortunately, you are running into two Cypress bugs, which are fixed in pending releases

  • 1) an input that already has focus is being validated before .type, which is wrong

  • 2) when the browser is out of focus chrome does not fire blur/focus events, which react-select relies on. Due to this bug, you won't see the dropdown appear when the chrome window is not focused.
    The next version of Cypress will polyfill these events, fixing this problem.

    workarounds:

    for 1) you'll have to use {force:true} during the .type (see below)

    for 2) you can either make sure to have the window focused when running the test, or see the workaround in the code below

it('react-select', () => {   cy.visit('https://react-select.com/creatable')   cy.get('.css-10nd86i input').eq(1) // get the first react-select input     .focus() // workaround for bug #2     .type('Ocean', {force:true}) // workaround for bug #1 }) 

another example:

it('react-select', () => {   cy.visit('https://react-select.com/creatable')   cy.get('.css-10nd86i').eq(1)     .click() // click on the react-select div     .find('input').focus() // workaround for bug #2   cy.contains('Ocean').click({force:true}) // workaround for bug #1   // Other actions to take 👇   // cy.focused().type('{downarrow}{enter}', {force:true})    // cy.focused().type('{enter}', {force:true})   // cy.focused().type('Ocean', {force:true}) }) 
like image 35
bkucera Avatar answered Oct 28 '22 02:10

bkucera