Reputation: 453
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
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
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