@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,96 @@
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, {Fragment} from 'react'
9
+ import PropTypes from 'prop-types'
10
+ import {FormattedMessage} from 'react-intl'
11
+ import {Alert, Box, Button, Stack, Text} from '@chakra-ui/react'
12
+ import {AlertIcon, BrandLogo} from '@salesforce/retail-react-app/app/components/icons'
13
+ import LoginFields from '@salesforce/retail-react-app/app/components/forms/login-fields'
14
+ import {noop} from '@salesforce/retail-react-app/app/utils/utils'
15
+
16
+ const LoginForm = ({submitForm, clickForgotPassword = noop, clickCreateAccount = noop, form}) => {
17
+ return (
18
+ <Fragment>
19
+ <Stack justify="center" align="center" spacing={8} marginBottom={8}>
20
+ <BrandLogo width="60px" height="auto" />
21
+ <Text align="center" fontSize="xl" fontWeight="semibold">
22
+ <FormattedMessage
23
+ defaultMessage="Welcome Back"
24
+ id="login_form.message.welcome_back"
25
+ />
26
+ </Text>
27
+ </Stack>
28
+ <form
29
+ id="login-form"
30
+ onSubmit={form.handleSubmit(submitForm)}
31
+ data-testid="sf-auth-modal-form"
32
+ >
33
+ <Stack spacing={8} paddingLeft={4} paddingRight={4}>
34
+ {form.formState.errors?.global && (
35
+ <Alert status="error">
36
+ <AlertIcon color="red.500" boxSize={4} />
37
+ <Text fontSize="sm" ml={3}>
38
+ {form.formState.errors.global.message}
39
+ </Text>
40
+ </Alert>
41
+ )}
42
+ <Stack>
43
+ <LoginFields form={form} />
44
+
45
+ <Box>
46
+ <Button variant="link" size="sm" onClick={clickForgotPassword}>
47
+ <FormattedMessage
48
+ defaultMessage="Forgot password?"
49
+ id="login_form.link.forgot_password"
50
+ />
51
+ </Button>
52
+ </Box>
53
+ </Stack>
54
+ <Stack spacing={6}>
55
+ <Button
56
+ type="submit"
57
+ onClick={() => {
58
+ form.clearErrors('global')
59
+ }}
60
+ isLoading={form.formState.isSubmitting}
61
+ >
62
+ <FormattedMessage
63
+ defaultMessage="Sign In"
64
+ id="login_form.button.sign_in"
65
+ />
66
+ </Button>
67
+
68
+ <Stack direction="row" spacing={1} justify="center">
69
+ <Text fontSize="sm">
70
+ <FormattedMessage
71
+ defaultMessage="Don't have an account?"
72
+ id="login_form.message.dont_have_account"
73
+ />
74
+ </Text>
75
+ <Button variant="link" size="sm" onClick={clickCreateAccount}>
76
+ <FormattedMessage
77
+ defaultMessage="Create account"
78
+ id="login_form.action.create_account"
79
+ />
80
+ </Button>
81
+ </Stack>
82
+ </Stack>
83
+ </Stack>
84
+ </form>
85
+ </Fragment>
86
+ )
87
+ }
88
+
89
+ LoginForm.propTypes = {
90
+ submitForm: PropTypes.func,
91
+ clickForgotPassword: PropTypes.func,
92
+ clickCreateAccount: PropTypes.func,
93
+ form: PropTypes.object
94
+ }
95
+
96
+ export default LoginForm
@@ -0,0 +1,185 @@
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 PropTypes from 'prop-types'
10
+
11
+ // Components
12
+ import {
13
+ Accordion,
14
+ AccordionItem,
15
+ AccordionButton,
16
+ AccordionPanel,
17
+ Text,
18
+
19
+ // Hooks
20
+ useStyleConfig
21
+ } from '@chakra-ui/react'
22
+ import Link from '@salesforce/retail-react-app/app/components/link'
23
+ // Icons
24
+ import {ChevronDownIcon, ChevronRightIcon} from '@salesforce/retail-react-app/app/components/icons'
25
+
26
+ /**
27
+ * The nested accordion allows you to create, as the name suggest, a nests
28
+ * accordion given a hierarchical data structure. Each nests accordion will
29
+ * be indented to further enhance the hierary view.
30
+ */
31
+ const NestedAccordion = (props) => {
32
+ const styles = useStyleConfig('NestedAccordion')
33
+ const {
34
+ item,
35
+ initialDepth = 0,
36
+ itemsFilter = () => true,
37
+ itemsAfter,
38
+ itemsBefore,
39
+ itemsKey = 'items',
40
+ fontWeights = [],
41
+ fontSizes = [],
42
+ urlBuilder = (item) => `/${item.id}`,
43
+ ...rest
44
+ } = props
45
+
46
+ const depth = initialDepth
47
+ const items = item[itemsKey] || []
48
+
49
+ // Handle filters in the folr of a function or a object key string.
50
+ const filter = (item) =>
51
+ typeof itemsFilter === 'function' ? itemsFilter(item) : !!item[itemsFilter]
52
+
53
+ return (
54
+ <Accordion className="sf-nested-accordion" {...rest}>
55
+ {/* Optional accordion items before others in items list. */}
56
+ {typeof itemsBefore === 'function' ? itemsBefore({item, depth}) : itemsBefore}
57
+
58
+ {items.filter(filter).map((item) => {
59
+ const {id, name} = item
60
+ const items = item[itemsKey]
61
+
62
+ return (
63
+ <AccordionItem key={id} border="none">
64
+ {({isExpanded}) => (
65
+ <>
66
+ {/* Heading */}
67
+ <h2>
68
+ {/* Show item as a leaf node if it has no visible child items. */}
69
+ {items && items.filter(filter).length > 0 ? (
70
+ <AccordionButton {...styles.internalButton}>
71
+ {/* Replace default expanded/collapsed icons. */}
72
+ {isExpanded ? (
73
+ <ChevronDownIcon {...styles.internalButtonIcon} />
74
+ ) : (
75
+ <ChevronRightIcon {...styles.internalButtonIcon} />
76
+ )}
77
+
78
+ <Text
79
+ fontSize={fontSizes[depth]}
80
+ fontWeight={fontWeights[depth]}
81
+ >
82
+ {name}
83
+ </Text>
84
+ </AccordionButton>
85
+ ) : (
86
+ <AccordionButton
87
+ {...styles.leafButton}
88
+ as={Link}
89
+ to={urlBuilder(item)}
90
+ >
91
+ <Text
92
+ fontSize={fontSizes[depth]}
93
+ fontWeight={fontWeights[depth]}
94
+ >
95
+ {name}
96
+ </Text>
97
+ </AccordionButton>
98
+ )}
99
+ </h2>
100
+
101
+ {/* Child Items */}
102
+ {items && (
103
+ <AccordionPanel {...styles.panel}>
104
+ <NestedAccordion
105
+ {...styles.nestedAccordion}
106
+ {...props}
107
+ item={item}
108
+ initialDepth={depth + 1}
109
+ />
110
+ </AccordionPanel>
111
+ )}
112
+ </>
113
+ )}
114
+ </AccordionItem>
115
+ )
116
+ })}
117
+
118
+ {/* Optional accordion items after others in items list. */}
119
+ {typeof itemsAfter === 'function' ? itemsAfter({item, depth}) : itemsAfter}
120
+ </Accordion>
121
+ )
122
+ }
123
+
124
+ NestedAccordion.displayName = 'NestedAccordion'
125
+
126
+ NestedAccordion.propTypes = {
127
+ /**
128
+ * A POJO consistening of an id, name, and items array of object with
129
+ * similarly specified properties.
130
+ */
131
+ item: PropTypes.object.isRequired,
132
+ /**
133
+ * An array of `AccordionItem` components that will be displayed after all
134
+ * of the child items. Alternatively you can pass a function that will recieve
135
+ * the current item and it's depth, your should return an `AccordionItem` or
136
+ * array of `AccordionItem`'s.
137
+ */
138
+ itemsAfter: PropTypes.oneOfType([PropTypes.array, PropTypes.func]),
139
+ /**
140
+ * An array of `AccordionItem` components that will be displayed before all
141
+ * of the child items. Alternatively you can pass a function that will recieve
142
+ * the current item and it's depth, your should return an `AccordionItem` or
143
+ * array of `AccordionItem`'s.
144
+ */
145
+ itemsBefore: PropTypes.oneOfType([PropTypes.array, PropTypes.func]),
146
+ /**
147
+ * This is an internally used property used to pass the updated depth of the
148
+ * child accordion. This is used to access specfic styl data for accodions
149
+ * based on their depth.
150
+ */
151
+ initialDepth: PropTypes.number,
152
+ /**
153
+ * By default child items are keyed at `items` but if your data differs you
154
+ * can specify a custom key name for chile items. (e.g. children)
155
+ */
156
+ itemsKey: PropTypes.string,
157
+ /**
158
+ * Programatically filter out items that you do not want to show. You can do this by
159
+ * supplying a string that will be used to access an items value, the the value is truthy
160
+ * the item will be displayed. Otherwise you can pass a function, this function will be passed
161
+ * the item to be filtered, its return is expected to be true or false.
162
+ */
163
+ itemsFilter: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
164
+ /**
165
+ * An array of font size strings, the position in the array will
166
+ * indicate at what depth that size is applied.
167
+ * TODO: Think about making this optionally a string value to make it behave like
168
+ * chakra-ui responsive properties.
169
+ */
170
+ fontSizes: PropTypes.array,
171
+ /**
172
+ * An array of font weight strings, the position in the array will
173
+ * indicate at what depth that weight is applied.
174
+ * TODO: Think about making this optionally a string value to make it behave like
175
+ * chakra-ui responsive properties.
176
+ */
177
+ fontWeights: PropTypes.array,
178
+ /**
179
+ * This function builds the urls for leaf items. It accepts
180
+ * the current item, and returns a string.
181
+ */
182
+ urlBuilder: PropTypes.func
183
+ }
184
+
185
+ export default NestedAccordion
@@ -0,0 +1,98 @@
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 NestedAccordion from '@salesforce/retail-react-app/app/components/nested-accordion/index'
9
+ import {renderWithProviders} from '@salesforce/retail-react-app/app/utils/test-utils'
10
+
11
+ const mockItem = {
12
+ id: 't1',
13
+ name: 'Test One',
14
+ items: [
15
+ {
16
+ id: 't1-1',
17
+ name: 'Test One One'
18
+ },
19
+ {
20
+ id: 't1-2',
21
+ name: 'Test One Two',
22
+ items: [
23
+ {
24
+ id: 't1-2-1',
25
+ name: 'Test One Two One'
26
+ },
27
+ {
28
+ id: 't1-2-2',
29
+ name: 'Test One Two Two'
30
+ }
31
+ ]
32
+ }
33
+ ]
34
+ }
35
+ test('Renders NestedAccordion', () => {
36
+ renderWithProviders(<NestedAccordion item={mockItem} />)
37
+
38
+ const accordions = document.querySelectorAll('.sf-nested-accordion')
39
+
40
+ expect(accordions).toHaveLength(2)
41
+ })
42
+
43
+ test('Renders NestedAccordion with items elements before and after', () => {
44
+ renderWithProviders(
45
+ <NestedAccordion
46
+ item={mockItem}
47
+ itemsBefore={[
48
+ <div className="itemsBefore" key="before">
49
+ before
50
+ </div>
51
+ ]}
52
+ itemsAfter={[
53
+ <div className="itemsAfter" key="after">
54
+ before
55
+ </div>
56
+ ]}
57
+ />
58
+ )
59
+
60
+ const itemBefore = document.querySelector('.itemsBefore')
61
+ const itemAfter = document.querySelector('.itemsAfter')
62
+
63
+ expect(itemBefore).toBeInTheDocument()
64
+ expect(itemAfter).toBeInTheDocument()
65
+ })
66
+
67
+ test('Renders NestedAccordion with items functions before and after', () => {
68
+ const onItemsBefore = jest.fn(() => [
69
+ <div className="itemsBefore" key="before">
70
+ before
71
+ </div>
72
+ ])
73
+ const onItemsAfter = jest.fn(() => [
74
+ <div className="itemsAfter" key="after">
75
+ after
76
+ </div>
77
+ ])
78
+
79
+ renderWithProviders(
80
+ <NestedAccordion item={mockItem} itemsBefore={onItemsBefore} itemsAfter={onItemsAfter} />
81
+ )
82
+
83
+ const itemBefore = document.querySelector('.itemsBefore')
84
+ const itemAfter = document.querySelector('.itemsAfter')
85
+
86
+ expect(onItemsBefore).toHaveBeenCalled()
87
+ expect(onItemsAfter).toHaveBeenCalled()
88
+ expect(itemBefore).toBeInTheDocument()
89
+ expect(itemAfter).toBeInTheDocument()
90
+ })
91
+
92
+ test('Renders NestedAccordion with custom url builder', () => {
93
+ const mockPath = '/mock-path'
94
+ renderWithProviders(<NestedAccordion item={mockItem} urlBuilder={() => mockPath} />)
95
+
96
+ const firstLeafLink = document.querySelector('.sf-nested-accordion a')
97
+ expect(firstLeafLink.href.endsWith(mockPath)).toBe(true)
98
+ })
@@ -0,0 +1,40 @@
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 {useIntl} from 'react-intl'
10
+
11
+ // Components
12
+ import {
13
+ Alert,
14
+ Text,
15
+
16
+ // Hooks
17
+ useStyleConfig
18
+ } from '@chakra-ui/react'
19
+
20
+ // Icons
21
+ import {AlertIcon} from '@salesforce/retail-react-app/app/components/icons'
22
+
23
+ const OfflineBanner = () => {
24
+ const intl = useIntl()
25
+ const style = useStyleConfig('OfflineBanner')
26
+
27
+ return (
28
+ <Alert status="info" {...style.container}>
29
+ <AlertIcon {...style.icon} />
30
+ <Text {...style.message}>
31
+ {intl.formatMessage({
32
+ id: 'offline_banner.description.browsing_offline_mode',
33
+ defaultMessage: "You're currently browsing in offline mode"
34
+ })}
35
+ </Text>
36
+ </Alert>
37
+ )
38
+ }
39
+
40
+ export default OfflineBanner
@@ -0,0 +1,15 @@
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 {renderWithProviders} from '@salesforce/retail-react-app/app/utils/test-utils'
9
+ import OfflineBanner from '@salesforce/retail-react-app/app/components/offline-banner/index'
10
+ import {screen} from '@testing-library/react'
11
+
12
+ test('OfflineBanner component is rendered appropriately', () => {
13
+ renderWithProviders(<OfflineBanner />)
14
+ expect(screen.getByText("You're currently browsing in offline mode")).toBeInTheDocument()
15
+ })
@@ -0,0 +1,104 @@
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 PropTypes from 'prop-types'
9
+ import {withRouter} from 'react-router-dom'
10
+ import {Button} from '@chakra-ui/react'
11
+ import {AlertIcon} from '@salesforce/retail-react-app/app/components/icons'
12
+
13
+ // import Button from '@salesforce/pwa-kit-react-sdk/components/button'
14
+ // import Icon from '@salesforce/pwa-kit-react-sdk/components/icon'
15
+
16
+ /**
17
+ * OfflineBoundary is a React Error boundary that catches errors thrown when
18
+ * dynamically loading pages and renders a fallback.
19
+ */
20
+ class OfflineBoundary extends React.Component {
21
+ constructor(props) {
22
+ super(props)
23
+ this.state = {
24
+ chunkLoadError: false
25
+ }
26
+ }
27
+
28
+ componentDidCatch(e) {
29
+ // Only catch errors loading components with @loadable/components. Everything
30
+ // else should bubble up the component tree to the built-in root error boundary.
31
+ if (e.name !== 'ChunkLoadError') {
32
+ throw e
33
+ }
34
+ }
35
+
36
+ static getDerivedStateFromError() {
37
+ return {chunkLoadError: true}
38
+ }
39
+
40
+ componentDidUpdate(previousProps) {
41
+ const {location: previousLocation, isOnline: wasOnline} = previousProps
42
+ const {location, isOnline} = this.props
43
+
44
+ const cameOnline = !wasOnline && isOnline
45
+
46
+ const locationChanged = ['pathname', 'search'].some(
47
+ (k) => (previousLocation || {})[k] !== (location || {})[k]
48
+ )
49
+
50
+ const shouldClear = cameOnline || locationChanged
51
+
52
+ if (shouldClear) {
53
+ this.clearError()
54
+ }
55
+ }
56
+
57
+ clearError() {
58
+ // Use an updater in order to only re-render if the state needs to change
59
+ this.setState((prevState) => {
60
+ return prevState.chunkLoadError ? {chunkLoadError: false} : null
61
+ })
62
+ }
63
+
64
+ render() {
65
+ const {children} = this.props
66
+ const {chunkLoadError} = this.state
67
+
68
+ return (
69
+ <React.Fragment>
70
+ {chunkLoadError ? (
71
+ <div className="c-offline-boundary u-direction-column u-text-align-center u-padding-top u-padding-bottom">
72
+ <AlertIcon />
73
+
74
+ <h1 className="u-margin-bottom-md u-text-family">
75
+ You are currently offline
76
+ </h1>
77
+
78
+ <p className="u-margin-bottom-lg">
79
+ {"We couldn't load the next page on this connection. Please try again."}
80
+ </p>
81
+
82
+ <Button
83
+ className="u-width-block-full pw--primary qa-retry-button"
84
+ onClick={() => this.clearError()}
85
+ >
86
+ Retry Connection
87
+ </Button>
88
+ </div>
89
+ ) : (
90
+ children
91
+ )}
92
+ </React.Fragment>
93
+ )
94
+ }
95
+ }
96
+
97
+ OfflineBoundary.propTypes = {
98
+ isOnline: PropTypes.bool.isRequired,
99
+ location: PropTypes.object,
100
+ children: PropTypes.node
101
+ }
102
+
103
+ export {OfflineBoundary as UnwrappedOfflineBoundary}
104
+ export default withRouter(OfflineBoundary)
@@ -0,0 +1,123 @@
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 {screen} from '@testing-library/react'
9
+ // import userEvent from '@testing-library/user-event'
10
+
11
+ import OfflineBoundary from '@salesforce/retail-react-app/app/components/offline-boundary/index'
12
+ import {renderWithRouter} from '@salesforce/retail-react-app/app/utils/test-utils'
13
+
14
+ // class ChunkLoadError extends Error {
15
+ // constructor(...params) {
16
+ // // Pass remaining arguments (including vendor specific ones) to parent constructor
17
+ // super(...params)
18
+ // this.name = 'ChunkLoadError'
19
+ // }
20
+ // }
21
+
22
+ describe('The OfflineBoundary', () => {
23
+ beforeEach(() => {
24
+ // React's logging is noisey even when an Error Boundary catches. Silence
25
+ // the distracting logs during tests, since they are expected in any event.
26
+ jest.spyOn(console, 'error').mockImplementation(() => {})
27
+ })
28
+
29
+ afterEach(() => {
30
+ console.error.mockRestore()
31
+ })
32
+
33
+ test('should render its children', () => {
34
+ renderWithRouter(
35
+ <OfflineBoundary isOnline={true}>
36
+ <div id="child">child</div>
37
+ </OfflineBoundary>
38
+ )
39
+
40
+ expect(screen.getByText(/child/i)).toBeInTheDocument()
41
+ })
42
+
43
+ // TODO: Fix flaky/broken test
44
+ // eslint-disable-next-line jest/no-commented-out-tests
45
+ // test('should render the error splash when a child throws a chunk load error', () => {
46
+ // const ThrowingComponent = () => {
47
+ // throw new ChunkLoadError()
48
+ // }
49
+ // renderWithRouter(
50
+ // <OfflineBoundary isOnline={true}>
51
+ // <div>
52
+ // <ThrowingComponent />
53
+ // <div id="child">child</div>
54
+ // </div>
55
+ // </OfflineBoundary>
56
+ // )
57
+
58
+ // expect(screen.getByRole('img', {name: /offline cloud/i})).toBeInTheDocument()
59
+ // expect(
60
+ // screen.getByRole('heading', {name: /you are currently offline/i})
61
+ // ).toBeInTheDocument()
62
+ // expect(screen.queryByText(/child/i)).not.toBeInTheDocument()
63
+ // })
64
+
65
+ // TODO: Fix flaky/broken test
66
+ // eslint-disable-next-line jest/no-commented-out-tests
67
+ // test('should re-throw errors that are not chunk load errors', () => {
68
+ // const ThrowingComponent = () => {
69
+ // throw new Error('Anything else')
70
+ // }
71
+ // expect(() => {
72
+ // renderWithRouter(
73
+ // <OfflineBoundary isOnline={true}>
74
+ // <div>
75
+ // <ThrowingComponent />
76
+ // <div id="child">child</div>
77
+ // </div>
78
+ // </OfflineBoundary>
79
+ // )
80
+ // }).toThrow()
81
+ // })
82
+
83
+ // TODO: Fix flaky/broken test
84
+ // eslint-disable-next-line jest/no-commented-out-tests
85
+ // test('should attempt to reload the page when the user clicks retry', () => {
86
+ // let firstRender = true
87
+ // const ThrowingOnceComponent = () => {
88
+ // if (firstRender) {
89
+ // firstRender = false
90
+ // throw new ChunkLoadError()
91
+ // } else {
92
+ // return <div id="child">child</div>
93
+ // }
94
+ // }
95
+ // renderWithRouter(
96
+ // <OfflineBoundary isOnline={true}>
97
+ // <ThrowingOnceComponent />
98
+ // </OfflineBoundary>
99
+ // )
100
+
101
+ // expect(screen.getByRole('img', {name: /offline cloud/i})).toBeInTheDocument()
102
+ // expect(
103
+ // screen.getByRole('heading', {name: /you are currently offline/i})
104
+ // ).toBeInTheDocument()
105
+ // expect(screen.queryByText(/child/i)).not.toBeInTheDocument()
106
+
107
+ // userEvent.click(screen.getByRole('button', {name: /retry connection/i}))
108
+ // expect(screen.getByText(/child/i)).toBeInTheDocument()
109
+ // expect(screen.queryByRole('img', {name: /offline cloud/i})).not.toBeInTheDocument()
110
+ // expect(
111
+ // screen.queryByRole('heading', {name: /you are currently offline/i})
112
+ // ).not.toBeInTheDocument()
113
+ // })
114
+
115
+ // TODO: Fix flaky/broken test
116
+ // eslint-disable-next-line jest/no-commented-out-tests
117
+ // test('should derive state from a chunk load error', () => {
118
+ // const derived = UnwrappedOfflineBoundary.getDerivedStateFromError(
119
+ // new ChunkLoadError('test')
120
+ // )
121
+ // expect(derived).toEqual({chunkLoadError: true})
122
+ // })
123
+ })