Skip to content

Commit

Permalink
Fix: bug regarding the fact that the search and loadMoreOffers functi…
Browse files Browse the repository at this point in the history
…on do not share state
  • Loading branch information
TiagooGomess committed Apr 9, 2022
1 parent f99f165 commit 96e0035
Show file tree
Hide file tree
Showing 8 changed files with 32 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ const OfferItemsContainer = ({
return (overflowY === "scroll" || overflowY === "auto") && node.scrollHeight > node.clientHeight;
}, []);

// BUG: there is no refetching of new offers when the initial_limit is not enough

const refetchTriggerRef = useCallback((node) => {
if (node) setOfferResultsWrapperNode(node.parentElement);
}, []);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,35 +1,20 @@
import { createTheme } from "@material-ui/core";
import { getByRole, getByText, screen } from "@testing-library/react";
import React from "react";
import { renderWithStoreAndTheme } from "../../../../test-utils";
import { render } from "../../../../test-utils";
import Offer from "../Offer/Offer";
import OfferItemsContainer from "./OfferItemsContainer";

describe("OfferItemsContainer", () => {

const theme = createTheme();
const initialState = {};

beforeEach(() => {
// IntersectionObserver isn't available in test environment
const mockIntersectionObserver = jest.fn();
mockIntersectionObserver.mockReturnValue({
observe: () => null,
unobserve: () => null,
disconnect: () => null,
});
window.IntersectionObserver = mockIntersectionObserver;
});

describe("render", () => {
it("should show loading state when loading", () => {
renderWithStoreAndTheme(
render(
<OfferItemsContainer
loading
setSelectedOfferIdx={() => {}}
toggleShowSearchFilters={() => {}}
setShouldFetchMoreOffers={() => {}}
/>, { initialState, theme }
/>
);
expect(screen.getAllByTestId("offer-item-loading")).toHaveLength(3);
});
Expand Down Expand Up @@ -60,13 +45,13 @@ describe("OfferItemsContainer", () => {
}),
];

renderWithStoreAndTheme(
render(
<OfferItemsContainer
offers={offers}
loading={false}
setSelectedOfferIdx={() => {}}
toggleShowSearchFilters={() => {}}
/>, { initialState, theme }
/>
);
const items = await screen.findAllByTestId("offer-item");
expect(items).toHaveLength(2);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ OffersList.propTypes = {
showSearchFilters: PropTypes.bool.isRequired,
toggleShowSearchFilters: PropTypes.func.isRequired,
offers: PropTypes.arrayOf(PropTypes.instanceOf(Offer)),
moreOffersLoading: PropTypes.bool,
loadMoreOffers: PropTypes.func,
searchQueryToken: PropTypes.string,
};

const OfferWidgetSection = ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ OffersList.propTypes = {
toggleShowSearchFilters: PropTypes.func.isRequired,
offers: PropTypes.arrayOf(PropTypes.instanceOf(Offer)),
moreOffersLoading: PropTypes.bool,
loadMoreOffers: PropTypes.func,
searchQueryToken: PropTypes.string,
};

export const OfferViewer = ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from "react";
import SearchResultsMobile from "./SearchResultsMobile";
import Offer from "../Offer/Offer";
import { createTheme } from "@material-ui/core/styles";
import { renderWithStoreAndTheme, screen } from "../../../../test-utils";
import { render, renderWithStoreAndTheme, screen } from "../../../../test-utils";
import { createMatchMedia } from "../../../../utils/media-queries";
import { waitForElementToBeRemoved } from "@testing-library/dom";
import { Simulate } from "react-dom/test-utils";
Expand Down Expand Up @@ -39,27 +39,14 @@ describe("SearchResultsMobile", () => {
}),
];

beforeEach(() => {
// IntersectionObserver isn't available in test environment
const mockIntersectionObserver = jest.fn();
mockIntersectionObserver.mockReturnValue({
observe: () => null,
unobserve: () => null,
disconnect: () => null,
});
window.IntersectionObserver = mockIntersectionObserver;
});

describe("render", () => {
it("Should render offers if present", () => {

const initialState = {};

const context = { offers };
renderWithStoreAndTheme(
render(
<SearchResultsControllerContext.Provider value={context}>
<SearchResultsMobile offers={offers} />
</SearchResultsControllerContext.Provider>, { initialState, theme }
</SearchResultsControllerContext.Provider>
);
expect(screen.getByRole("button", { name: "Adjust Filters" })).toBeInTheDocument();
expect(screen.getByText("position1")).toBeInTheDocument();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export const SearchResultsConstants = {
INITIAL_LIMIT: 2,
FETCH_NEW_OFFERS_LIMIT: 1,
INITIAL_LIMIT: 15,
FETCH_NEW_OFFERS_LIMIT: 10,
};
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,6 @@ describe("SearchResults", () => {
},
};

beforeEach(() => {
// IntersectionObserver isn't available in test environment
const mockIntersectionObserver = jest.fn();
mockIntersectionObserver.mockReturnValue({
observe: () => null,
unobserve: () => null,
disconnect: () => null,
});
window.IntersectionObserver = mockIntersectionObserver;
});

it("should display OfferItemsContainer", () => {

renderWithStoreAndTheme(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useCallback, useState } from "react";
import { useDispatch } from "react-redux";
import { useCallback, useState, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import {
resetOffersFetchError,
setLoadingOffers,
Expand All @@ -16,12 +16,26 @@ import {
export default (filters) => {

const dispatch = useDispatch();
const searchQueryToken = useSelector((state) => state.offerSearch.queryToken);

// TODO: Move this to redux!!!
const [hasMoreOffers, setHasMoreOffers] = useState(true);
const [moreOffersFetchError, setMoreOffersFetchError] = useState(null);
const [moreOffersLoading, setMoreOffersLoading] = useState(false);

// The "search" and "loadMoreOffers" functions do not share the same state;
// When we run "setHasMoreOffers(false)" on the "loadMoreOffers" function,
// the "search" function does not know that the "hasMoreOffers" variable has changed;
// In the same way, when we run "setHasMoreOffers(true) on the "search" function,
// the "loadMoreOffers" function does not know that the "hasMoreOffers" variable has changed;
// Then, when the "loadMoreOffers" function is executed after a previous execution where the
// "hasMoreOffers" variable became "false", the state of this variable is still false, which
// prevents the fetching of new offers.
// Knowing that, I needed a way to set the "hasMoreOffers" variable to "true" when the previous fact
// happens: setting the "hasMoreOffers" to true when the "queryToken" (which is stored in redux) changes
useEffect(() => {
setHasMoreOffers(true);
}, [searchQueryToken]);

// isInitialRequest = true on the first time the search request is made
// the following request will have isInitialRequest = false
const loadOffers = useCallback((isInitialRequest) => async (queryToken, limit) => {
Expand Down

0 comments on commit 96e0035

Please sign in to comment.