Skip to content

Commit

Permalink
Merge branch 'feature/showHiddenToAdmin' of github.com:NIAEFEUP/nijob…
Browse files Browse the repository at this point in the history
…s-fe into feature/showHiddenToAdmin
  • Loading branch information
diogofonte committed Feb 27, 2023
2 parents 598f1ae + 695e803 commit be605e5
Show file tree
Hide file tree
Showing 10 changed files with 394 additions and 268 deletions.
465 changes: 216 additions & 249 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions src/actions/searchOffersActions.js
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ export const adminEnableOffer = (offerIdx) => ({
offerIdx,
});

export const setShowHidden = (showHidden) => ({
type: OfferSearchTypes.SET_SHOW_HIDDEN,
showHidden,
});

export const resetAdvancedSearchFields = () => (dispatch) => {
dispatch(setJobType(INITIAL_JOB_TYPE));
dispatch(setShowJobDurationSlider(false));
Expand Down
12 changes: 12 additions & 0 deletions src/actions/searchOffersActions.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
resetAdvancedSearchFields,
setOffersFetchError,
resetOffersFetchError,
setShowHidden,
} from "./searchOffersActions";

import { INITIAL_JOB_TYPE, INITIAL_JOB_DURATION } from "../reducers/searchOffersReducer";
Expand Down Expand Up @@ -54,6 +55,17 @@ describe("Search Offers actions", () => {
expect(setSearchValue(value)).toEqual(expectedAction);
});

it("should return Set Show Hidden action", () => {

const showHidden = true;
const expectedAction = {
type: OfferSearchTypes.SET_SHOW_HIDDEN,
showHidden,
};

expect(setShowHidden(showHidden)).toEqual(expectedAction);
});

it("should return Set Job Duration action", () => {

const jobDuration = [1, 2];
Expand Down
4 changes: 4 additions & 0 deletions src/components/HomePage/SearchArea/SearchArea.js
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,10 @@ export const SearchArea = ({ onSubmit, searchValue,
</form>
<SubmitSearchButton
onClick={submitForm}
searchHasUserInput={
(searchValue !== "" && searchValue !== undefined)
|| advancedOptionsActive
}
/>
</Paper>
</ContextProvider>
Expand Down
144 changes: 139 additions & 5 deletions src/components/HomePage/SearchArea/SearchArea.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@ import {
setFields,
setTechs,
setShowJobDurationSlider,
setShowHidden,
} from "../../../actions/searchOffersActions";
import { createTheme } from "@material-ui/core";
import { renderWithStoreAndTheme, screen, fireEvent, act } from "../../../test-utils";

import { MemoryRouter } from "react-router-dom";

import PropTypes from "prop-types";

import qs from "qs";
import { INITIAL_JOB_TYPE } from "../../../reducers/searchOffersReducer";

// eslint-disable-next-line react/prop-types
const RouteWrappedContent = ({ children, url = "/" }) => (
Expand All @@ -22,6 +25,49 @@ const RouteWrappedContent = ({ children, url = "/" }) => (
</MemoryRouter>
);

const SearchAreaWrapper = ({
searchValue = "", jobType = INITIAL_JOB_TYPE, jobDuration = [null, null], filterJobDuration = false,
showJobDurationSlider = false, fields = [], technologies = [], setShowJobDurationSlider = () => { },
setTechs = () => { }, setJobDuration = () => { }, setFields = () => { }, setJobType = () => { },
setSearchValue = () => { }, onSubmit = () => {}, setShowHidden = () => { },
}) => (
<SearchArea
searchValue={searchValue}
jobType={jobType}
jobDuration={jobDuration}
filterJobDuration={filterJobDuration}
fields={fields}
technologies={technologies}
showJobDurationSlider={showJobDurationSlider}
setShowJobDurationSlider={setShowJobDurationSlider}
setTechs={setTechs}
setJobDuration={setJobDuration}
setFields={setFields}
setJobType={setJobType}
setSearchValue={setSearchValue}
onSubmit={onSubmit}
setShowHidden={setShowHidden}
/>
);

SearchAreaWrapper.propTypes = {
onSubmit: PropTypes.func,
searchValue: PropTypes.string.isRequired,
jobType: PropTypes.string,
setSearchValue: PropTypes.func.isRequired,
setJobDuration: PropTypes.func.isRequired,
setJobType: PropTypes.func.isRequired,
fields: PropTypes.array.isRequired,
technologies: PropTypes.array.isRequired,
showJobDurationSlider: PropTypes.bool.isRequired,
setFields: PropTypes.func.isRequired,
setTechs: PropTypes.func.isRequired,
setShowJobDurationSlider: PropTypes.func.isRequired,
jobDuration: PropTypes.number,
filterJobDuration: PropTypes.bool,
setShowHidden: PropTypes.bool,
};

describe("SearchArea", () => {
let onSubmit;
const theme = createTheme();
Expand All @@ -34,7 +80,7 @@ describe("SearchArea", () => {
it("should render a Paper, a Form, a Search Bar, a Search Button and Advanced Options Button", () => {
renderWithStoreAndTheme(
<RouteWrappedContent>
<SearchArea
<SearchAreaWrapper
onSubmit={onSubmit}
fields={[]}
technologies={[]}
Expand All @@ -44,6 +90,7 @@ describe("SearchArea", () => {
setFields={() => { }}
setJobType={() => { }}
setSearchValue={() => { }}
setShowHidden={() => { }}
/>
</RouteWrappedContent>,
{ initialState, theme }
Expand All @@ -55,6 +102,88 @@ describe("SearchArea", () => {
expect(screen.getByRole("button", { name: "Search" })).toBeInTheDocument();
expect(screen.getByRole("button", { name: "Toggle Advanced Search" })).toBeInTheDocument();
});
it("should render a text='Show All' in the default state of searchArea", () => {
const searchArea = renderWithStoreAndTheme(
<RouteWrappedContent>
<SearchAreaWrapper />
</RouteWrappedContent>,
{ initialState, theme }
);

expect(searchArea.getByRole("button", { name: "Search" })).toHaveTextContent("Show All");
});
it("should render a text='Search' when search bar value != ''", () => {
const searchArea = renderWithStoreAndTheme(
<RouteWrappedContent>
<SearchAreaWrapper
searchValue={"somevalue"}
/>
</RouteWrappedContent>,
{ initialState, theme }
);

expect(searchArea.getByRole("button", { name: "Search" })).toHaveTextContent("Search");
});
it("should render a text='Show All' when search bar has undefined value", () => {
const searchArea = renderWithStoreAndTheme(
<RouteWrappedContent>
<SearchAreaWrapper
searchValue={undefined}
/>
</RouteWrappedContent>,
{ initialState, theme }
);

expect(searchArea.getByRole("button", { name: "Search" })).toHaveTextContent("Show All");
});
it("should render a text='Search' when fields != []", () => {
const searchArea = renderWithStoreAndTheme(
<RouteWrappedContent>
<SearchAreaWrapper
fields={["field1", "field2"]}
/>
</RouteWrappedContent>,
{ initialState, theme }
);

expect(searchArea.getByRole("button", { name: "Search" })).toHaveTextContent("Search");
});
it("should render a text='Search' when technologies != []", () => {
const searchArea = renderWithStoreAndTheme(
<RouteWrappedContent>
<SearchAreaWrapper
technologies={["tech1", "tech2"]}
/>
</RouteWrappedContent>,
{ initialState, theme }
);

expect(searchArea.getByRole("button", { name: "Search" })).toHaveTextContent("Search");
});
it("should render a text='Search' when jobType != INITIAL_JOB_TYPE", () => {
const searchArea = renderWithStoreAndTheme(
<RouteWrappedContent>
<SearchAreaWrapper
jobType={"JOB"}
/>
</RouteWrappedContent>,
{ initialState, theme }
);

expect(searchArea.getByRole("button", { name: "Search" })).toHaveTextContent("Search");
});
it("should render a text='Search' when showJobDurationSlider = true ", () => {
const searchArea = renderWithStoreAndTheme(
<RouteWrappedContent>
<SearchAreaWrapper
showJobDurationSlider={true}
/>
</RouteWrappedContent>,
{ initialState, theme }
);

expect(searchArea.getByRole("button", { name: "Search" })).toHaveTextContent("Search");
});
});

describe("interaction", () => {
Expand All @@ -80,6 +209,7 @@ describe("SearchArea", () => {
setJobDuration={() => { }}
setFields={() => { }}
setJobType={() => { }}
setShowHidden={() => { }}
onSubmit={onSubmit}
fields={[]}
technologies={[]}
Expand Down Expand Up @@ -124,15 +254,13 @@ describe("SearchArea", () => {

renderWithStoreAndTheme(
<RouteWrappedContent url={url}>
<SearchArea
<SearchAreaWrapper
onSubmit={onSubmit}
setSearchValue={setSearchValue}
setJobType={setJobType}
setJobDuration={setJobDuration}
setShowJobDurationSlider={setShowJobDurationSlider}
fields={[]}
setFields={setFields}
technologies={[]}
setTechs={setTechs}
/>
</RouteWrappedContent>,
Expand All @@ -157,6 +285,7 @@ describe("SearchArea", () => {
jobDuration: [1, 2],
fields: ["field1", "field2"],
technologies: ["tech1", "tech2"],
showHidden: true,
},
};
expect(mapStateToProps(mockState)).toEqual({
Expand All @@ -166,6 +295,7 @@ describe("SearchArea", () => {
jobMaxDuration: 2,
fields: ["field1", "field2"],
technologies: ["tech1", "tech2"],
showHidden: true,
});
});

Expand Down Expand Up @@ -194,6 +324,10 @@ describe("SearchArea", () => {
props.setShowJobDurationSlider(filterJobDuration);
expect(dispatch).toHaveBeenCalledWith(setShowJobDurationSlider(false));

const showHidden = true;
props.setShowHidden(showHidden);
expect(dispatch).toHaveBeenCalledWith(setShowHidden(true));

dispatch.mockClear();
props.resetAdvancedSearchFields();
expect(dispatch).toHaveBeenCalled();
Expand Down
15 changes: 10 additions & 5 deletions src/components/HomePage/SearchArea/SubmitSearchButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,32 @@ import React from "react";
import PropTypes from "prop-types";

import { Fab } from "@material-ui/core";
import { Search } from "@material-ui/icons";

import useSearchAreaStyle from "./searchAreaStyle";

const ShowAdvancedOptionsButton = ({ onClick }) => {
const SubmitSearchButton = ({ onClick, searchHasUserInput }) => {
const classes = useSearchAreaStyle();
return (
<div className={classes.submitSearchButtonWrapper}>
<Fab
color="primary"
aria-label="Search"
variant="extended"
onClick={onClick}
>
<Search />
<span>
{searchHasUserInput
? "Search"
: "Show All"}
</span>
</Fab>
</div>
);
};

ShowAdvancedOptionsButton.propTypes = {
SubmitSearchButton.propTypes = {
onClick: PropTypes.func.isRequired,
searchHasUserInput: PropTypes.bool.isRequired,
};

export default ShowAdvancedOptionsButton;
export default SubmitSearchButton;
4 changes: 0 additions & 4 deletions src/components/HomePage/SearchArea/SubmitSearchButton.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from "react";
import { Search } from "@material-ui/icons";
import { Fab } from "@material-ui/core";
import SubmitSearchButton from "./SubmitSearchButton";

Expand All @@ -11,9 +10,6 @@ describe("SubmitSearchButton", () => {
.find(Fab).exists()
).toBe(true);
});
it("should render 'search' icon", () => {
expect(shallow(<SubmitSearchButton />).find(Search).exists()).toBe(true);
});
});

describe("interaction", () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const OffersList = ({
showSearchFilters, toggleShowSearchFilters, offers, moreOffersLoading, loadMoreOffers, searchQueryToken,
}) => (
<Grid item md={4} id="offer_list" className={classes.fullHeight}>
<Grid container className={classes.fullHeight}>
<Grid container className={classes.heightOffersList}>
<div className={classes.offerItemsContainer}>
{noOffers ?
<div className={classes.noOffersColumn}>
Expand Down Expand Up @@ -51,6 +51,7 @@ OffersList.propTypes = {
classes: PropTypes.shape({
divider: PropTypes.string.isRequired,
fullHeight: PropTypes.string.isRequired,
heightOffersList: PropTypes.string.isRequired,
offerItemsContainer: PropTypes.string.isRequired,
noOffersColumn: PropTypes.string.isRequired,
errorLoadingOffersIcon: PropTypes.string.isRequired,
Expand Down Expand Up @@ -139,6 +140,7 @@ const SearchResultsDesktop = () => {

const offersListClasses = {
fullHeight: classes.fullHeight,
heightOffersList: classes.heightOffersList,
noOffersColumn: classes.noOffersColumn,
errorLoadingOffersIcon: classes.errorLoadingOffersIcon,
divider: classes.divider,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ export default makeStyles((theme) => ({
fullWidth: {
width: "100%",
},
heightOffersList: {
height: "100%",
overflow: "auto",
},
searchResults: {
boxSizing: "border-box",
height: "100vh",
Expand Down Expand Up @@ -58,8 +62,6 @@ export default makeStyles((theme) => ({
display: "flex",
justifyContent: "space-between",
width: "100%",
height: "100%",
overflow: "auto",
},
offerBodyContainer: {
height: "100%",
Expand All @@ -69,7 +71,6 @@ export default makeStyles((theme) => ({
offerHeader: {
marginBottom: theme.spacing(1),
alignItems: "flex-start",

},
verticalDivider: {
"&&": {
Expand Down
2 changes: 1 addition & 1 deletion src/hooks/useComponentController.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from "react";
export const DefaultContext = React.createContext();

/**
* This is based on the pattern described here: https://angeloteixeira.me/blog/reactive-controller-pattern
* This is based on the pattern described here: https://angeloteixeira.eu/blog/reactive-controller-pattern
* With it, components can abstract logic common to different view layouts (such as desktop/mobile) and both can read from the given Context
*
* @param controller - A function (can be a React Hook) that handles some logic.
Expand Down

0 comments on commit be605e5

Please sign in to comment.