Why does Cypress not recognise the testid of a react-datepicker element?

3.8k views Asked by At

Target

To make Cypress recognise and manipulate a DatePicker element.

Problem

I cannot make Cypress recognise the data-testid of a DatePicker element, and so have no way of testing it E2E.

Error

Timed out retrying: Expected to find element: [data-testid="edit_dob"], but never found it.

Attempts

I have tried placing the DatePicker element inside input and div elements to target instead, but they fail as expected for other reasons.

I have also looked through the docs for both DatePicker and Cypress for mention of the other, and for similar questions here.

Code

The code below works as expected, it's just Cypress that seems to be incompatible with the DatePicker input.

  function displayEditDetails() {
    let listOfForms = [];
    for (const detail in details) {
        listOfForms.push(
          <FormGroup controlId={detail} key={`key_edit_${detail}`}>
            <FormLabel>{detail.charAt(0).toUpperCase() + detail.slice(1).replace('_', ' ')}</FormLabel>
            <FormControl
              data-testid={`edit_${detail}`}
              type={detail}
              value={details[detail] || ''}
              onChange={handleDetailsChange}
            />
          </FormGroup>
        )
    }
    listOfForms.push(
      <DatePicker
        data-testid={'edit_dob'}
        selected={dob}
        onChange={setDob}
        maxDate={new Date()}
      />
    );
    return(
      listOfForms
    )
  }

Test

  it('Displays the edit fields', () => {
    cy.get('[data-testid="accountButton"]')
      .click();

    cy.get('[data-testid="editUserDetailsButton"]')
      .click();

    cy.get('[data-testid="user_email"]')
      .should('not.be.visible');

    cy.get('[data-testid="edit_full_name"]')
      .should('be.visible');

    cy.get('[data-testid="edit_dob"]')
      .should('be.visible');

    cy.get('[data-testid="edit_email"]')
      .should('be.visible')
      .should('have.value', '[email protected]');
  })

Once I can target it, I plan to test clearing the current input and typing a new date in. Any help targeting the picker and warnings of further potential pitfalls are appreciated.

Edit: Here's the generated HTML of the form.

<form>
  <div class="form-group">
    <label class="form-label" for="email">Email</label>
    <input data-testid="edit_email" type="email" id="email" class="form-control" value="[email protected]" style="background-image: url(&quot;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABHklEQVQ4EaVTO26DQBD1ohQWaS2lg9JybZ+AK7hNwx2oIoVf4UPQ0Lj1FdKktevIpel8AKNUkDcWMxpgSaIEaTVv3sx7uztiTdu2s/98DywOw3Dued4Who/M2aIx5lZV1aEsy0+qiwHELyi+Ytl0PQ69SxAxkWIA4RMRTdNsKE59juMcuZd6xIAFeZ6fGCdJ8kY4y7KAuTRNGd7jyEBXsdOPE3a0QGPsniOnnYMO67LgSQN9T41F2QGrQRRFCwyzoIF2qyBuKKbcOgPXdVeY9rMWgNsjf9ccYesJhk3f5dYT1HX9gR0LLQR30TnjkUEcx2uIuS4RnI+aj6sJR0AM8AaumPaM/rRehyWhXqbFAA9kh3/8/NvHxAYGAsZ/il8IalkCLBfNVAAAAABJRU5ErkJggg==&quot;); background-repeat: no-repeat; background-attachment: scroll; background-size: 16px 18px; background-position: 98% 50%; cursor: auto;">
  </div>

  <div class="form-group">
    <label class="form-label" for="full_name">Full name</label>
    <input data-testid="edit_full_name" type="full_name" id="full_name" class="form-control" value="Jareth">
  </div>

  <div class="form-group">
    <label class="form-label" for="address">Address</label>
    <input data-testid="edit_address" type="address" id="address" class="form-control" value="">
  </div>

  <div class="form-group">
    <label class="form-label" for="postcode">Postcode</label>
    <input data-testid="edit_postcode" type="postcode" id="postcode" class="form-control" value="">
  </div>

  <div data-testid="edit_dob">
    <div class="react-datepicker-wrapper">
      <div class="react-datepicker__input-container">
        <input type="text" class="" value="04/03/1999">
      </div>
    </div>
  </div>

  <button data-testid="confirmChangesButton" type="submit" class="LoaderButton  btn btn-primary btn-block">Confirm Changes</button></form>
2

There are 2 answers

0
Jules On BEST ANSWER

The problem is visible when looking at the HTML generated by running the app.

DatePicker HTML

  <div data-testid="edit_dob">
    <div class="react-datepicker-wrapper">
      <div class="react-datepicker__input-container">
        <input type="text" class="" value="04/03/1999">
      </div>
    </div>
  </div>

The DatePicker is rendered as an input element inside a few divs, and the test id doesn't target the input.

Solution

The Selector Playground API for Cypress suggests cy.get('.react-datepicker__input-container > input'), the class of the parent div of the input. With this I can target the DatePicker, clear it, and type new input.

Notes For Next Time

  1. Examine the HTML
  2. Read the Docs more thoroughly
0
Kevin Old On

Reference the concepts used in the cy.pickDateRange command in the Cypress Real World App. It is a payment application to demonstrate real-world usage of Cypress testing methods, patterns, and workflows.

In the code for the command, you will find it is necessary to examine the HTML produced and traverse it appropriately for your needs.