4

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

2 Answers 2

5

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

Sign up to request clarification or add additional context in comments.

Comments

2

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());
  });
  ...

5 Comments

For some reason I am now getting TypeError: getByText is not a function in the test when i use getByText straight away.
How do you use it straight away exactly? I don't see how it's possible because if getAllByText is available, getByText should be there too, testing-library.com/docs/dom-testing-library/api-queries . FWIW, it's not practical to destructure render result at this point because this results in boilerplate code, the result has tons of properties, any of which may be required at some point, I'd suggest to use let result; ... result = renderComponent() instead.
I updated the question with my usage and the error I'm getting
I don't see how it's possible, considering that renderComponent really returns render result as in the question, and beforeEach is applied to the test where you use the result, I expect that some parts differ from what you shown. If done correctly, it's very straightforward, render returns result object, it's called in beforeEach before a test, a test accesses result object. You can debug what render(<myComp />) returns and make sure it's called at all. In case the problem persists, please, provide a way to reproduce it.
This answer is wrong/outdated. RTL recommends using screen from the library itself so you don't have to worry about destructuring

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.