import { runSaga } from "redux-saga"; import * as api from "../../request/processesReguest"; import { render } from "@testing-library/react"; import * as redux from "react-redux"; import SelectionProcessPage from "../../pages/selectionProcessPage/selectionProcessPage"; ("../../pages/SelectionProcessPage/SelectionProcessPage"); import store from "../../store"; import "../../i18n"; import { mockState } from "../../mockState"; import { FETCH_PROCESSES_REQ } from "../../store/actions/processes/processesActionConstants"; import { Router } from "react-router-dom"; import history from "../../store/utils/history"; import { getProcesses, getFilteredProcesses, } from "../../store/saga/processSaga"; import { setProcesses, setProcessesError, } from "../../store/actions/processes/processesAction"; describe("SelectionProcessPage render tests", () => { const cont = ( ); let spyOnUseSelector; let spyOnUseDispatch; let mockDispatch; beforeEach(() => { // Mock useSelector hook spyOnUseSelector = jest.spyOn(redux, "useSelector"); spyOnUseSelector .mockReturnValueOnce(mockState.selections) .mockReturnValueOnce(mockState.selections.processes) .mockReturnValueOnce(mockState.selections.statuses); // Mock useDispatch hook spyOnUseDispatch = jest.spyOn(redux, "useDispatch"); // Mock dispatch function returned from useDispatch mockDispatch = jest.fn(); spyOnUseDispatch.mockReturnValue(mockDispatch); }); afterEach(() => { jest.restoreAllMocks(); }); it("Should dispatch get processes request when rendered", () => { render(cont); expect(mockDispatch).toHaveBeenCalledWith({ type: FETCH_PROCESSES_REQ, }); }); it("should load and handle levels with processes in case of success", async () => { // we push all dispatched actions to make assertions easier // and our tests less brittle const dispatchedActions = []; // we don't want to perform an actual api call in our tests // so we will mock the getAllUsers api with jest // this will mutate the dependency which we may reset if other tests // are dependent on it const mockedCall = { data: mockState.selections.processes }; api.getAllLevels = jest.fn(() => Promise.resolve(mockedCall)); const fakeStore = { getState: () => mockState.selections.processes, dispatch: (action) => dispatchedActions.push(action), }; // wait for saga to complete await runSaga(fakeStore, getProcesses).done; expect(api.getAllLevels.mock.calls.length).toBe(1); expect(dispatchedActions).toContainEqual(setProcesses(mockedCall.data)); }); it("should handle processes load errors in case of failure", async () => { const dispatchedActions = []; // we simulate an error by rejecting the promise // then we assert if our saga dispatched the action(s) correctly const error = { response: { data: { message: mockState.selections.fetchSelectionsErrorMessage }, }, }; api.getAllLevels = jest.fn(() => Promise.reject(error)); const fakeStore = { getState: () => mockState.users.users, dispatch: (action) => dispatchedActions.push(action), }; await runSaga(fakeStore, getProcesses).done; expect(api.getAllLevels.mock.calls.length).toBe(1); expect(dispatchedActions).toContainEqual( setProcessesError(error.response.data.message) ); }); it("should load and handle levels with filtered processes in case of success", async () => { // we push all dispatched actions to make assertions easier // and our tests less brittle const dispatchedActions = []; const filter = { statuses: ["Zakazan", "Odrađen"], dateStart: new Date(2023, 0, 5), dateEnd: new Date(2024, 1, 1), }; const filteredData = []; mockState.selections.processes.forEach((level) => { const filteredLevel = level; filteredLevel.selectionProcesses = level.selectionProcesses.filter( (v) => v.date >= filter.dateStart && v.date <= filter.dateEnd && filter.statuses.includes(v.status) ); filteredData.push(filteredLevel); }); // we don't want to perform an actual api call in our tests // so we will mock the getAllUsers api with jest // this will mutate the dependency which we may reset if other tests // are dependent on it const mockedCall = { data: filteredData }; api.getAllFilteredProcessesReq = jest.fn(() => Promise.resolve(mockedCall)); const fakeStore = { getState: () => mockState.selections.processes, dispatch: (action) => dispatchedActions.push(action), }; // wait for saga to complete await runSaga(fakeStore, getFilteredProcesses, filter).done; expect(api.getAllFilteredProcessesReq.mock.calls.length).toBe(1); expect(dispatchedActions).toContainEqual(setProcesses(filteredData)); }); it("should handle process to set it done in case of success", async () => { // we push all dispatched actions to make assertions easier // and our tests less brittle const dispatchedActions = []; const filter = { statuses: ["Zakazan", "Odrađen"], dateStart: new Date(2023, 0, 5), dateEnd: new Date(2024, 1, 1), }; const filteredData = []; mockState.selections.processes.forEach((level) => { const filteredLevel = level; filteredLevel.selectionProcesses = level.selectionProcesses.filter( (v) => v.date >= filter.dateStart && v.date <= filter.dateEnd && filter.statuses.includes(v.status) ); filteredData.push(filteredLevel); }); // we don't want to perform an actual api call in our tests // so we will mock the getAllUsers api with jest // this will mutate the dependency which we may reset if other tests // are dependent on it const mockedCall = { data: filteredData }; api.getAllFilteredProcessesReq = jest.fn(() => Promise.resolve(mockedCall)); const fakeStore = { getState: () => mockState.selections.processes, dispatch: (action) => dispatchedActions.push(action), }; // wait for saga to complete await runSaga(fakeStore, getFilteredProcesses, filter).done; expect(api.getAllFilteredProcessesReq.mock.calls.length).toBe(1); expect(dispatchedActions).toContainEqual(setProcesses(filteredData)); }); });