Best way to test a text in a div or p tag in react-testing-library

What is the best way to test a text in a div or a p tag in react-testing-library ?

Let's pretend that we have a react component as such :

const Greeting = ({name}) => {
  return <div>Hello {name}!</div>
}

What would be the best way to test that the component renders the expected value, would it be using toBeInTheDocument() :

import {render, screen} from '@testing-library/react'
import Greeting from './greeting'

test('it renders the given name in the greeting', () => {
  render(<Greeting name="John Doe"/>)
  expect(screen.getByText(`Welcome John Doe!`)).toBeInTheDocument()
})

or using toBeVisible()

import {render, screen} from '@testing-library/react'
import Greeting from './greeting'

test('it renders the given name in the greeting', () => {
  render(<Greeting name="John Doe"/>)
  expect(screen.getByText(`Welcome John Doe!`)).toBeVisible()
})

or neither:

import {render, screen} from '@testing-library/react'
import Greeting from './greeting'

test('it renders the given name in the greeting', () => {
  render(<Greeting name="John Doe"/>)
  screen.getByText(`Welcome John Doe!`)
})

The last one makes more sense to me as if 'Welcome John Doe!' is not on the page, it will immediately fail whereas if it is on the page, the two first propositions would be equivalent to: expect(true).toBe(true)

am I missing something here?


The difference between .toBeInTheDocument() and .toBeVisible() are explained clearly in the doc.

In short: An element can be present in the document but not visible to the user.

E.g.

import { render, screen } from '@testing-library/react';
import React from 'react';
import '@testing-library/jest-dom/extend-expect';

function Test() {
  return <div style={{ display: 'none' }}>test</div>;
}

describe('toBeVisible-VS-toBeInDocument', () => {
  test('should pass', () => {
    render(<Test />);
    expect(screen.getByText(/test/)).not.toBeVisible();
    expect(screen.getByText(/test/)).toBeInTheDocument();
  });
});

Test result:

 PASS  examples/toBeVisible-VS-toBeInDocument/index.test.tsx (8.595 s)
  toBeVisible-VS-toBeInDocument
    ✓ should pass (49 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        9.099 s, estimated 10 s

get* or query*?

The only reason the query* variant of the queries is exposed is for you to have a function you can call which does not throw an error if no element is found to match the query (it returns null if no element is found). The only reason this is useful is to verify that an element is not rendered to the page. The reason this is so important is because the get* and find* variants will throw an extremely helpful error if no element is found–it prints out the whole document so you can see what's rendered and maybe why your query failed to find what you were looking for. Whereas query* will only return null and the best toBeInTheDocument can do is say: "null isn't in the document" which is not very helpful.

In short: Only use the query* variants for asserting that an element cannot be found.

get* query is the best way to check if an element is present in the document.

From the Using get* variants as assertions post.

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

Aside from the point in the article, I think it would be much more readable.

So:

// You can do this
screen.getByText(`Welcome John Doe!`);

// better, much more readable
expect(screen.getByText(`Welcome John Doe!`)).toBeInTheDocument();