I'm trying to create a unit test using react testing library jest in my nextjs app, it's a simples test, once a click on the button without fill the fields, it should show a error message "Please enter all fields", but I can't find the error message after the button is clicked, I think it might have something to do with the state, because once the button is clicked is going to set error true to show the message.
My register component:
import Head from "next/head";
import { useState } from "react";
const Register = () => {
const [error, setError] = useState(false);
const [showPass, setShowPass] = useState(false);
const handleSubmit = async (event: React.SyntheticEvent) => {
event.preventDefault();
const name = (event?.target as any).nome?.value;
const email = (event?.target as any).email?.value;
const password = (event?.target as any).password?.value;
if (name === "" || email === "" || password === "") {
setError(true);
return;
}
const data = {
name,
email,
password,
};
const resp = await fetch("http://localhost:5000/register", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data),
});
const data2 = await resp.json();
};
return (
<div className="center text-textLight">
<Head>
<title>Forum</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<h2 className="title mb-8">Register</h2>
{error && <h2 className="text-error">Please enter all fields</h2>}
<form onSubmit={handleSubmit}>
<div>
<input
className="inputStyle mb-2"
type="text"
name="nome"
placeholder="name"
/>
</div>
<div>
<input
className="inputStyle mb-2"
type="text"
name="email"
placeholder="email"
/>
</div>
<div>
<div>
<input
className="inputStyle dark:text-textLight"
type={showPass ? "text" : "password"}
name="password"
placeholder="password"
/>
</div>
<div className="mt-2 flex items-center justify-center">
<input
onChange={() => setShowPass((prev) => !prev)}
className="mr-2"
type="checkbox"
id="showPas"
name="showPas"
/>
<label className="dark:text-textDark" htmlFor="showPas">
Show password
</label>
</div>
</div>
<button className="btn mt-6 dark:text-textDark">Submit</button>
</form>
</div>
);
};
export default Register;
My test for register:
import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import Register from "../src/pages/register";
test("should show error message if username and password is empty", async () => {
const user = userEvent.setup();
render(<Register />);
await user.click(screen.getByRole("button", { name: /submit/i }));
expect(screen.findByTestId("error")).toHaveTextContent(
"Please enter all fields"
);
});
jest.congif.js
const nextJest = require("next/jest");
const createJestConfig = nextJest({
dir: "./",
});
/** @type {import('jest').Config} */
const customJestConfig = {
moduleDirectories: ["node_modules", "src"],
testEnvironment: "jest-environment-jsdom",
setupFilesAfterEnv: ["<rootDir>/jest.setup.js"],
};
module.exports = createJestConfig(customJestConfig);
jest.setup.js
import "@testing-library/jest-dom/extend-expect";
import "@testing-library/user-event";
CodePudding user response:
Here you try to find an element with a testid = error.
expect(screen.findByTestId("error")).toHaveTextContent("Please enter all fields");
The element you want to get by this statement is
<h2 className="text-error">Please enter all fields</h2>
Which does not have a testid. See https://testing-library.com/docs/queries/bytestid/
So do <h2 className="test-error" data-testid="error">Please enter all fields</h2>
To be able to select this element byTestId.
However as you will see in the documentation for byTestId it is not recommended. In this particular case I would suggest getByText. Here is the documentation https://testing-library.com/docs/queries/bytext
And the implementation
expect(screen.getByText("Please enter all fields")).toBeInTheDocument()