React-testing-library how test conditional rendering
Asked Answered
B

2

6

i'm newbie on react-testing-library

i'm trying to test my component which inside have conditional rendering.

is my Component:

const ComponentA = () => {
   const [isActive, setIsActive] = (false);
   const toggle = () => {
     setIsActive(!isActive)
   }
   return (
     <>
       <div>
         <h1 onClick={toggle}>Title</h1>
       </div>
       {isActive && (<div className="some"><h4>SubTitle</h4></div>)}
     </>
   )
}

and its my test:

import React from "react";
import { ComponentA } from "./";
import { render } from "@testing-library/react";

it("renders without crashing", async () => {
  const wrapper = render(
      <ComponentA />
  );
  expect(wrapper).toMatchSnapshot();
  wrapper.unmount();
});

here is test passed but i wan't to test isActive case. So if is active true div with className some will render or not eg.

how i can do that?

Boulware answered 13/5, 2020 at 19:40 Comment(0)
G
4

It's best to test your components as closely as possible to how they will be used in the browser. In your case, that means clicking the element with text "Title". @testing-library/react has a nice way to do that with fireEvent.

import React from "react";
import { ComponentA } from "./";
import { render, screen, fireEvent } from "@testing-library/react";
import '@testing-library/jest-dom';

it("renders without crashing", () => {
  render(
      <ComponentA />
  );

  expect(screen.getByText("Title")).toBeInTheDocument();
  // use queryBy* for checking existence,
  // no element with text "Subtitle" should be on screen
  expect(screen.queryByText("Subtitle")).toBe(null); 

  // Simulate clicking on "Title"
  fireEvent.click(screen.getByText("Title"));
  // Now "Subtitle" should be on screen
  expect(screen.getByText("Subtitle")).toBeInTheDocument();

  // Click again so that "Subtitle" disappears
  fireEvent.click(screen.getByText("Title"));
  // "Subtitle" should be gone
  expect(screen.queryByText("Subtitle")).toBe(null);

  // cleanup done automatically
});
Gurgle answered 13/5, 2020 at 19:54 Comment(1)
Yeah, but this does not work for me. Could you please check my question: #65407310Broadnax
F
3

The ComponentA is crashing because it's not using the state properly. useState is missing from the code.

ComponentA.js

import { useState } from "react";
export const ComponentA = () => {
    // useState hook
    const [isActive, setIsActive] = useState(false);
    const toggle = () => {
      setIsActive(!isActive)
    }
    return (
      <>
        <div>
          <h1 onClick={toggle}>Title</h1>
        </div>
        {isActive && (<div className="some"><h4>SubTitle</h4></div>)}
      </>
    )
 }

The corresponding test can be written something like below.

ComponentA.test.js

import { render, screen } from "@testing-library/react";
import userEvent from '@testing-library/user-event';

import { ComponentA } from "./ComponentA";

test('CompoentA test', () => {
  render(<ComponentA/>)
  // Check Title present on the screen
  expect(screen.getByText("Title")).toBeInTheDocument();
  // Check "Subtitle" not on the screen
  expect(screen.queryByText("SubTitle")).toBe(null);

  // Simulate clicking on "Title" using userEvent
  userEvent.click(screen.getByText("Title"));
  // Check "SubTitle" visible on the screen.
  expect(screen.getByText("SubTitle")).toBeInTheDocument();

  // Click again so that "SubTitle" disappears
  userEvent.click(screen.getByText("Title"));
  // "SubTitle" should not be on the screen
  expect(screen.queryByText("SubTitle")).toBe(null);
})
Freckle answered 17/10, 2021 at 5:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.