Home > front end >  Describe method can only pass with 1 test unless re-rendering each component again and again
Describe method can only pass with 1 test unless re-rendering each component again and again

Time:01-20

I'm trying to figure out why my test - which passes when ran alone - is failing whenever the describe block contains more than 1 test. Take this example, which I've taken from my real code and simplified:

describe('Create Account Form', () => {
  const {container} = render(<CreateAccountForm />);
  const email = container.querySelector('input[name="email"]');
  const password1 = container.querySelector('input[name="password1"]');

  it('Should render all fields', () => {
    allInputs.forEach((input) => {
      expect(input).toBeInTheDocument();
    });
  });

  it('Another test', () => {
    expect(email).toBeInTheDocument(); // fails
  });
});

The 2nd test fails, but passes only when commenting out the first test, or re-rendering the container again in the test like this:

  it('Another test', () => {
    const {container} = render(<CreateAccountForm />);
    const email = container.querySelector('input[name="email"]');
    expect(email).toBeInTheDocument(); // passes
  });

Why does this have to happen? I would much rather not have to re-render the container and declare new variables inside each test block.

Thank you

CodePudding user response:

RTL will unmount React trees that were mounted with render in afterEach hook. See cleanup.

Please note that this is done automatically if the testing framework you're using supports the afterEach global and it is injected to your testing environment (like mocha, Jest, and Jasmine).

Move the render code into beforeEach or individual test case. So that we can create react trees before each test case. Isolate test cases from each other, using their own test data without affecting the rest.

E.g.

index.tsx:

import React from 'react';

export function Example() {
  return (
    <div>
      <input name="email" />
      <input name="password1" />
    </div>
  );
}

index.test.tsx:

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

describe('70753645', () => {
  let email, password1, allInputs;
  beforeEach(() => {
    const { container } = render(<Example />);
    email = container.querySelector('input[name="email"]');
    password1 = container.querySelector('input[name="password1"]');
    allInputs = container.querySelectorAll('input');
  });

  it('Should render all fields', () => {
    allInputs.forEach((input) => {
      expect(input).toBeInTheDocument();
    });
  });

  it('Another test', () => {
    expect(email).toBeInTheDocument();
  });
});

Test result:

 PASS  stackoverflow/70753645/index.test.tsx (9.222 s)
  70753645
    ✓ Should render all fields (24 ms)
    ✓ Another test (3 ms)

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        9.717 s

package versions:

"@testing-library/react": "^11.2.2",
"jest": "^26.6.3",
  •  Tags:  
  • Related