Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

processesReducer.test.js 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. import { runSaga } from "redux-saga";
  2. import * as api from "../../request/processesReguest";
  3. import { render } from "@testing-library/react";
  4. import * as redux from "react-redux";
  5. import SelectionProcessPage from "../../pages/selectionProcessPage/selectionProcessPage";
  6. ("../../pages/SelectionProcessPage/SelectionProcessPage");
  7. import store from "../../store";
  8. import "../../i18n";
  9. import { mockState } from "../../mockState";
  10. import { FETCH_PROCESSES_REQ } from "../../store/actions/processes/processesActionConstants";
  11. import { Router } from "react-router-dom";
  12. import history from "../../store/utils/history";
  13. import {
  14. getProcesses,
  15. getFilteredProcesses,
  16. finishProcess,
  17. changeStatus,
  18. changeInterviewer,
  19. getApplicantProcesses,
  20. } from "../../store/saga/processSaga";
  21. import {
  22. setProcesses,
  23. setProcessesError,
  24. } from "../../store/actions/processes/processesAction";
  25. import { SelectionProvider } from "../../context/SelectionContext";
  26. import {
  27. setDoneProcess,
  28. setDoneProcessError,
  29. setUpdateInterviewerErr,
  30. setUpdateInterviewerSucc,
  31. setUpdateStatusErr,
  32. setUpdateStatusSucc,
  33. } from "../../store/actions/processes/processAction";
  34. import {
  35. setApplicant,
  36. setApplicantError,
  37. } from "../../store/actions/processes/applicantAction";
  38. describe("SelectionProcessPage render tests", () => {
  39. const cont = (
  40. <redux.Provider store={store}>
  41. <SelectionProvider>
  42. <Router history={history}>
  43. <SelectionProcessPage />
  44. </Router>
  45. </SelectionProvider>
  46. </redux.Provider>
  47. );
  48. let spyOnUseSelector;
  49. let spyOnUseDispatch;
  50. let mockDispatch;
  51. beforeEach(() => {
  52. // Mock useSelector hook
  53. spyOnUseSelector = jest.spyOn(redux, "useSelector");
  54. spyOnUseSelector
  55. .mockReturnValueOnce(mockState.selections)
  56. .mockReturnValueOnce(mockState.selections.processes)
  57. .mockReturnValueOnce(mockState.selections.statuses);
  58. // Mock useDispatch hook
  59. spyOnUseDispatch = jest.spyOn(redux, "useDispatch");
  60. // Mock dispatch function returned from useDispatch
  61. mockDispatch = jest.fn();
  62. spyOnUseDispatch.mockReturnValue(mockDispatch);
  63. });
  64. afterEach(() => {
  65. jest.restoreAllMocks();
  66. });
  67. it("Should dispatch get processes request when rendered", () => {
  68. render(cont);
  69. expect(mockDispatch).toHaveBeenCalledWith({
  70. type: FETCH_PROCESSES_REQ,
  71. });
  72. });
  73. it("should load and handle levels with processes in case of success", async () => {
  74. // we push all dispatched actions to make assertions easier
  75. // and our tests less brittle
  76. const dispatchedActions = [];
  77. // we don't want to perform an actual api call in our tests
  78. // so we will mock the getAllUsers api with jest
  79. // this will mutate the dependency which we may reset if other tests
  80. // are dependent on it
  81. const mockedCall = { data: mockState.selections.processes };
  82. api.getAllLevels = jest.fn(() => Promise.resolve(mockedCall));
  83. const fakeStore = {
  84. getState: () => mockState.selections.processes,
  85. dispatch: (action) => dispatchedActions.push(action),
  86. };
  87. // wait for saga to complete
  88. await runSaga(fakeStore, getProcesses).done;
  89. expect(api.getAllLevels.mock.calls.length).toBe(1);
  90. expect(dispatchedActions).toContainEqual(setProcesses(mockedCall.data));
  91. });
  92. it("should handle processes load errors in case of failure", async () => {
  93. const dispatchedActions = [];
  94. // we simulate an error by rejecting the promise
  95. // then we assert if our saga dispatched the action(s) correctly
  96. const error = {
  97. response: {
  98. data: { message: mockState.selections.fetchSelectionsErrorMessage },
  99. },
  100. };
  101. api.getAllLevels = jest.fn(() => Promise.reject(error));
  102. const fakeStore = {
  103. getState: () => mockState.users.users,
  104. dispatch: (action) => dispatchedActions.push(action),
  105. };
  106. await runSaga(fakeStore, getProcesses).done;
  107. expect(api.getAllLevels.mock.calls.length).toBe(1);
  108. expect(dispatchedActions).toContainEqual(
  109. setProcessesError(error.response.data.message)
  110. );
  111. });
  112. it("should load and handle levels with filtered processes in case of success", async () => {
  113. // we push all dispatched actions to make assertions easier
  114. // and our tests less brittle
  115. const dispatchedActions = [];
  116. const filter = {
  117. statuses: ["Zakazan", "Odrađen"],
  118. dateStart: new Date(2023, 0, 5),
  119. dateEnd: new Date(2024, 1, 1),
  120. };
  121. const filteredData = [];
  122. mockState.selections.processes.forEach((level) => {
  123. const filteredLevel = level;
  124. filteredLevel.selectionProcesses = level.selectionProcesses.filter(
  125. (v) =>
  126. v.date >= filter.dateStart &&
  127. v.date <= filter.dateEnd &&
  128. filter.statuses.includes(v.status)
  129. );
  130. filteredData.push(filteredLevel);
  131. });
  132. // we don't want to perform an actual api call in our tests
  133. // so we will mock the getAllUsers api with jest
  134. // this will mutate the dependency which we may reset if other tests
  135. // are dependent on it
  136. const mockedCall = { data: filteredData };
  137. api.getAllFilteredProcessesReq = jest.fn(() => Promise.resolve(mockedCall));
  138. const fakeStore = {
  139. getState: () => mockState.selections.processes,
  140. dispatch: (action) => dispatchedActions.push(action),
  141. };
  142. // wait for saga to complete
  143. await runSaga(fakeStore, getFilteredProcesses, filter).done;
  144. expect(api.getAllFilteredProcessesReq.mock.calls.length).toBe(1);
  145. expect(dispatchedActions).toContainEqual(setProcesses(filteredData));
  146. });
  147. it("should handle error in case of exception", async () => {
  148. const dispatchedActions = [];
  149. const filter = {
  150. statuses: ["Zakazan", "Odrađen"],
  151. dateStart: new Date(2023, 0, 5),
  152. dateEnd: new Date(2024, 1, 1),
  153. };
  154. const error = {
  155. response: {
  156. data: { message: mockState.selections.fetchSelectionsErrorMessage },
  157. },
  158. };
  159. api.getAllFilteredProcessesReq = jest.fn(() => Promise.reject(error));
  160. const fakeStore = {
  161. getState: () => mockState.selections.processes,
  162. dispatch: (action) => dispatchedActions.push(action),
  163. };
  164. // wait for saga to complete
  165. await runSaga(fakeStore, getFilteredProcesses, filter).done;
  166. expect(dispatchedActions).toContainEqual(
  167. setProcessesError(error.response.data.message)
  168. );
  169. });
  170. it("should handle process to set it done in case of success", async () => {
  171. // we push all dispatched actions to make assertions easier
  172. // and our tests less brittle
  173. const dispatchedActions = [];
  174. const filter = {
  175. statuses: ["Zakazan", "Odrađen"],
  176. dateStart: new Date(2023, 0, 5),
  177. dateEnd: new Date(2024, 1, 1),
  178. };
  179. const filteredData = [];
  180. mockState.selections.processes.forEach((level) => {
  181. const filteredLevel = level;
  182. filteredLevel.selectionProcesses = level.selectionProcesses.filter(
  183. (v) =>
  184. v.date >= filter.dateStart &&
  185. v.date <= filter.dateEnd &&
  186. filter.statuses.includes(v.status)
  187. );
  188. filteredData.push(filteredLevel);
  189. });
  190. // we don't want to perform an actual api call in our tests
  191. // so we will mock the getAllUsers api with jest
  192. // this will mutate the dependency which we may reset if other tests
  193. // are dependent on it
  194. const mockedCall = { data: filteredData };
  195. api.getAllFilteredProcessesReq = jest.fn(() => Promise.resolve(mockedCall));
  196. const fakeStore = {
  197. getState: () => mockState.selections.processes,
  198. dispatch: (action) => dispatchedActions.push(action),
  199. };
  200. // wait for saga to complete
  201. await runSaga(fakeStore, getFilteredProcesses, filter).done;
  202. expect(api.getAllFilteredProcessesReq.mock.calls.length).toBe(1);
  203. expect(dispatchedActions).toContainEqual(setProcesses(filteredData));
  204. });
  205. it("should handle process to set it done in case of finish success", async () => {
  206. const dispatchedActions = [];
  207. const mockedCall = { data: { isSuccess: true } };
  208. api.doneProcess = jest.fn(() => Promise.resolve(mockedCall));
  209. const fakeStore = {
  210. getState: () => mockState.selections.processes,
  211. dispatch: (action) => dispatchedActions.push(action),
  212. };
  213. // wait for saga to complete
  214. await runSaga(fakeStore, finishProcess, {
  215. payload: {
  216. id: 1,
  217. name: "Some random name",
  218. applicantId: 5,
  219. schedulerId: 10,
  220. },
  221. }).done;
  222. expect(api.doneProcess.mock.calls.length).toBe(1);
  223. expect(dispatchedActions).toContainEqual(setDoneProcess(mockedCall.data));
  224. });
  225. it("should handle error in case of finish process exception", async () => {
  226. const dispatchedActions = [];
  227. const error = {
  228. response: {
  229. data: { message: mockState.selections.fetchSelectionsErrorMessage },
  230. },
  231. };
  232. api.doneProcess = jest.fn(() => Promise.reject(error));
  233. const fakeStore = {
  234. getState: () => mockState.selections.processes,
  235. dispatch: (action) => dispatchedActions.push(action),
  236. };
  237. // wait for saga to complete
  238. await runSaga(fakeStore, finishProcess, {
  239. payload: {
  240. id: 1,
  241. name: "Some random name",
  242. applicantId: 5,
  243. schedulerId: 10,
  244. },
  245. }).done;
  246. expect(api.doneProcess.mock.calls.length).toBe(1);
  247. expect(dispatchedActions).toContainEqual(
  248. setDoneProcessError(error.response.data.message)
  249. );
  250. });
  251. it("should handle process status update", async () => {
  252. const dispatchedActions = [];
  253. const mockedCall = { data: { isSuccess: true } };
  254. api.updateStatus = jest.fn(() => Promise.resolve(mockedCall));
  255. const fakeStore = {
  256. getState: () => mockState.selections.processes,
  257. dispatch: (action) => dispatchedActions.push(action),
  258. };
  259. // wait for saga to complete
  260. await runSaga(fakeStore, changeStatus, {
  261. payload: {
  262. data: {
  263. schedulerId: 3,
  264. appointment: "22-10-2023",
  265. newStatus: "Odrađen",
  266. processId: 1,
  267. },
  268. },
  269. }).done;
  270. expect(api.updateStatus.mock.calls.length).toBe(1);
  271. expect(dispatchedActions).toContainEqual(setUpdateStatusSucc());
  272. });
  273. it("should call responsehandler while handling process status update", async () => {
  274. const dispatchedActions = [];
  275. const mockedCall = { data: { isSuccess: true } };
  276. api.updateStatus = jest.fn(() => Promise.resolve(mockedCall));
  277. const mockfn = jest.fn();
  278. const fakeStore = {
  279. getState: () => mockState.selections.processes,
  280. dispatch: (action) => dispatchedActions.push(action),
  281. };
  282. // wait for saga to complete
  283. await runSaga(fakeStore, changeStatus, {
  284. payload: {
  285. data: {
  286. schedulerId: 3,
  287. appointment: "22-10-2023",
  288. newStatus: "Odrađen",
  289. processId: 1,
  290. },
  291. responseHandler: mockfn,
  292. },
  293. }).done;
  294. expect(mockfn).toHaveBeenCalled();
  295. });
  296. it("should handle process status update error if exception is thrown", async () => {
  297. const dispatchedActions = [];
  298. const error = {
  299. response: {
  300. data: { message: mockState.selections.fetchSelectionsErrorMessage },
  301. },
  302. };
  303. api.updateStatus = jest.fn(() => Promise.reject(error));
  304. const fakeStore = {
  305. getState: () => mockState.selections.processes,
  306. dispatch: (action) => dispatchedActions.push(action),
  307. };
  308. // wait for saga to complete
  309. await runSaga(fakeStore, changeStatus, {
  310. payload: {
  311. data: {
  312. schedulerId: 3,
  313. appointment: "22-10-2023",
  314. newStatus: "Odrađen",
  315. processId: 1,
  316. },
  317. },
  318. }).done;
  319. expect(api.updateStatus.mock.calls.length).toBe(1);
  320. expect(dispatchedActions).toContainEqual(
  321. setUpdateStatusErr(error.response.data.message)
  322. );
  323. });
  324. it("should not call responseHandler if exception is thrown", async () => {
  325. const dispatchedActions = [];
  326. const error = {
  327. response: {
  328. data: { message: mockState.selections.fetchSelectionsErrorMessage },
  329. },
  330. };
  331. api.updateStatus = jest.fn(() => Promise.reject(error));
  332. const mockfn = jest.fn();
  333. const fakeStore = {
  334. getState: () => mockState.selections.processes,
  335. dispatch: (action) => dispatchedActions.push(action),
  336. };
  337. // wait for saga to complete
  338. await runSaga(fakeStore, changeStatus, {
  339. payload: {
  340. data: {
  341. schedulerId: 3,
  342. appointment: "22-10-2023",
  343. newStatus: "Odrađen",
  344. processId: 1,
  345. },
  346. responseHandler: mockfn,
  347. },
  348. }).done;
  349. expect(mockfn).not.toHaveBeenCalled();
  350. });
  351. it("should handle interviewer update", async () => {
  352. const dispatchedActions = [];
  353. const mockedCall = { data: { isSuccess: true } };
  354. api.updateInterviewer = jest.fn(() => Promise.resolve(mockedCall));
  355. const fakeStore = {
  356. getState: () => mockState.selections.processes,
  357. dispatch: (action) => dispatchedActions.push(action),
  358. };
  359. // wait for saga to complete
  360. await runSaga(fakeStore, changeInterviewer, {
  361. payload: {
  362. data: {
  363. schedulerId: 1,
  364. processId: 2,
  365. },
  366. // responseHandler: apiSuccess,
  367. },
  368. }).done;
  369. expect(api.updateInterviewer.mock.calls.length).toBe(1);
  370. expect(dispatchedActions).toContainEqual(setUpdateInterviewerSucc());
  371. });
  372. it("should call response handler on change success", async () => {
  373. const dispatchedActions = [];
  374. const mockedCall = { data: { isSuccess: true } };
  375. api.updateInterviewer = jest.fn(() => Promise.resolve(mockedCall));
  376. const fakeStore = {
  377. getState: () => mockState.selections.processes,
  378. dispatch: (action) => dispatchedActions.push(action),
  379. };
  380. const mockfn = jest.fn();
  381. // wait for saga to complete
  382. await runSaga(fakeStore, changeInterviewer, {
  383. payload: {
  384. data: {
  385. schedulerId: 1,
  386. processId: 2,
  387. },
  388. responseHandler: mockfn,
  389. },
  390. }).done;
  391. expect(mockfn).toHaveBeenCalled();
  392. });
  393. it("should handle interviewer update error if exception is thrown", async () => {
  394. const dispatchedActions = [];
  395. const error = {
  396. response: {
  397. data: { message: mockState.selections.fetchSelectionsErrorMessage },
  398. },
  399. };
  400. api.updateInterviewer = jest.fn(() => Promise.reject(error));
  401. const fakeStore = {
  402. getState: () => mockState.selections.processes,
  403. dispatch: (action) => dispatchedActions.push(action),
  404. };
  405. // wait for saga to complete
  406. await runSaga(fakeStore, changeInterviewer, {
  407. payload: {
  408. data: {
  409. schedulerId: 1,
  410. processId: 2,
  411. },
  412. // responseHandler: mockfn,
  413. },
  414. }).done;
  415. expect(api.updateInterviewer.mock.calls.length).toBe(1);
  416. expect(dispatchedActions).toContainEqual(
  417. setUpdateInterviewerErr(error.response.data.message)
  418. );
  419. });
  420. it("should not call response handler if exception is thrown", async () => {
  421. const dispatchedActions = [];
  422. const error = {
  423. response: {
  424. data: { message: mockState.selections.fetchSelectionsErrorMessage },
  425. },
  426. };
  427. api.updateInterviewer = jest.fn(() => Promise.reject(error));
  428. const mockfn = jest.fn();
  429. const fakeStore = {
  430. getState: () => mockState.selections.processes,
  431. dispatch: (action) => dispatchedActions.push(action),
  432. };
  433. // wait for saga to complete
  434. await runSaga(fakeStore, changeInterviewer, {
  435. payload: {
  436. data: {
  437. schedulerId: 1,
  438. processId: 2,
  439. },
  440. responseHandler: mockfn,
  441. },
  442. }).done;
  443. expect(mockfn).not.toHaveBeenCalled();
  444. });
  445. it("should handle applicant processess if succeeded", async () => {
  446. const dispatchedActions = [];
  447. const mockedCall = { data: {} };
  448. api.getProcessesOfApplicant = jest.fn(() => Promise.resolve(mockedCall));
  449. const fakeStore = {
  450. getState: () => mockState.selections.processes,
  451. dispatch: (action) => dispatchedActions.push(action),
  452. };
  453. // wait for saga to complete
  454. await runSaga(fakeStore, getApplicantProcesses, {
  455. payload: {
  456. id: 1,
  457. },
  458. }).done;
  459. expect(api.getProcessesOfApplicant.mock.calls.length).toBe(1);
  460. expect(dispatchedActions).toContainEqual(setApplicant(mockedCall.data));
  461. });
  462. it("should handle applicant processess error if exception is thrown", async () => {
  463. const dispatchedActions = [];
  464. const error = {
  465. response: {
  466. data: { message: mockState.selections.fetchSelectionsErrorMessage },
  467. },
  468. };
  469. api.getProcessesOfApplicant = jest.fn(() => Promise.reject(error));
  470. const fakeStore = {
  471. getState: () => mockState.selections.processes,
  472. dispatch: (action) => dispatchedActions.push(action),
  473. };
  474. // wait for saga to complete
  475. await runSaga(fakeStore, getApplicantProcesses, {
  476. payload: {
  477. id: 1,
  478. },
  479. }).done;
  480. expect(api.getProcessesOfApplicant.mock.calls.length).toBe(1);
  481. expect(dispatchedActions).toContainEqual(
  482. setApplicantError(error.response.data.message)
  483. );
  484. });
  485. });