I'm trying the unit test for the first time. I would like to test the function of rendering in modal or dialog depending on the condition.
I've seen countless posts and videos, but I haven't seen a case like mine. In the case of my modal, I saw Udemy and implemented a course by Maximilian Schwarzmüller.
This is a YouTube link from one of the videos I referenced. https://youtu.be/To2PzUT1lQ4?si=MYC_E_i_S2jafa-z
This is another Question , but this is Props,i'm not using props conditional component How to test conditional rendering of components using Jest and Enzyme
I think it's the most similar question, but it's hard for me to apply it to my case. testing conditional rendering that relies on state using react testing library
https://medium.com/@manojmukherjee777/react-testing-library-portal-modal-b05aaeb5dda7
the Test Order
rendering FetchRenderTest
click "Testing Start" Button
Running fetchmock
It is assumed that a request or communication to a response fails. so change isError to true
rendering ErrorModal.tsx <- I don't know what to do from this part. (Explain it again - ErrorModal is a modal or dialog that appears on the screen as described above.)
"Error dialog close" button Verifying Rendered
my code here
FetchRenderTest.tsx
import React, { useState, Fragment } from "react";
import ErrorModal from "./UI/ErrorModal";
function FetchRenderTest() {
const [isError, setIsError] = useState(false);
const errorHandler = () => {
setIsError(false);
};
const confirmHandler = async () => {
let domain = window.location.hostname;
try {
const response = await fetch("<this is url>", {
method: "PUT",
headers: {
"Content-type": "application/json",
},
body: JSON.stringify({ SendData: "test" }),
});
if (response.status === 200) {
return;
} else {
setIsError(true);
return;
}
} catch (error) {
setIsError(true);
}
};
return (
<>
{isError && <ErrorModal role="dialog" title="Modal, Dialog Test" message="" onConfirm={errorHandler} />}
<div>
<button onClick={confirmHandler}> Testing Start</button>
</div>
</>
);
}
export default FetchRenderTest;
ErrorModal.tsx
import React, { Fragment } from "react";
import ReactDOM from "react-dom";
import PopupDragControl from "./PopupDragControl";
import Button from "./Button";
import classes from "./ErrorModal.module.css";
const ErrorModalOverlay = (props: any) => {
return (
<div>
<div className={classes.backdrop} />
<PopupDragControl>
<header className={classes.header}>
<h2>{props.title}</h2>
</header>
<div className={classes.content}>
<p>{props.message}</p>
</div>
<footer className={classes.action}>
<Button onClick={props.isConfirm}> Error dialog close </Button>
</footer>
</PopupDragControl>
</div>
);
};
const portalElement = document.getElementById("overlays"); <- I tried the "root"
const ErrorModal = (props: any) => {
const { title, message, onConfirm } = props;
if (!portalElement) {
return null;
}
const messageText = message ? message.result : null;
const errorModalElements = ReactDOM.createPortal(<ErrorModalOverlay title={title} message={messageText} isConfirm={onConfirm}></ErrorModalOverlay>, portalElement);
return <Fragment>{errorModalElements}</Fragment>;
};
export default ErrorModal;
Button.tsx
const Button = (props : any) => {
return (
<button
type={props.type || "button"}
className={`${classes.button} ${props.className}`}
onClick={props.onClick}
disabled={props.disabled}
>
{props.children}
</button>
);
};
export default Button;
And Test code FetchRenderTest.test.tsx
import React from "react";
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
import "@testing-library/jest-dom";
import FetchRenderTest from "./FetchRenderTest";
test("renders learn react link", async () => {
global.fetch = jest.fn().mockRejectedValueOnce({
json: jest.fn().mockRejectedValueOnce({ success: true }),
ok: true,
status: 500,
});
render(<FetchRenderTest />);
fireEvent.click(screen.getByText(/Testing Start/i, { exact: false }));
await waitFor(() => {
expect(global.fetch).toHaveBeenCalledWith("<this is url>", {
method: "PUT",
headers: {
"Content-type": "application/json",
},
body: JSON.stringify({ SendData: "test" }),
});
});
fireEvent.click(screen.getByText(/Error dialog close/i, { exact: false }));
});
an idea from one of the attempts Default setting for React In addition, modals that are not all renders Rendering to .
I guess the problem is id So I modified it all to root, but it still doesn't test.
And I looked up all the usual methods with Googling, but it didn't fit my case.
The search method may not have been good.
In this case, if you have to test each component separately, please let me know
In your test code, you are on the right track. After clicking the "Error dialog close" button, you need to mock fetch request, render, assert. Here's how you can modify your test to achieve this:
Full Code with added your code and test file. Please run npm run test
https://stackblitz.com/~/github.com/2manoj1/example-model-test-vitest
If you want to local run: clone below repo https://github.com/2manoj1/example-model-test-vitest
npm i
npm run test or npm run test:ui
run project
npm run dev
Using [MSW][1]
// FetchRenderTest.test.js
import {
render,
screen,
userEvent,
waitFor,
debug,
act,
} from "./utils/test-utils";
import { http, HttpResponse } from "msw";
import { setupServer } from "msw/node";
import FetchRenderTest from "./FetchRenderTest";
const handlers = [
http.put("https://65d1ac70987977636bfb57a9.mockapi.io/api/v1/test", () => {
return HttpResponse.json({ msg: "Invalid request" }, { status: 400 }); // Simulate error response
}),
];
const server = setupServer(...handlers);
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
test("renders ErrorModal when fetch fails", async () => {
render(<FetchRenderTest />, { container: document.body });
const testingStartButton = screen.getByText("Testing Start");
await act(async () => {
// Click the button to trigger the fetch request
await userEvent.click(testingStartButton);
});
// Wait for the ErrorModal to render
await waitFor(() => {
const errorModal = screen.getByRole("dialog");
expect(errorModal).toBeInTheDocument();
});
// Verify the modal content
const modalTitle = screen.getByText("Modal, Dialog Test");
expect(modalTitle).toBeInTheDocument();
// Verify the close button is rendered
const closeButton = screen.getByRole("button", {
name: /Error dialog close/i,
});
expect(closeButton).toBeInTheDocument();
});
This test:
This test ensures that the component behaves correctly when a fetch request fails, displaying the error modal and allowing the user to close it.