Skip to content

Commit e91b345

Browse files
eug123davemacaulay
andauthored
[PWA-589] Page Reset on Sort (#2458)
* PWA-589: Page Reset on Sort * PWA-589: Page Reset on Sort * PWA-589: Page Reset on Sort * PWA-589: Page Reset on Sort * PWA-589: Page Reset on Sort * PWA-589: Page Reset on Sort * PWA-589: Page Reset on Sort * PWA-589: Page Reset on Sort * PWA-589: Page Reset on Sort * PWA-589: Page Reset on Sort Co-authored-by: Dave Macaulay <[email protected]>
1 parent e95eed0 commit e91b345

File tree

6 files changed

+372
-8
lines changed

6 files changed

+372
-8
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`returns the correct shape 1`] = `
4+
Object {
5+
"data": Object {
6+
"products": Object {
7+
"page_info": Object {
8+
"total_pages": 6,
9+
},
10+
},
11+
},
12+
"error": null,
13+
"filters": undefined,
14+
"loading": false,
15+
"openDrawer": [Function],
16+
"pageControl": Object {
17+
"currentPage": 3,
18+
"setPage": [MockFunction],
19+
"totalPages": 6,
20+
},
21+
"sortProps": Array [
22+
Object {
23+
"sortAttribute": "relevance",
24+
"sortDirection": "DESC",
25+
"sortText": "Best Match",
26+
},
27+
[MockFunction],
28+
],
29+
}
30+
`;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
import React from 'react';
2+
import { act } from 'react-test-renderer';
3+
4+
import { useSearchPage } from '../useSearchPage';
5+
import createTestInstance from '../../../util/createTestInstance';
6+
7+
jest.mock('react-router-dom', () => ({
8+
useHistory: jest.fn(() => ({ push: jest.fn() })),
9+
useLocation: jest.fn(() => ({ pathname: '', search: '' }))
10+
}));
11+
12+
jest.mock('../../../context/app', () => {
13+
const state = {};
14+
const api = {
15+
toggleDrawer: jest.fn()
16+
};
17+
const useAppContext = jest.fn(() => [state, api]);
18+
19+
return { useAppContext };
20+
});
21+
22+
const mockUseSort = jest
23+
.fn()
24+
.mockReturnValue([
25+
{
26+
sortText: 'Best Match',
27+
sortAttribute: 'relevance',
28+
sortDirection: 'DESC'
29+
},
30+
jest.fn()
31+
])
32+
.mockName('mockUseSort');
33+
34+
const mockSetCurrentPage = jest.fn().mockName('mockSetCurrentPage');
35+
36+
jest.mock('@magento/peregrine', () => {
37+
const usePagination = jest.fn(() => [
38+
{
39+
currentPage: 3,
40+
totalPages: 6
41+
},
42+
{
43+
setCurrentPage: jest
44+
.fn()
45+
.mockImplementation(() => mockSetCurrentPage()),
46+
setTotalPages: jest.fn()
47+
}
48+
]);
49+
const useSort = jest.fn().mockImplementation(() => mockUseSort());
50+
51+
return {
52+
useSort,
53+
usePagination
54+
};
55+
});
56+
57+
jest.mock('@apollo/react-hooks', () => {
58+
const useQuery = jest.fn().mockReturnValue({
59+
data: {
60+
__type: {
61+
inputFields: []
62+
}
63+
},
64+
error: null,
65+
loading: false
66+
});
67+
const runQuery = jest.fn();
68+
const queryResult = {
69+
data: {
70+
products: {
71+
page_info: {
72+
total_pages: 6
73+
}
74+
}
75+
},
76+
error: null,
77+
loading: false
78+
};
79+
const useLazyQuery = jest.fn(() => [runQuery, queryResult]);
80+
81+
return { useLazyQuery, useQuery };
82+
});
83+
84+
const mockProps = {
85+
queries: {
86+
filterIntrospection: 'filterIntrospectionQuery',
87+
getProductFiltersBySearch: 'getProductFiltersBySearchQuery',
88+
productSearch: 'productSearchQuery'
89+
}
90+
};
91+
92+
const Component = props => {
93+
const talonProps = useSearchPage(props);
94+
return <i talonProps={talonProps} />;
95+
};
96+
97+
const tree = createTestInstance(<Component {...mockProps} />);
98+
99+
test('returns the correct shape', () => {
100+
const { root } = tree;
101+
const { talonProps } = root.findByType('i').props;
102+
103+
expect(talonProps).toMatchSnapshot();
104+
});
105+
106+
const testCases = [
107+
[
108+
'sortText does not reset',
109+
{
110+
sortText: 'Changed',
111+
sortAttribute: 'relevance',
112+
sortDirection: 'DESC'
113+
},
114+
0
115+
],
116+
[
117+
'sortAttribute resets',
118+
{
119+
sortText: 'Best Match',
120+
sortAttribute: 'Changed',
121+
sortDirection: 'DESC'
122+
},
123+
1
124+
],
125+
[
126+
'sortDirection resets',
127+
{
128+
sortText: 'Best Match',
129+
sortAttribute: 'relevance',
130+
sortDirection: 'Changed'
131+
},
132+
1
133+
]
134+
];
135+
136+
test.each(testCases)(
137+
'Changing %s current page to 1.',
138+
(description, sortParams, expected) => {
139+
mockUseSort.mockReturnValueOnce([sortParams, jest.fn()]);
140+
act(() => {
141+
tree.update(<Component {...mockProps} />);
142+
});
143+
144+
expect(mockSetCurrentPage).toHaveBeenCalledTimes(expected);
145+
}
146+
);

packages/peregrine/lib/talons/SearchPage/useSearchPage.js

+14-4
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ export const useSearchPage = props => {
2929
const [currentSort] = sortProps;
3030
const { sortAttribute, sortDirection } = currentSort;
3131

32+
// Keep track of the sort criteria so we can tell when they change.
33+
const previousSort = useRef(currentSort);
34+
3235
// Set up pagination.
3336
const [paginationValues, paginationApi] = usePagination();
3437
const { currentPage, totalPages } = paginationValues;
@@ -151,22 +154,29 @@ export const useSearchPage = props => {
151154
};
152155
}, [data, setTotalPages]);
153156

154-
// Reset the current page back to one (1) when the search string or filters
155-
// change.
157+
// Reset the current page back to one (1) when the search string, filters
158+
// or sort criteria change.
156159
useEffect(() => {
157160
// We don't want to compare page value.
158161
const prevSearch = new URLSearchParams(previousSearch.current);
159162
const nextSearch = new URLSearchParams(search);
160163
prevSearch.delete('page');
161164
nextSearch.delete('page');
162165

163-
if (prevSearch.toString() != nextSearch.toString()) {
166+
if (
167+
prevSearch.toString() !== nextSearch.toString() ||
168+
previousSort.current.sortAttribute.toString() !==
169+
currentSort.sortAttribute.toString() ||
170+
previousSort.current.sortDirection.toString() !==
171+
currentSort.sortDirection.toString()
172+
) {
164173
// The search term changed.
165174
setCurrentPage(1);
166175
// And update the ref.
167176
previousSearch.current = search;
177+
previousSort.current = currentSort;
168178
}
169-
}, [search, setCurrentPage]);
179+
}, [currentSort, search, setCurrentPage]);
170180

171181
// Fetch category filters for when a user is searching in a category.
172182
const [getFilters, { data: filterData, error: filterError }] = useLazyQuery(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`renders the correct tree 1`] = `
4+
Array [
5+
"Meta",
6+
<CategoryContent
7+
categoryId={3}
8+
classes={Object {}}
9+
data={
10+
Object {
11+
"products": Object {
12+
"page_info": Object {
13+
"total_pages": 6,
14+
},
15+
},
16+
}
17+
}
18+
pageControl={
19+
Object {
20+
"currentPage": 3,
21+
"setPage": [MockFunction],
22+
"totalPages": 6,
23+
}
24+
}
25+
sortProps={
26+
Array [
27+
Object {
28+
"sortAttribute": "relevance",
29+
"sortDirection": "DESC",
30+
"sortText": "Best Match",
31+
},
32+
[MockFunction],
33+
]
34+
}
35+
/>,
36+
]
37+
`;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
import React from 'react';
2+
import { act } from 'react-test-renderer';
3+
import createTestInstance from '@magento/peregrine/lib/util/createTestInstance';
4+
import Category from '../category';
5+
6+
jest.mock('react-router-dom', () => ({
7+
useHistory: jest.fn(() => ({ push: jest.fn() })),
8+
useLocation: jest.fn(() => ({ pathname: '', search: '' }))
9+
}));
10+
11+
jest.mock('../../../components/Head', () => ({
12+
HeadProvider: ({ children }) => <div>{children}</div>,
13+
Title: () => 'Title',
14+
Meta: () => 'Meta'
15+
}));
16+
17+
jest.mock('../categoryContent', () => 'CategoryContent');
18+
19+
const mockUseSort = jest
20+
.fn()
21+
.mockReturnValue([
22+
{
23+
sortText: 'Best Match',
24+
sortAttribute: 'relevance',
25+
sortDirection: 'DESC'
26+
},
27+
jest.fn()
28+
])
29+
.mockName('mockUseSort');
30+
31+
const mockSetCurrentPage = jest.fn().mockName('mockSetCurrentPage');
32+
33+
jest.mock('@magento/peregrine', () => {
34+
const usePagination = jest.fn(() => [
35+
{
36+
currentPage: 3,
37+
totalPages: 6
38+
},
39+
{
40+
setCurrentPage: jest
41+
.fn()
42+
.mockImplementation(() => mockSetCurrentPage()),
43+
setTotalPages: jest.fn()
44+
}
45+
]);
46+
const useSort = jest.fn().mockImplementation(() => mockUseSort());
47+
48+
return {
49+
useSort,
50+
usePagination
51+
};
52+
});
53+
54+
jest.mock('@apollo/react-hooks', () => {
55+
const useQuery = jest.fn().mockReturnValue({
56+
data: {
57+
__type: {
58+
inputFields: []
59+
}
60+
},
61+
error: null,
62+
loading: false
63+
});
64+
const runQuery = jest.fn();
65+
const queryResult = {
66+
data: {
67+
products: {
68+
page_info: {
69+
total_pages: 6
70+
}
71+
}
72+
},
73+
error: null,
74+
loading: false
75+
};
76+
const useLazyQuery = jest.fn(() => [runQuery, queryResult]);
77+
78+
return { useLazyQuery, useQuery };
79+
});
80+
81+
const categoryProps = {
82+
id: 3,
83+
pageSize: 6
84+
};
85+
const tree = createTestInstance(<Category {...categoryProps} />);
86+
87+
test('renders the correct tree', () => {
88+
expect(tree.toJSON()).toMatchSnapshot();
89+
});
90+
91+
const testCases = [
92+
[
93+
'sortText does not reset',
94+
{
95+
sortText: 'Changed',
96+
sortAttribute: 'relevance',
97+
sortDirection: 'DESC'
98+
},
99+
0
100+
],
101+
[
102+
'sortAttribute resets',
103+
{
104+
sortText: 'Best Match',
105+
sortAttribute: 'Changed',
106+
sortDirection: 'DESC'
107+
},
108+
1
109+
],
110+
[
111+
'sortDirection resets',
112+
{
113+
sortText: 'Best Match',
114+
sortAttribute: 'relevance',
115+
sortDirection: 'Changed'
116+
},
117+
1
118+
]
119+
];
120+
121+
test.each(testCases)(
122+
'Changing %s current page to 1.',
123+
(description, sortParams, expected) => {
124+
mockUseSort.mockReturnValueOnce([sortParams, jest.fn()]);
125+
act(() => {
126+
tree.update(<Category {...categoryProps} />);
127+
});
128+
129+
expect(mockSetCurrentPage).toHaveBeenCalledTimes(expected);
130+
}
131+
);

0 commit comments

Comments
 (0)