2
votes

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
Can you share the generated HTML that's being targeted please?Old Schooled
Posting the HTML got me on the right track. I've just found out about the Selector Playground and it's working as intended.Jules

2 Answers

1
votes

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
votes

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.