meerkat
meerkat

Reputation: 1122

Render same component in beforeAll/beforeEvery: testing-library/react

I'm testing different things in a single component in separate tests. I want to not have to write render inside every single test, but the code underneath does not work.

I have understood that the cleanup function clears the rendered component after each test, so that is good.

import React from "react";
import { Router } from "react-router-dom";
import { render } from "@testing-library/react";
import "@testing-library/jest-dom";

import myComp from './myComp'

const renderComponent = () => {
  return render(<myComp />);
};

describe("desc", () => {
  beforeEach(() => {
   const {getAllByText, getByText, getByRole} = renderComponent()
  });

  test("1", () => {
      console.log(getAllByText) // not defined
  });

  test("2", () => {
      console.log(getAllByText) // not defined

  });

})

The setup above results in the error:

ReferenceError: getAllByText is not defined

My current workaround is to include renderComponent() function call in each test, but this does not look so clean.

test("1", () => {
    const {getAllByText, getByText, getByRole} = renderComponent()
});

Attempt:

let result;
beforeEach(() => {
    result = renderComponent();
    }
test("renders success state", () => {
    const { getByText } = result;
    expect(getByText(noAccess)).toBeInTheDocument();
    expect(getByText(applyForAccessButton)).toBeInTheDocument();});

Error I get then is:

    TypeError: Cannot read property 'getByText' of undefined

Upvotes: 4

Views: 10708

Answers (2)

hafiz ali
hafiz ali

Reputation: 1456

sorry late to the party but i will point out a good practice by kent c dodd

import { render, screen } from '@testing-library/react';

describe('Your Page',() => {
    beforeEach(() => {
        render(
            <YourComponent />
        );
    })
   test("renders success state", () => {
        expect(screen.getByText(noAccess)).toBeInTheDocument();
   })
})

here is the article refers to using screen.getByText rather than destructing it.

The benefit of using screen is you no longer need to keep the render call destructure up-to-date as you add/remove the queries you need. You only need to type screen. and let your editor's magic autocomplete take care of the rest.

link to the article : https://kentcdodds.com/blog/common-mistakes-with-react-testing-library

Upvotes: 5

Estus Flask
Estus Flask

Reputation: 222696

getAllByText is local to beforeEach function, it's not defined in test scopes where it's accessed. In order to be workable this way, it should be:

  let getAllByText, getByText, getByRole;

  beforeEach(() => {
   ({getAllByText, getByText, getByRole} = renderComponent());
  });
  ...

Upvotes: 2

Related Questions