Home > Back-end >  How to remove cleanup in Jest
How to remove cleanup in Jest

Time:10-02

I'd like to write unit tests and make them really small. But I have a problem. React testing library unmounts root component every time test passes. So, I can do this

describe('Some test', () => {
  const { rerender } = render(<Component prop1={0} />);

  test('Title 1', () => {
    // logic1
  });

  test('Title 2', () => {
    rerender(<Component prop1={0} />);
    // logic2
  });

  test('Title 3', () => {
    rerender(<Component prop1={1} />);
    // logic3
  });

  test('Title 4', () => {
    rerender(null);
    // logic4
  });
});

I'd like to call rerender function in each test and then add a specific logic for each test. But I'm getting an error Error: Cannot update an unmounted root. from the 2nd test onwards.

I can write my test in this way

test('Some test', () => {
  const { rerender } = render(<Component prop1={0} />);

  // logic1

  rerender(<Component prop1={0} />);
  // logic2

  rerender(<Component prop1={1} />);
  // logic3

  rerender(null);
  // logic4
});

But in this case the test becomes too massive.

So, the question is: Is it possible to write tests in the first example? If yes, how is it possible?

CodePudding user response:

Skipping Auto Cleanup

you could import @testing-library/react/pure in all your tests that you don't want the cleanup to run and the afterEach won't be setup automatically.

If we import from @testing-library/react, it will import from index.js file.

src/index.js:

import {cleanup} from './pure'

// if we're running in a test runner that supports afterEach
// or teardown then we'll automatically run cleanup afterEach test
// this ensures that tests run in isolation from each other
// if you don't like this then either import the `pure` module
// or set the RTL_SKIP_AUTO_CLEANUP env variable to 'true'.
if (typeof process === 'undefined' || !process.env?.RTL_SKIP_AUTO_CLEANUP) {
  // ignore teardown() in code coverage because Jest does not support it
  /* istanbul ignore else */
  if (typeof afterEach === 'function') {
    afterEach(() => {
      cleanup()
    })
  } else if (typeof teardown === 'function') {
    // Block is guarded by `typeof` check.
    // eslint does not support `typeof` guards.
    // eslint-disable-next-line no-undef
    teardown(() => {
      cleanup()
    })
  }
}

export * from './pure';

As you can see in the source code, RTL calls the cleanup function imported from the ./pure module inside the afterEach hook.

We could import functions such as render from the @testing-library/react/pure module and call the cleanup function manually when needed.

import { render } from '@testing-library/react/pure';
import React from 'react';

const Component = ({ prop1 }) => <div>{prop1}</div>;

describe('Some test', () => {
  const { rerender, asFragment } = render(<Component prop1={0} />);

  test('Title 1', () => {
    rerender(<Component prop1={0} />);
    // logic1
    expect(asFragment().firstChild).toMatchInlineSnapshot(`
      <div>
        0
      </div>
    `);
  });

  test('Title 2', () => {
    rerender(<Component prop1={1} />);
    // logic2
    expect(asFragment().firstChild).toMatchInlineSnapshot(`
      <div>
        1
      </div>
    `);
  });
});
  • Related