From deb5988f4df22a8b024b60e438f30d3d634ab29b Mon Sep 17 00:00:00 2001 From: bipoza Date: Wed, 21 Dec 2022 11:38:02 +0100 Subject: [PATCH 01/12] Fixes: #3868 - Added the current page parameter in route in Listing and Search block --- .../Blocks/Listing/withQuerystringResults.jsx | 3 +-- .../manage/Blocks/Search/hocs/withSearch.jsx | 6 ++--- src/helpers/Utils/usePagination.js | 24 +++++++++++++++---- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/components/manage/Blocks/Listing/withQuerystringResults.jsx b/src/components/manage/Blocks/Listing/withQuerystringResults.jsx index d675fc050a..a4f4b450c3 100644 --- a/src/components/manage/Blocks/Listing/withQuerystringResults.jsx +++ b/src/components/manage/Blocks/Listing/withQuerystringResults.jsx @@ -25,7 +25,7 @@ export default function withQuerystringResults(WrappedComponent) { const [initialPath] = React.useState(getBaseUrl(path)); const copyFields = ['limit', 'query', 'sort_on', 'sort_order', 'depth']; - + const { currentPage, setCurrentPage } = usePagination(querystring, 1); const adaptedQuery = Object.assign( variation?.fullobjects ? { fullobjects: 1 } : { metadata_fields: '_all' }, { @@ -37,7 +37,6 @@ export default function withQuerystringResults(WrappedComponent) { : {}, ), ); - const { currentPage, setCurrentPage } = usePagination(querystring, 1); const querystringResults = useSelector( (state) => state.querystringsearch.subrequests, ); diff --git a/src/components/manage/Blocks/Search/hocs/withSearch.jsx b/src/components/manage/Blocks/Search/hocs/withSearch.jsx index 5177dd6304..0bb2fececc 100644 --- a/src/components/manage/Blocks/Search/hocs/withSearch.jsx +++ b/src/components/manage/Blocks/Search/hocs/withSearch.jsx @@ -165,7 +165,7 @@ const useHashState = () => { const setSearchData = React.useCallback( (searchData) => { - const newParams = qs.parse(location.hash); + const newParams = qs.parse(location.search); let changed = false; @@ -182,11 +182,11 @@ const useHashState = () => { if (changed) { history.push({ - hash: qs.stringify(newParams), + search: qs.stringify(newParams), }); } }, - [history, oldState, location.hash], + [history, oldState, location.search], ); return [current, setSearchData]; diff --git a/src/helpers/Utils/usePagination.js b/src/helpers/Utils/usePagination.js index acb12d2ac5..4df0d81617 100644 --- a/src/helpers/Utils/usePagination.js +++ b/src/helpers/Utils/usePagination.js @@ -1,7 +1,9 @@ -import React from 'react'; +import React, { useEffect } from 'react'; import { isEqual } from 'lodash'; import { usePrevious } from './usePrevious'; import useDeepCompareEffect from 'use-deep-compare-effect'; +import { useLocation } from 'react-router-dom'; +import qs from 'query-string'; /** * A pagination helper that tracks the query and resets pagination in case the @@ -9,11 +11,23 @@ import useDeepCompareEffect from 'use-deep-compare-effect'; */ export const usePagination = (query, defaultPage = 1) => { const previousQuery = usePrevious(query); - const [currentPage, setCurrentPage] = React.useState(defaultPage); - + const location = useLocation(); + const queryParamPage = qs.parse(location.search).page || defaultPage; + const [currentPage, setCurrentPage] = React.useState(queryParamPage); useDeepCompareEffect(() => { - setCurrentPage(defaultPage); - }, [query, previousQuery, defaultPage]); + setCurrentPage(queryParamPage); + }, [queryParamPage, query, previousQuery]); + + useEffect(() => { + if (currentPage !== defaultPage) { + const newParams = { + ...qs.parse(location.search), + page: currentPage, + }; + const params = qs.stringify(newParams); + window.history.replaceState(null, null, '?' + params); + } + }, [currentPage, defaultPage, location.search]); return { currentPage: From 7115d8f49b4e5c8761780ba88230ab8bd219c70f Mon Sep 17 00:00:00 2001 From: bipoza Date: Wed, 21 Dec 2022 17:42:58 +0100 Subject: [PATCH 02/12] Documentation improvements --- src/components/manage/Blocks/Search/hocs/withSearch.jsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/manage/Blocks/Search/hocs/withSearch.jsx b/src/components/manage/Blocks/Search/hocs/withSearch.jsx index 0bb2fececc..fd1842fbc1 100644 --- a/src/components/manage/Blocks/Search/hocs/withSearch.jsx +++ b/src/components/manage/Blocks/Search/hocs/withSearch.jsx @@ -144,12 +144,16 @@ const getSearchFields = (searchData) => { }; /** - * A HOC that will mirror the search block state to a hash location + * A hook that will mirror the search block state to a hash location */ const useHashState = () => { const location = useLocation(); const history = useHistory(); + /** + * Required to maintain parameter compatibility. + With this we will maintain support for receiving hash (#) and search (?) type parameters. + */ const oldState = React.useMemo(() => { return { ...qs.parse(location.search), From dd88b26fe1d901dbfe9b5550dc95339a0321b835 Mon Sep 17 00:00:00 2001 From: bipoza Date: Wed, 21 Dec 2022 17:44:03 +0100 Subject: [PATCH 03/12] Added support for multiple paginations --- .../Blocks/Listing/withQuerystringResults.jsx | 2 +- src/helpers/Utils/usePagination.js | 62 ++++++++++++------- 2 files changed, 42 insertions(+), 22 deletions(-) diff --git a/src/components/manage/Blocks/Listing/withQuerystringResults.jsx b/src/components/manage/Blocks/Listing/withQuerystringResults.jsx index a4f4b450c3..c550cf93cb 100644 --- a/src/components/manage/Blocks/Listing/withQuerystringResults.jsx +++ b/src/components/manage/Blocks/Listing/withQuerystringResults.jsx @@ -25,7 +25,7 @@ export default function withQuerystringResults(WrappedComponent) { const [initialPath] = React.useState(getBaseUrl(path)); const copyFields = ['limit', 'query', 'sort_on', 'sort_order', 'depth']; - const { currentPage, setCurrentPage } = usePagination(querystring, 1); + const { currentPage, setCurrentPage } = usePagination(data.block, 1); const adaptedQuery = Object.assign( variation?.fullobjects ? { fullobjects: 1 } : { metadata_fields: '_all' }, { diff --git a/src/helpers/Utils/usePagination.js b/src/helpers/Utils/usePagination.js index 4df0d81617..ac9ce420cd 100644 --- a/src/helpers/Utils/usePagination.js +++ b/src/helpers/Utils/usePagination.js @@ -1,39 +1,59 @@ -import React, { useEffect } from 'react'; -import { isEqual } from 'lodash'; -import { usePrevious } from './usePrevious'; -import useDeepCompareEffect from 'use-deep-compare-effect'; -import { useLocation } from 'react-router-dom'; +import React, { useEffect, useRef } from 'react'; +import { useHistory, useLocation } from 'react-router-dom'; import qs from 'query-string'; +import { useSelector } from 'react-redux'; +import { slugify } from '@plone/volto/helpers/Utils/Utils'; + +/** + * Check if are multiple blocks with pagination + */ +const useCheckIfMultiplePaginations = () => { + const paginationBlocksType = ['search', 'listing']; + const blocks = useSelector((state) => state.content.data.blocks); + const checkIfMultiplePaginations = + Object.values(blocks).filter((item) => + paginationBlocksType.includes(item['@type']), + ).length > 1 || false; + return checkIfMultiplePaginations; +}; /** * A pagination helper that tracks the query and resets pagination in case the * query changes. */ -export const usePagination = (query, defaultPage = 1) => { - const previousQuery = usePrevious(query); +export const usePagination = (id = null, defaultPage = 1) => { const location = useLocation(); - const queryParamPage = qs.parse(location.search).page || defaultPage; - const [currentPage, setCurrentPage] = React.useState(queryParamPage); - useDeepCompareEffect(() => { - setCurrentPage(queryParamPage); - }, [queryParamPage, query, previousQuery]); + const history = useHistory(); + const multiplePagination = useCheckIfMultiplePaginations(); + const pageSlug = slugify(`page-${id}`); + const pageQueryParam = + qs.parse(location.search)[multiplePagination ? pageSlug : 'page'] || + defaultPage; + const [currentPage, setCurrentPage] = React.useState(pageQueryParam); + const firstUpdate = useRef(true); useEffect(() => { - if (currentPage !== defaultPage) { + if (!firstUpdate.current) { const newParams = { ...qs.parse(location.search), - page: currentPage, + [multiplePagination ? pageSlug : 'page']: currentPage, }; - const params = qs.stringify(newParams); - window.history.replaceState(null, null, '?' + params); + history.replace({ + search: qs.stringify(newParams), + }); } - }, [currentPage, defaultPage, location.search]); + firstUpdate.current = false; + }, [ + currentPage, + pageSlug, + defaultPage, + location.search, + multiplePagination, + history, + ]); return { - currentPage: - previousQuery && !isEqual(previousQuery, query) - ? defaultPage - : currentPage, + currentPage, setCurrentPage, }; }; From fb04de8432fcf48abc7a6ac8ce458b3d3bf0d917 Mon Sep 17 00:00:00 2001 From: bipoza Date: Wed, 21 Dec 2022 18:06:06 +0100 Subject: [PATCH 04/12] usePagination code refactoring --- src/helpers/Utils/usePagination.js | 32 ++++++++++++------------------ 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/src/helpers/Utils/usePagination.js b/src/helpers/Utils/usePagination.js index ac9ce420cd..c0144ce07d 100644 --- a/src/helpers/Utils/usePagination.js +++ b/src/helpers/Utils/usePagination.js @@ -5,16 +5,19 @@ import { useSelector } from 'react-redux'; import { slugify } from '@plone/volto/helpers/Utils/Utils'; /** - * Check if are multiple blocks with pagination + * @function useCreatePageQueryStringKey + * @description A hook that creates a key with an id if there are multiple blocks with pagination. + * @returns {string} Example: page || page_012345678 */ -const useCheckIfMultiplePaginations = () => { - const paginationBlocksType = ['search', 'listing']; +const useCreatePageQueryStringKey = (id) => { + const blockTypesWithPagination = ['search', 'listing']; const blocks = useSelector((state) => state.content.data.blocks); - const checkIfMultiplePaginations = + const hasMultiplePaginations = Object.values(blocks).filter((item) => - paginationBlocksType.includes(item['@type']), + blockTypesWithPagination.includes(item['@type']), ).length > 1 || false; - return checkIfMultiplePaginations; + + return hasMultiplePaginations ? slugify(`page-${id}`) : 'page'; }; /** @@ -24,11 +27,9 @@ const useCheckIfMultiplePaginations = () => { export const usePagination = (id = null, defaultPage = 1) => { const location = useLocation(); const history = useHistory(); - const multiplePagination = useCheckIfMultiplePaginations(); - const pageSlug = slugify(`page-${id}`); + const pageQueryStringKey = useCreatePageQueryStringKey(id); const pageQueryParam = - qs.parse(location.search)[multiplePagination ? pageSlug : 'page'] || - defaultPage; + qs.parse(location.search)[pageQueryStringKey] || defaultPage; const [currentPage, setCurrentPage] = React.useState(pageQueryParam); const firstUpdate = useRef(true); @@ -36,21 +37,14 @@ export const usePagination = (id = null, defaultPage = 1) => { if (!firstUpdate.current) { const newParams = { ...qs.parse(location.search), - [multiplePagination ? pageSlug : 'page']: currentPage, + [pageQueryStringKey]: currentPage, }; history.replace({ search: qs.stringify(newParams), }); } firstUpdate.current = false; - }, [ - currentPage, - pageSlug, - defaultPage, - location.search, - multiplePagination, - history, - ]); + }, [currentPage, defaultPage, location.search, history, pageQueryStringKey]); return { currentPage, From 5f18384bf7ae5c6803e5a3a59c7659d4f9ea6736 Mon Sep 17 00:00:00 2001 From: bipoza Date: Wed, 21 Dec 2022 19:13:47 +0100 Subject: [PATCH 05/12] Added unit test --- .../Blocks/Listing/ListingBody.test.jsx | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/components/manage/Blocks/Listing/ListingBody.test.jsx b/src/components/manage/Blocks/Listing/ListingBody.test.jsx index d52c7df814..8a5c359972 100644 --- a/src/components/manage/Blocks/Listing/ListingBody.test.jsx +++ b/src/components/manage/Blocks/Listing/ListingBody.test.jsx @@ -36,6 +36,26 @@ test('renders a ListingBody component', () => { content: { data: { is_folderish: true, + blocks: { + '839ee00b-013b-4f4a-9b10-8867938fdac3': { + '@type': 'listing', + block: '839ee00b-013b-4f4a-9b10-8867938fdac3', + headlineTag: 'h2', + query: [], + querystring: { + b_size: '2', + query: [ + { + i: 'path', + o: 'plone.app.querystring.operation.string.absolutePath', + v: '/', + }, + ], + sort_order: 'ascending', + }, + variation: 'default', + }, + }, }, }, intl: { From 0ca3316364e9650e1b7e79eea0899a185f2f0613 Mon Sep 17 00:00:00 2001 From: bipoza Date: Wed, 21 Dec 2022 19:28:40 +0100 Subject: [PATCH 06/12] Added changelog --- news/4159.bug | 1 + 1 file changed, 1 insertion(+) create mode 100644 news/4159.bug diff --git a/news/4159.bug b/news/4159.bug new file mode 100644 index 0000000000..d9b9f18dfa --- /dev/null +++ b/news/4159.bug @@ -0,0 +1 @@ +Added current page parameter to route in listing and search block pagination - Fix: #3868 @bipoza \ No newline at end of file From a7b3cc97c6039c73557735b3dcfa767a815579bc Mon Sep 17 00:00:00 2001 From: bipoza Date: Thu, 30 Mar 2023 13:40:32 +0200 Subject: [PATCH 07/12] fixed the bug when combining the search block with the pagination --- src/helpers/Utils/usePagination.js | 39 ++++++++++++++++++------------ 1 file changed, 23 insertions(+), 16 deletions(-) diff --git a/src/helpers/Utils/usePagination.js b/src/helpers/Utils/usePagination.js index c0144ce07d..070ae2db9c 100644 --- a/src/helpers/Utils/usePagination.js +++ b/src/helpers/Utils/usePagination.js @@ -1,4 +1,4 @@ -import React, { useEffect, useRef } from 'react'; +import React, { useRef, useEffect } from 'react'; import { useHistory, useLocation } from 'react-router-dom'; import qs from 'query-string'; import { useSelector } from 'react-redux'; @@ -11,9 +11,12 @@ import { slugify } from '@plone/volto/helpers/Utils/Utils'; */ const useCreatePageQueryStringKey = (id) => { const blockTypesWithPagination = ['search', 'listing']; - const blocks = useSelector((state) => state.content.data.blocks); + const blocks = useSelector((state) => state?.content?.data?.blocks) || []; + const blocksLayout = + useSelector((state) => state?.content?.data?.blocks_layout?.items) || []; + const displayedBlocks = blocksLayout?.map((item) => blocks[item]); const hasMultiplePaginations = - Object.values(blocks).filter((item) => + displayedBlocks.filter((item) => blockTypesWithPagination.includes(item['@type']), ).length > 1 || false; @@ -24,26 +27,30 @@ const useCreatePageQueryStringKey = (id) => { * A pagination helper that tracks the query and resets pagination in case the * query changes. */ -export const usePagination = (id = null, defaultPage = 1) => { +export const usePagination = (blockId = null, defaultPage = '1') => { + console.log('blockId', blockId); const location = useLocation(); const history = useHistory(); - const pageQueryStringKey = useCreatePageQueryStringKey(id); + const pageQueryStringKey = useCreatePageQueryStringKey(blockId); const pageQueryParam = qs.parse(location.search)[pageQueryStringKey] || defaultPage; - const [currentPage, setCurrentPage] = React.useState(pageQueryParam); - const firstUpdate = useRef(true); + const [currentPage, setCurrentPage] = React.useState( + parseInt(pageQueryParam), + ); + const queryRef = useRef(qs.parse(location.search)?.query); useEffect(() => { - if (!firstUpdate.current) { - const newParams = { - ...qs.parse(location.search), - [pageQueryStringKey]: currentPage, - }; - history.replace({ - search: qs.stringify(newParams), - }); + if (queryRef.current !== qs.parse(location.search)?.query) { + setCurrentPage(defaultPage); + queryRef.current = qs.parse(location.search)?.query; } - firstUpdate.current = false; + const newParams = { + ...qs.parse(location.search), + [pageQueryStringKey]: currentPage, + }; + history.replace({ + search: qs.stringify(newParams), + }); }, [currentPage, defaultPage, location.search, history, pageQueryStringKey]); return { From bdc850de03fc8d4849358dcb0444ef9c82f73ed1 Mon Sep 17 00:00:00 2001 From: bipoza Date: Thu, 30 Mar 2023 13:41:24 +0200 Subject: [PATCH 08/12] usePagination jest tests --- src/helpers/Utils/usePagination.test.js | 147 ++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 src/helpers/Utils/usePagination.test.js diff --git a/src/helpers/Utils/usePagination.test.js b/src/helpers/Utils/usePagination.test.js new file mode 100644 index 0000000000..c1a77787a2 --- /dev/null +++ b/src/helpers/Utils/usePagination.test.js @@ -0,0 +1,147 @@ +import { renderHook } from '@testing-library/react-hooks'; +import { usePagination } from './usePagination'; +import * as redux from 'react-redux'; +import routeData from 'react-router'; + +const state = { + content: { + data: { + blocks: { + '1a4ebb48-8095-4182-98a5-d7ccf5761bd2': { + '@type': 'title', + }, + '545b33de-92cf-4747-969d-68851837b317': { + '@type': 'search', + query: { + b_size: '4', + query: [ + { + i: 'path', + o: 'plone.app.querystring.operation.string.relativePath', + v: '', + }, + ], + sort_order: 'ascending', + }, + showSearchInput: true, + showTotalResults: true, + }, + '454b33de-92cf-4747-969d-68851837b317': { + '@type': 'search', + query: { + b_size: '4', + query: [ + { + i: 'path', + o: 'plone.app.querystring.operation.string.relativePath', + v: '', + }, + ], + sort_order: 'ascending', + }, + showSearchInput: true, + showTotalResults: true, + }, + '81509424-dcbc-4478-8db0-903c74b28b3d': { + '@type': 'slate', + plaintext: '', + value: [ + { + children: [ + { + text: '', + }, + ], + type: 'p', + }, + ], + }, + }, + blocks_layout: { + items: [ + '545b33de-92cf-4747-969d-68851837b317', + '81509424-dcbc-4478-8db0-903c74b28b3d', + ], + }, + }, + }, +}; + +let mockUseLocationValue = { + pathname: '/testroute', + search: '', +}; + +// jest.mock('react-router-dom', () => ({ +// ...jest.requireActual('react-router-dom'), +// useLocation: () => ({ +// pathname: 'localhost:3000/example/path', +// }), +// })); + +const setUp = (searchParam) => { + mockUseLocationValue.search = searchParam; + return renderHook( + ({ blockId, defaultPage }) => usePagination(blockId, defaultPage), + { + initialProps: { + blockId: '545b33de-92cf-4747-969d-68851837b317', + defaultPage: 1, + }, + }, + ); +}; + +// jest.mock('react-router-dom', () => ({ +// useHistory: () => ({ replace: jest.fn() }), +// useLocation: () => ({ +// search: jest.fn().mockImplementation(() => { +// return mockUseLocationValue; +// }), +// }), +// })); + +jest.spyOn(redux, 'useSelector').mockImplementation((cb) => cb(state)); +describe('Utils tests', () => { + const useLocation = jest.spyOn(routeData, 'useLocation'); + const useHistory = jest.spyOn(routeData, 'useHistory'); + const useSelector = jest.spyOn(redux, 'useSelector'); + beforeEach(() => { + useLocation.mockReturnValue(mockUseLocationValue); + useHistory.mockReturnValue({ replace: jest.fn() }); + // useSelector.mockReturnValue((cb) => cb(state)); + }); + + it('with blockId and defaultPage 1 - shoud be 1', () => { + const { result } = setUp(); + expect(result.current.currentPage).toBe(1); + }); + + it('without params - shoud be 1', () => { + const { result } = setUp(); + expect(result.current.currentPage).toBe(1); + }); + + it('with page 2 param - shoud be 2', () => { + const { result } = setUp('?page=2'); + expect(result.current.currentPage).toBe(2); + }); + + it('first time with page 2 - shoud be 2', () => { + const { result } = setUp('?page-545b33de-92cf-4747-969d-68851837b317=2'); + expect(result.current.currentPage).toBe(2); + }); +}); + +// it('should always return previous state after each update', () => { +// const { result, rerender } = setUp(); + +// rerender({ state: 2 }); +// expect(result.current).toBe(0); + +// rerender({ state: 4 }); +// expect(result.current).toBe(2); + +// rerender({ state: 6 }); +// expect(result.current).toBe(4); +// }); From 3d54c674589e9bfc4ba1e0746b40e2a5eb83aced Mon Sep 17 00:00:00 2001 From: bipoza Date: Thu, 30 Mar 2023 13:41:46 +0200 Subject: [PATCH 09/12] eslist --- src/helpers/Utils/usePagination.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/helpers/Utils/usePagination.js b/src/helpers/Utils/usePagination.js index 070ae2db9c..030c5ecbbf 100644 --- a/src/helpers/Utils/usePagination.js +++ b/src/helpers/Utils/usePagination.js @@ -28,7 +28,6 @@ const useCreatePageQueryStringKey = (id) => { * query changes. */ export const usePagination = (blockId = null, defaultPage = '1') => { - console.log('blockId', blockId); const location = useLocation(); const history = useHistory(); const pageQueryStringKey = useCreatePageQueryStringKey(blockId); From 015572fc2849690425310f6f8081191f06fb15ae Mon Sep 17 00:00:00 2001 From: ionlizarazu Date: Thu, 30 Mar 2023 16:53:58 +0200 Subject: [PATCH 10/12] rename the blockId param to id and the defaultPage param to be 1 instead of '1' --- src/helpers/Utils/usePagination.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/helpers/Utils/usePagination.js b/src/helpers/Utils/usePagination.js index 030c5ecbbf..dc984e9932 100644 --- a/src/helpers/Utils/usePagination.js +++ b/src/helpers/Utils/usePagination.js @@ -27,10 +27,10 @@ const useCreatePageQueryStringKey = (id) => { * A pagination helper that tracks the query and resets pagination in case the * query changes. */ -export const usePagination = (blockId = null, defaultPage = '1') => { +export const usePagination = (id = null, defaultPage = 1) => { const location = useLocation(); const history = useHistory(); - const pageQueryStringKey = useCreatePageQueryStringKey(blockId); + const pageQueryStringKey = useCreatePageQueryStringKey(id); const pageQueryParam = qs.parse(location.search)[pageQueryStringKey] || defaultPage; const [currentPage, setCurrentPage] = React.useState( From cc9b1cd61b67cb54423812c2d98da744c9cb8e8a Mon Sep 17 00:00:00 2001 From: ionlizarazu Date: Thu, 30 Mar 2023 16:54:22 +0200 Subject: [PATCH 11/12] fix and add tests for usePagination.js --- src/helpers/Utils/usePagination.test.js | 164 ++++++++++-------------- 1 file changed, 66 insertions(+), 98 deletions(-) diff --git a/src/helpers/Utils/usePagination.test.js b/src/helpers/Utils/usePagination.test.js index c1a77787a2..26924d78a0 100644 --- a/src/helpers/Utils/usePagination.test.js +++ b/src/helpers/Utils/usePagination.test.js @@ -2,66 +2,34 @@ import { renderHook } from '@testing-library/react-hooks'; import { usePagination } from './usePagination'; import * as redux from 'react-redux'; import routeData from 'react-router'; +import { slugify } from '@plone/volto/helpers/Utils/Utils'; -const state = { +const searchBlockId = '545b33de-92cf-4747-969d-68851837b317'; +const searchBlockId2 = '454b33de-92cf-4747-969d-68851837b713'; +const searchBlock = { + '@type': 'search', + query: { + b_size: '4', + query: [ + { + i: 'path', + o: 'plone.app.querystring.operation.string.relativePath', + v: '', + }, + ], + sort_order: 'ascending', + }, + showSearchInput: true, + showTotalResults: true, +}; +let state = { content: { data: { blocks: { - '1a4ebb48-8095-4182-98a5-d7ccf5761bd2': { - '@type': 'title', - }, - '545b33de-92cf-4747-969d-68851837b317': { - '@type': 'search', - query: { - b_size: '4', - query: [ - { - i: 'path', - o: 'plone.app.querystring.operation.string.relativePath', - v: '', - }, - ], - sort_order: 'ascending', - }, - showSearchInput: true, - showTotalResults: true, - }, - '454b33de-92cf-4747-969d-68851837b317': { - '@type': 'search', - query: { - b_size: '4', - query: [ - { - i: 'path', - o: 'plone.app.querystring.operation.string.relativePath', - v: '', - }, - ], - sort_order: 'ascending', - }, - showSearchInput: true, - showTotalResults: true, - }, - '81509424-dcbc-4478-8db0-903c74b28b3d': { - '@type': 'slate', - plaintext: '', - value: [ - { - children: [ - { - text: '', - }, - ], - type: 'p', - }, - ], - }, + [searchBlockId]: searchBlock, }, blocks_layout: { - items: [ - '545b33de-92cf-4747-969d-68851837b317', - '81509424-dcbc-4478-8db0-903c74b28b3d', - ], + items: [searchBlockId], }, }, }, @@ -72,76 +40,76 @@ let mockUseLocationValue = { search: '', }; -// jest.mock('react-router-dom', () => ({ -// ...jest.requireActual('react-router-dom'), -// useLocation: () => ({ -// pathname: 'localhost:3000/example/path', -// }), -// })); - -const setUp = (searchParam) => { +const setUp = (searchParam, numberOfSearches) => { mockUseLocationValue.search = searchParam; - return renderHook( - ({ blockId, defaultPage }) => usePagination(blockId, defaultPage), - { - initialProps: { - blockId: '545b33de-92cf-4747-969d-68851837b317', - defaultPage: 1, - }, + if (numberOfSearches > 1) { + state.content.data.blocks[searchBlockId2] = searchBlock; + state.content.data.blocks_layout.items.push(searchBlockId2); + } + return renderHook(({ id, defaultPage }) => usePagination(id, defaultPage), { + initialProps: { + id: searchBlockId, + defaultPage: 1, }, - ); + }); }; -// jest.mock('react-router-dom', () => ({ -// useHistory: () => ({ replace: jest.fn() }), -// useLocation: () => ({ -// search: jest.fn().mockImplementation(() => { -// return mockUseLocationValue; -// }), -// }), -// })); - -jest.spyOn(redux, 'useSelector').mockImplementation((cb) => cb(state)); -describe('Utils tests', () => { +describe(`Tests for usePagination, for the block ${searchBlockId}`, () => { const useLocation = jest.spyOn(routeData, 'useLocation'); const useHistory = jest.spyOn(routeData, 'useHistory'); const useSelector = jest.spyOn(redux, 'useSelector'); beforeEach(() => { useLocation.mockReturnValue(mockUseLocationValue); useHistory.mockReturnValue({ replace: jest.fn() }); - // useSelector.mockReturnValue((cb) => cb(state)); + useSelector.mockImplementation((cb) => cb(state)); }); - it('with blockId and defaultPage 1 - shoud be 1', () => { + it('1 paginated block with id and defaultPage 1 - shoud be 1', () => { const { result } = setUp(); expect(result.current.currentPage).toBe(1); }); - it('without params - shoud be 1', () => { + it('1 paginated block without params - shoud be 1', () => { const { result } = setUp(); expect(result.current.currentPage).toBe(1); }); - it('with page 2 param - shoud be 2', () => { - const { result } = setUp('?page=2'); + const param1 = '?page=2'; + it(`1 paginated block with params: ${param1} - shoud be 2`, () => { + const { result } = setUp(param1); expect(result.current.currentPage).toBe(2); }); - it('first time with page 2 - shoud be 2', () => { - const { result } = setUp('?page-545b33de-92cf-4747-969d-68851837b317=2'); + const param2 = `?${slugify(`page-${searchBlockId}`)}=2`; + it(`2 paginated blocks with current block in the params: ${param2} - shoud be 2`, () => { + const { result } = setUp(param2, 2); expect(result.current.currentPage).toBe(2); }); -}); -// it('should always return previous state after each update', () => { -// const { result, rerender } = setUp(); + const param3 = `?${slugify(`page-${searchBlockId2}`)}=2`; + it(`2 paginated blocks with the other block in the params: ${param3} - shoud be 1`, () => { + const { result } = setUp(param3, 2); + expect(result.current.currentPage).toBe(1); + }); -// rerender({ state: 2 }); -// expect(result.current).toBe(0); + const param4 = `?${slugify(`page-${searchBlockId}`)}=2&${slugify( + `page-${searchBlockId2}`, + )}=1`; + it(`2 paginated blocks with both blocks in the params, current 2: ${param4} - shoud be 2`, () => { + const { result } = setUp(param4, 2); + expect(result.current.currentPage).toBe(2); + }); -// rerender({ state: 4 }); -// expect(result.current).toBe(2); + const param5 = `?${slugify(`page-${searchBlockId}`)}=1&${slugify( + `page-${searchBlockId2}`, + )}=2`; + it(`2 paginated blocks with both blocks in the params, current 1: ${param5} - shoud be 1`, () => { + const { result } = setUp(param5, 2); + expect(result.current.currentPage).toBe(1); + }); -// rerender({ state: 6 }); -// expect(result.current).toBe(4); -// }); + it(`2 paginated blocks with wrong page param: ${param1} - shoud be 1`, () => { + const { result } = setUp(param1, 2); + expect(result.current.currentPage).toBe(1); + }); +}); From 88b2ae56b3dd53b85bf41a8d636c9dfd98bb2492 Mon Sep 17 00:00:00 2001 From: ionlizarazu Date: Fri, 31 Mar 2023 13:18:21 +0200 Subject: [PATCH 12/12] changelog --- news/{4159.bug => 4159.bugfix} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename news/{4159.bug => 4159.bugfix} (100%) diff --git a/news/4159.bug b/news/4159.bugfix similarity index 100% rename from news/4159.bug rename to news/4159.bugfix