testing-library / cypress-testing-library

🐅 Simple and complete custom Cypress commands and utilities that encourage good testing practices.
http://npm.im/@testing-library/cypress
MIT License
1.8k stars 152 forks source link

findByRole and findAllByRole only work globally #203

Open steve-taylor opened 3 years ago

steve-taylor commented 3 years ago

Relevant code or config

cypress/support/commands.js

import '@testing-library/cypress/add-commands'

cypress.json:

{
  "component": {
    "testFiles": "**/*.test.{ts,tsx}",
    "componentFolder": "."
  },
  "viewportWidth": 960,
  "viewportHeight": 640,
  "video": false,
  "screenshotOnRunFailure": false
}

What you did:

const practiceSelector = cy.findByTestId('PracticeSelector')

practiceSelector.findByText('Option 1').should('exist')
practiceSelector.click()

// At this point, the practice selector has opened and the DOM structure is the same as shown below.

// This fails with a timeout error despite the <ul role="listbox"> element being visible.
const listBox = practiceSelector.findByRole('listbox')
<!-- class and style attributes have been removed -->
<div data-testid="PracticeSelector">
  <button aria-label="Select an option" aria-haspopup="listbox">
    <div>
      <svg aria-visible="false">
        <!-- Omitted -->
      </svg>
      <span>Option 1</span>
    </div>
    <svg aria-hidden="true">
        <!-- Omitted -->
    </svg>
  </button>
  <div>
    <div>
      <div>
        <div>
          <ul role="listbox">
            <li role="option" aria-selected="false">
              <button>
                <div>
                  Option 1<svg aria-label="Selected"><!-- Omitted --></svg>
                </div>
              </button>
            </li>
            <li role="option" aria-selected="false">
              <button>
                <div>
                    Option 2
                </div>
              </button>
            </li>
            <li role="option" aria-selected="true">
              <button>
                <div>
                  Option 3
                </div>
              </button>
            </li>
            <li role="option" aria-selected="true">
              <button>
                <div>
                  Option 4
                </div>
              </button>
            </li>
          </ul>
        </div>
        <div></div>
      </div>
    </div>
  </div>
</div>

What happened:

image

Reproduction repository:

(Will create one if this is a bug.)

Problem description:

practiceSelector.findByRole('listbox') should find the <ul role="listbox"> element, because it's inside the practiceSelector element. However, it's timing out.

Additionally, practiceSelector.findAllByRole('option') times out.

However, cy.findByRole('listbox') and cy.findAllByRole('option') both work.

Suggested solution:

Use cy.findByRole and cy.findAllByRole as workarounds in the short term.

psacawa commented 3 years ago

I've replicated this with

it("login", () => {
  cy.visit("/login/")
    .findByLabelText(/Email Address/i)
    .type(myEmail);
})

cypress.json

{
  "baseUrl": "http://localhost:3000",
  "video": false,
  "screenshotOnRunFailure": false,
  "env": {
    "FAIL_FAST_ENABLED": true
  }
}