| @@ -0,0 +1,68 @@ | |||
| import * as redux from "react-redux"; | |||
| import store from "../../store"; | |||
| import { Router } from "react-router-dom"; | |||
| import history from "../../store/utils/history"; | |||
| import { mockState } from "../../mockState"; | |||
| import * as api from '../../request/registerRequest' | |||
| import { render } from "@testing-library/react"; | |||
| import UserDetails from "../../pages/UsersPage/UserDetails"; | |||
| import ColorModeProvider from "../../context/ColorModeContext"; | |||
| import { | |||
| USER_DETAILS_REQ, | |||
| } from "../../store/actions/users/usersActionConstants"; | |||
| import { registerSuccess } from "../../store/actions/register/registerActions"; | |||
| import { runSaga } from "redux-saga"; | |||
| import { userDetails } from "../../store/saga/usersSaga"; | |||
| import { registerUser } from "../../store/saga/registerSaga"; | |||
| describe("UserDetails reducer tests", () => { | |||
| let spyOnUseSelector; | |||
| let spyOnUseDispatch; | |||
| let mockDispatch; | |||
| beforeEach(() => { | |||
| // Mock useSelector hook | |||
| spyOnUseSelector = jest.spyOn(redux, "useSelector"); | |||
| spyOnUseSelector.mockReturnValueOnce(mockState.user.user); | |||
| // 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 run register saga function with actions", async () => { | |||
| const dispatchedActions = []; | |||
| api.register = jest.fn(() => Promise.resolve()); | |||
| const fakeStore = { | |||
| getState: () => ({ | |||
| isSuccess: false, | |||
| errorMessage: "", | |||
| }), | |||
| dispatch: (action) => dispatchedActions.push(action), | |||
| }; | |||
| await runSaga(fakeStore, registerUser, { | |||
| payload: { | |||
| password:'', | |||
| email:'', | |||
| confirm:'', | |||
| position:'', | |||
| linkedIn:'', | |||
| phone:'', | |||
| token:'', | |||
| }, | |||
| }).done; | |||
| expect(api.register.mock.calls.length).toBe(1); | |||
| expect(dispatchedActions).toContainEqual(registerSuccess()); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,83 @@ | |||
| import * as redux from "react-redux"; | |||
| import store from "../../store"; | |||
| import { Router } from "react-router-dom"; | |||
| import history from "../../store/utils/history"; | |||
| import { mockState } from "../../mockState"; | |||
| import { render } from "@testing-library/react"; | |||
| import * as api from '../../request/usersRequest' | |||
| import UserDetails from "../../pages/UsersPage/UserDetails"; | |||
| import ColorModeProvider from "../../context/ColorModeContext"; | |||
| import { | |||
| USER_DETAILS_REQ, | |||
| } from "../../store/actions/users/usersActionConstants"; | |||
| import { userDetails } from "../../store/saga/usersSaga"; | |||
| import { stateUserDetailsSuccess } from "../../store/actions/users/usersActions"; | |||
| import { runSaga } from "redux-saga"; | |||
| jest.mock("react-router-dom", () => ({ | |||
| ...jest.requireActual("react-router-dom"), | |||
| useParams: () => ({ | |||
| id: 1, | |||
| }), | |||
| })); | |||
| describe("UserDetails reducer tests", () => { | |||
| const cont = ( | |||
| <ColorModeProvider> | |||
| <redux.Provider store={store}> | |||
| <Router history={history}> | |||
| <UserDetails /> | |||
| </Router> | |||
| </redux.Provider> | |||
| </ColorModeProvider> | |||
| ); | |||
| let spyOnUseSelector; | |||
| let spyOnUseDispatch; | |||
| let mockDispatch; | |||
| beforeEach(() => { | |||
| // Mock useSelector hook | |||
| spyOnUseSelector = jest.spyOn(redux, "useSelector"); | |||
| spyOnUseSelector.mockReturnValueOnce(mockState.user.user); | |||
| // 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 user details with params request when rendered", () => { | |||
| render(cont); | |||
| expect(mockDispatch).toHaveBeenCalledWith({ | |||
| type: USER_DETAILS_REQ, | |||
| payload: { id: 1 }, | |||
| }); | |||
| }); | |||
| it("should run userDetails saga function with actions", async () => { | |||
| const dispatchedActions = []; | |||
| api.userDetailsRequest = jest.fn(() => Promise.resolve({ data: mockState.user.user })); | |||
| const fakeStore = { | |||
| getState: () => mockState.user, | |||
| dispatch: (action) => dispatchedActions.push(action), | |||
| }; | |||
| await runSaga(fakeStore, userDetails, { | |||
| payload: { | |||
| id: 1, | |||
| }, | |||
| }).done; | |||
| expect(api.userDetailsRequest.mock.calls.length).toBe(1); | |||
| expect(dispatchedActions).toContainEqual(stateUserDetailsSuccess(mockState.user.user)); | |||
| }); | |||
| }); | |||
| @@ -8,11 +8,17 @@ import UsersPage from "../../pages/UsersPage/UsersPage"; | |||
| import * as api from "../../request/usersRequest"; | |||
| import { runSaga } from "redux-saga"; | |||
| import { FETCH_USERS_REQ } from "../../store/actions/users/usersActionConstants"; | |||
| import { setUsersError } from "../../store/actions/users/usersActions"; | |||
| import { getUsers } from "../../store/saga/usersSaga"; | |||
| import { useTranslation } from 'react-i18next'; | |||
| import { | |||
| deleteStateUser, | |||
| setEnableUsers, | |||
| setUsers, | |||
| setUsersError, | |||
| toggleSingleUser, | |||
| } from "../../store/actions/users/usersActions"; | |||
| import { deleteUser, enableUser, getUsers } from "../../store/saga/usersSaga"; | |||
| import { useTranslation } from "react-i18next"; | |||
| describe("Stats reducer tests", () => { | |||
| describe("User management reducer tests", () => { | |||
| const cont = ( | |||
| <redux.Provider store={store}> | |||
| <Router history={history}> | |||
| @@ -52,10 +58,10 @@ describe("Stats reducer tests", () => { | |||
| it("should handle users 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 } }, | |||
| response: { | |||
| data: { message: mockState.selections.fetchSelectionsErrorMessage }, | |||
| }, | |||
| }; | |||
| api.getAllUsers = jest.fn(() => Promise.reject(error)); | |||
| @@ -67,8 +73,66 @@ describe("Stats reducer tests", () => { | |||
| await runSaga(fakeStore, getUsers).done; | |||
| expect(api.getAllUsers.mock.calls.length).toBe(1); | |||
| expect(dispatchedActions).toContainEqual( | |||
| setUsersError(undefined) | |||
| ); | |||
| expect(dispatchedActions).toContainEqual(setUsersError(undefined)); | |||
| }); | |||
| it("should run getUsers saga function with actions", async () => { | |||
| const dispatchedActions = []; | |||
| api.getAllUsers = jest | |||
| .fn() | |||
| .mockResolvedValue({ data: mockState.users.users }); | |||
| const fakeStore = { | |||
| getState: () => mockState.users, | |||
| dispatch: (action) => dispatchedActions.push(action), | |||
| }; | |||
| // wait for saga to complete | |||
| await runSaga(fakeStore, getUsers).done; | |||
| expect(api.getAllUsers.mock.calls.length).toBe(1); | |||
| expect(dispatchedActions).toContainEqual(setUsers(mockState.users.users)); | |||
| }); | |||
| it("should run enableUser saga function with actions", async () => { | |||
| const dispatchedActions = []; | |||
| api.enableUserRequest = jest.fn(() => Promise.resolve(1)); | |||
| const fakeStore = { | |||
| getState: () => mockState.users, | |||
| dispatch: (action) => dispatchedActions.push(action), | |||
| }; | |||
| await runSaga(fakeStore, enableUser, { | |||
| payload: { | |||
| id: 1, | |||
| }, | |||
| }).done; | |||
| expect(api.enableUserRequest.mock.calls.length).toBe(1); | |||
| expect(dispatchedActions).toContainEqual(setEnableUsers()); | |||
| expect(dispatchedActions).toContainEqual(toggleSingleUser()); | |||
| }); | |||
| it("should run deleteUser saga function with actions", async () => { | |||
| const dispatchedActions = []; | |||
| api.deleteUserRequest = jest.fn(() => Promise.resolve({ data: 1 })); | |||
| const fakeStore = { | |||
| getState: () => mockState.users, | |||
| dispatch: (action) => dispatchedActions.push(action), | |||
| }; | |||
| await runSaga(fakeStore, deleteUser, { | |||
| payload: { | |||
| id: 1, | |||
| }, | |||
| }).done; | |||
| expect(api.deleteUserRequest.mock.calls.length).toBe(1); | |||
| expect(dispatchedActions).toContainEqual(deleteStateUser(1)); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,53 @@ | |||
| import * as redux from "react-redux"; | |||
| import store from "../../store"; | |||
| import { Router } from "react-router-dom"; | |||
| import history from "../../store/utils/history"; | |||
| import { mockState } from "../../mockState"; | |||
| import { render, screen, fireEvent, waitFor } from "@testing-library/react"; | |||
| import RegisterPage from "../../pages/RegisterPage/RegisterPage"; | |||
| import { FormProvider } from "../../context/FormContext"; | |||
| const token ='' | |||
| const mail = ""; | |||
| const mockHistoryPush = jest.fn(); | |||
| jest.mock("react-router-dom", () => ({ | |||
| ...jest.requireActual("react-router-dom"), | |||
| useHistory: () => ({ | |||
| push: mockHistoryPush, | |||
| }), | |||
| useLocation: () => ({ | |||
| search: `/register?token=${token}&email=${mail}`, | |||
| }), | |||
| })); | |||
| describe("Register page tests", () => { | |||
| var props = { | |||
| history: { | |||
| replace: jest.fn(), | |||
| push: jest.fn(), | |||
| location: { | |||
| pathname: "", | |||
| }, | |||
| }, | |||
| }; | |||
| const cont = ( | |||
| <FormProvider> | |||
| <redux.Provider store={store}> | |||
| <Router history={history}> | |||
| <RegisterPage {...props} /> | |||
| </Router> | |||
| </redux.Provider> | |||
| </FormProvider> | |||
| ); | |||
| afterEach(() => { | |||
| jest.restoreAllMocks(); | |||
| }); | |||
| it("Should render error message", () => { | |||
| render(cont); | |||
| expect(screen.getByTestId("error-h")).toBeDefined(); | |||
| }); | |||
| }); | |||
| @@ -0,0 +1,90 @@ | |||
| import * as redux from "react-redux"; | |||
| import store from "../../store"; | |||
| import { Router } from "react-router-dom"; | |||
| import history from "../../store/utils/history"; | |||
| import { mockState } from "../../mockState"; | |||
| import { render, screen, fireEvent, waitFor } from "@testing-library/react"; | |||
| import RegisterPage from "../../pages/RegisterPage/RegisterPage"; | |||
| import { FormProvider } from "../../context/FormContext"; | |||
| const token = | |||
| "CfDJ8N77hhxpq99AuN1MAz9yxEG4HLGzmqe2fKGnXq8%2b3IWmhUdA3BZfaRAyhqLgUA%2fTAKarHSos484YEGrm13edjQbYXboYRnzXfEBdrhdAO5yFiEoij24x6k9os6JVfIiCVDfEmAA9zS23zaTqak9URTkUxYk4%2fsxR0DyE4YFqH485q%2fvIG0flGlotuHyLeE5i%2bQ%3d%3d"; | |||
| const mail = "jest@dilig.net"; | |||
| const mockHistoryPush = jest.fn(); | |||
| jest.mock("react-router-dom", () => ({ | |||
| ...jest.requireActual("react-router-dom"), | |||
| useHistory: () => ({ | |||
| push: mockHistoryPush, | |||
| }), | |||
| useLocation: () => ({ | |||
| search: `/register?token=${token}&email=${mail}`, | |||
| }), | |||
| })); | |||
| describe("Register page tests", () => { | |||
| var props = { | |||
| history: { | |||
| replace: jest.fn(), | |||
| push: jest.fn(), | |||
| location: { | |||
| pathname: "", | |||
| }, | |||
| }, | |||
| }; | |||
| const cont = ( | |||
| <FormProvider> | |||
| <redux.Provider store={store}> | |||
| <Router history={history}> | |||
| <RegisterPage {...props} /> | |||
| </Router> | |||
| </redux.Provider> | |||
| </FormProvider> | |||
| ); | |||
| // let spyOnUseSelector; | |||
| // let spyOnUseDispatch; | |||
| // let mockDispatch; | |||
| beforeEach(() => { | |||
| // | |||
| }); | |||
| afterEach(() => { | |||
| jest.restoreAllMocks(); | |||
| }); | |||
| it("Should render", () => { | |||
| render(cont); | |||
| expect(screen.getByTestId("btn")).toBeDefined(); | |||
| }); | |||
| it("Email input should have default value", () => { | |||
| render(cont); | |||
| expect(screen.getByTestId("reg-input-1").value).toBe("jest@dilig.net"); | |||
| }); | |||
| it("Email input should be disabled by default", () => { | |||
| render(cont); | |||
| expect(screen.getByTestId("reg-input-1")).toHaveAttribute("disabled"); | |||
| }); | |||
| it("Should show second step form after submiting first", async () => { | |||
| render(cont); | |||
| fireEvent.change(screen.getByTestId("reg-input-2"), { | |||
| target: { value: "Password123!" }, | |||
| }); | |||
| fireEvent.change(screen.getByTestId("reg-input-3"), { | |||
| target: { value: "Password123!" }, | |||
| }); | |||
| fireEvent.click(screen.getByTestId("btn")); | |||
| // waiting for formik validation | |||
| await waitFor(() => | |||
| expect(screen.getByTestId("reg-input-4")).toBeDefined() | |||
| ); | |||
| }); | |||
| }); | |||
| @@ -94,6 +94,7 @@ function FirstStepForm() { | |||
| margin="normal" | |||
| disabled | |||
| fullWidth | |||
| inputProps={{ "data-testid": "reg-input-1" }} | |||
| value={formik.values.email} | |||
| onChange={formik.handleChange} | |||
| error={formik.touched.email && Boolean(formik.errors.email)} | |||
| @@ -106,6 +107,7 @@ function FirstStepForm() { | |||
| margin="normal" | |||
| type={showPassword ? "text" : "password"} | |||
| fullWidth | |||
| inputProps={{ "data-testid": "reg-input-2" }} | |||
| onChange={formik.handleChange} | |||
| error={formik.touched.password && Boolean(formik.errors.password)} | |||
| helperText={formik.touched.password && formik.errors.password} | |||
| @@ -129,6 +131,7 @@ function FirstStepForm() { | |||
| margin="normal" | |||
| type={showPassword ? "text" : "password"} | |||
| fullWidth | |||
| inputProps={{ "data-testid": "reg-input-3" }} | |||
| onChange={formik.handleChange} | |||
| error={formik.touched.confirm && Boolean(formik.errors.confirm)} | |||
| helperText={formik.touched.confirm && formik.errors.confirm} | |||
| @@ -70,12 +70,14 @@ function SecondStepForm() { | |||
| label={t("registration.phone")} | |||
| margin="normal" | |||
| fullWidth | |||
| inputProps={{ "data-testid": "reg-input-4" }} | |||
| onChange={formik.handleChange} | |||
| error={formik.touched.phone && Boolean(formik.errors.phone)} | |||
| helperText={formik.touched.phone && formik.errors.phone} | |||
| /> | |||
| <TextField | |||
| name="position" | |||
| inputProps={{ "data-testid": "reg-input-5" }} | |||
| label={t("registration.position")} | |||
| margin="normal" | |||
| fullWidth | |||
| @@ -85,6 +87,7 @@ function SecondStepForm() { | |||
| /> | |||
| <TextField | |||
| name="linkedin" | |||
| inputProps={{ "data-testid": "reg-input-6" }} | |||
| label={t("registration.linkedinProfile")} | |||
| margin="normal" | |||
| fullWidth | |||
| @@ -1,4 +1,18 @@ | |||
| export const mockState = { | |||
| user: { | |||
| user: { | |||
| id: 1, | |||
| firstName: "User", | |||
| lastName: "User", | |||
| email: "user.user@dilig.net", | |||
| isEnabled: true, | |||
| phoneNumber: "123123", | |||
| position: "ss", | |||
| linkedIn: "ss", | |||
| }, | |||
| errorMessage: "", | |||
| }, | |||
| schedule: { | |||
| schedule: [ | |||
| { | |||
| @@ -97,7 +97,6 @@ const RegisterPage = ({ history }) => { | |||
| <> | |||
| <Container | |||
| component="main" | |||
| maxWidth="xl" | |||
| className="c-login-container" | |||
| fullwidth="true" | |||
| > | |||
| @@ -146,7 +145,7 @@ const RegisterPage = ({ history }) => { | |||
| <Step /> | |||
| </> | |||
| ) : ( | |||
| <h3 style={{ margin: "50px 0px" }}>There was a mistake...</h3> | |||
| <h3 data-testid='error-h' style={{ margin: "50px 0px" }}>There was a mistake...</h3> | |||
| )} | |||
| </Box> | |||
| </Container> | |||