0

I generated a project using create-react-app with the --typescript option.

This is my app:

import React from 'react';

const App: React.FC = () => {
  return (
    <div className="App">
        <div>
            <h1 id="pageHeader">Home page</h1>
            <p>This is the Home page</p>
        </div>
    </div>
  );
};

export default App;

My current test is:

import React from 'react';
import ReactDOM from 'react-dom';
import {render} from '@testing-library/react';
import "@testing-library/jest-dom/extend-expect";
import App from './App';

test('Verify page header', () => {
    const {getByText} = render(<App/>);
    expect(getByText('Home page')).toBeInTheDocument;
});

The question: I want to test a little more. Besides testing if "Home page" occurs anywhere in my page, I want to make sure that the text "Home Page" is located in the h1 element. How do I get the full element (preferably via getElementById) from the react-testing-library so I can do assertions on it with Jest?

2 Answers 2

2

A couple of points, based on your own answer:

  1. You should avoid any logic branches in tests. Logic in tests can lead to flaky tests, since the logic in the test isn't tested. In your case, the if blocks are unnecessary, since the test will already fail if the text content doesn't exist.

  2. There are a couple of simple ways to test that the text "Home Page" is in the h1:

Find the text and expect the element to be h1:

test('Verify page header', () => {
    const {getByText} = render(<App/>);
    expect(getByText('Home page').tagName).toBe('H1');
});

Or give the h1 a data-testid and use getByTestId:

<h1 data-testid="pageHeader">Home Page</h1> // <-- In your component

test('Verify page header', () => {
    const {getByTestId} = render(<App/>);
    expect(getByTestId('pageHeader').textContent).toBe('Home Page');
});
Sign up to request clarification or add additional context in comments.

2 Comments

Do you know why there is a method for getByTestId but not for getById? I was looking on the internet for a reason but I don't understand why we simply can't use the id. Adding data-testid's to code just for tests feels weird.
I don't have a great explanation for you, but the react-testing-library author has some thoughts about using id vs data-testid in this thread: github.com/testing-library/react-testing-library/issues/183 He also links to a blog article: kentcdodds.com/blog/making-your-ui-tests-resilient-to-change
0

I managed to solve it like this:

test('Verify page header', () => {
    const {container} = render(<App/>);
    const pageHeaderElement = container.querySelector('#pageHeader');
    if (pageHeaderElement) {
        const pageHeaderElementContent = pageHeaderElement.firstChild;
        if (pageHeaderElementContent) {
            // You can either do:
            expect(pageHeaderElementContent.textContent).toMatch('Home page');
            // Or:
            expect(pageHeaderElementContent).toMatchInlineSnapshot('Home page');
        } else {
            fail('Should have existed.');
        }
    } else {
        fail('Should have existed.');
    }
});

I found out about this toMatchInlineSnapshot method in the documentation of react-testing library: https://testing-library.com/docs/react-testing-library/api#render

Shorter version with the new TypeScript optional chaining:

test('Verify page header', () => {
    const {container} = render(<App/>);
    const pageHeaderContent = container.querySelector("#pageHeader")?.firstChild?.textContent;
    expect(pageHeaderContent).toMatch('Home page');
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.