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?

2 Answers 2

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
});
Sign up to request clarification or add additional context in comments.

1 Comment

Yeah, but this does not work for me. Could you please check my question: stackoverflow.com/questions/65406810/…
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);
})

Comments

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.