Преглед изворни кода

Merge branch 'feature/unit_tests_candidate_details_page-fe' of Neca/HRCenter into FE_dev

pull/155/head
safet.purkovic пре 3 година
родитељ
комит
f201f72588

+ 133
- 0
src/__tests__/ReduxTests/candidateDetailsPageReducer.test.js Прегледај датотеку

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/candidatesRequest";
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 {
fetchCandidateSuccess,
fetchCandidateError,
} from "../../store/actions/candidate/candidateActions";
import * as helper from "../../util/helpers/rejectErrorCodeHelper";
import CandidateDetailsPage from "../../pages/CandidatesPage/CandidateDetailsPage";

const mockHistoryPush = jest.fn();

// mock param which we send as part of URL
jest.mock("react-router-dom", () => ({
...jest.requireActual("react-router-dom"),
useHistory: () => ({
push: mockHistoryPush,
}),
useParams: () => ({
id: 1,
}),
}));

describe("CandidateDetailsPage render tests", () => {
var props = {
history: {
replace: jest.fn(),
push: jest.fn(),
location: {
pathname: "",
},
},
};
const cont = (
<redux.Provider store={store}>
<Router history={history}>
<CandidateDetailsPage {...props} />
</Router>
</redux.Provider>
);

let spyOnUseSelector;
let spyOnUseDispatch;
let mockDispatch;

beforeEach(() => {
spyOnUseSelector = jest.spyOn(redux, "useSelector");
spyOnUseSelector
.mockReturnValueOnce(mockState.users.users)
.mockReturnValueOnce(mockState.users.user)
.mockReturnValueOnce(mockState.candidate.candidate);

spyOnUseDispatch = jest.spyOn(redux, "useDispatch");

// Mock dispatch function returned from useDispatch
mockDispatch = jest.fn();
spyOnUseDispatch.mockReturnValue(mockDispatch);
});

afterEach(() => {
jest.restoreAllMocks();
});

it("Should dispatch fetch candidate request when rendered", () => {
render(cont);
expect(mockDispatch).toHaveBeenCalledWith({
payload: { id: 1 },
type: CANDIDATE_FETCH,
});
});

it("Should dispatch fetch users request when rendered", () => {
render(cont);
expect(mockDispatch).toHaveBeenCalledWith({
type: FETCH_USERS_REQ,
});
});

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));

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

await runSaga(fakeStore, getSingleCandidate, { payload: { id: 1 } }).done;
expect(api.getCandidate.mock.calls.length).toBe(1);
expect(dispatchedActions).toContainEqual(
fetchCandidateSuccess(mockedCall.data)
);
});

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

helper.rejectErrorCodeHelper = jest.fn(
() => mockState.candidate.fetchCandidateErrorMessage
);

const error = {
response: {
data: { message: mockState.candidate.fetchCandidateErrorMessage },
},
};
api.getCandidate = jest.fn(() => Promise.reject(error));

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

await runSaga(fakeStore, getSingleCandidate, { payload: { id: 1 } }).done;

expect(api.getCandidate.mock.calls.length).toBe(1);
expect(dispatchedActions).toContainEqual(
fetchCandidateError(error.response.data.message)
);
});
});

+ 0
- 3
src/__tests__/ReduxTests/candidatesPageReducer.test.js Прегледај датотеку

let mockDispatch; let mockDispatch;


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


// Mock dispatch function returned from useDispatch
mockDispatch = jest.fn(); mockDispatch = jest.fn();
spyOnUseDispatch.mockReturnValue(mockDispatch); spyOnUseDispatch.mockReturnValue(mockDispatch);
}); });

+ 23
- 18
src/__tests__/ReduxTests/tableViewPageReducer.test.js Прегледај датотеку

filterCandidatesError, filterCandidatesError,
} from "../../store/actions/candidates/candidatesActions"; } from "../../store/actions/candidates/candidatesActions";
import { PAGE_SIZE_CANDIDATES } from "../../constants/keyCodeConstants"; import { PAGE_SIZE_CANDIDATES } from "../../constants/keyCodeConstants";
import * as helper from "../../util/helpers/rejectErrorCodeHelper";


describe("TableViewPage render tests", () => { describe("TableViewPage render tests", () => {
const cont = ( const cont = (
); );
}); });


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

helper.rejectErrorCodeHelper = jest.fn(
() => mockState.candidates.fetchCandidatesErrorMessage
);


// const error = {
// response: {
// data: { message: mockState.candidates.fetchCandidatesErrorMessage },
// },
// };
// api.getFilteredCandidates = jest.fn(() => Promise.reject(error));
const error = {
response: {
data: { message: mockState.candidates.fetchCandidatesErrorMessage },
},
};
api.getFilteredCandidates = jest.fn(() => Promise.reject(error));


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


// await runSaga(fakeStore, fc.filterCandidates, {}).done;
await runSaga(fakeStore, fc.filterCandidates, {}).done;


// expect(api.getFilteredCandidates.mock.calls.length).toBe(1);
// expect(dispatchedActions).toContainEqual(
// filterCandidatesError(error.response.data.message)
// );
// });
expect(api.getFilteredCandidates.mock.calls.length).toBe(1);
expect(dispatchedActions).toContainEqual(
filterCandidatesError(error.response.data.message)
);
});
}); });

+ 22
- 3
src/__tests__/UITests/adsCandidatesPageUI.test.js Прегледај датотеку

import { render } from "@testing-library/react";
import { render, fireEvent } from "@testing-library/react";
import * as redux from "react-redux"; import * as redux from "react-redux";
import store from "../../store"; import store from "../../store";
import { mockState } from "../../mockState"; import { mockState } from "../../mockState";
import AdsCandidatesPage from "../../pages/CandidatesPage/AdsCandidatesPage"; import AdsCandidatesPage from "../../pages/CandidatesPage/AdsCandidatesPage";


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

const cont = ( const cont = (
<redux.Provider store={store}> <redux.Provider store={store}>
<Router history={history}> <Router history={history}>
<AdsCandidatesPage search="" />
<AdsCandidatesPage search="" {...props} />
</Router> </Router>
</redux.Provider> </redux.Provider>
); );
).toBeDefined(); ).toBeDefined();
}); });


it("Number of sliders should be equal to length of our array adsCandidates", () => {
it("Number of sliders should be equal to length of our adsCandidates array", () => {
const { container } = render(cont); const { container } = render(cont);
expect(container.getElementsByClassName("ads-candidates").length).toBe( expect(container.getElementsByClassName("ads-candidates").length).toBe(
mockState.candidates.adsCandidates.length mockState.candidates.adsCandidates.length
container.getElementsByClassName("active-ads-ads-arrows").length container.getElementsByClassName("active-ads-ads-arrows").length
).toBe(0); ).toBe(0);
}); });

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

+ 97
- 0
src/__tests__/UITests/candidateDetailsPageUI.test.js Прегледај датотеку

import { render, fireEvent, screen } from "@testing-library/react";
import * as redux from "react-redux";
import store from "../../store";
import { mockState } from "../../mockState";
import { Router } from "react-router-dom";
import history from "../../store/utils/history";
import CandidateDetailsPage from "../../pages/CandidatesPage/CandidateDetailsPage";

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

const cont = (
<redux.Provider store={store}>
<Router history={history}>
<CandidateDetailsPage {...props} />
</Router>
</redux.Provider>
);

let spyOnUseSelector;

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

afterEach(() => {
jest.restoreAllMocks();
});

it("Should render", () => {
const { container } = render(cont);
expect(
container.getElementsByClassName("main-candidate-container")[0]
).toBeDefined();
});

it("Should render button for deleting candidate", () => {
const { container } = render(cont);
expect(container.getElementsByClassName("candidate-btn")[0]).toBeDefined();
});

it("Should render dialog after clicking button for deleting candidate", () => {
const { container } = render(cont);
fireEvent.click(container.getElementsByClassName("candidate-btn")[0]);
expect(screen.getByTestId("alert-container")).toBeDefined();
});

it("Should render div for sending comment", () => {
const { container } = render(cont);
expect(
container.getElementsByClassName("comment-container")[0]
).toBeDefined();
});

it("Should render button for downloading CV", () => {
const { container } = render(cont);
expect(
container.getElementsByClassName("applicant-cv-button")[0]
).toBeDefined();
});

it("Should render two ads for candidate", () => {
const { container } = render(cont);
expect(container.getElementsByClassName("applicant-add").length).toBe(2);
});

it("Should render three comments", () => {
const { container } = render(cont);
expect(
container.getElementsByClassName("comment-sub-container").length
).toBe(3);
});

it("Should render page with all candidates", () => {
const { container } = render(cont);
fireEvent.click(
container.getElementsByClassName("applicant-ads-back-button")[0]
);
const arg = { pathname: "/candidates" };
expect(props.history.push).toHaveBeenCalledWith(arg);
});
});

+ 1
- 0
src/assets/styles/components/_candidatePage.scss Прегледај датотеку

line-height: 20px; line-height: 20px;
text-decoration-line: underline; text-decoration-line: underline;
color: #226cb0; color: #226cb0;
cursor: pointer;
} }


.tagStyle { .tagStyle {

+ 0
- 3
src/components/Candidates/CandidateCard.js Прегледај датотеку

const navigateToDetailsPage = () => { const navigateToDetailsPage = () => {
history.push({ history.push({
pathname: CANDIDATES_PAGE + "/" + candidate.applicantId, pathname: CANDIDATES_PAGE + "/" + candidate.applicantId,
state: {
from: history.location.pathname,
},
}); });
}; };



+ 19
- 7
src/pages/CandidatesPage/CandidateDetailsPage.js Прегледај датотеку

import React from "react"; import React from "react";
import { useEffect, useState, useRef } from "react"; import { useEffect, useState, useRef } from "react";
import { Link, useParams } from "react-router-dom";
import { useParams } from "react-router-dom";
import deleteImage from "../../../src/assets/images/delete.png"; import deleteImage from "../../../src/assets/images/delete.png";
import planeImage from "../../../src/assets/images/planeVectorBlue.png"; import planeImage from "../../../src/assets/images/planeVectorBlue.png";
import IconButton from "../../components/IconButton/IconButton"; import IconButton from "../../components/IconButton/IconButton";
} }
}; };


const goToPageWithAllCandidates = () => {
history.push({
pathname: "/candidates",
});
};

return (candidate && Object.keys(candidate).length === 0) || return (candidate && Object.keys(candidate).length === 0) ||
user === undefined ? ( user === undefined ? (
<p>Loading...</p> <p>Loading...</p>
> >
<p className="candidate-property-value">{candidate.email}</p> <p className="candidate-property-value">{candidate.email}</p>
<p className="candidate-property-value"> <p className="candidate-property-value">
{candidate.phoneNumber}
{candidate.phoneNumber === "" ? "/" : candidate.phoneNumber}
</p> </p>
</div> </div>
</div> </div>
className="candidate-property-container" className="candidate-property-container"
> >
<p className="candidate-property-value"> <p className="candidate-property-value">
{candidate.linkedlnLink ?? "/"}
{candidate.linkedlnLink === "" ? "/" : candidate.linkedlnLink}
</p> </p>
<p className="candidate-property-value"> <p className="candidate-property-value">
{candidate.gitHubLink ?? "/"}
{candidate.githubLink === "" ? "/" : candidate.githubLink}
</p> </p>
<p className="candidate-property-value"> <p className="candidate-property-value">
{candidate.bitBucketLink ?? "/"}
{candidate.bitBucketLink === ""
? "/"
: candidate.bitBucketLink}
</p> </p>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div className="applicant-ads-buttons-container"> <div className="applicant-ads-buttons-container">
<Link to="/candidates" className="applicant-ads-back-button">
<p
to="/candidates"
className="applicant-ads-back-button"
onClick={goToPageWithAllCandidates}
>
Nazad na sve kandidate Nazad na sve kandidate
</Link>
</p>
<a <a
className="applicant-cv-button" className="applicant-cv-button"
download={candidate.firstName + candidate.lastName + ".pdf"} download={candidate.firstName + candidate.lastName + ".pdf"}

Loading…
Откажи
Сачувај