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 153 forks source link

Queries match elements inside the <head /> part of the document #134

Open gnapse opened 4 years ago

gnapse commented 4 years ago

Relevant code or config

<html>
  <head>
    <title>Hello world</title>
  </head>
  <body>
    <h1>Hello world</h1>
  </body>
</html>
cy.findByText('Hello world')

What you did

Find an element by its text content.

What happened

Since the document title element in the head area also matches, the query tells me that it found more than one element with the expected text content.

Problem description

The queries are using the entire document as the container.

Suggested solution

Maybe the queries should use the body as the container. Elements in the head area cannot be interacted with and are generally not visible to the user. Except maybe for the title, but there should be more declarative ways to check for it than findByText.

pranjaljately commented 4 years ago

Hi @gnapse

As far as I know, to only find the h1 in the body, you could do something like: cy.findByText(/hello world/i, { selector: 'h1' }).should('exist'); (The second param, 'options', is what's important here)

However, this kinda becomes testing implementation details because if you were to change the <h1> tag to a <h2> tag, your test would fail (which we would not want).

Maybe @kentcdodds has a better suggestion 😅...

Thanks, Pranjal

kentcdodds commented 4 years ago

Thanks @pranjaljately!

This would be best:

cy.findByRole('heading', {name: /hello world/i }).should('exist')

That would work regardless of the level of heading. It's also more semantically correct 🤘

kentcdodds commented 4 years ago

As for the assertion that queries should be scoped to the body, I'm curious how Cypress does this... I'm pretty sure they scope to the whole document.

pranjaljately commented 4 years ago

Awesome! Just learnt something new 😁

Thanks, @kentcdodds

gnapse commented 4 years ago

Indeed, the findByRole is the best approach, and a natural workaround. I started using it almost exclusively recently, after I filed this issue.

However, I'd still argue the issue remains, as the other queries are still valid queries, and a findByText(...) when a role query is not possible will still possibly yield the page title as a false positive.

kentcdodds commented 4 years ago

Well... Maybe we should do this then: https://github.com/testing-library/dom-testing-library/issues/593