@salesforce/retail-react-app 1.0.0-preview.0
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/.eslintignore +7 -0
- package/.eslintrc.js +25 -0
- package/.prettierignore +4 -0
- package/.prettierrc.yaml +7 -0
- package/CHANGELOG.md +173 -0
- package/LICENSE +14 -0
- package/README.md +48 -0
- package/app/assets/svg/account.svg +3 -0
- package/app/assets/svg/alert.svg +3 -0
- package/app/assets/svg/basket.svg +3 -0
- package/app/assets/svg/brand-logo.svg +10 -0
- package/app/assets/svg/cc-amex.svg +7 -0
- package/app/assets/svg/cc-cvv.svg +8 -0
- package/app/assets/svg/cc-discover.svg +14 -0
- package/app/assets/svg/cc-mastercard.svg +8 -0
- package/app/assets/svg/cc-visa.svg +11 -0
- package/app/assets/svg/check-circle.svg +3 -0
- package/app/assets/svg/check.svg +3 -0
- package/app/assets/svg/chevron-down.svg +3 -0
- package/app/assets/svg/chevron-left.svg +3 -0
- package/app/assets/svg/chevron-right.svg +3 -0
- package/app/assets/svg/chevron-up.svg +3 -0
- package/app/assets/svg/close.svg +3 -0
- package/app/assets/svg/dashboard.svg +4 -0
- package/app/assets/svg/figma-logo.svg +14 -0
- package/app/assets/svg/file.svg +3 -0
- package/app/assets/svg/filter.svg +3 -0
- package/app/assets/svg/flag-ca.svg +5 -0
- package/app/assets/svg/flag-cn.svg +19 -0
- package/app/assets/svg/flag-fr.svg +19 -0
- package/app/assets/svg/flag-gb.svg +16 -0
- package/app/assets/svg/flag-it.svg +29 -0
- package/app/assets/svg/flag-jp.svg +10 -0
- package/app/assets/svg/flag-us.svg +7 -0
- package/app/assets/svg/github-logo.svg +40 -0
- package/app/assets/svg/hamburger.svg +8 -0
- package/app/assets/svg/heart-solid.svg +7 -0
- package/app/assets/svg/heart.svg +3 -0
- package/app/assets/svg/info.svg +3 -0
- package/app/assets/svg/like.svg +4 -0
- package/app/assets/svg/location.svg +3 -0
- package/app/assets/svg/lock.svg +3 -0
- package/app/assets/svg/paypal.svg +19 -0
- package/app/assets/svg/plug.svg +3 -0
- package/app/assets/svg/plus.svg +3 -0
- package/app/assets/svg/receipt.svg +3 -0
- package/app/assets/svg/search.svg +8 -0
- package/app/assets/svg/signout.svg +3 -0
- package/app/assets/svg/social-facebook.svg +3 -0
- package/app/assets/svg/social-instagram.svg +3 -0
- package/app/assets/svg/social-pinterest.svg +4 -0
- package/app/assets/svg/social-twitter.svg +3 -0
- package/app/assets/svg/social-youtube.svg +3 -0
- package/app/assets/svg/user.svg +3 -0
- package/app/assets/svg/visibility-off.svg +5 -0
- package/app/assets/svg/visibility.svg +3 -0
- package/app/components/_app/index.jsx +401 -0
- package/app/components/_app/index.test.js +85 -0
- package/app/components/_app/partials/above-header.jsx +10 -0
- package/app/components/_app-config/index.jsx +125 -0
- package/app/components/_app-config/index.test.js +77 -0
- package/app/components/_error/index.jsx +142 -0
- package/app/components/_error/index.test.js +25 -0
- package/app/components/action-card/index.jsx +75 -0
- package/app/components/address-display/index.jsx +30 -0
- package/app/components/basic-tile/index.jsx +65 -0
- package/app/components/basic-tile/index.test.js +23 -0
- package/app/components/breadcrumb/index.jsx +67 -0
- package/app/components/breadcrumb/index.test.js +30 -0
- package/app/components/confirmation-modal/index.jsx +111 -0
- package/app/components/confirmation-modal/index.test.js +98 -0
- package/app/components/drawer-menu/index.jsx +405 -0
- package/app/components/drawer-menu/index.test.js +33 -0
- package/app/components/dynamic-image/index.jsx +56 -0
- package/app/components/field/index.jsx +161 -0
- package/app/components/footer/index.jsx +269 -0
- package/app/components/footer/index.test.js +22 -0
- package/app/components/forms/address-fields.jsx +49 -0
- package/app/components/forms/credit-card-fields.jsx +149 -0
- package/app/components/forms/form-action-buttons.jsx +55 -0
- package/app/components/forms/login-fields.jsx +31 -0
- package/app/components/forms/password-requirements.jsx +99 -0
- package/app/components/forms/post-checkout-registration-fields.jsx +43 -0
- package/app/components/forms/profile-fields.jsx +36 -0
- package/app/components/forms/promo-code-fields.jsx +43 -0
- package/app/components/forms/registration-fields.jsx +42 -0
- package/app/components/forms/reset-password-fields.jsx +31 -0
- package/app/components/forms/state-province-options.jsx +75 -0
- package/app/components/forms/update-password-fields.jsx +49 -0
- package/app/components/forms/useAddressFields.jsx +196 -0
- package/app/components/forms/useCreditCardFields.jsx +146 -0
- package/app/components/forms/useLoginFields.jsx +52 -0
- package/app/components/forms/useProfileFields.jsx +95 -0
- package/app/components/forms/usePromoCodeFields.jsx +39 -0
- package/app/components/forms/useRegistrationFields.jsx +136 -0
- package/app/components/forms/useResetPasswordFields.jsx +40 -0
- package/app/components/forms/useUpdatePasswordFields.jsx +89 -0
- package/app/components/header/index.jsx +290 -0
- package/app/components/header/index.test.js +217 -0
- package/app/components/hero/index.jsx +84 -0
- package/app/components/hero/index.test.js +40 -0
- package/app/components/icons/index.jsx +158 -0
- package/app/components/icons/index.test.js +20 -0
- package/app/components/image-gallery/index.jsx +176 -0
- package/app/components/image-gallery/index.test.js +485 -0
- package/app/components/item-variant/index.jsx +33 -0
- package/app/components/item-variant/item-attributes.jsx +107 -0
- package/app/components/item-variant/item-image.jsx +73 -0
- package/app/components/item-variant/item-name.jsx +28 -0
- package/app/components/item-variant/item-price.jsx +117 -0
- package/app/components/link/index.jsx +32 -0
- package/app/components/link/index.test.js +72 -0
- package/app/components/links-list/index.jsx +89 -0
- package/app/components/links-list/index.test.js +62 -0
- package/app/components/list-menu/index.jsx +280 -0
- package/app/components/list-menu/index.test.js +44 -0
- package/app/components/loading-spinner/index.jsx +46 -0
- package/app/components/locale-selector/index.jsx +124 -0
- package/app/components/locale-selector/index.test.js +37 -0
- package/app/components/locale-text/index.jsx +97 -0
- package/app/components/locale-text/index.test.js +36 -0
- package/app/components/login/index.jsx +96 -0
- package/app/components/nested-accordion/index.jsx +185 -0
- package/app/components/nested-accordion/index.test.js +98 -0
- package/app/components/offline-banner/index.jsx +40 -0
- package/app/components/offline-banner/index.test.js +15 -0
- package/app/components/offline-boundary/index.jsx +104 -0
- package/app/components/offline-boundary/index.test.js +123 -0
- package/app/components/order-summary/index.jsx +331 -0
- package/app/components/page-action-placeholder/index.jsx +50 -0
- package/app/components/pagination/index.jsx +134 -0
- package/app/components/pagination/index.test.js +25 -0
- package/app/components/product-item/index.jsx +146 -0
- package/app/components/product-item/index.test.js +38 -0
- package/app/components/product-scroller/index.jsx +172 -0
- package/app/components/product-scroller/index.test.js +98 -0
- package/app/components/product-tile/index.jsx +195 -0
- package/app/components/product-tile/index.test.js +96 -0
- package/app/components/product-view/index.jsx +538 -0
- package/app/components/product-view/index.test.js +224 -0
- package/app/components/product-view-modal/index.jsx +48 -0
- package/app/components/product-view-modal/index.test.js +72 -0
- package/app/components/promo-code/index.jsx +162 -0
- package/app/components/promo-popover/index.jsx +83 -0
- package/app/components/quantity-picker/index.jsx +58 -0
- package/app/components/radio-card/index.jsx +75 -0
- package/app/components/recommended-products/index.jsx +227 -0
- package/app/components/register/index.jsx +114 -0
- package/app/components/reset-password/index.jsx +87 -0
- package/app/components/responsive/index.jsx +29 -0
- package/app/components/scroll-to-top/index.jsx +24 -0
- package/app/components/scroll-to-top/index.test.js +46 -0
- package/app/components/search/index.jsx +279 -0
- package/app/components/search/index.test.js +127 -0
- package/app/components/search/partials/recent-searches.jsx +76 -0
- package/app/components/search/partials/search-suggestions.jsx +45 -0
- package/app/components/search/partials/suggestions.jsx +43 -0
- package/app/components/section/index.jsx +68 -0
- package/app/components/seo/index.jsx +33 -0
- package/app/components/social-icons/index.jsx +101 -0
- package/app/components/social-icons/index.test.js +30 -0
- package/app/components/swatch-group/index.jsx +77 -0
- package/app/components/swatch-group/index.test.js +136 -0
- package/app/components/swatch-group/swatch.jsx +94 -0
- package/app/components/toggle-card/index.jsx +97 -0
- package/app/components/with-registration/index.jsx +58 -0
- package/app/components/with-registration/index.test.js +85 -0
- package/app/constants.js +109 -0
- package/app/contexts/index.js +92 -0
- package/app/hooks/einstein-mock-data.js +916 -0
- package/app/hooks/index.js +17 -0
- package/app/hooks/use-add-to-cart-modal.js +344 -0
- package/app/hooks/use-add-to-cart-modal.test.js +625 -0
- package/app/hooks/use-auth-modal.js +337 -0
- package/app/hooks/use-auth-modal.test.js +365 -0
- package/app/hooks/use-currency.js +20 -0
- package/app/hooks/use-currency.test.js +41 -0
- package/app/hooks/use-current-basket.js +39 -0
- package/app/hooks/use-current-customer.js +29 -0
- package/app/hooks/use-derived-product.js +77 -0
- package/app/hooks/use-derived-product.test.js +69 -0
- package/app/hooks/use-einstein.js +512 -0
- package/app/hooks/use-einstein.test.js +224 -0
- package/app/hooks/use-intersection-observer.js +64 -0
- package/app/hooks/use-limit-urls.js +31 -0
- package/app/hooks/use-limit-urls.test.js +40 -0
- package/app/hooks/use-multi-site.js +36 -0
- package/app/hooks/use-multi-site.test.js +53 -0
- package/app/hooks/use-navigation.js +37 -0
- package/app/hooks/use-navigation.test.js +109 -0
- package/app/hooks/use-page-urls.js +35 -0
- package/app/hooks/use-page-urls.test.js +39 -0
- package/app/hooks/use-pdp-search-params.js +16 -0
- package/app/hooks/use-pdp-search-params.test.js +52 -0
- package/app/hooks/use-previous.js +17 -0
- package/app/hooks/use-product-view-modal.js +93 -0
- package/app/hooks/use-product-view-modal.test.js +172 -0
- package/app/hooks/use-search-params.js +96 -0
- package/app/hooks/use-search-params.test.js +91 -0
- package/app/hooks/use-sort-urls.js +33 -0
- package/app/hooks/use-sort-urls.test.js +42 -0
- package/app/hooks/use-toast.js +68 -0
- package/app/hooks/use-toast.test.js +58 -0
- package/app/hooks/use-variant.js +32 -0
- package/app/hooks/use-variant.test.js +81 -0
- package/app/hooks/use-variation-attributes.js +138 -0
- package/app/hooks/use-variation-attributes.test.js +119 -0
- package/app/hooks/use-variation-params.js +31 -0
- package/app/hooks/use-variation-params.test.js +73 -0
- package/app/hooks/use-wish-list.js +42 -0
- package/app/main.jsx +14 -0
- package/app/mocks/basket-with-suit.js +146 -0
- package/app/mocks/empty-basket.js +39 -0
- package/app/mocks/mock-data.js +5632 -0
- package/app/mocks/product-set-winter-lookM.js +1224 -0
- package/app/mocks/searchResults.js +144 -0
- package/app/mocks/variant-750518699578M.js +434 -0
- package/app/page-designer/README.md +102 -0
- package/app/page-designer/assets/image-tile/index.jsx +51 -0
- package/app/page-designer/assets/image-tile/index.test.js +30 -0
- package/app/page-designer/assets/image-with-text/index.jsx +140 -0
- package/app/page-designer/assets/image-with-text/index.test.js +38 -0
- package/app/page-designer/assets/index.js +9 -0
- package/app/page-designer/index.js +10 -0
- package/app/page-designer/layouts/carousel/index.jsx +222 -0
- package/app/page-designer/layouts/carousel/index.test.js +43 -0
- package/app/page-designer/layouts/index.js +14 -0
- package/app/page-designer/layouts/mobileGrid1r1c/index.jsx +36 -0
- package/app/page-designer/layouts/mobileGrid1r1c/index.test.js +35 -0
- package/app/page-designer/layouts/mobileGrid2r1c/index.jsx +37 -0
- package/app/page-designer/layouts/mobileGrid2r1c/index.test.js +47 -0
- package/app/page-designer/layouts/mobileGrid2r2c/index.jsx +37 -0
- package/app/page-designer/layouts/mobileGrid2r2c/index.test.js +71 -0
- package/app/page-designer/layouts/mobileGrid2r3c/index.jsx +37 -0
- package/app/page-designer/layouts/mobileGrid2r3c/index.test.js +95 -0
- package/app/page-designer/layouts/mobileGrid3r1c/index.jsx +37 -0
- package/app/page-designer/layouts/mobileGrid3r1c/index.test.js +59 -0
- package/app/page-designer/layouts/mobileGrid3r2c/index.jsx +37 -0
- package/app/page-designer/layouts/mobileGrid3r2c/index.test.js +95 -0
- package/app/page-designer/utils.js +14 -0
- package/app/pages/account/addresses.jsx +382 -0
- package/app/pages/account/addresses.test.js +120 -0
- package/app/pages/account/constant.js +57 -0
- package/app/pages/account/index.jsx +237 -0
- package/app/pages/account/index.test.js +188 -0
- package/app/pages/account/order-detail.jsx +397 -0
- package/app/pages/account/order-history.jsx +264 -0
- package/app/pages/account/orders.jsx +30 -0
- package/app/pages/account/orders.test.js +95 -0
- package/app/pages/account/profile.jsx +357 -0
- package/app/pages/account/wishlist/index.jsx +195 -0
- package/app/pages/account/wishlist/index.mock.js +1481 -0
- package/app/pages/account/wishlist/index.test.js +56 -0
- package/app/pages/account/wishlist/partials/wishlist-primary-action.jsx +170 -0
- package/app/pages/account/wishlist/partials/wishlist-primary-action.mock.js +1623 -0
- package/app/pages/account/wishlist/partials/wishlist-primary-action.test.js +99 -0
- package/app/pages/account/wishlist/partials/wishlist-secondary-button-group.jsx +120 -0
- package/app/pages/account/wishlist/partials/wishlist-secondary-button-group.test.js +391 -0
- package/app/pages/cart/index.jsx +476 -0
- package/app/pages/cart/index.test.js +481 -0
- package/app/pages/cart/partials/cart-cta.jsx +46 -0
- package/app/pages/cart/partials/cart-secondary-button-group.jsx +135 -0
- package/app/pages/cart/partials/cart-secondary-button-group.test.js +103 -0
- package/app/pages/cart/partials/cart-skeleton.jsx +93 -0
- package/app/pages/cart/partials/cart-title.jsx +27 -0
- package/app/pages/cart/partials/empty-cart.jsx +86 -0
- package/app/pages/checkout/confirmation.jsx +541 -0
- package/app/pages/checkout/confirmation.mock.js +450 -0
- package/app/pages/checkout/confirmation.test.js +114 -0
- package/app/pages/checkout/index.jsx +169 -0
- package/app/pages/checkout/index.test.js +582 -0
- package/app/pages/checkout/partials/cc-radio-group.jsx +122 -0
- package/app/pages/checkout/partials/checkout-footer.jsx +140 -0
- package/app/pages/checkout/partials/checkout-footer.test.js +16 -0
- package/app/pages/checkout/partials/checkout-header.jsx +54 -0
- package/app/pages/checkout/partials/checkout-header.test.js +16 -0
- package/app/pages/checkout/partials/checkout-skeleton.jsx +52 -0
- package/app/pages/checkout/partials/contact-info.jsx +251 -0
- package/app/pages/checkout/partials/contact-info.test.js +43 -0
- package/app/pages/checkout/partials/payment-form.jsx +97 -0
- package/app/pages/checkout/partials/payment.jsx +276 -0
- package/app/pages/checkout/partials/shipping-address-selection.jsx +377 -0
- package/app/pages/checkout/partials/shipping-address.jsx +132 -0
- package/app/pages/checkout/partials/shipping-options.jsx +232 -0
- package/app/pages/checkout/util/checkout-context.js +94 -0
- package/app/pages/home/data.js +134 -0
- package/app/pages/home/index.jsx +301 -0
- package/app/pages/home/index.test.js +23 -0
- package/app/pages/login/index.jsx +123 -0
- package/app/pages/login/index.test.js +229 -0
- package/app/pages/login-redirect/index.jsx +23 -0
- package/app/pages/login-redirect/index.test.js +16 -0
- package/app/pages/page-not-found/index.jsx +90 -0
- package/app/pages/page-not-found/index.test.js +31 -0
- package/app/pages/product-detail/index.jsx +394 -0
- package/app/pages/product-detail/index.mock.js +197 -0
- package/app/pages/product-detail/index.test.js +162 -0
- package/app/pages/product-detail/partials/information-accordion.jsx +121 -0
- package/app/pages/product-list/index.jsx +735 -0
- package/app/pages/product-list/index.test.js +180 -0
- package/app/pages/product-list/partials/above-page-header.jsx +10 -0
- package/app/pages/product-list/partials/checkbox-refinements.jsx +41 -0
- package/app/pages/product-list/partials/checkbox-refinements.test.js +53 -0
- package/app/pages/product-list/partials/color-refinements.jsx +88 -0
- package/app/pages/product-list/partials/empty-results.jsx +118 -0
- package/app/pages/product-list/partials/link-refinements.jsx +38 -0
- package/app/pages/product-list/partials/page-header.jsx +42 -0
- package/app/pages/product-list/partials/radio-refinements.jsx +60 -0
- package/app/pages/product-list/partials/refinements.jsx +144 -0
- package/app/pages/product-list/partials/selected-refinements.jsx +100 -0
- package/app/pages/product-list/partials/size-refinements.jsx +55 -0
- package/app/pages/registration/index.jsx +87 -0
- package/app/pages/registration/index.test.jsx +132 -0
- package/app/pages/reset-password/index.jsx +112 -0
- package/app/pages/reset-password/index.test.jsx +141 -0
- package/app/request-processor.js +118 -0
- package/app/request-processor.test.js +23 -0
- package/app/routes.jsx +111 -0
- package/app/routes.test.js +13 -0
- package/app/ssr.js +70 -0
- package/app/static/ico/favicon.ico +0 -0
- package/app/static/img/global/app-icon-192.png +0 -0
- package/app/static/img/global/app-icon-512.png +0 -0
- package/app/static/img/global/apple-touch-icon.png +0 -0
- package/app/static/img/hero.png +0 -0
- package/app/static/manifest.json +19 -0
- package/app/static/robots.txt +2 -0
- package/app/theme/components/base/accordion.js +21 -0
- package/app/theme/components/base/alert.js +17 -0
- package/app/theme/components/base/badge.js +25 -0
- package/app/theme/components/base/button.js +77 -0
- package/app/theme/components/base/checkbox.js +30 -0
- package/app/theme/components/base/container.js +17 -0
- package/app/theme/components/base/drawer.js +26 -0
- package/app/theme/components/base/formLabel.js +13 -0
- package/app/theme/components/base/icon.js +13 -0
- package/app/theme/components/base/input.js +44 -0
- package/app/theme/components/base/modal.js +11 -0
- package/app/theme/components/base/popover.js +61 -0
- package/app/theme/components/base/radio.js +33 -0
- package/app/theme/components/base/select.js +15 -0
- package/app/theme/components/base/skeleton.js +12 -0
- package/app/theme/components/base/tooltip.js +19 -0
- package/app/theme/components/project/_app.js +25 -0
- package/app/theme/components/project/breadcrumb.js +25 -0
- package/app/theme/components/project/checkout-footer.js +35 -0
- package/app/theme/components/project/drawer-menu.js +66 -0
- package/app/theme/components/project/footer.js +84 -0
- package/app/theme/components/project/header.js +84 -0
- package/app/theme/components/project/image-gallery.js +59 -0
- package/app/theme/components/project/links-list.js +43 -0
- package/app/theme/components/project/list-menu.js +91 -0
- package/app/theme/components/project/locale-selector.js +42 -0
- package/app/theme/components/project/nested-accordion.js +26 -0
- package/app/theme/components/project/offline-banner.js +25 -0
- package/app/theme/components/project/pagination.js +22 -0
- package/app/theme/components/project/product-tile.js +32 -0
- package/app/theme/components/project/social-icons.js +52 -0
- package/app/theme/components/project/swatch-group.js +115 -0
- package/app/theme/foundations/colors.js +170 -0
- package/app/theme/foundations/gradients.js +9 -0
- package/app/theme/foundations/layerStyles.js +41 -0
- package/app/theme/foundations/shadows.js +9 -0
- package/app/theme/foundations/sizes.js +18 -0
- package/app/theme/foundations/space.js +9 -0
- package/app/theme/foundations/styles.js +21 -0
- package/app/theme/index.js +104 -0
- package/app/utils/cc-utils.js +112 -0
- package/app/utils/cc-utils.test.js +41 -0
- package/app/utils/image-groups-utils.js +62 -0
- package/app/utils/image-groups-utils.test.js +65 -0
- package/app/utils/locale.js +78 -0
- package/app/utils/locale.test.js +112 -0
- package/app/utils/password-utils.js +21 -0
- package/app/utils/phone-utils.js +22 -0
- package/app/utils/phone-utils.test.js +15 -0
- package/app/utils/product-utils.js +35 -0
- package/app/utils/product-utils.test.js +51 -0
- package/app/utils/responsive-image.js +198 -0
- package/app/utils/responsive-image.test.js +170 -0
- package/app/utils/routes-utils.js +111 -0
- package/app/utils/routes-utils.test.js +291 -0
- package/app/utils/site-utils.js +222 -0
- package/app/utils/site-utils.test.js +376 -0
- package/app/utils/test-utils.js +257 -0
- package/app/utils/url.js +291 -0
- package/app/utils/url.test.js +421 -0
- package/app/utils/utils.js +201 -0
- package/app/utils/utils.test.js +182 -0
- package/babel.config.js +7 -0
- package/cache-hash-config.json +8 -0
- package/config/default.js +64 -0
- package/config/mocks/default.js +131 -0
- package/config/sites.js +78 -0
- package/jest-setup.js +191 -0
- package/jest.config.js +50 -0
- package/jsconfig.json +13 -0
- package/package.json +105 -0
- package/scripts/extract-default-messages.js +92 -0
- package/tests/lighthouserc.js +37 -0
- package/translations/README.md +127 -0
- package/translations/compiled/de-DE.json +3212 -0
- package/translations/compiled/en-GB.json +3212 -0
- package/translations/compiled/en-US.json +3212 -0
- package/translations/compiled/en-XA.json +6948 -0
- package/translations/compiled/es-MX.json +3216 -0
- package/translations/compiled/fr-FR.json +3216 -0
- package/translations/compiled/it-IT.json +3188 -0
- package/translations/compiled/ja-JP.json +3200 -0
- package/translations/compiled/ko-KR.json +3180 -0
- package/translations/compiled/pt-BR.json +3220 -0
- package/translations/compiled/zh-CN.json +3212 -0
- package/translations/compiled/zh-TW.json +3208 -0
- package/translations/de-DE.json +1417 -0
- package/translations/en-GB.json +1417 -0
- package/translations/en-US.json +1417 -0
- package/translations/es-MX.json +1417 -0
- package/translations/fr-FR.json +1417 -0
- package/translations/it-IT.json +1417 -0
- package/translations/ja-JP.json +1417 -0
- package/translations/ko-KR.json +1417 -0
- package/translations/pt-BR.json +1417 -0
- package/translations/zh-CN.json +1417 -0
- package/translations/zh-TW.json +1417 -0
- package/worker/main.js +36 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2021, salesforce.com, inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
5
|
+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react'
|
|
8
|
+
import {useToast} from '@salesforce/retail-react-app/app/hooks/use-toast'
|
|
9
|
+
import {Button} from '@chakra-ui/react'
|
|
10
|
+
import {renderWithProviders} from '@salesforce/retail-react-app/app/utils/test-utils'
|
|
11
|
+
import {screen, waitFor} from '@testing-library/react'
|
|
12
|
+
import userEvent from '@testing-library/user-event'
|
|
13
|
+
|
|
14
|
+
jest.setTimeout(60000)
|
|
15
|
+
const MockedComponent = (props) => {
|
|
16
|
+
const showToast = useToast()
|
|
17
|
+
|
|
18
|
+
const renderToast = () => {
|
|
19
|
+
showToast({
|
|
20
|
+
...props,
|
|
21
|
+
title: 'Demo Notification',
|
|
22
|
+
status: 'success',
|
|
23
|
+
duration: 1000,
|
|
24
|
+
variant: 'subtle'
|
|
25
|
+
})
|
|
26
|
+
}
|
|
27
|
+
return (
|
|
28
|
+
<>
|
|
29
|
+
<Button onClick={renderToast}>show toast</Button>
|
|
30
|
+
</>
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Set up and clean up
|
|
35
|
+
beforeEach(() => {
|
|
36
|
+
jest.resetModules()
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test('renders toast with action', async () => {
|
|
40
|
+
const user = userEvent.setup()
|
|
41
|
+
const handleActionClick = jest.fn()
|
|
42
|
+
const toastAction = <Button onClick={handleActionClick}>action</Button>
|
|
43
|
+
|
|
44
|
+
renderWithProviders(<MockedComponent action={toastAction} />)
|
|
45
|
+
|
|
46
|
+
const toastTrigger = await screen.findByRole('button', {name: /show toast/i})
|
|
47
|
+
await user.click(toastTrigger)
|
|
48
|
+
|
|
49
|
+
await waitFor(() => {
|
|
50
|
+
// Chakra UI renders multiple elements with toast title in DOM for accessibility.
|
|
51
|
+
// We need to assert the actual text within the alert
|
|
52
|
+
expect(screen.getByRole('alert')).toHaveTextContent(/demo notification/i)
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
const toastActionTrigger = await screen.findByRole('button', {name: /action/i})
|
|
56
|
+
await user.click(toastActionTrigger)
|
|
57
|
+
expect(handleActionClick).toHaveBeenCalledTimes(1)
|
|
58
|
+
})
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2021, salesforce.com, inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
5
|
+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Hooks
|
|
9
|
+
import {useVariationParams} from '@salesforce/retail-react-app/app/hooks/use-variation-params'
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* This hook returns the currently selected
|
|
13
|
+
* variant or undefined. NOTE: All attributes must be selected before a variant
|
|
14
|
+
* will be returned.
|
|
15
|
+
*
|
|
16
|
+
* @param {Object} product
|
|
17
|
+
* @returns {Object} the currently selected `Variant` object.
|
|
18
|
+
*/
|
|
19
|
+
export const useVariant = (product = {}, isProductPartOfSet = false) => {
|
|
20
|
+
const {variants = []} = product
|
|
21
|
+
const variationParams = useVariationParams(product, isProductPartOfSet)
|
|
22
|
+
|
|
23
|
+
// Get a filtered array of variants. The resulting array will only have variants
|
|
24
|
+
// which have all the current variation params values set.
|
|
25
|
+
const filteredVariants = variants.filter(({variationValues}) =>
|
|
26
|
+
// A single liner that will return true if the current variation has all the
|
|
27
|
+
// same attribute values as the passing in params.
|
|
28
|
+
Object.keys(variationParams).every((key) => variationValues[key] === variationParams[key])
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
return filteredVariants.length === 1 ? filteredVariants[0] : undefined
|
|
32
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2021, salesforce.com, inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
5
|
+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React from 'react'
|
|
9
|
+
import {Router} from 'react-router'
|
|
10
|
+
|
|
11
|
+
import {render} from '@testing-library/react'
|
|
12
|
+
import {createMemoryHistory} from 'history'
|
|
13
|
+
import {useVariant} from '@salesforce/retail-react-app/app/hooks/use-variant'
|
|
14
|
+
|
|
15
|
+
// Below is a partial product used for mocking purposes. Note: only the properties
|
|
16
|
+
// that are used in the hook at defined.
|
|
17
|
+
const MockProduct = {
|
|
18
|
+
variationAttributes: [
|
|
19
|
+
{id: 'color', name: 'Color', values: []},
|
|
20
|
+
{id: 'size', name: 'Size', values: []}
|
|
21
|
+
],
|
|
22
|
+
variants: [
|
|
23
|
+
{
|
|
24
|
+
orderable: true,
|
|
25
|
+
price: 195,
|
|
26
|
+
productId: '883360352473M',
|
|
27
|
+
variationValues: {
|
|
28
|
+
color: 'B9W',
|
|
29
|
+
size: '34'
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
orderable: true,
|
|
34
|
+
price: 195,
|
|
35
|
+
productId: '883360492148M',
|
|
36
|
+
variationValues: {
|
|
37
|
+
color: 'DKL',
|
|
38
|
+
size: '34'
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const MockComponent = () => {
|
|
45
|
+
const variant = useVariant(MockProduct)
|
|
46
|
+
return (
|
|
47
|
+
<script data-testid="variant" type="application/json">
|
|
48
|
+
{JSON.stringify(variant)}
|
|
49
|
+
</script>
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
describe('The useVariant', () => {
|
|
54
|
+
test('returns undefined when a single variant cannot be deduced from the location search params.', () => {
|
|
55
|
+
const history = createMemoryHistory()
|
|
56
|
+
history.push('/test/path?size=34')
|
|
57
|
+
|
|
58
|
+
const wrapper = render(
|
|
59
|
+
<Router history={history}>
|
|
60
|
+
<MockComponent />
|
|
61
|
+
</Router>
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
expect(wrapper.getByTestId('variant').text).toBe('')
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
test('returns the correct variant when one can be deduced from the location search params.', () => {
|
|
68
|
+
const history = createMemoryHistory()
|
|
69
|
+
history.push('/test/path?size=34&color=DKL')
|
|
70
|
+
|
|
71
|
+
const wrapper = render(
|
|
72
|
+
<Router history={history}>
|
|
73
|
+
<MockComponent />
|
|
74
|
+
</Router>
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
expect(wrapper.getByTestId('variant').text).toBe(
|
|
78
|
+
'{"orderable":true,"price":195,"productId":"883360492148M","variationValues":{"color":"DKL","size":"34"}}'
|
|
79
|
+
)
|
|
80
|
+
})
|
|
81
|
+
})
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2021, salesforce.com, inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
5
|
+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {useMemo} from 'react'
|
|
9
|
+
import {useLocation} from 'react-router-dom'
|
|
10
|
+
|
|
11
|
+
// Other Hooks
|
|
12
|
+
import {useVariationParams} from '@salesforce/retail-react-app/app/hooks/use-variation-params'
|
|
13
|
+
|
|
14
|
+
// Utils
|
|
15
|
+
import {updateSearchParams} from '@salesforce/retail-react-app/app/utils/url'
|
|
16
|
+
import {usePDPSearchParams} from '@salesforce/retail-react-app/app/hooks/use-pdp-search-params'
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Return the first image in the `swatch` type image group for a given
|
|
20
|
+
* variation value of a product.
|
|
21
|
+
*
|
|
22
|
+
* @param {Object} product
|
|
23
|
+
* @param {Object} variationValue
|
|
24
|
+
* @returns {Object} image
|
|
25
|
+
*/
|
|
26
|
+
const getVariantValueSwatch = (product, variationValue) => {
|
|
27
|
+
const {imageGroups = []} = product
|
|
28
|
+
|
|
29
|
+
const imageGroup = imageGroups
|
|
30
|
+
.filter(({viewType}) => viewType === 'swatch')
|
|
31
|
+
.find(({variationAttributes = []}) => {
|
|
32
|
+
const colorAttribute = variationAttributes.find(({id}) => id === 'color')
|
|
33
|
+
const colorValues = colorAttribute?.values || []
|
|
34
|
+
|
|
35
|
+
// A single image can represent multiple variation values, so we only need
|
|
36
|
+
// ensure the variation values appears in once of the images represented values.
|
|
37
|
+
return colorValues.some(({value}) => value === variationValue.value)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
return imageGroup?.images?.[0]
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Build a product href
|
|
45
|
+
*
|
|
46
|
+
* @param {Object} product
|
|
47
|
+
* @param {Object} params
|
|
48
|
+
* @param {Object} location
|
|
49
|
+
* @returns {String} a product url for the current variation value.
|
|
50
|
+
*/
|
|
51
|
+
const buildVariantValueHref = ({
|
|
52
|
+
pathname,
|
|
53
|
+
existingParams,
|
|
54
|
+
newParams,
|
|
55
|
+
productId,
|
|
56
|
+
isProductPartOfSet
|
|
57
|
+
}) => {
|
|
58
|
+
const [allParams, productParams] = existingParams
|
|
59
|
+
|
|
60
|
+
if (isProductPartOfSet) {
|
|
61
|
+
updateSearchParams(productParams, newParams)
|
|
62
|
+
allParams.set(productId, productParams.toString())
|
|
63
|
+
} else {
|
|
64
|
+
updateSearchParams(allParams, newParams)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return `${pathname}?${allParams.toString()}`
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Determine if a products variant attribute value is orderable without having to
|
|
72
|
+
* load the variant in question, but filtering the list of variants with the
|
|
73
|
+
* passed in attribute values.
|
|
74
|
+
*
|
|
75
|
+
* @param {Object} product
|
|
76
|
+
* @param {Object} variationParams
|
|
77
|
+
* @returns
|
|
78
|
+
*/
|
|
79
|
+
const isVariantValueOrderable = (product, variationParams) => {
|
|
80
|
+
return product.variants
|
|
81
|
+
.filter(({variationValues}) =>
|
|
82
|
+
Object.keys(variationParams).every(
|
|
83
|
+
(key) => variationValues[key] === variationParams[key]
|
|
84
|
+
)
|
|
85
|
+
)
|
|
86
|
+
.some(({orderable}) => orderable)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Use a decorated version of a product variation attributes. This version
|
|
91
|
+
* will have the following additions: which variation attribute is selected,
|
|
92
|
+
* each value will have a product url, the swatch image if there is one, and
|
|
93
|
+
* an updated orderable flag.
|
|
94
|
+
*
|
|
95
|
+
* @param {Object} product
|
|
96
|
+
* @returns {Array} a decorated variation attributes list.
|
|
97
|
+
*
|
|
98
|
+
*/
|
|
99
|
+
export const useVariationAttributes = (product = {}, isProductPartOfSet = false) => {
|
|
100
|
+
const {variationAttributes = []} = product
|
|
101
|
+
const location = useLocation()
|
|
102
|
+
const variationParams = useVariationParams(product, isProductPartOfSet)
|
|
103
|
+
|
|
104
|
+
const existingParams = usePDPSearchParams(product.id)
|
|
105
|
+
|
|
106
|
+
return useMemo(
|
|
107
|
+
() =>
|
|
108
|
+
variationAttributes.map((variationAttribute) => ({
|
|
109
|
+
...variationAttribute,
|
|
110
|
+
selectedValue: {
|
|
111
|
+
name: variationAttribute.values.find(
|
|
112
|
+
({value}) => value === variationParams?.[variationAttribute.id]
|
|
113
|
+
)?.name,
|
|
114
|
+
value: variationParams?.[variationAttribute.id]
|
|
115
|
+
},
|
|
116
|
+
values: variationAttribute.values.map((value) => {
|
|
117
|
+
const params = {
|
|
118
|
+
...variationParams,
|
|
119
|
+
[variationAttribute.id]: value.value
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
...value,
|
|
124
|
+
image: getVariantValueSwatch(product, value),
|
|
125
|
+
href: buildVariantValueHref({
|
|
126
|
+
pathname: location.pathname,
|
|
127
|
+
existingParams,
|
|
128
|
+
newParams: params,
|
|
129
|
+
productId: product.id,
|
|
130
|
+
isProductPartOfSet
|
|
131
|
+
}),
|
|
132
|
+
orderable: isVariantValueOrderable(product, params)
|
|
133
|
+
}
|
|
134
|
+
})
|
|
135
|
+
})),
|
|
136
|
+
[location.search, product]
|
|
137
|
+
)
|
|
138
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2021, salesforce.com, inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
5
|
+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React from 'react'
|
|
9
|
+
import {Router} from 'react-router'
|
|
10
|
+
|
|
11
|
+
import {render} from '@testing-library/react'
|
|
12
|
+
import {createMemoryHistory} from 'history'
|
|
13
|
+
import {useVariationAttributes} from '@salesforce/retail-react-app/app/hooks/use-variation-attributes'
|
|
14
|
+
|
|
15
|
+
// Below is a partial product used for mocking purposes. Note: only the properties
|
|
16
|
+
// that are used in the hook at defined.
|
|
17
|
+
const MockProduct = {
|
|
18
|
+
master: {
|
|
19
|
+
masterId: '73910532M',
|
|
20
|
+
orderable: true,
|
|
21
|
+
price: 195
|
|
22
|
+
},
|
|
23
|
+
imageGroups: [
|
|
24
|
+
{
|
|
25
|
+
images: [
|
|
26
|
+
{
|
|
27
|
+
alt: 'Basic Leg Trousers, , swatch',
|
|
28
|
+
disBaseLink:
|
|
29
|
+
'https://edge.disstg.commercecloud.salesforce.com/dw/image/v2/ZZRF_001/on/demandware.static/-/Sites-apparel-m-catalog/default/dw6cc11129/images/swatch/90011212_001_sw.jpg',
|
|
30
|
+
link: 'https://zzrf-001.dx.commercecloud.salesforce.com/on/demandware.static/-/Sites-apparel-m-catalog/default/dw6cc11129/images/swatch/90011212_001_sw.jpg',
|
|
31
|
+
title: 'Basic Leg Trousers, '
|
|
32
|
+
}
|
|
33
|
+
],
|
|
34
|
+
viewType: 'swatch'
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
images: [
|
|
38
|
+
{
|
|
39
|
+
alt: 'Basic Leg Trousers, Black, swatch',
|
|
40
|
+
disBaseLink:
|
|
41
|
+
'https://edge.disstg.commercecloud.salesforce.com/dw/image/v2/ZZRF_001/on/demandware.static/-/Sites-apparel-m-catalog/default/dw6cc11129/images/swatch/90011212_001_sw.jpg',
|
|
42
|
+
link: 'https://zzrf-001.dx.commercecloud.salesforce.com/on/demandware.static/-/Sites-apparel-m-catalog/default/dw6cc11129/images/swatch/90011212_001_sw.jpg',
|
|
43
|
+
title: 'Basic Leg Trousers, Black'
|
|
44
|
+
}
|
|
45
|
+
],
|
|
46
|
+
variationAttributes: [
|
|
47
|
+
{
|
|
48
|
+
id: 'color',
|
|
49
|
+
values: [
|
|
50
|
+
{
|
|
51
|
+
value: '001'
|
|
52
|
+
}
|
|
53
|
+
]
|
|
54
|
+
}
|
|
55
|
+
],
|
|
56
|
+
viewType: 'swatch'
|
|
57
|
+
}
|
|
58
|
+
],
|
|
59
|
+
variants: [
|
|
60
|
+
{
|
|
61
|
+
orderable: true,
|
|
62
|
+
price: 195,
|
|
63
|
+
productId: '883858858302M',
|
|
64
|
+
variationValues: {
|
|
65
|
+
color: '001',
|
|
66
|
+
size: '28'
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
variationAttributes: [
|
|
71
|
+
{
|
|
72
|
+
id: 'color',
|
|
73
|
+
name: 'Color',
|
|
74
|
+
values: [
|
|
75
|
+
{
|
|
76
|
+
name: 'Black',
|
|
77
|
+
orderable: true,
|
|
78
|
+
value: '001'
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
id: 'size',
|
|
84
|
+
name: 'Size',
|
|
85
|
+
values: [
|
|
86
|
+
{
|
|
87
|
+
name: '28',
|
|
88
|
+
orderable: true,
|
|
89
|
+
value: '28'
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const MockComponent = () => {
|
|
97
|
+
const params = useVariationAttributes(MockProduct)
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<script data-testid="variationAttributes" type="application/json">
|
|
101
|
+
{JSON.stringify(params)}
|
|
102
|
+
</script>
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
describe('The useVariationAttributes', () => {
|
|
107
|
+
test('returns variation attributes decorated with hrefs and images.', () => {
|
|
108
|
+
const history = createMemoryHistory()
|
|
109
|
+
history.push('/test/path?color=blue&size=2')
|
|
110
|
+
const wrapper = render(
|
|
111
|
+
<Router history={history}>
|
|
112
|
+
<MockComponent />
|
|
113
|
+
</Router>
|
|
114
|
+
)
|
|
115
|
+
expect(wrapper.getByTestId('variationAttributes').text).toBe(
|
|
116
|
+
'[{"id":"color","name":"Color","values":[{"name":"Black","orderable":false,"value":"001","image":{"alt":"Basic Leg Trousers, Black, swatch","disBaseLink":"https://edge.disstg.commercecloud.salesforce.com/dw/image/v2/ZZRF_001/on/demandware.static/-/Sites-apparel-m-catalog/default/dw6cc11129/images/swatch/90011212_001_sw.jpg","link":"https://zzrf-001.dx.commercecloud.salesforce.com/on/demandware.static/-/Sites-apparel-m-catalog/default/dw6cc11129/images/swatch/90011212_001_sw.jpg","title":"Basic Leg Trousers, Black"},"href":"/test/path?color=001&size=2"}],"selectedValue":{"value":"blue"}},{"id":"size","name":"Size","values":[{"name":"28","orderable":false,"value":"28","href":"/test/path?color=blue&size=28"}],"selectedValue":{"value":"2"}}]'
|
|
117
|
+
)
|
|
118
|
+
})
|
|
119
|
+
})
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2021, salesforce.com, inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
5
|
+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {usePDPSearchParams} from '@salesforce/retail-react-app/app/hooks/use-pdp-search-params'
|
|
9
|
+
|
|
10
|
+
/*
|
|
11
|
+
* This hook will return only the params that are also product attributes for the
|
|
12
|
+
* passed in product object.
|
|
13
|
+
*/
|
|
14
|
+
export const useVariationParams = (product = {}, isProductPartOfSet = false) => {
|
|
15
|
+
const {variationAttributes = [], variationValues = {}} = product
|
|
16
|
+
|
|
17
|
+
const [allParams, productParams] = usePDPSearchParams(product.id)
|
|
18
|
+
const params = isProductPartOfSet ? productParams : allParams
|
|
19
|
+
|
|
20
|
+
// Using all the variation attribute id from the array generated below, get
|
|
21
|
+
// the value if there is one from the location search params and add it to the
|
|
22
|
+
// accumulator.
|
|
23
|
+
const variationParams = variationAttributes
|
|
24
|
+
.map(({id}) => id)
|
|
25
|
+
.reduce((acc, key) => {
|
|
26
|
+
let value = params.get(`${key}`) || variationValues?.[key]
|
|
27
|
+
return value ? {...acc, [key]: value} : acc
|
|
28
|
+
}, {})
|
|
29
|
+
|
|
30
|
+
return variationParams
|
|
31
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2021, salesforce.com, inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
5
|
+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import React from 'react'
|
|
9
|
+
import {Router} from 'react-router'
|
|
10
|
+
|
|
11
|
+
import {render} from '@testing-library/react'
|
|
12
|
+
import {createMemoryHistory} from 'history'
|
|
13
|
+
import {useVariationParams} from '@salesforce/retail-react-app/app/hooks/use-variation-params'
|
|
14
|
+
|
|
15
|
+
// Below is a partial product used for mocking purposes. Note: only the properties
|
|
16
|
+
// that are used in the hook at defined.
|
|
17
|
+
const MockProduct = {
|
|
18
|
+
variationAttributes: [
|
|
19
|
+
{id: 'color', name: 'Color', values: []},
|
|
20
|
+
{id: 'size', name: 'Size', values: []}
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const MockComponent = () => {
|
|
25
|
+
const params = useVariationParams(MockProduct)
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<script data-testid="params" type="application/json">
|
|
29
|
+
{JSON.stringify(params)}
|
|
30
|
+
</script>
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
describe('The useVariationParams', () => {
|
|
35
|
+
test('returns correct params when there are no non-product params in the url.', () => {
|
|
36
|
+
const history = createMemoryHistory()
|
|
37
|
+
history.push('/test/path?color=blue&size=2')
|
|
38
|
+
|
|
39
|
+
const wrapper = render(
|
|
40
|
+
<Router history={history}>
|
|
41
|
+
<MockComponent />
|
|
42
|
+
</Router>
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
expect(wrapper.getByTestId('params').text).toBe('{"color":"blue","size":"2"}')
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
test('returns correct params when there are non-product params in the url.', () => {
|
|
49
|
+
const history = createMemoryHistory()
|
|
50
|
+
history.push('/test/path?color=blue&size=2&nonproductattribute=true')
|
|
51
|
+
|
|
52
|
+
const wrapper = render(
|
|
53
|
+
<Router history={history}>
|
|
54
|
+
<MockComponent />
|
|
55
|
+
</Router>
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
expect(wrapper.getByTestId('params').text).toBe('{"color":"blue","size":"2"}')
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
test('returns correct params when there is only a subset product params in the url.', () => {
|
|
62
|
+
const history = createMemoryHistory()
|
|
63
|
+
history.push('/test/path?color=blue')
|
|
64
|
+
|
|
65
|
+
const wrapper = render(
|
|
66
|
+
<Router history={history}>
|
|
67
|
+
<MockComponent />
|
|
68
|
+
</Router>
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
expect(wrapper.getByTestId('params').text).toBe('{"color":"blue"}')
|
|
72
|
+
})
|
|
73
|
+
})
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2022, Salesforce, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
5
|
+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {useCustomerProductLists, useShopperCustomersMutation} from '@salesforce/commerce-sdk-react'
|
|
9
|
+
import {useCurrentCustomer} from '@salesforce/retail-react-app/app/hooks/use-current-customer'
|
|
10
|
+
const onClient = typeof window !== 'undefined'
|
|
11
|
+
// TODO: remove `listId` input -> use the first list of type wish_list instead
|
|
12
|
+
// (mimic the logic in the other older hook 'use-wishlist.js')
|
|
13
|
+
export const useWishList = ({listId = ''} = {}) => {
|
|
14
|
+
const {data: customer} = useCurrentCustomer()
|
|
15
|
+
const {customerId} = customer
|
|
16
|
+
const createCustomerProductList = useShopperCustomersMutation('createCustomerProductList')
|
|
17
|
+
const {data: productLists, ...restOfQuery} = useCustomerProductLists(
|
|
18
|
+
{
|
|
19
|
+
parameters: {customerId}
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
onSuccess: (data) => {
|
|
23
|
+
if (!data.total) {
|
|
24
|
+
createCustomerProductList.mutate({
|
|
25
|
+
parameters: {customerId},
|
|
26
|
+
// we only use one type of product lists for now
|
|
27
|
+
body: {type: 'wish_list'}
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
enabled: onClient && Boolean(customerId)
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
const wishLists = productLists?.data?.filter((list) => list.type === 'wish_list') || []
|
|
36
|
+
const currentWishlist = wishLists.find((list) => list.id === listId)
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
data: !listId ? wishLists[0] : currentWishlist,
|
|
40
|
+
...restOfQuery
|
|
41
|
+
}
|
|
42
|
+
}
|
package/app/main.jsx
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2021, salesforce.com, inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
* SPDX-License-Identifier: BSD-3-Clause
|
|
5
|
+
* For full license text, see the LICENSE file in the repo root or https://opensource.org/licenses/BSD-3-Clause
|
|
6
|
+
*/
|
|
7
|
+
import {start, registerServiceWorker} from '@salesforce/pwa-kit-react-sdk/ssr/browser/main'
|
|
8
|
+
|
|
9
|
+
const main = () => {
|
|
10
|
+
// The path to your service worker should match what is set up in ssr.js
|
|
11
|
+
return Promise.all([start(), registerServiceWorker('/worker.js')])
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
main()
|