Explorar el Código

Merge branch 'feature/unit_tests_aditional_tests' of Neca/HRCenter into FE_dev

pull/158/head
safet.purkovic hace 3 años
padre
commit
0f5ce9da76

+ 2
- 4
src/__tests__/ReduxTests/adsCandidatesPageReducer.test.js Ver fichero

@@ -29,15 +29,13 @@ describe("AdsCandidatesPage render tests", () => {
let mockDispatch;

beforeEach(() => {
// Mock useSelector hook
spyOnUseSelector = jest.spyOn(redux, "useSelector");
spyOnUseSelector
.mockReturnValueOnce(mockState.candidates.adsCandidates)
.mockReturnValueOnce(mockState.candidates.adsCandidates);
// Mock useDispatch hook
spyOnUseDispatch = jest.spyOn(redux, "useDispatch");

// Mock dispatch function returned from useDispatch
mockDispatch = jest.fn();
spyOnUseDispatch.mockReturnValue(mockDispatch);
});
@@ -66,7 +64,7 @@ describe("AdsCandidatesPage render tests", () => {
it("should load and handle adsCandidates in case of success", async () => {
const dispatchedActions = [];

const mockedCall = { data: mockState.technologies.technologies };
const mockedCall = { data: mockState.candidates.adsCandidates };
api.getFilteredAdsCandidates = jest.fn(() => Promise.resolve(mockedCall));

const fakeStore = {

+ 51
- 2
src/__tests__/ReduxTests/candidateDetailsPageReducer.test.js Ver fichero

@@ -5,14 +5,20 @@ import history from "../../store/utils/history";
import { mockState } from "../../mockState";
import { render } from "@testing-library/react";
import * as api from "../../request/candidatesRequest";
import * as api2 from '../../request/usersRequest';
import { runSaga } from "redux-saga";
import { CANDIDATE_FETCH } from "../../store/actions/candidate/candidateActionConstants";
import { FETCH_USERS_REQ } from "../../store/actions/users/usersActionConstants";
import { getSingleCandidate } from "../../store/saga/candidatesSaga";
import {getUsers} from '../../store/saga/usersSaga'
import {
fetchCandidateSuccess,
fetchCandidateError,
} from "../../store/actions/candidate/candidateActions";
import {
setUsers,
setUsersError
} from "../../store/actions/users/usersActions";
import * as helper from "../../util/helpers/rejectErrorCodeHelper";
import CandidateDetailsPage from "../../pages/CandidatesPage/CandidateDetailsPage";

@@ -87,8 +93,6 @@ describe("CandidateDetailsPage render tests", () => {
it("should load and handle candidate in case of success", async () => {
const dispatchedActions = [];

helper.rejectErrorCodeHelper = jest.fn(() => "Server error");

const mockedCall = { data: mockState.candidate.candidate };
api.getCandidate = jest.fn(() => Promise.resolve(mockedCall));

@@ -104,6 +108,24 @@ describe("CandidateDetailsPage render tests", () => {
);
});

it("should load and handle users in case of success", async () => {
const dispatchedActions = [];

const mockedCall = { data: mockState.users.users };
api2.getAllUsers = jest.fn(() => Promise.resolve(mockedCall));

const fakeStore = {
getState: () => mockState.users.users,
dispatch: (action) => dispatchedActions.push(action),
};

await runSaga(fakeStore, getUsers).done;
expect(api2.getAllUsers.mock.calls.length).toBe(1);
expect(dispatchedActions).toContainEqual(
setUsers(mockedCall.data)
);
});

it("should handle candidate load errors in case of failure", async () => {
const dispatchedActions = [];

@@ -130,4 +152,31 @@ describe("CandidateDetailsPage render tests", () => {
fetchCandidateError(error.response.data.message)
);
});

it("should handle users load errors in case of failure", async () => {
const dispatchedActions = [];

helper.rejectErrorCodeHelper = jest.fn(
() => mockState.users.fetchUsersErrorMessage
);

const error = {
response: {
data: { message: mockState.users.fetchUsersErrorMessage },
},
};
api2.getAllUsers = jest.fn(() => Promise.reject(error));

const fakeStore = {
getState: () => mockState.users.users,
dispatch: (action) => dispatchedActions.push(action),
};

await runSaga(fakeStore, getUsers).done;

expect(api2.getAllUsers.mock.calls.length).toBe(1);
expect(dispatchedActions).toContainEqual(
setUsersError(error.response.data.message)
);
});
});

+ 0
- 2
src/__tests__/ReduxTests/candidatesPageReducer.test.js Ver fichero

@@ -51,8 +51,6 @@ describe("CandidatesPage render tests", () => {
it("should load and handle techonologies in case of success", async () => {
const dispatchedActions = [];

helper.rejectErrorCodeHelper = jest.fn(()=> 'Server error')

const mockedCall = { data: mockState.technologies.technologies };
api.getAllTechnologies = jest.fn(() => Promise.resolve(mockedCall));


+ 3
- 2
src/__tests__/ReduxTests/schedulePageReducer.test.js Ver fichero

@@ -47,11 +47,12 @@ describe("SchedulePage render tests", () => {

it("Should dispatch get schedule request when rendered", () => {
render(cont);
const date = new Date()
expect(mockDispatch).toHaveBeenCalledWith({
type: SCHEDULE_FETCH,
payload: {
month: 12,
year: 2022,
month: date.getMonth() + 1,
year: date.getFullYear(),
},
});
});

+ 3
- 3
src/__tests__/ReduxTests/tableViewPageReducer.test.js Ver fichero

@@ -11,7 +11,7 @@ import { runSaga } from "redux-saga";

import * as fc from "../../store/saga/candidatesSaga";
import {
filterCandidates,
filterCandidatesSuccess,
filterCandidatesError,
} from "../../store/actions/candidates/candidatesActions";
import { PAGE_SIZE_CANDIDATES } from "../../constants/keyCodeConstants";
@@ -76,8 +76,8 @@ describe("TableViewPage render tests", () => {

await runSaga(fakeStore, fc.filterCandidates, {}).done;
expect(api.getFilteredCandidates.mock.calls.length).toBe(1);
expect(dispatchedActions[0].payload).toEqual(
filterCandidates(mockedCall.data).payload
expect(dispatchedActions).toContainEqual(
filterCandidatesSuccess(mockedCall.data)
);
});


+ 37
- 4
src/__tests__/UITests/adsCandidatesPageUI.test.js Ver fichero

@@ -1,4 +1,4 @@
import { render, fireEvent } from "@testing-library/react";
import { render, fireEvent, waitFor } from "@testing-library/react";
import * as redux from "react-redux";
import store from "../../store";
import { mockState } from "../../mockState";
@@ -50,14 +50,47 @@ describe("TableViewPage render tests", () => {
);
});

it("Number of arrows (left and right) should be 0 because there is no more than 4 candidates in any of ads", () => {
it("Number of candidates in slider (vissible and hidden) should be equal to the number of candidates which applied for ad", () => {
const { container } = render(cont);
expect(
container
.getElementsByClassName("ads-candidates")[0]
.getElementsByClassName("slick-slide").length
).toBe(mockState.candidates.adsCandidates[0].applicants.length);
});

it("Number of arrows (left and right) should be 1 because there is more than 4 candidates which applied for ad", () => {
const { container } = render(cont);
expect(
container.getElementsByClassName("active-ads-ads-arrows").length
).toBe(0);
).toBe(1);
});

it("After clicking on right arrow of first slider, first slider should show fifth candidate as forth card of slider", async () => {
const { container } = render(cont);
fireEvent.click(
container
.getElementsByClassName("active-ads-ads-arrows")[0]
.getElementsByTagName("button")[1]
);

await waitFor(() =>
expect(
container
.getElementsByClassName("ads-candidates")[0]
.getElementsByClassName("slick-active")[3]
.getElementsByClassName("candidate-card-container")[0]
.getElementsByClassName("candidate-card-applicant-name")[0]
.textContent
).toBe(
mockState.candidates.adsCandidates[0].applicants[4].firstName +
" " +
mockState.candidates.adsCandidates[0].applicants[4].lastName
)
);
});

it("Should render candidate details page", () => {
it("Should render candidate details page after clicking on candidate card", () => {
const { container } = render(cont);
fireEvent.click(
container.getElementsByClassName("candidate-card-container")[0]

+ 13
- 9
src/__tests__/UITests/candidatesPageUI.test.js Ver fichero

@@ -1,4 +1,4 @@
import { render, screen, fireEvent } from "@testing-library/react";
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
import * as redux from "react-redux";
import CandidatesPage from "../../pages/CandidatesPage/CandidatesPage";
import store from "../../store";
@@ -19,7 +19,7 @@ describe("CandidatesPage render tests", () => {

beforeEach(() => {
spyOnUseSelector = jest.spyOn(redux, "useSelector");
spyOnUseSelector.mockReturnValueOnce(mockState.technologies.technologies)
spyOnUseSelector.mockReturnValueOnce(mockState.technologies.technologies);
});

afterEach(() => {
@@ -53,11 +53,13 @@ describe("CandidatesPage render tests", () => {
);
});

// it("input for searching by name should be shown after clicking button for first time", () => {
// it("input for searching by name should be shown after clicking button for first time", async () => {
// const { container } = render(cont);
// fireEvent.click(container.getElementsByClassName("candidate-btn")[1]);
// expect(container.getElementsByClassName("proba")[0].style.visibility).toBe(
// "vissible"
// await waitFor(() =>
// expect(
// container.getElementsByClassName("proba")[0].style.visibility
// ).toBe("vissible")
// );
// });

@@ -68,11 +70,13 @@ describe("CandidatesPage render tests", () => {
).toBeDefined();
});

// it("should render AdsCandidatesPage component when button for switching to another view is clicked for the first time", () => {
// it("should render AdsCandidatesPage component when button for switching to another view is clicked for the first time", async () => {
// const { container } = render(cont);
// fireEvent.click(container.getElementsByClassName("candidate-btn")[0]);
// expect(
// container.getElementsByClassName("ads-candidates-container")[0]
// ).toBeDefined();
// await waitFor(() =>
// expect(
// container.getElementsByClassName("ads-candidates-container")[0]
// ).toBeDefined()
// );
// });
});

+ 14
- 0
src/__tests__/UITests/dayDetailsComponentUI.test.js Ver fichero

@@ -38,6 +38,20 @@ describe("DayDetailsComponent render tests", () => {
expect(screen.getByTestId("day-component-dialog")).toBeDefined();
});

it("Should render left arrow as disabled because we set that currenlty selected day is first day of month", () => {
render(cont);
expect(
screen.getAllByTestId("day-datails-left-arrow")[0]
).toBeDefined();
});

it("Should render right arrow as enabled because we set that currenlty selected day is first day of month", () => {
render(cont);
expect(
screen.getAllByTestId("day-datails-right-arrow")[0]
).toBeDefined();
});

it("Should show all interviews which we pass to component", () => {
render(cont);
expect(screen.getAllByTestId("day-details-component-process").length).toBe(

+ 41
- 4
src/__tests__/UITests/tableViewPageUI.test.js Ver fichero

@@ -1,4 +1,4 @@
import { render, screen, fireEvent } from "@testing-library/react";
import { render, screen, fireEvent,waitFor } from "@testing-library/react";
import * as redux from "react-redux";
import store from "../../store";
import { mockState } from "../../mockState";
@@ -6,12 +6,23 @@ import { Router } from "react-router-dom";
import history from "../../store/utils/history";
import TableViewPage from "../../pages/CandidatesPage/TableViewPage";
import { PAGE_SIZE_CANDIDATES } from "../../constants/keyCodeConstants";
import * as requests from '../../request/candidatesRequest'

describe("TableViewPage render tests", () => {
var props = {
history: {
replace: jest.fn(),
push: jest.fn(),
location: {
pathname: "/candidates",
},
},
};

const cont = (
<redux.Provider store={store}>
<Router history={history}>
<TableViewPage search="" />
<TableViewPage search="" {...props} />
</Router>
</redux.Provider>
);
@@ -43,7 +54,7 @@ describe("TableViewPage render tests", () => {
).toBeDefined();
});

it("Pagination component should show 1 page because number of elements of our candidates arrat is 2 and the size of page is 2)", () => {
it("Here we check if our component is displaying as many pages as it should display", () => {
const { container } = render(cont);
expect(
container
@@ -59,10 +70,36 @@ describe("TableViewPage render tests", () => {
);
});

it("Table should initialy contain 2 rows", () => {
it("The number of table rows should be equal to the number of candidates", () => {
const { container } = render(cont);
expect(container.getElementsByClassName("cadidate-row").length).toBe(
mockState.candidates.candidates.length
);
});

it("Should render candidate details page after clicking on table row", () => {
const { container } = render(cont);
fireEvent.click(container.getElementsByClassName("cadidate-row")[0]);
const arg = { pathname: "/candidates/1" };
expect(props.history.push).toHaveBeenCalledWith(arg);
});

it("Initially CV of candidate isn't displayed", () => {
const { container } = render(cont);
expect(container.getElementsByClassName('candidates-cv')[0].style.opacity).toBe("0")
});

// How to mock getCV() function ?
// it("Should render CV of candidate after clicking on CV name", async () => {
// const mockedCall = { data: mockState.candidates.adsCandidates };
// requests.getCV = {}
// const { container } = render(cont);
// fireEvent.click(
// container
// .getElementsByClassName("cadidate-row")[0]
// .getElementsByTagName("td")[4]
// .getElementsByTagName("span")[0]
// );
// await waitFor(() => expect(container.getElementsByClassName('candidates-cv')[0].style.opacity).toBe("1"));
// });
});

+ 5
- 6
src/assets/styles/components/_candidatesPage.scss Ver fichero

@@ -233,15 +233,15 @@
}

.cls1 .slick-track {
margin-left: 30px !important;
margin-left: 35px !important;
}

.cls2 .slick-track {
margin-left: 20 !important;
margin-left: 20px !important;
}

.cls3 .slick-track {
margin-left: 20 !important;
margin-left: 0px !important;
}

.cls4 .slick-track {
@@ -254,10 +254,9 @@
}

.candidates-cv {
width: 695px;
height: 595px;
width: 500px;
height: 610px;
margin-right: 72px;
margin-top: 37px;
}

@media only screen and (max-width: 600px) {

+ 2
- 1
src/components/Schedules/DayDetailsComponent.js Ver fichero

@@ -142,7 +142,7 @@ const DayDetailsComponent = ({
}}
>
{isLeftArrowDisabled === true ? (
<div className="day-datails-arrow-container">
<div className="day-datails-arrow-container" data-testid="day-datails-left-arrow">
<img src={arrowLeftDisabled} />
</div>
) : (
@@ -161,6 +161,7 @@ const DayDetailsComponent = ({
<div
className="day-datails-arrow-container"
onClick={goForwardOneDay}
data-testid="day-datails-right-arrow"
>
<img src={arrowRight} />
</div>

+ 20
- 4
src/mockState.js Ver fichero

@@ -1,5 +1,4 @@
export const mockState = {
user: {
user: {
id: 1,
@@ -49,7 +48,7 @@ export const mockState = {
name: "HR intervju",
},
applicant: {
applicantId: 1,
applicantId: 11,
firstName: "Dzenis",
lastName: "Hadzifejzovic",
},
@@ -62,7 +61,7 @@ export const mockState = {
name: "HR intervju",
},
applicant: {
applicantId: 25,
applicantId: 22,
firstName: "Meris",
lastName: "Ahmatovic",
},
@@ -549,8 +548,25 @@ export const mockState = {
},
],
},
{
applicantId: 42,
firstName: "Safet",
lastName: "Purkovic",
dateOfApplication: "2022-12-14T11:30:36.3658961",
cv: "PDF",
experience: 3,
technologyApplicants: [
{
technology: {
technologyId: 1,
technologyType: "Backend",
name: ".NET",
},
},
],
},
],
nubmerOfApplicants: 4,
nubmerOfApplicants: 5,
},
{
id: 2,

+ 7
- 7
src/pages/CandidatesPage/AdsCandidatesPage.js Ver fichero

@@ -38,8 +38,8 @@ const AdsCandidatesPage = ({ history, search }) => {
dots: false,
infinite: false,
speed: 400,
slidesToShow: 3,
slidesToScroll: 3,
slidesToShow: 4,
slidesToScroll: 4,
initialSlide: 0,
arrows: true,
variableWidth: true,
@@ -47,8 +47,8 @@ const AdsCandidatesPage = ({ history, search }) => {
{
breakpoint: 1024,
settings: {
slidesToShow: 2,
slidesToScroll: 2,
slidesToShow: 3,
slidesToScroll: 3,
infinite: true,
dots: false,
},
@@ -56,8 +56,8 @@ const AdsCandidatesPage = ({ history, search }) => {
{
breakpoint: 900,
settings: {
slidesToShow: 1,
slidesToScroll: 1,
slidesToShow: 2,
slidesToScroll: 2,
initialSlide: 0,
},
},
@@ -120,7 +120,7 @@ const AdsCandidatesPage = ({ history, search }) => {
<button onClick={() => activeAdsArrowLeftHandler(index)}>
<img src={arrow_left} alt="arrow-left" />
</button>
<button onClick={() => activeAdsArrowRightHandler(index)}>
<button onClick={() => activeAdsArrowRightHandler(index)} className="kp">
<img src={arrow_right} alt="arrow-right" />
</button>
</div>

+ 7
- 7
src/pages/CandidatesPage/CandidatesPage.js Ver fichero

@@ -25,8 +25,8 @@ const CandidatesPage = ({ history }) => {
const technologies = useSelector(selectTechnologies);
const [search, setSearch] = useState("");
const [isSearchFieldVisible, setIsSearchFieldVisible] = useState(false);
const [isCVDisplayed, setIsCVDisplayed] = useState(false);
const [linkToCV, setLinkToCV] = useState("");
// const [isCVDisplayed, setIsCVDisplayed] = useState(false);
// const [linkToCV, setLinkToCV] = useState("");

useEffect(() => {
dispatch(setTechnologiesReq());
@@ -188,20 +188,20 @@ const CandidatesPage = ({ history }) => {
page={page}
setPage={setPage}
search={search}
setIsCVDisplayed={setIsCVDisplayed}
isCVDisplayed={isCVDisplayed}
setLinkToCV={setLinkToCV}
// setIsCVDisplayed={setIsCVDisplayed}
// isCVDisplayed={isCVDisplayed}
// setLinkToCV={setLinkToCV}
/>
) : (
<AdsCandidatesPage history={history} search={search} />
)}
{isTableView ? (
{/* {isTableView ? (
<Fade in={isCVDisplayed} timeout={400} className="candidates-cv">
<embed src={`data:application/pdf;base64,${linkToCV}`} />
</Fade>
) : (
""
)}
)} */}
</div>
</div>
);

+ 30
- 18
src/pages/CandidatesPage/TableViewPage.js Ver fichero

@@ -1,4 +1,4 @@
import React, { useEffect } from "react";
import React, { useEffect, useState } from "react";
import Pagination from "@mui/material/Pagination";
import { formatDate } from "../../util/helpers/dateHelpers";
import { useDispatch, useSelector } from "react-redux";
@@ -13,30 +13,24 @@ import {
selectPagination,
} from "../../store/selectors/candidatesSelectors";
import { getCV } from "../../request/candidatesRequest";
import Fade from "@mui/material/Fade";

const TableViewPage = ({
history,
setPage,
page,
search,
setIsCVDisplayed,
isCVDisplayed,
setLinkToCV,
// setIsCVDisplayed,
// isCVDisplayed,
// setLinkToCV,
}) => {
const dispatch = useDispatch();
const candidates = useSelector(selectCandidates);
const pagination = useSelector(selectPagination);
const theme = useTheme();
const matches = useMediaQuery(theme.breakpoints.down("361"));

const navigate = (applicantId) => {
history.push({
pathname: CANDIDATES_PAGE + "/" + applicantId,
state: {
from: history.location.pathname,
},
});
};
const [linkToCV, setLinkToCV] = useState("");
const [isCVDisplayed, setIsCVDisplayed] = useState(false);

useEffect(() => {
dispatch(
@@ -101,9 +95,22 @@ const TableViewPage = ({
.catch((e) => console.log(e));
};

const navigateToCandidateDetailsPage = (applicantId) => {
history.push({
pathname: CANDIDATES_PAGE + "/" + applicantId,
});
};

return (
<div className="candidates-table">
<div style={{ overflowX: "auto", marginLeft: matches ? 36 : 72 }}>
<div
style={{
overflowX: "auto",
marginLeft: matches ? 36 : 72,
display: "flex",
justifyContent:'space-between'
}}
>
<table
className="usersTable"
style={{ width: isCVDisplayed ? "784px" : "914px" }}
@@ -132,7 +139,9 @@ const TableViewPage = ({
style={{
cursor: "pointer",
}}
onClick={() => navigate(candidate.applicantId)}
onClick={() =>
navigateToCandidateDetailsPage(candidate.applicantId)
}
>
<td>
{(
@@ -172,6 +181,9 @@ const TableViewPage = ({
))}
</tbody>
</table>
<Fade in={isCVDisplayed} timeout={400}>
<embed src={`data:application/pdf;base64,${linkToCV}`} className="candidates-cv"/>
</Fade>
</div>
<Pagination
size={matches ? "small" : "medium"}
@@ -200,9 +212,9 @@ TableViewPage.propTypes = {
setPage: PropTypes.func,
page: PropTypes.number,
search: PropTypes.string,
setIsCVDisplayed: PropTypes.func,
isCVDisplayed: PropTypes.bool,
setLinkToCV: PropTypes.func,
// setIsCVDisplayed: PropTypes.func,
// isCVDisplayed: PropTypes.bool,
// setLinkToCV: PropTypes.func,
};

export default TableViewPage;

+ 3
- 2
src/request/candidatesRequest.js Ver fichero

@@ -1,4 +1,4 @@
import { deleteRequest, getRequest, postRequest,downloadPdf } from ".";
import { deleteRequest, getRequest, postRequest, downloadPdf } from ".";
import apiEndpoints from "./apiEndpoints";

export const getFilteredCandidates = (payload) => {
@@ -64,4 +64,5 @@ export const getCandidateOptions = () =>
export const initializeProcessRequest = (payload) =>
postRequest(apiEndpoints.candidates.initProcess, payload);

export const getCV = (fileName) => downloadPdf(apiEndpoints.applicant.getCV + "?fileName=" + fileName);
export const getCV = (fileName) =>
downloadPdf(apiEndpoints.applicant.getCV + "?fileName=" + fileName);

Cargando…
Cancelar
Guardar