How to test a React application index.js


index.js keeps failing in my test coverage report

When we start a project with Create React App and set test coverage thresholds, index.js file becomes a problem since it prevents us from hitting the configured thresholds.

We can solve this by writing the following test for index.js and get 100% test coverage on it.

// index.test.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';

// mocks react-dom and its render method
// so that we can assert that render is
// called with <App /> and HTML element with id = root
jest.mock('react-dom', () => ({ render: jest.fn() }));

test('renders with App and root div', () => {
  // Create and append to document body
  // an HTML element with id = root
  const root = document.createElement('div');
  root.id = 'root';
  document.body.appendChild(root);

  // Requires index.js so that react-dom render method is called
  require('./index.js');

  // Asserts render was called with <App />
  // and HTML element with id = root
  expect(ReactDOM.render).toHaveBeenCalledWith(<App />, root);
});
// index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

ReactDOM.render(<App />, document.getElementById('root'));

However, an important question to ask before we write a test is "What are we trying to achieve with this test?".

When we write tests, we should write them with a clear vision of their goals, and not just for the sake of test coverage.

The code above tests that index.js does what we expect of it. But it doesn't test that the application starts, and maybe that's what we want to check.

To test that the application starts without problems, we can write an E2E test that asserts an element of the home page is rendered. We can use a tool like Cypress for that.

Writing the E2E test and a test specifically for index.js are not mutually exclusive approaches, and we should do both if that gives us more confidence that our application is working correctly. But I'd argue that since an E2E test covers 100% of index.js and since index.js is easy to understand, that writing a test just for it ends up being redundant.

If you end up going with only doing the E2E test, you'll need to remove index.js from the test coverage report. Otherwise, you won't meet the test coverage threshold. To do that, add the option below to package.json.

"jest": {
"collectCoverageFrom": [
    "src/**/*.{js,jsx,ts,tsx}",
    "!src/index.js"
  ],
  ...
}

Put it into practice

  1. Define what you want to test.
  2. If it is that the application starts, write an E2E test, and remove index.js from the test coverage.
  3. If it is that index.js does what is expected, write a targeted test like the one shown in this article.
  4. If you want to test both, write the E2E test and the targeted index.js test.