reactjsjestjsreact-domtesting-library

Why we have to use toBeInTheDocument in Testing Library


On the Testing Library documentation on some pages appears this example using screen.getByText:

  expect(screen.getByText(/you are home/i)).toBeInTheDocument()

Link

My question is how is this different from this:

  screen.getByText(/you are home/i)

Why the documentation is using .toBeInTheDocument() when screen.getByText is doing the same (throws an error when "you are home" text is not in the document)? is it not redundant?.


Solution

  • It's not necessary, but some people think it helps communicate intention more clearly.


    From the blog post Common mistakes with React Testing Library (written by Kent, the original contributor):

    Using get* variants as assertions

    Importance: low

    // ❌
    screen.getByRole('alert', {name: /error/i})
    
    // ✅
    expect(screen.getByRole('alert', {name: /error/i})).toBeInTheDocument()
    

    This one's not really a big deal actually, but I thought I'd mention it and give my opinion on it. If get* queries are unsuccessful in finding the element, they'll throw a really helpful error message that shows you the full DOM structure (with syntax highlighting) which will help you during debugging. Because of this, the assertion could never possibly fail (because the query will throw before the assertion has a chance to).

    For this reason, many people skip the assertion. This really is fine honestly, but I personally normally keep the assertion in there just to communicate to readers of the code that it's not just an old query hanging around after a refactor but that I'm explicitly asserting that it exists.

    Advice: If you want to assert that something exists, make that assertion explicit.