@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.
Files changed (425) hide show
  1. package/.eslintignore +7 -0
  2. package/.eslintrc.js +25 -0
  3. package/.prettierignore +4 -0
  4. package/.prettierrc.yaml +7 -0
  5. package/CHANGELOG.md +173 -0
  6. package/LICENSE +14 -0
  7. package/README.md +48 -0
  8. package/app/assets/svg/account.svg +3 -0
  9. package/app/assets/svg/alert.svg +3 -0
  10. package/app/assets/svg/basket.svg +3 -0
  11. package/app/assets/svg/brand-logo.svg +10 -0
  12. package/app/assets/svg/cc-amex.svg +7 -0
  13. package/app/assets/svg/cc-cvv.svg +8 -0
  14. package/app/assets/svg/cc-discover.svg +14 -0
  15. package/app/assets/svg/cc-mastercard.svg +8 -0
  16. package/app/assets/svg/cc-visa.svg +11 -0
  17. package/app/assets/svg/check-circle.svg +3 -0
  18. package/app/assets/svg/check.svg +3 -0
  19. package/app/assets/svg/chevron-down.svg +3 -0
  20. package/app/assets/svg/chevron-left.svg +3 -0
  21. package/app/assets/svg/chevron-right.svg +3 -0
  22. package/app/assets/svg/chevron-up.svg +3 -0
  23. package/app/assets/svg/close.svg +3 -0
  24. package/app/assets/svg/dashboard.svg +4 -0
  25. package/app/assets/svg/figma-logo.svg +14 -0
  26. package/app/assets/svg/file.svg +3 -0
  27. package/app/assets/svg/filter.svg +3 -0
  28. package/app/assets/svg/flag-ca.svg +5 -0
  29. package/app/assets/svg/flag-cn.svg +19 -0
  30. package/app/assets/svg/flag-fr.svg +19 -0
  31. package/app/assets/svg/flag-gb.svg +16 -0
  32. package/app/assets/svg/flag-it.svg +29 -0
  33. package/app/assets/svg/flag-jp.svg +10 -0
  34. package/app/assets/svg/flag-us.svg +7 -0
  35. package/app/assets/svg/github-logo.svg +40 -0
  36. package/app/assets/svg/hamburger.svg +8 -0
  37. package/app/assets/svg/heart-solid.svg +7 -0
  38. package/app/assets/svg/heart.svg +3 -0
  39. package/app/assets/svg/info.svg +3 -0
  40. package/app/assets/svg/like.svg +4 -0
  41. package/app/assets/svg/location.svg +3 -0
  42. package/app/assets/svg/lock.svg +3 -0
  43. package/app/assets/svg/paypal.svg +19 -0
  44. package/app/assets/svg/plug.svg +3 -0
  45. package/app/assets/svg/plus.svg +3 -0
  46. package/app/assets/svg/receipt.svg +3 -0
  47. package/app/assets/svg/search.svg +8 -0
  48. package/app/assets/svg/signout.svg +3 -0
  49. package/app/assets/svg/social-facebook.svg +3 -0
  50. package/app/assets/svg/social-instagram.svg +3 -0
  51. package/app/assets/svg/social-pinterest.svg +4 -0
  52. package/app/assets/svg/social-twitter.svg +3 -0
  53. package/app/assets/svg/social-youtube.svg +3 -0
  54. package/app/assets/svg/user.svg +3 -0
  55. package/app/assets/svg/visibility-off.svg +5 -0
  56. package/app/assets/svg/visibility.svg +3 -0
  57. package/app/components/_app/index.jsx +401 -0
  58. package/app/components/_app/index.test.js +85 -0
  59. package/app/components/_app/partials/above-header.jsx +10 -0
  60. package/app/components/_app-config/index.jsx +125 -0
  61. package/app/components/_app-config/index.test.js +77 -0
  62. package/app/components/_error/index.jsx +142 -0
  63. package/app/components/_error/index.test.js +25 -0
  64. package/app/components/action-card/index.jsx +75 -0
  65. package/app/components/address-display/index.jsx +30 -0
  66. package/app/components/basic-tile/index.jsx +65 -0
  67. package/app/components/basic-tile/index.test.js +23 -0
  68. package/app/components/breadcrumb/index.jsx +67 -0
  69. package/app/components/breadcrumb/index.test.js +30 -0
  70. package/app/components/confirmation-modal/index.jsx +111 -0
  71. package/app/components/confirmation-modal/index.test.js +98 -0
  72. package/app/components/drawer-menu/index.jsx +405 -0
  73. package/app/components/drawer-menu/index.test.js +33 -0
  74. package/app/components/dynamic-image/index.jsx +56 -0
  75. package/app/components/field/index.jsx +161 -0
  76. package/app/components/footer/index.jsx +269 -0
  77. package/app/components/footer/index.test.js +22 -0
  78. package/app/components/forms/address-fields.jsx +49 -0
  79. package/app/components/forms/credit-card-fields.jsx +149 -0
  80. package/app/components/forms/form-action-buttons.jsx +55 -0
  81. package/app/components/forms/login-fields.jsx +31 -0
  82. package/app/components/forms/password-requirements.jsx +99 -0
  83. package/app/components/forms/post-checkout-registration-fields.jsx +43 -0
  84. package/app/components/forms/profile-fields.jsx +36 -0
  85. package/app/components/forms/promo-code-fields.jsx +43 -0
  86. package/app/components/forms/registration-fields.jsx +42 -0
  87. package/app/components/forms/reset-password-fields.jsx +31 -0
  88. package/app/components/forms/state-province-options.jsx +75 -0
  89. package/app/components/forms/update-password-fields.jsx +49 -0
  90. package/app/components/forms/useAddressFields.jsx +196 -0
  91. package/app/components/forms/useCreditCardFields.jsx +146 -0
  92. package/app/components/forms/useLoginFields.jsx +52 -0
  93. package/app/components/forms/useProfileFields.jsx +95 -0
  94. package/app/components/forms/usePromoCodeFields.jsx +39 -0
  95. package/app/components/forms/useRegistrationFields.jsx +136 -0
  96. package/app/components/forms/useResetPasswordFields.jsx +40 -0
  97. package/app/components/forms/useUpdatePasswordFields.jsx +89 -0
  98. package/app/components/header/index.jsx +290 -0
  99. package/app/components/header/index.test.js +217 -0
  100. package/app/components/hero/index.jsx +84 -0
  101. package/app/components/hero/index.test.js +40 -0
  102. package/app/components/icons/index.jsx +158 -0
  103. package/app/components/icons/index.test.js +20 -0
  104. package/app/components/image-gallery/index.jsx +176 -0
  105. package/app/components/image-gallery/index.test.js +485 -0
  106. package/app/components/item-variant/index.jsx +33 -0
  107. package/app/components/item-variant/item-attributes.jsx +107 -0
  108. package/app/components/item-variant/item-image.jsx +73 -0
  109. package/app/components/item-variant/item-name.jsx +28 -0
  110. package/app/components/item-variant/item-price.jsx +117 -0
  111. package/app/components/link/index.jsx +32 -0
  112. package/app/components/link/index.test.js +72 -0
  113. package/app/components/links-list/index.jsx +89 -0
  114. package/app/components/links-list/index.test.js +62 -0
  115. package/app/components/list-menu/index.jsx +280 -0
  116. package/app/components/list-menu/index.test.js +44 -0
  117. package/app/components/loading-spinner/index.jsx +46 -0
  118. package/app/components/locale-selector/index.jsx +124 -0
  119. package/app/components/locale-selector/index.test.js +37 -0
  120. package/app/components/locale-text/index.jsx +97 -0
  121. package/app/components/locale-text/index.test.js +36 -0
  122. package/app/components/login/index.jsx +96 -0
  123. package/app/components/nested-accordion/index.jsx +185 -0
  124. package/app/components/nested-accordion/index.test.js +98 -0
  125. package/app/components/offline-banner/index.jsx +40 -0
  126. package/app/components/offline-banner/index.test.js +15 -0
  127. package/app/components/offline-boundary/index.jsx +104 -0
  128. package/app/components/offline-boundary/index.test.js +123 -0
  129. package/app/components/order-summary/index.jsx +331 -0
  130. package/app/components/page-action-placeholder/index.jsx +50 -0
  131. package/app/components/pagination/index.jsx +134 -0
  132. package/app/components/pagination/index.test.js +25 -0
  133. package/app/components/product-item/index.jsx +146 -0
  134. package/app/components/product-item/index.test.js +38 -0
  135. package/app/components/product-scroller/index.jsx +172 -0
  136. package/app/components/product-scroller/index.test.js +98 -0
  137. package/app/components/product-tile/index.jsx +195 -0
  138. package/app/components/product-tile/index.test.js +96 -0
  139. package/app/components/product-view/index.jsx +538 -0
  140. package/app/components/product-view/index.test.js +224 -0
  141. package/app/components/product-view-modal/index.jsx +48 -0
  142. package/app/components/product-view-modal/index.test.js +72 -0
  143. package/app/components/promo-code/index.jsx +162 -0
  144. package/app/components/promo-popover/index.jsx +83 -0
  145. package/app/components/quantity-picker/index.jsx +58 -0
  146. package/app/components/radio-card/index.jsx +75 -0
  147. package/app/components/recommended-products/index.jsx +227 -0
  148. package/app/components/register/index.jsx +114 -0
  149. package/app/components/reset-password/index.jsx +87 -0
  150. package/app/components/responsive/index.jsx +29 -0
  151. package/app/components/scroll-to-top/index.jsx +24 -0
  152. package/app/components/scroll-to-top/index.test.js +46 -0
  153. package/app/components/search/index.jsx +279 -0
  154. package/app/components/search/index.test.js +127 -0
  155. package/app/components/search/partials/recent-searches.jsx +76 -0
  156. package/app/components/search/partials/search-suggestions.jsx +45 -0
  157. package/app/components/search/partials/suggestions.jsx +43 -0
  158. package/app/components/section/index.jsx +68 -0
  159. package/app/components/seo/index.jsx +33 -0
  160. package/app/components/social-icons/index.jsx +101 -0
  161. package/app/components/social-icons/index.test.js +30 -0
  162. package/app/components/swatch-group/index.jsx +77 -0
  163. package/app/components/swatch-group/index.test.js +136 -0
  164. package/app/components/swatch-group/swatch.jsx +94 -0
  165. package/app/components/toggle-card/index.jsx +97 -0
  166. package/app/components/with-registration/index.jsx +58 -0
  167. package/app/components/with-registration/index.test.js +85 -0
  168. package/app/constants.js +109 -0
  169. package/app/contexts/index.js +92 -0
  170. package/app/hooks/einstein-mock-data.js +916 -0
  171. package/app/hooks/index.js +17 -0
  172. package/app/hooks/use-add-to-cart-modal.js +344 -0
  173. package/app/hooks/use-add-to-cart-modal.test.js +625 -0
  174. package/app/hooks/use-auth-modal.js +337 -0
  175. package/app/hooks/use-auth-modal.test.js +365 -0
  176. package/app/hooks/use-currency.js +20 -0
  177. package/app/hooks/use-currency.test.js +41 -0
  178. package/app/hooks/use-current-basket.js +39 -0
  179. package/app/hooks/use-current-customer.js +29 -0
  180. package/app/hooks/use-derived-product.js +77 -0
  181. package/app/hooks/use-derived-product.test.js +69 -0
  182. package/app/hooks/use-einstein.js +512 -0
  183. package/app/hooks/use-einstein.test.js +224 -0
  184. package/app/hooks/use-intersection-observer.js +64 -0
  185. package/app/hooks/use-limit-urls.js +31 -0
  186. package/app/hooks/use-limit-urls.test.js +40 -0
  187. package/app/hooks/use-multi-site.js +36 -0
  188. package/app/hooks/use-multi-site.test.js +53 -0
  189. package/app/hooks/use-navigation.js +37 -0
  190. package/app/hooks/use-navigation.test.js +109 -0
  191. package/app/hooks/use-page-urls.js +35 -0
  192. package/app/hooks/use-page-urls.test.js +39 -0
  193. package/app/hooks/use-pdp-search-params.js +16 -0
  194. package/app/hooks/use-pdp-search-params.test.js +52 -0
  195. package/app/hooks/use-previous.js +17 -0
  196. package/app/hooks/use-product-view-modal.js +93 -0
  197. package/app/hooks/use-product-view-modal.test.js +172 -0
  198. package/app/hooks/use-search-params.js +96 -0
  199. package/app/hooks/use-search-params.test.js +91 -0
  200. package/app/hooks/use-sort-urls.js +33 -0
  201. package/app/hooks/use-sort-urls.test.js +42 -0
  202. package/app/hooks/use-toast.js +68 -0
  203. package/app/hooks/use-toast.test.js +58 -0
  204. package/app/hooks/use-variant.js +32 -0
  205. package/app/hooks/use-variant.test.js +81 -0
  206. package/app/hooks/use-variation-attributes.js +138 -0
  207. package/app/hooks/use-variation-attributes.test.js +119 -0
  208. package/app/hooks/use-variation-params.js +31 -0
  209. package/app/hooks/use-variation-params.test.js +73 -0
  210. package/app/hooks/use-wish-list.js +42 -0
  211. package/app/main.jsx +14 -0
  212. package/app/mocks/basket-with-suit.js +146 -0
  213. package/app/mocks/empty-basket.js +39 -0
  214. package/app/mocks/mock-data.js +5632 -0
  215. package/app/mocks/product-set-winter-lookM.js +1224 -0
  216. package/app/mocks/searchResults.js +144 -0
  217. package/app/mocks/variant-750518699578M.js +434 -0
  218. package/app/page-designer/README.md +102 -0
  219. package/app/page-designer/assets/image-tile/index.jsx +51 -0
  220. package/app/page-designer/assets/image-tile/index.test.js +30 -0
  221. package/app/page-designer/assets/image-with-text/index.jsx +140 -0
  222. package/app/page-designer/assets/image-with-text/index.test.js +38 -0
  223. package/app/page-designer/assets/index.js +9 -0
  224. package/app/page-designer/index.js +10 -0
  225. package/app/page-designer/layouts/carousel/index.jsx +222 -0
  226. package/app/page-designer/layouts/carousel/index.test.js +43 -0
  227. package/app/page-designer/layouts/index.js +14 -0
  228. package/app/page-designer/layouts/mobileGrid1r1c/index.jsx +36 -0
  229. package/app/page-designer/layouts/mobileGrid1r1c/index.test.js +35 -0
  230. package/app/page-designer/layouts/mobileGrid2r1c/index.jsx +37 -0
  231. package/app/page-designer/layouts/mobileGrid2r1c/index.test.js +47 -0
  232. package/app/page-designer/layouts/mobileGrid2r2c/index.jsx +37 -0
  233. package/app/page-designer/layouts/mobileGrid2r2c/index.test.js +71 -0
  234. package/app/page-designer/layouts/mobileGrid2r3c/index.jsx +37 -0
  235. package/app/page-designer/layouts/mobileGrid2r3c/index.test.js +95 -0
  236. package/app/page-designer/layouts/mobileGrid3r1c/index.jsx +37 -0
  237. package/app/page-designer/layouts/mobileGrid3r1c/index.test.js +59 -0
  238. package/app/page-designer/layouts/mobileGrid3r2c/index.jsx +37 -0
  239. package/app/page-designer/layouts/mobileGrid3r2c/index.test.js +95 -0
  240. package/app/page-designer/utils.js +14 -0
  241. package/app/pages/account/addresses.jsx +382 -0
  242. package/app/pages/account/addresses.test.js +120 -0
  243. package/app/pages/account/constant.js +57 -0
  244. package/app/pages/account/index.jsx +237 -0
  245. package/app/pages/account/index.test.js +188 -0
  246. package/app/pages/account/order-detail.jsx +397 -0
  247. package/app/pages/account/order-history.jsx +264 -0
  248. package/app/pages/account/orders.jsx +30 -0
  249. package/app/pages/account/orders.test.js +95 -0
  250. package/app/pages/account/profile.jsx +357 -0
  251. package/app/pages/account/wishlist/index.jsx +195 -0
  252. package/app/pages/account/wishlist/index.mock.js +1481 -0
  253. package/app/pages/account/wishlist/index.test.js +56 -0
  254. package/app/pages/account/wishlist/partials/wishlist-primary-action.jsx +170 -0
  255. package/app/pages/account/wishlist/partials/wishlist-primary-action.mock.js +1623 -0
  256. package/app/pages/account/wishlist/partials/wishlist-primary-action.test.js +99 -0
  257. package/app/pages/account/wishlist/partials/wishlist-secondary-button-group.jsx +120 -0
  258. package/app/pages/account/wishlist/partials/wishlist-secondary-button-group.test.js +391 -0
  259. package/app/pages/cart/index.jsx +476 -0
  260. package/app/pages/cart/index.test.js +481 -0
  261. package/app/pages/cart/partials/cart-cta.jsx +46 -0
  262. package/app/pages/cart/partials/cart-secondary-button-group.jsx +135 -0
  263. package/app/pages/cart/partials/cart-secondary-button-group.test.js +103 -0
  264. package/app/pages/cart/partials/cart-skeleton.jsx +93 -0
  265. package/app/pages/cart/partials/cart-title.jsx +27 -0
  266. package/app/pages/cart/partials/empty-cart.jsx +86 -0
  267. package/app/pages/checkout/confirmation.jsx +541 -0
  268. package/app/pages/checkout/confirmation.mock.js +450 -0
  269. package/app/pages/checkout/confirmation.test.js +114 -0
  270. package/app/pages/checkout/index.jsx +169 -0
  271. package/app/pages/checkout/index.test.js +582 -0
  272. package/app/pages/checkout/partials/cc-radio-group.jsx +122 -0
  273. package/app/pages/checkout/partials/checkout-footer.jsx +140 -0
  274. package/app/pages/checkout/partials/checkout-footer.test.js +16 -0
  275. package/app/pages/checkout/partials/checkout-header.jsx +54 -0
  276. package/app/pages/checkout/partials/checkout-header.test.js +16 -0
  277. package/app/pages/checkout/partials/checkout-skeleton.jsx +52 -0
  278. package/app/pages/checkout/partials/contact-info.jsx +251 -0
  279. package/app/pages/checkout/partials/contact-info.test.js +43 -0
  280. package/app/pages/checkout/partials/payment-form.jsx +97 -0
  281. package/app/pages/checkout/partials/payment.jsx +276 -0
  282. package/app/pages/checkout/partials/shipping-address-selection.jsx +377 -0
  283. package/app/pages/checkout/partials/shipping-address.jsx +132 -0
  284. package/app/pages/checkout/partials/shipping-options.jsx +232 -0
  285. package/app/pages/checkout/util/checkout-context.js +94 -0
  286. package/app/pages/home/data.js +134 -0
  287. package/app/pages/home/index.jsx +301 -0
  288. package/app/pages/home/index.test.js +23 -0
  289. package/app/pages/login/index.jsx +123 -0
  290. package/app/pages/login/index.test.js +229 -0
  291. package/app/pages/login-redirect/index.jsx +23 -0
  292. package/app/pages/login-redirect/index.test.js +16 -0
  293. package/app/pages/page-not-found/index.jsx +90 -0
  294. package/app/pages/page-not-found/index.test.js +31 -0
  295. package/app/pages/product-detail/index.jsx +394 -0
  296. package/app/pages/product-detail/index.mock.js +197 -0
  297. package/app/pages/product-detail/index.test.js +162 -0
  298. package/app/pages/product-detail/partials/information-accordion.jsx +121 -0
  299. package/app/pages/product-list/index.jsx +735 -0
  300. package/app/pages/product-list/index.test.js +180 -0
  301. package/app/pages/product-list/partials/above-page-header.jsx +10 -0
  302. package/app/pages/product-list/partials/checkbox-refinements.jsx +41 -0
  303. package/app/pages/product-list/partials/checkbox-refinements.test.js +53 -0
  304. package/app/pages/product-list/partials/color-refinements.jsx +88 -0
  305. package/app/pages/product-list/partials/empty-results.jsx +118 -0
  306. package/app/pages/product-list/partials/link-refinements.jsx +38 -0
  307. package/app/pages/product-list/partials/page-header.jsx +42 -0
  308. package/app/pages/product-list/partials/radio-refinements.jsx +60 -0
  309. package/app/pages/product-list/partials/refinements.jsx +144 -0
  310. package/app/pages/product-list/partials/selected-refinements.jsx +100 -0
  311. package/app/pages/product-list/partials/size-refinements.jsx +55 -0
  312. package/app/pages/registration/index.jsx +87 -0
  313. package/app/pages/registration/index.test.jsx +132 -0
  314. package/app/pages/reset-password/index.jsx +112 -0
  315. package/app/pages/reset-password/index.test.jsx +141 -0
  316. package/app/request-processor.js +118 -0
  317. package/app/request-processor.test.js +23 -0
  318. package/app/routes.jsx +111 -0
  319. package/app/routes.test.js +13 -0
  320. package/app/ssr.js +70 -0
  321. package/app/static/ico/favicon.ico +0 -0
  322. package/app/static/img/global/app-icon-192.png +0 -0
  323. package/app/static/img/global/app-icon-512.png +0 -0
  324. package/app/static/img/global/apple-touch-icon.png +0 -0
  325. package/app/static/img/hero.png +0 -0
  326. package/app/static/manifest.json +19 -0
  327. package/app/static/robots.txt +2 -0
  328. package/app/theme/components/base/accordion.js +21 -0
  329. package/app/theme/components/base/alert.js +17 -0
  330. package/app/theme/components/base/badge.js +25 -0
  331. package/app/theme/components/base/button.js +77 -0
  332. package/app/theme/components/base/checkbox.js +30 -0
  333. package/app/theme/components/base/container.js +17 -0
  334. package/app/theme/components/base/drawer.js +26 -0
  335. package/app/theme/components/base/formLabel.js +13 -0
  336. package/app/theme/components/base/icon.js +13 -0
  337. package/app/theme/components/base/input.js +44 -0
  338. package/app/theme/components/base/modal.js +11 -0
  339. package/app/theme/components/base/popover.js +61 -0
  340. package/app/theme/components/base/radio.js +33 -0
  341. package/app/theme/components/base/select.js +15 -0
  342. package/app/theme/components/base/skeleton.js +12 -0
  343. package/app/theme/components/base/tooltip.js +19 -0
  344. package/app/theme/components/project/_app.js +25 -0
  345. package/app/theme/components/project/breadcrumb.js +25 -0
  346. package/app/theme/components/project/checkout-footer.js +35 -0
  347. package/app/theme/components/project/drawer-menu.js +66 -0
  348. package/app/theme/components/project/footer.js +84 -0
  349. package/app/theme/components/project/header.js +84 -0
  350. package/app/theme/components/project/image-gallery.js +59 -0
  351. package/app/theme/components/project/links-list.js +43 -0
  352. package/app/theme/components/project/list-menu.js +91 -0
  353. package/app/theme/components/project/locale-selector.js +42 -0
  354. package/app/theme/components/project/nested-accordion.js +26 -0
  355. package/app/theme/components/project/offline-banner.js +25 -0
  356. package/app/theme/components/project/pagination.js +22 -0
  357. package/app/theme/components/project/product-tile.js +32 -0
  358. package/app/theme/components/project/social-icons.js +52 -0
  359. package/app/theme/components/project/swatch-group.js +115 -0
  360. package/app/theme/foundations/colors.js +170 -0
  361. package/app/theme/foundations/gradients.js +9 -0
  362. package/app/theme/foundations/layerStyles.js +41 -0
  363. package/app/theme/foundations/shadows.js +9 -0
  364. package/app/theme/foundations/sizes.js +18 -0
  365. package/app/theme/foundations/space.js +9 -0
  366. package/app/theme/foundations/styles.js +21 -0
  367. package/app/theme/index.js +104 -0
  368. package/app/utils/cc-utils.js +112 -0
  369. package/app/utils/cc-utils.test.js +41 -0
  370. package/app/utils/image-groups-utils.js +62 -0
  371. package/app/utils/image-groups-utils.test.js +65 -0
  372. package/app/utils/locale.js +78 -0
  373. package/app/utils/locale.test.js +112 -0
  374. package/app/utils/password-utils.js +21 -0
  375. package/app/utils/phone-utils.js +22 -0
  376. package/app/utils/phone-utils.test.js +15 -0
  377. package/app/utils/product-utils.js +35 -0
  378. package/app/utils/product-utils.test.js +51 -0
  379. package/app/utils/responsive-image.js +198 -0
  380. package/app/utils/responsive-image.test.js +170 -0
  381. package/app/utils/routes-utils.js +111 -0
  382. package/app/utils/routes-utils.test.js +291 -0
  383. package/app/utils/site-utils.js +222 -0
  384. package/app/utils/site-utils.test.js +376 -0
  385. package/app/utils/test-utils.js +257 -0
  386. package/app/utils/url.js +291 -0
  387. package/app/utils/url.test.js +421 -0
  388. package/app/utils/utils.js +201 -0
  389. package/app/utils/utils.test.js +182 -0
  390. package/babel.config.js +7 -0
  391. package/cache-hash-config.json +8 -0
  392. package/config/default.js +64 -0
  393. package/config/mocks/default.js +131 -0
  394. package/config/sites.js +78 -0
  395. package/jest-setup.js +191 -0
  396. package/jest.config.js +50 -0
  397. package/jsconfig.json +13 -0
  398. package/package.json +105 -0
  399. package/scripts/extract-default-messages.js +92 -0
  400. package/tests/lighthouserc.js +37 -0
  401. package/translations/README.md +127 -0
  402. package/translations/compiled/de-DE.json +3212 -0
  403. package/translations/compiled/en-GB.json +3212 -0
  404. package/translations/compiled/en-US.json +3212 -0
  405. package/translations/compiled/en-XA.json +6948 -0
  406. package/translations/compiled/es-MX.json +3216 -0
  407. package/translations/compiled/fr-FR.json +3216 -0
  408. package/translations/compiled/it-IT.json +3188 -0
  409. package/translations/compiled/ja-JP.json +3200 -0
  410. package/translations/compiled/ko-KR.json +3180 -0
  411. package/translations/compiled/pt-BR.json +3220 -0
  412. package/translations/compiled/zh-CN.json +3212 -0
  413. package/translations/compiled/zh-TW.json +3208 -0
  414. package/translations/de-DE.json +1417 -0
  415. package/translations/en-GB.json +1417 -0
  416. package/translations/en-US.json +1417 -0
  417. package/translations/es-MX.json +1417 -0
  418. package/translations/fr-FR.json +1417 -0
  419. package/translations/it-IT.json +1417 -0
  420. package/translations/ja-JP.json +1417 -0
  421. package/translations/ko-KR.json +1417 -0
  422. package/translations/pt-BR.json +1417 -0
  423. package/translations/zh-CN.json +1417 -0
  424. package/translations/zh-TW.json +1417 -0
  425. package/worker/main.js +36 -0
@@ -0,0 +1,582 @@
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 Checkout from '@salesforce/retail-react-app/app/pages/checkout/index'
9
+ import {Route, Switch} from 'react-router-dom'
10
+ import {screen, waitFor, within} from '@testing-library/react'
11
+ import {rest} from 'msw'
12
+ import {
13
+ renderWithProviders,
14
+ createPathWithDefaults,
15
+ registerUserToken
16
+ } from '@salesforce/retail-react-app/app/utils/test-utils'
17
+ import {
18
+ scapiBasketWithItem,
19
+ mockShippingMethods,
20
+ mockedRegisteredCustomer,
21
+ mockedCustomerProductLists
22
+ } from '@salesforce/retail-react-app/app/mocks/mock-data'
23
+ import mockConfig from '@salesforce/retail-react-app/config/mocks/default'
24
+ import userEvent from '@testing-library/user-event'
25
+
26
+ jest.setTimeout(30000)
27
+
28
+ // Minimal subset of `ocapiOrderResponse` in app/mocks/mock-data.js
29
+ const scapiOrderResponse = {
30
+ orderNo: '00000101',
31
+ customerInfo: {
32
+ customerId: 'customerid',
33
+ customerNo: 'jlebowski',
34
+ email: 'jeff@lebowski.com'
35
+ }
36
+ }
37
+
38
+ const defaultShippingMethod = mockShippingMethods.applicableShippingMethods.find(
39
+ (method) => method.id === mockShippingMethods.defaultShippingMethodId
40
+ )
41
+
42
+ // This is our wrapped component for testing. It handles initialization of the customer
43
+ // and basket the same way it would be when rendered in the real app. We also set up
44
+ // fake routes to simulate moving from checkout to confirmation page.
45
+ const WrappedCheckout = () => {
46
+ return (
47
+ <Switch>
48
+ <Route exact path={createPathWithDefaults('/checkout')}>
49
+ <Checkout />
50
+ </Route>
51
+ <Route
52
+ exact
53
+ path={createPathWithDefaults(
54
+ `/checkout/confirmation/${scapiOrderResponse.orderNo}`
55
+ )}
56
+ >
57
+ <div>success</div>
58
+ </Route>
59
+ </Switch>
60
+ )
61
+ }
62
+
63
+ // Set up and clean up
64
+ beforeEach(() => {
65
+ global.server.use(
66
+ // mock product details
67
+ rest.get('*/products', (req, res, ctx) => {
68
+ return res(ctx.json({data: [{id: '701642811398M'}]}))
69
+ }),
70
+ // mock the available shipping methods
71
+ rest.get('*/shipments/me/shipping-methods', (req, res, ctx) => {
72
+ return res(ctx.delay(0), ctx.json(mockShippingMethods))
73
+ })
74
+ )
75
+ })
76
+ afterEach(() => {
77
+ jest.resetModules()
78
+ localStorage.clear()
79
+ })
80
+
81
+ test('Renders skeleton until customer and basket are loaded', () => {
82
+ const {getByTestId, queryByTestId} = renderWithProviders(<Checkout />)
83
+
84
+ expect(getByTestId('sf-checkout-skeleton')).toBeInTheDocument()
85
+ expect(queryByTestId('sf-checkout-container')).not.toBeInTheDocument()
86
+ })
87
+
88
+ test('Can proceed through checkout steps as guest', async () => {
89
+ // Keep a *deep* copy of the initial mocked basket. Our mocked fetch responses will continuously
90
+ // update this object, which essentially mimics a saved basket on the backend.
91
+ let currentBasket = JSON.parse(JSON.stringify(scapiBasketWithItem))
92
+
93
+ // Set up additional requests for intercepting/mocking for just this test.
94
+ global.server.use(
95
+ // mock adding guest email to basket
96
+ rest.put('*/baskets/:basketId/customer', (req, res, ctx) => {
97
+ currentBasket.customerInfo.email = 'test@test.com'
98
+ return res(ctx.json(currentBasket))
99
+ }),
100
+
101
+ // mock add shipping and billing address to basket
102
+ rest.put('*/shipping-address', (req, res, ctx) => {
103
+ const shippingBillingAddress = {
104
+ address1: '123 Main St',
105
+ city: 'Tampa',
106
+ countryCode: 'US',
107
+ firstName: 'Tester',
108
+ fullName: 'Tester McTesting',
109
+ id: '047b18d4aaaf4138f693a4b931',
110
+ lastName: 'McTesting',
111
+ phone: '(727) 555-1234',
112
+ postalCode: '33610',
113
+ stateCode: 'FL'
114
+ }
115
+ currentBasket.shipments[0].shippingAddress = shippingBillingAddress
116
+ currentBasket.billingAddress = shippingBillingAddress
117
+ return res(ctx.json(currentBasket))
118
+ }),
119
+
120
+ // mock add billing address to basket
121
+ rest.put('*/billing-address', (req, res, ctx) => {
122
+ const shippingBillingAddress = {
123
+ address1: '123 Main St',
124
+ city: 'Tampa',
125
+ countryCode: 'US',
126
+ firstName: 'Tester',
127
+ fullName: 'Tester McTesting',
128
+ id: '047b18d4aaaf4138f693a4b931',
129
+ lastName: 'McTesting',
130
+ phone: '(727) 555-1234',
131
+ postalCode: '33610',
132
+ stateCode: 'FL'
133
+ }
134
+ currentBasket.shipments[0].shippingAddress = shippingBillingAddress
135
+ currentBasket.billingAddress = shippingBillingAddress
136
+ return res(ctx.json(currentBasket))
137
+ }),
138
+
139
+ // mock add shipping method
140
+ rest.put('*/shipments/me/shipping-method', (req, res, ctx) => {
141
+ currentBasket.shipments[0].shippingMethod = defaultShippingMethod
142
+ return res(ctx.json(currentBasket))
143
+ }),
144
+
145
+ // mock add payment instrument
146
+ rest.post('*/baskets/:basketId/payment-instruments', (req, res, ctx) => {
147
+ currentBasket.paymentInstruments = [
148
+ {
149
+ amount: 0,
150
+ paymentCard: {
151
+ cardType: 'Visa',
152
+ creditCardExpired: false,
153
+ expirationMonth: 12,
154
+ expirationYear: 2024,
155
+ holder: 'Testy McTester',
156
+ maskedNumber: '************1111',
157
+ numberLastDigits: '1111',
158
+ validFromMonth: 1,
159
+ validFromYear: 2020
160
+ },
161
+ paymentInstrumentId: '875cae2724408c9a3eb45715ba',
162
+ paymentMethodId: 'CREDIT_CARD'
163
+ }
164
+ ]
165
+ return res(ctx.json(currentBasket))
166
+ }),
167
+
168
+ // mock place order
169
+ rest.post('*/orders', (req, res, ctx) => {
170
+ currentBasket = {
171
+ ...scapiOrderResponse,
172
+ customerInfo: {...scapiOrderResponse.customerInfo, email: 'test@test.com'}
173
+ }
174
+ return res(ctx.json(currentBasket))
175
+ }),
176
+
177
+ rest.get('*/baskets', (req, res, ctx) => {
178
+ const baskets = {
179
+ baskets: [currentBasket],
180
+ total: 1
181
+ }
182
+ return res(ctx.json(baskets))
183
+ })
184
+ )
185
+
186
+ // Set the initial browser router path and render our component tree.
187
+ window.history.pushState({}, 'Checkout', createPathWithDefaults('/checkout'))
188
+ const {user} = renderWithProviders(<WrappedCheckout history={history} />, {
189
+ wrapperProps: {isGuest: true, siteAlias: 'uk', appConfig: mockConfig.app}
190
+ })
191
+
192
+ // Wait for checkout to load and display first step
193
+ await screen.findByText(/checkout as guest/i)
194
+
195
+ // Verify cart products display
196
+ await user.click(screen.getByText(/2 items in cart/i))
197
+ expect(await screen.findByText(/Long Sleeve Crew Neck/i)).toBeInTheDocument()
198
+
199
+ // Provide customer email and submit
200
+ const emailInput = screen.getByLabelText(/email/i)
201
+ const submitBtn = screen.getByText(/checkout as guest/i)
202
+ await user.type(emailInput, 'test@test.com')
203
+ await user.click(submitBtn)
204
+
205
+ // Wait for next step to render
206
+ await waitFor(() =>
207
+ expect(screen.getByTestId('sf-toggle-card-step-1-content')).not.toBeEmptyDOMElement()
208
+ )
209
+
210
+ // Email should be displayed in previous step summary
211
+ expect(screen.getByText('test@test.com')).toBeInTheDocument()
212
+
213
+ // Fill out shipping address form and submit
214
+ await user.type(screen.getByLabelText(/first name/i), 'Tester')
215
+ await user.type(screen.getByLabelText(/last name/i), 'McTesting')
216
+ await user.type(screen.getByLabelText(/phone/i), '(727) 555-1234')
217
+ await user.type(screen.getByLabelText(/address/i), '123 Main St')
218
+ await user.type(screen.getByLabelText(/city/i), 'Tampa')
219
+ await user.selectOptions(screen.getByLabelText(/state/i), ['FL'])
220
+ await user.type(screen.getByLabelText(/zip code/i), '33610')
221
+ await user.click(screen.getByText(/continue to shipping method/i))
222
+
223
+ // Wait for next step to render
224
+ await waitFor(() => {
225
+ expect(screen.getByTestId('sf-toggle-card-step-2-content')).not.toBeEmptyDOMElement()
226
+ })
227
+
228
+ // Shipping address displayed in previous step summary
229
+ expect(screen.getByText('Tester McTesting')).toBeInTheDocument()
230
+ expect(screen.getByText('123 Main St')).toBeInTheDocument()
231
+ expect(screen.getByText('Tampa, FL 33610')).toBeInTheDocument()
232
+ expect(screen.getByText('US')).toBeInTheDocument()
233
+
234
+ // Default shipping option should be selected
235
+ const shippingOptionsForm = screen.getByTestId('sf-checkout-shipping-options-form')
236
+
237
+ await waitFor(() =>
238
+ expect(shippingOptionsForm).toHaveFormValues({
239
+ 'shipping-options-radiogroup': mockShippingMethods.defaultShippingMethodId
240
+ })
241
+ )
242
+
243
+ // Submit selected shipping method
244
+ await user.click(screen.getByText(/continue to payment/i))
245
+
246
+ // Wait for next step to render
247
+ await waitFor(() => {
248
+ expect(screen.getByTestId('sf-toggle-card-step-3-content')).not.toBeEmptyDOMElement()
249
+ })
250
+
251
+ // Applied shipping method should be displayed in previous step summary
252
+ expect(screen.getByText(defaultShippingMethod.name)).toBeInTheDocument()
253
+
254
+ // Fill out credit card payment form
255
+ await user.type(screen.getByLabelText(/card number/i), '4111111111111111')
256
+ await user.type(screen.getByLabelText(/name on card/i), 'Testy McTester')
257
+ await user.type(screen.getByLabelText(/expiration date/i), '1224')
258
+ await user.type(screen.getByLabelText(/security code/i), '123')
259
+
260
+ // Same as shipping checkbox selected by default
261
+ expect(screen.getByLabelText(/same as shipping address/i)).toBeChecked()
262
+
263
+ // Should display billing address that matches shipping address
264
+ const step3Content = within(screen.getByTestId('sf-toggle-card-step-3-content'))
265
+ expect(step3Content.getByText('Tester McTesting')).toBeInTheDocument()
266
+ expect(step3Content.getByText('123 Main St')).toBeInTheDocument()
267
+ expect(step3Content.getByText('Tampa, FL 33610')).toBeInTheDocument()
268
+ expect(step3Content.getByText('US')).toBeInTheDocument()
269
+
270
+ // Move to final review step
271
+ await user.click(screen.getByText(/review order/i))
272
+
273
+ const placeOrderBtn = await screen.findByTestId('sf-checkout-place-order-btn', undefined, {
274
+ timeout: 5000
275
+ })
276
+
277
+ // Verify applied payment and billing address
278
+ expect(step3Content.getByText('Visa')).toBeInTheDocument()
279
+ expect(step3Content.getByText('•••• 1111')).toBeInTheDocument()
280
+ expect(step3Content.getByText('12/2024')).toBeInTheDocument()
281
+
282
+ expect(step3Content.getByText('Tester McTesting')).toBeInTheDocument()
283
+ expect(step3Content.getByText('123 Main St')).toBeInTheDocument()
284
+ expect(step3Content.getByText('Tampa, FL 33610')).toBeInTheDocument()
285
+ expect(step3Content.getByText('US')).toBeInTheDocument()
286
+ // Place the order
287
+ await user.click(placeOrderBtn)
288
+
289
+ // Should now be on our mocked confirmation route/page
290
+ expect(await screen.findByText(/success/i)).toBeInTheDocument()
291
+ })
292
+
293
+ test('Can proceed through checkout as registered customer', async () => {
294
+ const user = userEvent.setup()
295
+ await logInDuringCheckout()
296
+
297
+ // Email should be displayed in previous step summary
298
+ expect(screen.getByText('customer@test.com')).toBeInTheDocument()
299
+
300
+ // Select a saved address and continue
301
+ await user.click(screen.getByDisplayValue('savedaddress1'))
302
+ await user.click(screen.getByText(/continue to shipping method/i))
303
+
304
+ // Wait for next step to render
305
+ await waitFor(() => {
306
+ expect(screen.getByTestId('sf-toggle-card-step-2-content')).not.toBeEmptyDOMElement()
307
+ })
308
+
309
+ // Shipping address displayed in previous step summary
310
+ expect(screen.getByText('Test McTester')).toBeInTheDocument()
311
+ expect(screen.getByText('123 Main St')).toBeInTheDocument()
312
+
313
+ // Default shipping option should be selected
314
+ const shippingOptionsForm = screen.getByTestId('sf-checkout-shipping-options-form')
315
+ await waitFor(() =>
316
+ expect(shippingOptionsForm).toHaveFormValues({
317
+ 'shipping-options-radiogroup': mockShippingMethods.defaultShippingMethodId
318
+ })
319
+ )
320
+
321
+ // Submit selected shipping method
322
+ await user.click(screen.getByText(/continue to payment/i))
323
+
324
+ // Wait for next step to render
325
+ await waitFor(() => {
326
+ expect(screen.getByTestId('sf-toggle-card-step-3-content')).not.toBeEmptyDOMElement()
327
+ })
328
+
329
+ // Applied shipping method should be displayed in previous step summary
330
+ expect(screen.getByText(defaultShippingMethod.name)).toBeInTheDocument()
331
+
332
+ // Fill out credit card payment form
333
+ // (we no longer have saved payment methods)
334
+ await user.type(screen.getByLabelText(/card number/i), '4111111111111111')
335
+ await user.type(screen.getByLabelText(/name on card/i), 'Testy McTester')
336
+ await user.type(screen.getByLabelText(/expiration date/i), '1224')
337
+ await user.type(screen.getByLabelText(/security code/i), '123')
338
+
339
+ // Same as shipping checkbox selected by default
340
+ expect(screen.getByLabelText(/same as shipping address/i)).toBeChecked()
341
+
342
+ // Should display billing address that matches shipping address
343
+ const step3Content = within(screen.getByTestId('sf-toggle-card-step-3-content'))
344
+ expect(step3Content.getByText('123 Main St')).toBeInTheDocument()
345
+
346
+ // Move to final review step
347
+ await user.click(screen.getByText(/review order/i))
348
+
349
+ const placeOrderBtn = await screen.findByTestId('sf-checkout-place-order-btn', undefined, {
350
+ timeout: 5000
351
+ })
352
+
353
+ // Verify applied payment and billing address
354
+ expect(step3Content.getByText('Master Card')).toBeInTheDocument()
355
+ expect(step3Content.getByText('•••• 5454')).toBeInTheDocument()
356
+ expect(step3Content.getByText('1/2030')).toBeInTheDocument()
357
+
358
+ expect(step3Content.getByText('123 Main St')).toBeInTheDocument()
359
+
360
+ // Place the order
361
+ await user.click(placeOrderBtn)
362
+
363
+ // Should now be on our mocked confirmation route/page
364
+ expect(await screen.findByText(/success/i)).toBeInTheDocument()
365
+ })
366
+
367
+ test('Can edit address during checkout as a registered customer', async () => {
368
+ const user = userEvent.setup()
369
+
370
+ await logInDuringCheckout()
371
+
372
+ const firstAddress = screen.getByTestId('sf-checkout-shipping-address-0')
373
+ await user.click(within(firstAddress).getByText(/edit/i))
374
+
375
+ // Wait for the edit address form to render
376
+ await waitFor(() =>
377
+ expect(screen.getByTestId('sf-shipping-address-edit-form')).not.toBeEmptyDOMElement()
378
+ )
379
+
380
+ expect(screen.getByLabelText(/first name/i)).toBeInTheDocument()
381
+
382
+ // Edit and save the address
383
+ await user.clear(screen.getByLabelText('Address'))
384
+ await user.type(screen.getByLabelText('Address'), '369 Main Street')
385
+ await user.click(screen.getByText(/save & continue to shipping method/i))
386
+
387
+ // Wait for next step to render
388
+ await waitFor(() => {
389
+ expect(screen.getByTestId('sf-toggle-card-step-2-content')).not.toBeEmptyDOMElement()
390
+ })
391
+
392
+ expect(screen.getByText('369 Main Street')).toBeInTheDocument()
393
+ })
394
+
395
+ test('Can add address during checkout as a registered customer', async () => {
396
+ const user = userEvent.setup()
397
+ await logInDuringCheckout()
398
+
399
+ global.server.use(
400
+ rest.post('*/customers/:customerId/addresses', (req, res, ctx) => {
401
+ return res(ctx.delay(0), ctx.status(200), ctx.json(req.body))
402
+ })
403
+ )
404
+
405
+ // Add address
406
+ await user.click(screen.getByText(/add new address/i))
407
+
408
+ const firstName = await screen.findByLabelText(/first name/i)
409
+ await user.type(firstName, 'Test2')
410
+ await user.type(screen.getByLabelText(/last name/i), 'McTester')
411
+ await user.type(screen.getByLabelText(/phone/i), '7275551234')
412
+ await user.selectOptions(screen.getByLabelText(/country/i), ['US'])
413
+ await user.type(screen.getByLabelText(/address/i), 'Tropicana Field')
414
+ await user.type(screen.getByLabelText(/city/i), 'Tampa')
415
+ await user.selectOptions(screen.getByLabelText(/state/i), ['FL'])
416
+ await user.type(screen.getByLabelText(/zip code/i), '33712')
417
+
418
+ await user.click(screen.getByText(/save & continue to shipping method/i))
419
+
420
+ // Wait for next step to render
421
+ await waitFor(() => {
422
+ expect(screen.getByTestId('sf-toggle-card-step-2-content')).not.toBeEmptyDOMElement()
423
+ })
424
+ })
425
+
426
+ const logInDuringCheckout = async () => {
427
+ // Keep a *deep* of the initial mocked basket. Our mocked fetch responses will continuously
428
+ // update this object, which essentially mimics a saved basket on the backend.
429
+ let currentBasket = JSON.parse(JSON.stringify(scapiBasketWithItem))
430
+
431
+ // Set up additional requests for intercepting/mocking for just this test.
432
+ global.server.use(
433
+ // mock adding guest email to basket
434
+ rest.put('*/baskets/:basketId/customer', (req, res, ctx) => {
435
+ currentBasket.customerInfo.email = 'customer@test.com'
436
+ return res(ctx.json(currentBasket))
437
+ }),
438
+
439
+ // mock fetch product lists
440
+ rest.get('*/customers/:customerId/product-lists', (req, res, ctx) => {
441
+ return res(ctx.json(mockedCustomerProductLists))
442
+ }),
443
+
444
+ // mock add shipping and billing address to basket
445
+ rest.put('*/shipping-address', (req, res, ctx) => {
446
+ const shippingBillingAddress = {
447
+ address1: req.body.address1,
448
+ city: 'Tampa',
449
+ countryCode: 'US',
450
+ firstName: 'Test',
451
+ fullName: 'Test McTester',
452
+ id: '047b18d4aaaf4138f693a4b931',
453
+ lastName: 'McTester',
454
+ phone: '(727) 555-1234',
455
+ postalCode: '33712',
456
+ stateCode: 'FL'
457
+ }
458
+ currentBasket.shipments[0].shippingAddress = shippingBillingAddress
459
+ currentBasket.billingAddress = shippingBillingAddress
460
+ return res(ctx.json(currentBasket))
461
+ }),
462
+
463
+ // mock add billing address to basket
464
+ rest.put('*/billing-address', (req, res, ctx) => {
465
+ const shippingBillingAddress = {
466
+ address1: '123 Main St',
467
+ city: 'Tampa',
468
+ countryCode: 'US',
469
+ firstName: 'Test',
470
+ fullName: 'Test McTester',
471
+ id: '047b18d4aaaf4138f693a4b931',
472
+ lastName: 'McTester',
473
+ phone: '(727) 555-1234',
474
+ postalCode: '33712',
475
+ stateCode: 'FL',
476
+ _type: 'orderAddress'
477
+ }
478
+ currentBasket.shipments[0].shippingAddress = shippingBillingAddress
479
+ currentBasket.billingAddress = shippingBillingAddress
480
+ return res(ctx.json(currentBasket))
481
+ }),
482
+
483
+ // mock add shipping method
484
+ rest.put('*/shipments/me/shipping-method', (req, res, ctx) => {
485
+ currentBasket.shipments[0].shippingMethod = defaultShippingMethod
486
+ return res(ctx.json(currentBasket))
487
+ }),
488
+
489
+ // mock add payment instrument
490
+ rest.post('*/baskets/:basketId/payment-instruments', (req, res, ctx) => {
491
+ currentBasket.paymentInstruments = [
492
+ {
493
+ amount: 0,
494
+ paymentCard: {
495
+ cardType: 'Master Card',
496
+ creditCardExpired: false,
497
+ expirationMonth: 1,
498
+ expirationYear: 2030,
499
+ holder: 'Test McTester',
500
+ maskedNumber: '************5454',
501
+ numberLastDigits: '5454',
502
+ validFromMonth: 1,
503
+ validFromYear: 2020
504
+ },
505
+ paymentInstrumentId: 'testcard1',
506
+ paymentMethodId: 'CREDIT_CARD'
507
+ }
508
+ ]
509
+ return res(ctx.json(currentBasket))
510
+ }),
511
+
512
+ // mock update address
513
+ rest.patch('*/addresses/savedaddress1', (req, res, ctx) => {
514
+ return res(ctx.json(mockedRegisteredCustomer.addresses[0]))
515
+ }),
516
+
517
+ // mock place order
518
+ rest.post('*/orders', (req, res, ctx) => {
519
+ currentBasket = {
520
+ ...scapiOrderResponse,
521
+ customerInfo: {...scapiOrderResponse.customerInfo, email: 'customer@test.com'}
522
+ }
523
+ return res(ctx.json(currentBasket))
524
+ }),
525
+
526
+ rest.get('*/baskets', (req, res, ctx) => {
527
+ const baskets = {
528
+ baskets: [currentBasket],
529
+ total: 1
530
+ }
531
+ return res(ctx.json(baskets))
532
+ })
533
+ )
534
+
535
+ // Set the initial browser router path and render our component tree.
536
+ window.history.pushState({}, 'Checkout', createPathWithDefaults('/checkout'))
537
+ const {user} = renderWithProviders(<WrappedCheckout history={history} />, {
538
+ wrapperProps: {
539
+ // Not bypassing auth as usual, so we can test the guest-to-registered flow
540
+ bypassAuth: false,
541
+ siteAlias: 'uk',
542
+ locale: {id: 'en-GB'},
543
+ appConfig: mockConfig.app
544
+ }
545
+ })
546
+
547
+ // Switch to login
548
+ const haveAccountButton = await screen.findByText(/already have an account/i)
549
+ await user.click(haveAccountButton)
550
+
551
+ // Wait for checkout to load and display first step
552
+ const loginBtn = await screen.findByText(/log in/i)
553
+
554
+ // Planning to log in
555
+ global.server.use(
556
+ rest.post('*/oauth2/token', (req, res, ctx) => {
557
+ return res(
558
+ ctx.delay(0),
559
+ ctx.json({
560
+ customer_id: 'customerid_1',
561
+ access_token: registerUserToken,
562
+ refresh_token: 'testrefeshtoken_1',
563
+ usid: 'testusid_1',
564
+ enc_user_id: 'testEncUserId_1',
565
+ id_token: 'testIdToken_1'
566
+ })
567
+ )
568
+ })
569
+ )
570
+
571
+ // Provide customer email and submit
572
+ const emailInput = screen.getByLabelText('Email')
573
+ const pwInput = screen.getByLabelText('Password')
574
+ await user.type(emailInput, 'customer@test.com')
575
+ await user.type(pwInput, 'Password!1')
576
+ await user.click(loginBtn)
577
+
578
+ // Wait for next step to render
579
+ await waitFor(() =>
580
+ expect(screen.getByTestId('sf-toggle-card-step-1-content')).not.toBeEmptyDOMElement()
581
+ )
582
+ }