Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
TiagooGomess committed Mar 28, 2022

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
1 parent b6aec0c commit cbf11ee
Showing 8 changed files with 32 additions and 54 deletions.
Original file line number Diff line number Diff line change
@@ -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);
}, []);
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);
});
@@ -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);
Original file line number Diff line number Diff line change
@@ -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 = ({
Original file line number Diff line number Diff line change
@@ -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 = ({
Original file line number Diff line number Diff line change
@@ -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";
@@ -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();
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
@@ -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(
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,
@@ -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) => {

0 comments on commit cbf11ee

Please sign in to comment.