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 with name matching isn't working properly for elements added to the DOM #205

Open jgoux opened 2 years ago

jgoux commented 2 years ago

Hello,

I think there is a race condition / an issue with matching the name of elements that are mount to the DOM during the test. I use findByRole along with its name option heavily in all my tests, but I have this one case where it doesn't seem to be able to match the element by name (a toaster with aria-role="status"). It does match the element on its role, because chaining with contains() makes the test pass.

Relevant code or config

// submit project
      cy.intercept("POST", "/api/graphql", (req) => {
        aliasMutation(req, "createProject");
      });

      cy.findByRole("button", { name: /create new project/i }).click();

      cy.wait("@createProject");

      // toast feedback that appears on the DOM once the createProject response is received
      cy.findByRole("status", { name: /Your project has been created/i })
        .should("exist");

      // this version is working!
      // cy.findByRole("status")
      //   .contains("Your project has been created")
      //   .should("exist");

What you did: I run the above test

What happened: The cy.findByRole("status", { name: /Your project has been created/i }) .should("exist"); fail with a timeout because the name part is never found.

Reproduction repository:

Problem description:

Suggested solution:

EDIT : It seems that something seriously broke cypress-testing-library when bumping to the v8 of testing-library-dom.

I just downgraded to v7.0.7 and all my tests are back to normal.

I'm not sure what changed in v8 but every findBy* selectors seem to enter in conflict with cypress runtime. This is why for example in the above code snippet, I had to intercept a query and wait for its result before I could call testing-library selector. If I don't, both the http query and the selector and called and stuck forever until the timeout kicks in.

RandomDude123 commented 2 years ago

Experiencing similar issues with findByRole and a Dialog that gets added to the Dom while loading the page.

  1. get('#uc-btn-accept-banner') βœ…
  2. findByText(/^accept$/i, { role: 'button' }) βœ…
  3. findByRole('button', { name: /^accept$/i }) ❌

After adding hidden to 3. findByRole('button', { name: /^accept$/i, hidden: true }) as suggested by the error log i get the following error:

Timed out retrying after 4000ms: Unable to find an element with the role "button" and name /^accept$/i

There are no available roles.

Ignored nodes: comments, <script />, <style />
<button
  aria-label="Accept"
  class="uc-btn-new  uc-btn-accept"
  id="uc-btn-accept-banner"
>
  Accept

  <span
    id="uc-optin-timer-display"
  />
</button>

...
alex1701c commented 1 year ago

findByText(/^accept$/i, { role: 'button' }) βœ…

I get typescript errors about the key not existing and it does not work as expected. If there was a span inside of the button, the span would be yielded instead of the button.

selrond commented 7 months ago

Just ran into this β€” surprised this doesn’t get more attention

mkoterba-agorapulse commented 4 months ago

hello, same here with the following configuration

"cypress": "^13.6.6",
"@testing-library/cypress": "10.0.1",

The code in the test:

cy.wrap(element)
    .trigger('mouseenter')
        .within(() => cy.findByRole('button', { name: 'container '}).click());
// etc.

In our case, the button appear after a mouseover (we use cypress trigger('mouseenter') function in the test)

any update on this issue ?