ciz30
ciz30

Reputation: 453

React-testing-library how test conditional rendering

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?

Upvotes: 6

Views: 25844

Answers (2)

Tapan Prakash
Tapan Prakash

Reputation: 803

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

Upvotes: 3

joshwilsonvu
joshwilsonvu

Reputation: 2679

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

Upvotes: 4

Related Questions