@magento/venia-ui 11.5.0 → 11.6.0-alpha.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/RootComponents/Category/__tests__/__snapshots__/categoryContent.shimmer.spec.js.snap +12 -12
- package/lib/RootComponents/Category/categoryContent.js +2 -1
- package/lib/components/AuthBar/authBar.js +6 -4
- package/lib/components/ButtonTab/button.module.css +123 -0
- package/lib/components/ButtonTab/buttonTab.js +99 -0
- package/lib/components/ButtonTab/index.js +1 -0
- package/lib/components/CartPage/PriceSummary/__tests__/__snapshots__/priceSummary.spec.js.snap +0 -2
- package/lib/components/CartPage/PriceSummary/priceSummary.js +1 -0
- package/lib/components/CartPage/ProductListing/EditModal/__tests__/__snapshots__/productForm.spec.js.snap +2 -2
- package/lib/components/CartPage/__tests__/__snapshots__/cartPage.spec.js.snap +12 -6
- package/lib/components/CartPage/cartPage.js +12 -6
- package/lib/components/CheckoutPage/ItemsReview/__tests__/__snapshots__/itemsReview.spec.js.snap +3 -3
- package/lib/components/CheckoutPage/ItemsReview/itemsReview.js +1 -16
- package/lib/components/CheckoutPage/OrderConfirmationPage/__fixtures__/cartItems.js +33 -0
- package/lib/components/CheckoutPage/OrderConfirmationPage/__tests__/__snapshots__/orderConfirmationPage.spec.js.snap +135 -1
- package/lib/components/CheckoutPage/OrderConfirmationPage/__tests__/orderConfirmationPage.spec.js +40 -3
- package/lib/components/CheckoutPage/OrderConfirmationPage/orderConfirmationPage.js +118 -103
- package/lib/components/CheckoutPage/ShippingInformation/AddressForm/__tests__/__snapshots__/guestForm.spec.js.snap +12 -36
- package/lib/components/CheckoutPage/ShippingInformation/AddressForm/guestForm.js +1 -1
- package/lib/components/CheckoutPage/ShippingMethod/__tests__/__snapshots__/shippingMethod.spec.js.snap +8 -16
- package/lib/components/CheckoutPage/ShippingMethod/shippingMethod.js +1 -1
- package/lib/components/CheckoutPage/__tests__/__snapshots__/checkoutPage.spec.js.snap +1 -1
- package/lib/components/CheckoutPage/checkoutPage.js +16 -7
- package/lib/components/CreateAccount/__tests__/createAccount.spec.js +30 -0
- package/lib/components/CreateAccount/createAccount.js +2 -2
- package/lib/components/FilterModal/CurrentFilters/__tests__/currentFilter.spec.js +6 -1
- package/lib/components/FilterModal/CurrentFilters/currentFilter.js +12 -2
- package/lib/components/FilterModal/FilterList/__tests__/filterList.spec.js +16 -3
- package/lib/components/FilterModal/FilterList/filterList.js +81 -31
- package/lib/components/FilterModal/filterBlock.js +2 -1
- package/lib/components/FilterSidebar/__tests__/filterSidebar.spec.js +51 -19
- package/lib/components/FilterSidebar/filterSidebar.js +36 -2
- package/lib/components/Gallery/__tests__/__snapshots__/gallery.spec.js.snap +2 -2
- package/lib/components/Gallery/__tests__/__snapshots__/item.spec.js.snap +3 -3
- package/lib/components/MiniCart/ProductList/__tests__/__snapshots__/item.spec.js.snap +4 -4
- package/lib/components/MiniCart/miniCart.js +16 -12
- package/lib/components/Newsletter/__tests__/__snapshots__/newsletter.spec.js.snap +4 -4
- package/lib/components/Newsletter/newsletter.js +2 -2
- package/lib/components/OrderHistoryPage/OrderDetails/__tests__/__snapshots__/item.spec.js.snap +1 -1
- package/lib/components/OrderHistoryPage/collapsedImageGallery.js +3 -0
- package/lib/components/ProductImageCarousel/__tests__/__snapshots__/carousel.spec.js.snap +7 -7
- package/lib/components/ProductImageCarousel/__tests__/__snapshots__/thumbnail.spec.js.snap +4 -4
- package/lib/components/RangeSlider/rangeSlider.js +127 -0
- package/lib/components/RangeSlider/rangeSlider.module.css +76 -0
- package/lib/components/SearchBar/__tests__/__snapshots__/suggestedProduct.spec.js.snap +1 -1
- package/lib/components/SignIn/__tests__/__snapshots__/signIn.spec.js.snap +6 -6
- package/lib/components/SignIn/__tests__/signIn.spec.js +31 -0
- package/lib/components/SignIn/signIn.js +3 -5
- package/lib/components/WishlistPage/__tests__/__snapshots__/wishlistItem.spec.js.snap +2 -2
- package/lib/defaultRoutes.json +6 -0
- package/package.json +4 -4
- package/upward.yml +31 -1
|
@@ -2,14 +2,13 @@ import React, { Fragment, useEffect } from 'react';
|
|
|
2
2
|
import { shape, string } from 'prop-types';
|
|
3
3
|
import { FormattedMessage, useIntl } from 'react-intl';
|
|
4
4
|
import { AlertCircle as AlertCircleIcon } from 'react-feather';
|
|
5
|
-
import { Link } from 'react-router-dom';
|
|
5
|
+
import { Link, useHistory } from 'react-router-dom';
|
|
6
6
|
|
|
7
7
|
import { useWindowSize, useToasts } from '@magento/peregrine';
|
|
8
8
|
import {
|
|
9
9
|
CHECKOUT_STEP,
|
|
10
10
|
useCheckoutPage
|
|
11
11
|
} from '@magento/peregrine/lib/talons/CheckoutPage/useCheckoutPage';
|
|
12
|
-
|
|
13
12
|
import { useStyle } from '../../classify';
|
|
14
13
|
import Button from '../Button';
|
|
15
14
|
import { StoreTitle } from '../Head';
|
|
@@ -25,8 +24,8 @@ import payments from './PaymentInformation/paymentMethodCollection';
|
|
|
25
24
|
import PriceAdjustments from './PriceAdjustments';
|
|
26
25
|
import ShippingMethod from './ShippingMethod';
|
|
27
26
|
import ShippingInformation from './ShippingInformation';
|
|
28
|
-
import OrderConfirmationPage from './OrderConfirmationPage';
|
|
29
27
|
import ItemsReview from './ItemsReview';
|
|
28
|
+
import OrderConfirmationPage from './OrderConfirmationPage';
|
|
30
29
|
import GoogleReCaptcha from '../GoogleReCaptcha';
|
|
31
30
|
|
|
32
31
|
import defaultClasses from './checkoutPage.module.css';
|
|
@@ -35,6 +34,7 @@ import ScrollAnchor from '../ScrollAnchor/scrollAnchor';
|
|
|
35
34
|
const errorIcon = <Icon src={AlertCircleIcon} size={20} />;
|
|
36
35
|
|
|
37
36
|
const CheckoutPage = props => {
|
|
37
|
+
const history = useHistory();
|
|
38
38
|
const { classes: propClasses } = props;
|
|
39
39
|
const { formatMessage } = useIntl();
|
|
40
40
|
const talonProps = useCheckoutPage();
|
|
@@ -58,8 +58,8 @@ const CheckoutPage = props => {
|
|
|
58
58
|
isGuestCheckout,
|
|
59
59
|
isLoading,
|
|
60
60
|
isUpdating,
|
|
61
|
-
orderDetailsData,
|
|
62
61
|
orderDetailsLoading,
|
|
62
|
+
orderDetailsData,
|
|
63
63
|
orderNumber,
|
|
64
64
|
placeOrderLoading,
|
|
65
65
|
placeOrderButtonClicked,
|
|
@@ -83,7 +83,15 @@ const CheckoutPage = props => {
|
|
|
83
83
|
} = talonProps;
|
|
84
84
|
|
|
85
85
|
const [, { addToast }] = useToasts();
|
|
86
|
-
|
|
86
|
+
const orderCount = localStorage.getItem('orderCount');
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
if (isGuestCheckout && !orderDetailsData) {
|
|
89
|
+
if (orderCount === '1') {
|
|
90
|
+
history.push('/');
|
|
91
|
+
localStorage.setItem('orderCount', '0');
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}, [isGuestCheckout, history, orderDetailsData, orderCount]);
|
|
87
95
|
useEffect(() => {
|
|
88
96
|
if (hasError) {
|
|
89
97
|
const message =
|
|
@@ -125,7 +133,7 @@ const CheckoutPage = props => {
|
|
|
125
133
|
defaultMessage: 'Checkout'
|
|
126
134
|
});
|
|
127
135
|
|
|
128
|
-
if (
|
|
136
|
+
if (isGuestCheckout && orderDetailsData && orderNumber) {
|
|
129
137
|
return (
|
|
130
138
|
<OrderConfirmationPage
|
|
131
139
|
data={orderDetailsData}
|
|
@@ -245,6 +253,7 @@ const CheckoutPage = props => {
|
|
|
245
253
|
checkoutStep === CHECKOUT_STEP.PAYMENT ? (
|
|
246
254
|
<Button
|
|
247
255
|
onClick={handleReviewOrder}
|
|
256
|
+
onTouchStart={handleReviewOrder}
|
|
248
257
|
onKeyDown={handleReviewOrderEnterKeyPress}
|
|
249
258
|
priority="high"
|
|
250
259
|
className={classes.review_order_button}
|
|
@@ -265,7 +274,7 @@ const CheckoutPage = props => {
|
|
|
265
274
|
const itemsReview =
|
|
266
275
|
checkoutStep === CHECKOUT_STEP.REVIEW ? (
|
|
267
276
|
<div className={classes.items_review_container}>
|
|
268
|
-
<ItemsReview />
|
|
277
|
+
<ItemsReview items={cartItems} />
|
|
269
278
|
</div>
|
|
270
279
|
) : null;
|
|
271
280
|
|
|
@@ -4,6 +4,8 @@ import { createTestInstance } from '@magento/peregrine';
|
|
|
4
4
|
|
|
5
5
|
import CreateAccount from '../createAccount';
|
|
6
6
|
|
|
7
|
+
import { useHistory, useLocation } from 'react-router-dom';
|
|
8
|
+
|
|
7
9
|
jest.mock('@apollo/client', () => ({
|
|
8
10
|
gql: jest.fn(),
|
|
9
11
|
useApolloClient: jest.fn().mockImplementation(() => {}),
|
|
@@ -24,6 +26,16 @@ jest.mock('@apollo/client', () => ({
|
|
|
24
26
|
}))
|
|
25
27
|
}));
|
|
26
28
|
|
|
29
|
+
// Mocking the react-router hooks
|
|
30
|
+
|
|
31
|
+
jest.mock('react-router-dom', () => ({
|
|
32
|
+
...jest.requireActual('react-router-dom'),
|
|
33
|
+
|
|
34
|
+
useHistory: jest.fn(),
|
|
35
|
+
|
|
36
|
+
useLocation: jest.fn()
|
|
37
|
+
}));
|
|
38
|
+
|
|
27
39
|
jest.mock('../../../util/formValidators');
|
|
28
40
|
jest.mock('@magento/peregrine/lib/context/user', () => {
|
|
29
41
|
const userState = {
|
|
@@ -58,6 +70,24 @@ jest.mock('@magento/peregrine/lib/hooks/useAwaitQuery', () => {
|
|
|
58
70
|
return { useAwaitQuery };
|
|
59
71
|
});
|
|
60
72
|
|
|
73
|
+
// Mocking useLocation and useHistory for the tests
|
|
74
|
+
|
|
75
|
+
beforeEach(() => {
|
|
76
|
+
useHistory.mockReturnValue({
|
|
77
|
+
push: jest.fn() // mock any methods you need from useHistory
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
useLocation.mockReturnValue({
|
|
81
|
+
pathname: '/mock-path', // mock the location properties
|
|
82
|
+
|
|
83
|
+
search: '',
|
|
84
|
+
|
|
85
|
+
hash: '',
|
|
86
|
+
|
|
87
|
+
state: null
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
61
91
|
jest.mock('@magento/peregrine/lib/context/eventing', () => ({
|
|
62
92
|
useEventingContext: jest.fn().mockReturnValue([{}, { dispatch: jest.fn() }])
|
|
63
93
|
}));
|
|
@@ -46,7 +46,7 @@ const CreateAccount = props => {
|
|
|
46
46
|
<Button
|
|
47
47
|
data-cy="CreateAccount-cancelButton"
|
|
48
48
|
className={classes.cancelButton}
|
|
49
|
-
disabled={isDisabled}
|
|
49
|
+
disabled={Boolean(isDisabled)}
|
|
50
50
|
type="button"
|
|
51
51
|
priority="low"
|
|
52
52
|
onClick={handleCancel}
|
|
@@ -62,7 +62,7 @@ const CreateAccount = props => {
|
|
|
62
62
|
const submitButton = (
|
|
63
63
|
<Button
|
|
64
64
|
className={classes.submitButton}
|
|
65
|
-
disabled={isDisabled}
|
|
65
|
+
disabled={Boolean(isDisabled)}
|
|
66
66
|
type="submit"
|
|
67
67
|
priority="high"
|
|
68
68
|
onKeyDown={handleEnterKeyPress}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { act } from 'react-test-renderer';
|
|
3
|
+
import { MemoryRouter } from 'react-router-dom';
|
|
3
4
|
|
|
4
5
|
import { createTestInstance } from '@magento/peregrine';
|
|
5
6
|
|
|
@@ -19,7 +20,11 @@ jest.mock('../../../Trigger', () => props => <mock-Trigger {...props} />);
|
|
|
19
20
|
let inputProps = {};
|
|
20
21
|
|
|
21
22
|
const Component = () => {
|
|
22
|
-
return
|
|
23
|
+
return (
|
|
24
|
+
<MemoryRouter>
|
|
25
|
+
<CurrentFilter {...inputProps} />
|
|
26
|
+
</MemoryRouter>
|
|
27
|
+
);
|
|
23
28
|
};
|
|
24
29
|
|
|
25
30
|
const givenDefaultValues = () => {
|
|
@@ -2,6 +2,7 @@ import React, { useCallback } from 'react';
|
|
|
2
2
|
import { useIntl } from 'react-intl';
|
|
3
3
|
import { shape, string, func } from 'prop-types';
|
|
4
4
|
import { X as Remove } from 'react-feather';
|
|
5
|
+
import { useHistory, useLocation } from 'react-router-dom';
|
|
5
6
|
|
|
6
7
|
import { useStyle } from '../../../classify';
|
|
7
8
|
import Icon from '../../Icon';
|
|
@@ -12,13 +13,22 @@ const CurrentFilter = props => {
|
|
|
12
13
|
const { group, item, removeItem, onRemove } = props;
|
|
13
14
|
const classes = useStyle(defaultClasses, props.classes);
|
|
14
15
|
const { formatMessage } = useIntl();
|
|
16
|
+
const location = useLocation();
|
|
17
|
+
const history = useHistory();
|
|
15
18
|
|
|
16
19
|
const handleClick = useCallback(() => {
|
|
17
20
|
removeItem({ group, item });
|
|
18
21
|
if (typeof onRemove === 'function') {
|
|
19
22
|
onRemove(group, item);
|
|
20
23
|
}
|
|
21
|
-
|
|
24
|
+
|
|
25
|
+
if (group == 'price') {
|
|
26
|
+
// preserve all existing params
|
|
27
|
+
const params = new URLSearchParams(location.search);
|
|
28
|
+
params.delete('price[filter]');
|
|
29
|
+
history.replace({ search: params.toString() });
|
|
30
|
+
}
|
|
31
|
+
}, [group, item, removeItem, onRemove, history, location.search]);
|
|
22
32
|
|
|
23
33
|
const ariaLabel = formatMessage(
|
|
24
34
|
{
|
|
@@ -34,7 +44,7 @@ const CurrentFilter = props => {
|
|
|
34
44
|
<span className={classes.root} data-cy="CurrentFilter-root">
|
|
35
45
|
<Trigger
|
|
36
46
|
action={handleClick}
|
|
37
|
-
|
|
47
|
+
aria-label={ariaLabel}
|
|
38
48
|
data-cy="CurrentFilter-trigger"
|
|
39
49
|
>
|
|
40
50
|
<Icon size={20} src={Remove} />
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { MemoryRouter } from 'react-router-dom';
|
|
2
3
|
|
|
3
4
|
import { createTestInstance } from '@magento/peregrine';
|
|
4
5
|
|
|
@@ -67,7 +68,11 @@ describe('#FilterList', () => {
|
|
|
67
68
|
});
|
|
68
69
|
|
|
69
70
|
it('renders without show more button', () => {
|
|
70
|
-
const { root } = createTestInstance(
|
|
71
|
+
const { root } = createTestInstance(
|
|
72
|
+
<MemoryRouter>
|
|
73
|
+
<Component />
|
|
74
|
+
</MemoryRouter>
|
|
75
|
+
);
|
|
71
76
|
|
|
72
77
|
expect(root.findAllByType(FilterItem)).toHaveLength(2);
|
|
73
78
|
expect(() => root.findByType('button')).toThrow();
|
|
@@ -76,7 +81,11 @@ describe('#FilterList', () => {
|
|
|
76
81
|
it('renders with show more button', () => {
|
|
77
82
|
givenShowMore();
|
|
78
83
|
|
|
79
|
-
const { root } = createTestInstance(
|
|
84
|
+
const { root } = createTestInstance(
|
|
85
|
+
<MemoryRouter>
|
|
86
|
+
<Component />
|
|
87
|
+
</MemoryRouter>
|
|
88
|
+
);
|
|
80
89
|
|
|
81
90
|
expect(() => root.findByType('button')).not.toThrow();
|
|
82
91
|
expect(root.findByType('button').children[0]).toBe(mockShowMore);
|
|
@@ -86,7 +95,11 @@ describe('#FilterList', () => {
|
|
|
86
95
|
givenShowMore();
|
|
87
96
|
givenExpanded();
|
|
88
97
|
|
|
89
|
-
const { root } = createTestInstance(
|
|
98
|
+
const { root } = createTestInstance(
|
|
99
|
+
<MemoryRouter>
|
|
100
|
+
<Component />
|
|
101
|
+
</MemoryRouter>
|
|
102
|
+
);
|
|
90
103
|
|
|
91
104
|
expect(() => root.findByType('button')).not.toThrow();
|
|
92
105
|
expect(root.findByType('button').children[0]).toBe(mockShowLess);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { Fragment, useMemo } from 'react';
|
|
1
|
+
import React, { Fragment, useMemo, useCallback } from 'react';
|
|
2
2
|
import { array, func, number, shape, string } from 'prop-types';
|
|
3
3
|
import { useIntl } from 'react-intl';
|
|
4
4
|
import setValidator from '@magento/peregrine/lib/validators/set';
|
|
@@ -8,6 +8,8 @@ import { useStyle } from '../../../classify';
|
|
|
8
8
|
import FilterItem from './filterItem';
|
|
9
9
|
import defaultClasses from './filterList.module.css';
|
|
10
10
|
import FilterItemRadioGroup from './filterItemRadioGroup';
|
|
11
|
+
import RangeSlider from '../../RangeSlider/rangeSlider';
|
|
12
|
+
import { useHistory, useLocation } from 'react-router-dom';
|
|
11
13
|
|
|
12
14
|
const labels = new WeakMap();
|
|
13
15
|
|
|
@@ -22,13 +24,46 @@ const FilterList = props => {
|
|
|
22
24
|
items,
|
|
23
25
|
onApply
|
|
24
26
|
} = props;
|
|
27
|
+
const { pathname, search } = useLocation();
|
|
28
|
+
const history = useHistory();
|
|
25
29
|
const classes = useStyle(defaultClasses, props.classes);
|
|
26
30
|
const talonProps = useFilterList({ filterState, items, itemCountToShow });
|
|
27
31
|
const { isListExpanded, handleListToggle } = talonProps;
|
|
28
32
|
const { formatMessage } = useIntl();
|
|
29
33
|
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
if (name === 'Price') {
|
|
35
|
+
var minRange = Number(items[0].value.split('_')[0]);
|
|
36
|
+
var maxRange = Number(items[items.length - 1].value.split('_')[1]);
|
|
37
|
+
if (filterState !== undefined) {
|
|
38
|
+
const filterArray = [...filterState];
|
|
39
|
+
var currentMinVal = Number(filterArray[0].value.split('_')[0]);
|
|
40
|
+
var currentMaxVal = Number(filterArray[0].value.split('_')[1]);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const handleChange = useCallback(
|
|
45
|
+
newValue => {
|
|
46
|
+
const test = String(search).split('&');
|
|
47
|
+
const filters = test.filter(element => {
|
|
48
|
+
return !element.includes('price');
|
|
49
|
+
});
|
|
50
|
+
const newSearch = filters.join('&');
|
|
51
|
+
const nextParams = new URLSearchParams(newSearch);
|
|
52
|
+
|
|
53
|
+
const DELIMITER = ',';
|
|
54
|
+
const title = String(newValue.min) + '-' + String(newValue.max);
|
|
55
|
+
const value = String(newValue.min) + '_' + String(newValue.max);
|
|
56
|
+
nextParams.append(
|
|
57
|
+
`${group}[filter]`,
|
|
58
|
+
`${title}${DELIMITER}${value}`
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
history.push({ pathname, search: String(nextParams) });
|
|
62
|
+
},
|
|
63
|
+
[group, history, pathname, search]
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
// Memoize item creation
|
|
32
67
|
const itemElements = useMemo(() => {
|
|
33
68
|
if (filterFrontendInput === 'boolean') {
|
|
34
69
|
const key = `item-${group}`;
|
|
@@ -51,36 +86,46 @@ const FilterList = props => {
|
|
|
51
86
|
);
|
|
52
87
|
}
|
|
53
88
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
const element = (
|
|
64
|
-
<li
|
|
65
|
-
key={key}
|
|
66
|
-
className={classes.item}
|
|
67
|
-
data-cy="FilterList-item"
|
|
68
|
-
>
|
|
69
|
-
<FilterItem
|
|
70
|
-
filterApi={filterApi}
|
|
71
|
-
filterState={filterState}
|
|
72
|
-
group={group}
|
|
73
|
-
item={item}
|
|
74
|
-
onApply={onApply}
|
|
89
|
+
if (name === 'Price') {
|
|
90
|
+
return (
|
|
91
|
+
<div className={classes.root}>
|
|
92
|
+
<RangeSlider
|
|
93
|
+
min={minRange}
|
|
94
|
+
max={maxRange}
|
|
95
|
+
initialMin={currentMinVal}
|
|
96
|
+
initialMax={currentMaxVal}
|
|
97
|
+
onChange={handleChange}
|
|
75
98
|
/>
|
|
76
|
-
</
|
|
99
|
+
</div>
|
|
77
100
|
);
|
|
101
|
+
} else {
|
|
102
|
+
return items.map((item, index) => {
|
|
103
|
+
const { title, value } = item;
|
|
104
|
+
const key = `item-${group}-${value}`;
|
|
105
|
+
|
|
106
|
+
if (!isListExpanded && index >= itemCountToShow) {
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
78
109
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
110
|
+
const element = (
|
|
111
|
+
<li
|
|
112
|
+
key={key}
|
|
113
|
+
className={classes.item}
|
|
114
|
+
data-cy="FilterList-item"
|
|
115
|
+
>
|
|
116
|
+
<FilterItem
|
|
117
|
+
filterApi={filterApi}
|
|
118
|
+
filterState={filterState}
|
|
119
|
+
group={group}
|
|
120
|
+
item={item}
|
|
121
|
+
onApply={onApply}
|
|
122
|
+
/>
|
|
123
|
+
</li>
|
|
124
|
+
);
|
|
125
|
+
labels.set(element, title.toUpperCase());
|
|
126
|
+
return element;
|
|
127
|
+
});
|
|
128
|
+
}
|
|
84
129
|
}, [
|
|
85
130
|
classes,
|
|
86
131
|
filterApi,
|
|
@@ -91,7 +136,12 @@ const FilterList = props => {
|
|
|
91
136
|
items,
|
|
92
137
|
isListExpanded,
|
|
93
138
|
itemCountToShow,
|
|
94
|
-
onApply
|
|
139
|
+
onApply,
|
|
140
|
+
minRange,
|
|
141
|
+
maxRange,
|
|
142
|
+
currentMinVal,
|
|
143
|
+
currentMaxVal,
|
|
144
|
+
handleChange
|
|
95
145
|
]);
|
|
96
146
|
|
|
97
147
|
const showMoreLessItem = useMemo(() => {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { act } from 'react-test-renderer';
|
|
3
|
+
import { MemoryRouter } from 'react-router-dom';
|
|
3
4
|
|
|
4
5
|
import { createTestInstance } from '@magento/peregrine';
|
|
5
6
|
|
|
@@ -51,6 +52,8 @@ const mockHandleApply = jest.fn();
|
|
|
51
52
|
|
|
52
53
|
const mockScrollTo = jest.fn();
|
|
53
54
|
|
|
55
|
+
const mockFilterOptions = jest.fn();
|
|
56
|
+
|
|
54
57
|
const mockGetBoundingClientRect = jest.fn();
|
|
55
58
|
|
|
56
59
|
let mockFilterState;
|
|
@@ -125,7 +128,8 @@ const Component = () => {
|
|
|
125
128
|
|
|
126
129
|
const givenDefaultValues = () => {
|
|
127
130
|
inputProps = {
|
|
128
|
-
filters: []
|
|
131
|
+
filters: [],
|
|
132
|
+
setFilterOptions: mockFilterOptions
|
|
129
133
|
};
|
|
130
134
|
|
|
131
135
|
mockFilterState = new Map();
|
|
@@ -133,13 +137,15 @@ const givenDefaultValues = () => {
|
|
|
133
137
|
|
|
134
138
|
const givenFilters = () => {
|
|
135
139
|
inputProps = {
|
|
136
|
-
filters: mockFilters
|
|
140
|
+
filters: mockFilters,
|
|
141
|
+
setFilterOptions: mockFilterOptions
|
|
137
142
|
};
|
|
138
143
|
};
|
|
139
144
|
|
|
140
145
|
const givenSelectedFilters = () => {
|
|
141
146
|
inputProps = {
|
|
142
|
-
filters: mockFilters
|
|
147
|
+
filters: mockFilters,
|
|
148
|
+
setFilterOptions: mockFilterOptions
|
|
143
149
|
};
|
|
144
150
|
|
|
145
151
|
mockFilterState = new Map([['group', 'item']]);
|
|
@@ -148,7 +154,8 @@ const givenSelectedFilters = () => {
|
|
|
148
154
|
const givenFiltersAndAmountToShow = () => {
|
|
149
155
|
inputProps = {
|
|
150
156
|
filters: mockFilters,
|
|
151
|
-
filterCountToOpen: mockFiltersOpenCount
|
|
157
|
+
filterCountToOpen: mockFiltersOpenCount,
|
|
158
|
+
setFilterOptions: mockFilterOptions
|
|
152
159
|
};
|
|
153
160
|
};
|
|
154
161
|
|
|
@@ -161,7 +168,11 @@ describe('#FilterSidebar', () => {
|
|
|
161
168
|
});
|
|
162
169
|
|
|
163
170
|
it('renders without filters', () => {
|
|
164
|
-
createTestInstance(
|
|
171
|
+
createTestInstance(
|
|
172
|
+
<MemoryRouter>
|
|
173
|
+
<Component />
|
|
174
|
+
</MemoryRouter>
|
|
175
|
+
);
|
|
165
176
|
|
|
166
177
|
expect(mockFilterBlock).not.toHaveBeenCalled();
|
|
167
178
|
expect(mockCurrentFilters).toHaveBeenCalled();
|
|
@@ -170,7 +181,11 @@ describe('#FilterSidebar', () => {
|
|
|
170
181
|
it('renders with filters and no selected filters', () => {
|
|
171
182
|
givenFilters();
|
|
172
183
|
|
|
173
|
-
const { root } = createTestInstance(
|
|
184
|
+
const { root } = createTestInstance(
|
|
185
|
+
<MemoryRouter>
|
|
186
|
+
<Component />
|
|
187
|
+
</MemoryRouter>
|
|
188
|
+
);
|
|
174
189
|
|
|
175
190
|
expect(() => root.findByType(LinkButton)).toThrow();
|
|
176
191
|
expect(mockFilterBlock).toHaveBeenCalledTimes(mockFilters.length);
|
|
@@ -179,7 +194,11 @@ describe('#FilterSidebar', () => {
|
|
|
179
194
|
it('renders with filters and selected filter', () => {
|
|
180
195
|
givenSelectedFilters();
|
|
181
196
|
|
|
182
|
-
const { root } = createTestInstance(
|
|
197
|
+
const { root } = createTestInstance(
|
|
198
|
+
<MemoryRouter>
|
|
199
|
+
<Component />
|
|
200
|
+
</MemoryRouter>
|
|
201
|
+
);
|
|
183
202
|
|
|
184
203
|
expect(() => root.findByType(LinkButton)).not.toThrow();
|
|
185
204
|
expect(mockFilterBlock).toHaveBeenCalledTimes(mockFilters.length);
|
|
@@ -188,7 +207,11 @@ describe('#FilterSidebar', () => {
|
|
|
188
207
|
it('handles when a user applies a filter and ref is not provided', () => {
|
|
189
208
|
givenSelectedFilters();
|
|
190
209
|
|
|
191
|
-
const { root } = createTestInstance(
|
|
210
|
+
const { root } = createTestInstance(
|
|
211
|
+
<MemoryRouter>
|
|
212
|
+
<Component />
|
|
213
|
+
</MemoryRouter>
|
|
214
|
+
);
|
|
192
215
|
|
|
193
216
|
act(() => {
|
|
194
217
|
root.findAllByType(FilterBlock)[0].props.onApply();
|
|
@@ -206,17 +229,22 @@ describe('#FilterSidebar', () => {
|
|
|
206
229
|
value: mockScrollTo
|
|
207
230
|
});
|
|
208
231
|
|
|
209
|
-
const { root } = createTestInstance(
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
232
|
+
const { root } = createTestInstance(
|
|
233
|
+
<MemoryRouter>
|
|
234
|
+
<Component />
|
|
235
|
+
</MemoryRouter>,
|
|
236
|
+
{
|
|
237
|
+
createNodeMock: () => {
|
|
238
|
+
return {
|
|
239
|
+
getBoundingClientRect: mockGetBoundingClientRect.mockReturnValue(
|
|
240
|
+
{
|
|
241
|
+
top: 250
|
|
242
|
+
}
|
|
243
|
+
)
|
|
244
|
+
};
|
|
245
|
+
}
|
|
218
246
|
}
|
|
219
|
-
|
|
247
|
+
);
|
|
220
248
|
|
|
221
249
|
act(() => {
|
|
222
250
|
root.findAllByType(FilterBlock)[0].props.onApply();
|
|
@@ -229,7 +257,11 @@ describe('#FilterSidebar', () => {
|
|
|
229
257
|
|
|
230
258
|
it('accepts configurable amount of open filters', () => {
|
|
231
259
|
givenFiltersAndAmountToShow();
|
|
232
|
-
createTestInstance(
|
|
260
|
+
createTestInstance(
|
|
261
|
+
<MemoryRouter>
|
|
262
|
+
<Component />
|
|
263
|
+
</MemoryRouter>
|
|
264
|
+
);
|
|
233
265
|
|
|
234
266
|
expect(mockFilterBlock).toHaveBeenCalledTimes(mockFilters.length);
|
|
235
267
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useMemo, useCallback, useRef } from 'react';
|
|
1
|
+
import React, { useMemo, useCallback, useRef, useEffect } from 'react';
|
|
2
2
|
import { FormattedMessage } from 'react-intl';
|
|
3
3
|
import { array, arrayOf, shape, string, number } from 'prop-types';
|
|
4
4
|
import { useFilterSidebar } from '@magento/peregrine/lib/talons/FilterSidebar';
|
|
@@ -8,6 +8,7 @@ import LinkButton from '../LinkButton';
|
|
|
8
8
|
import CurrentFilters from '../FilterModal/CurrentFilters';
|
|
9
9
|
import FilterBlock from '../FilterModal/filterBlock';
|
|
10
10
|
import defaultClasses from './filterSidebar.module.css';
|
|
11
|
+
import { useLocation } from 'react-router-dom';
|
|
11
12
|
|
|
12
13
|
const SCROLL_OFFSET = 150;
|
|
13
14
|
|
|
@@ -17,7 +18,7 @@ const SCROLL_OFFSET = 150;
|
|
|
17
18
|
* @param {Object} props.filters - filters to display
|
|
18
19
|
*/
|
|
19
20
|
const FilterSidebar = props => {
|
|
20
|
-
const { filters, filterCountToOpen } = props;
|
|
21
|
+
const { filters, filterCountToOpen, setFilterOptions } = props;
|
|
21
22
|
const talonProps = useFilterSidebar({ filters });
|
|
22
23
|
const {
|
|
23
24
|
filterApi,
|
|
@@ -31,6 +32,32 @@ const FilterSidebar = props => {
|
|
|
31
32
|
|
|
32
33
|
const filterRef = useRef();
|
|
33
34
|
const classes = useStyle(defaultClasses, props.classes);
|
|
35
|
+
const location = useLocation();
|
|
36
|
+
|
|
37
|
+
//adding the price filter values to the filterstate
|
|
38
|
+
const priceFilters = Array.from(filterItems, ([group]) => {
|
|
39
|
+
if (group == 'price') {
|
|
40
|
+
// preserve all existing params
|
|
41
|
+
const params = new URLSearchParams(location.search);
|
|
42
|
+
const uniqueKeys = new Set(params.keys());
|
|
43
|
+
// iterate over existing param keys
|
|
44
|
+
for (const key of uniqueKeys) {
|
|
45
|
+
// if a key matches a known filter, add its items to the next state
|
|
46
|
+
if (key == 'price[filter]') {
|
|
47
|
+
const value = params.get('price[filter]');
|
|
48
|
+
const item = {
|
|
49
|
+
title: value.split(',')[0],
|
|
50
|
+
value: value.split(',')[1]
|
|
51
|
+
};
|
|
52
|
+
const filterVar = new Set();
|
|
53
|
+
filterVar.add(item);
|
|
54
|
+
|
|
55
|
+
//to display the price filter value after selecting the filter
|
|
56
|
+
filterState.set('price', new Set(filterVar));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
});
|
|
34
61
|
|
|
35
62
|
const handleApplyFilter = useCallback(
|
|
36
63
|
(...args) => {
|
|
@@ -50,6 +77,12 @@ const FilterSidebar = props => {
|
|
|
50
77
|
[handleApply, filterRef]
|
|
51
78
|
);
|
|
52
79
|
|
|
80
|
+
useEffect(() => {
|
|
81
|
+
if (filterState) {
|
|
82
|
+
setFilterOptions(filterState);
|
|
83
|
+
}
|
|
84
|
+
}, [filterState, setFilterOptions]);
|
|
85
|
+
|
|
53
86
|
const filtersList = useMemo(
|
|
54
87
|
() =>
|
|
55
88
|
Array.from(filterItems, ([group, items], iteration) => {
|
|
@@ -115,6 +148,7 @@ const FilterSidebar = props => {
|
|
|
115
148
|
/>
|
|
116
149
|
</h2>
|
|
117
150
|
</div>
|
|
151
|
+
{priceFilters}
|
|
118
152
|
<CurrentFilters
|
|
119
153
|
filterApi={filterApi}
|
|
120
154
|
filterNames={filterNames}
|
|
@@ -20,7 +20,7 @@ exports[`renders if \`items\` is an array of objects 1`] = `
|
|
|
20
20
|
className="image placeholder_layoutOnly"
|
|
21
21
|
height={375}
|
|
22
22
|
loading="eager"
|
|
23
|
-
src="data:image/svg+xml;base64,
|
|
23
|
+
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0IiBoZWlnaHQ9IjUiIHZpZXdCb3g9Ii0yNSAtMjUgMzEyIDMxMiI+CiAgICA8ZyBpZD0iTGF5ZXJfMi0yIj4KICAgICAgICA8cGF0aCBjbGFzcz0ic3QwIiBzdHlsZT0iZmlsbDogI2YwZjBmMDsgZmlsbC1ydWxlOiBldmVub2RkOyIgZD0iTTM2LDE4OS40di0xMDkuMWMwLTAuNywwLjQtMS42LDEuMS0ybDk0LjctNTcuMWMwLjctMC41LDEuNy0wLjUsMi41LDBsOTEuNSw1N2MwLjcsMC40LDEuMSwxLjEsMS4xLDJ2MTA3LjljMCwwLjctMC40LDEuNS0xLjEsMmwtMTkuMywxMi42Yy0xLjUsMS0zLjYsMC0zLjYtMnYtMTA1LjljMC0wLjctMC40LTEuNi0xLjEtMmwtNjcuNS00MS4zYy0wLjctMC41LTEuNi0wLjUtMi4zLDBsLTY5LjYsNDEuM2MtMC43LDAuNC0xLjEsMS4xLTEuMSwydjEwNS45YzAsMS45LTIsMy0zLjYsMmwtMjEuNS0xMy41aDB2LjJaTTg2LDExMC45djEwNi4zYzAsMC45LDAuNCwxLjYsMS4xLDJsNDQuNSwyNi43YzAuNywwLjUsMS43LDAuNCwyLjUsMGw0Mi41LTI2LjdjMC43LTAuNCwxLjEtMS4xLDEuMS0ydi0xMDUuOGMwLTAuNy0wLjQtMS41LTEuMS0ybC0yOC43LTE3LjljLTEuNS0xLTMuNiwwLjEtMy42LDJ2MTIxLjZjMCwwLjctMC40LDEuNS0xLjEsMmwtOS4zLDUuOWMtMC43LDAuNS0xLjYsMC41LTIuMywwbC0xMS4xLTUuOWMtMC43LTAuNC0xLjItMS4yLTEuMi0yLjF2LTEyMS43YzAtMS43LTItMy0zLjUtMmwtMjguOCwxNi4yYy0wLjcsMC40LTEuMSwxLjEtMS4xLDJ2MS41aC4xWiIvPgogICAgPC9nPgo8L3N2Zz4K"
|
|
24
24
|
style={
|
|
25
25
|
Object {
|
|
26
26
|
"--height": "375px",
|
|
@@ -115,7 +115,7 @@ exports[`renders if \`items\` is an array of objects 1`] = `
|
|
|
115
115
|
className="image placeholder_layoutOnly"
|
|
116
116
|
height={375}
|
|
117
117
|
loading="eager"
|
|
118
|
-
src="data:image/svg+xml;base64,
|
|
118
|
+
src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI0IiBoZWlnaHQ9IjUiIHZpZXdCb3g9Ii0yNSAtMjUgMzEyIDMxMiI+CiAgICA8ZyBpZD0iTGF5ZXJfMi0yIj4KICAgICAgICA8cGF0aCBjbGFzcz0ic3QwIiBzdHlsZT0iZmlsbDogI2YwZjBmMDsgZmlsbC1ydWxlOiBldmVub2RkOyIgZD0iTTM2LDE4OS40di0xMDkuMWMwLTAuNywwLjQtMS42LDEuMS0ybDk0LjctNTcuMWMwLjctMC41LDEuNy0wLjUsMi41LDBsOTEuNSw1N2MwLjcsMC40LDEuMSwxLjEsMS4xLDJ2MTA3LjljMCwwLjctMC40LDEuNS0xLjEsMmwtMTkuMywxMi42Yy0xLjUsMS0zLjYsMC0zLjYtMnYtMTA1LjljMC0wLjctMC40LTEuNi0xLjEtMmwtNjcuNS00MS4zYy0wLjctMC41LTEuNi0wLjUtMi4zLDBsLTY5LjYsNDEuM2MtMC43LDAuNC0xLjEsMS4xLTEuMSwydjEwNS45YzAsMS45LTIsMy0zLjYsMmwtMjEuNS0xMy41aDB2LjJaTTg2LDExMC45djEwNi4zYzAsMC45LDAuNCwxLjYsMS4xLDJsNDQuNSwyNi43YzAuNywwLjUsMS43LDAuNCwyLjUsMGw0Mi41LTI2LjdjMC43LTAuNCwxLjEtMS4xLDEuMS0ydi0xMDUuOGMwLTAuNy0wLjQtMS41LTEuMS0ybC0yOC43LTE3LjljLTEuNS0xLTMuNiwwLjEtMy42LDJ2MTIxLjZjMCwwLjctMC40LDEuNS0xLjEsMmwtOS4zLDUuOWMtMC43LDAuNS0xLjYsMC41LTIuMywwbC0xMS4xLTUuOWMtMC43LTAuNC0xLjItMS4yLTEuMi0yLjF2LTEyMS43YzAtMS43LTItMy0zLjUtMmwtMjguOCwxNi4yYy0wLjcsMC40LTEuMSwxLjEtMS4xLDJ2MS41aC4xWiIvPgogICAgPC9nPgo8L3N2Zz4K"
|
|
119
119
|
style={
|
|
120
120
|
Object {
|
|
121
121
|
"--height": "375px",
|