// Delete.jsx
import React, {useCallback, useRef} from "react"
import {useDispatch} from "react-redux"
import {ModalComponent, modalOpen} from "../Modal"
export function Delete () {
const dispatch = useDispatch()
const modalRef = useRef(null)
const handleDelete = () => {
dispatchEvent(deleteData())
modalRef.current.close
}
return (
<Type>
<Button
onClick={modalOpen(modalRef)}
>
Delete
</Button>
<ModalComponent func={handleDelete} refer={modalRef} />
</Type>
)
}
// ModalComponent.jsx
import React, {useCallback} from "react"
export function ModalComponent (props) {
const modalRef = props.refer
return (
<Modal
ref={modalRef}
onClose={modalClose(modalRef)}
>
<Type>
Are you sure ?
</Type>
<Type>
<ButtonGroup>
<Button
id='DeleteButton'
onClick={modalClose(modalRef)}
>
Close
</Button>
<Button
onClick={props.func}
>
Confirm
</Button>
</ButtonGroup>
</Type>
</Modal>
)
}
export const modalOpen = (refModal) => {
return useCallback(
() => {
refModal.current.open()
}, [refModal]
)
}
export const modalClose = (refModal) => {
return useCallback(
() => {
refModal.current.close()
}, [refModal]
)
}
Above are the codes of Delete and ModalComponent, I'm trying to write unit test cases for Delete Button.
// Delete.test.js
import React from "react"
import {fireEvent, render} from "@testing-library/react"
import * as modal from '../ModalComponent'
jest.mock('react-redux', () => ({
...jest.requireActual('react-redux'),
useDispatch: jest.fn()
}))
describe('Delete button', () => {
it('should open modal when delete button is called', () => {
const modalSpy = jest.spyOn(modal, 'modalOpen').mockImplementation(() => jest.fn())
const component = render(
<Delete />
)
const button = component.container.querySelector('#DeleteButton')
fireEvent.click(button)
expect(modalSpy).toHaveBeenCalled()
})
})
Could somebody please help me to handle modal events so I can test handle edit ?
Don't mock what you are trying to unit test. Your unit tests should mirror how users or other components interact with the component, e.g. via its rendered UI and props.
Since you can't share the Modal
component I've created a mock modal component that exposes out open and close handlers via a React ref.
Mock Modal component:
import React, {
forwardRef,
useImperativeHandle,
useState
} from "react";
const Modal = forwardRef((props, ref) => {
const [open, setOpen] = useState(false);
useImperativeHandle(
ref,
() => ({
open: () => setOpen(true),
close: () => setOpen(false)
}),
[]
);
return open ? (
<div data-testid="modal">
<button type="button" onClick={props.onClose}>
x
</button>
<div>{props.children}</div>
</div>
) : null;
});
Delete
const modalOpen = (refModal) => () => {
refModal.current.open();
};
const modalClose = (refModal) => () => {
refModal.current.close();
};
export default function Delete() {
// const dispatch = useDispatch();
const modalRef = useRef(null);
const handleDelete = () => {
// dispatchEvent(deleteData())
modalRef.current.close();
};
return (
<Type>
<Button onClick={modalOpen(modalRef)}>Delete</Button>
<ModalComponent func={handleDelete} refer={modalRef} />
</Type>
);
}
Delete unit test
import React from "react";
import { fireEvent, render } from "@testing-library/react";
import "@testing-library/jest-dom";
import Delete from "./Delete";
describe("Delete button", () => {
it("should open modal when delete button is called", () => {
const { queryByText, queryByTestId } = render(<Delete />);
// Assert that the modal is not current in the DOM
expect(queryByTestId("modal")).not.toBeInTheDocument();
// Click delete button to toggle the modal open
fireEvent.click(queryByText("Delete"));
// Assert that the modal is now in the DOM
expect(queryByTestId("modal")).toBeInTheDocument();
// Click modal's close button to toggle the modal closed
fireEvent.click(queryByText("Close"));
// Assert that the modal is not current in the DOM
expect(queryByTestId("modal")).not.toBeInTheDocument();
});
});
When you update your code and uncomment the useDispatch
hook and dispatch
call you'll need to also create a Redux store for the test.
Basic example:
import React from "react";
import { fireEvent, render } from "@testing-library/react";
import "@testing-library/jest-dom";
import { configureStore } from "@reduxjs/toolkit";
import { Provider } from "react-redux";
import reducer from "../path/to/rootReducer";
import Delete from "./Delete";
const store = configureStore({
reducer,
});
const Providers = ({ children }) => (
<Provider store={store}>
{children}
</Provider>
);
describe("Delete button", () => {
it("should open modal when delete button is called", () => {
const { .... } = render(<Delete />, { wrapper: Providers });
... testing code ...
});
});
See the Redux Writing Tests documentation for further general testing information and strategies.