@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,280 @@
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, useRef, forwardRef, useEffect, useState} from 'react'
9
+ import PropTypes from 'prop-types'
10
+ import {useIntl} from 'react-intl'
11
+ import {Link as RouteLink} from 'react-router-dom'
12
+
13
+ // Project Components
14
+ import LinksList from '@salesforce/retail-react-app/app/components/links-list'
15
+
16
+ // Components
17
+ import {
18
+ Box,
19
+ Container,
20
+ SimpleGrid,
21
+ Fade,
22
+ Flex,
23
+ Stack,
24
+ Popover,
25
+ PopoverTrigger,
26
+ PopoverContent,
27
+ PopoverBody,
28
+ Center,
29
+ Spinner,
30
+
31
+ // Hooks
32
+ useTheme,
33
+ useDisclosure
34
+ } from '@chakra-ui/react'
35
+ import Link from '@salesforce/retail-react-app/app/components/link'
36
+ // Others
37
+ import {categoryUrlBuilder} from '@salesforce/retail-react-app/app/utils/url'
38
+ import {ChevronDownIcon} from '@salesforce/retail-react-app/app/components/icons'
39
+
40
+ const MAXIMUM_NUMBER_COLUMNS = 5
41
+
42
+ const ChevronIconTrigger = forwardRef(function ChevronIconTrigger(props, ref) {
43
+ return (
44
+ <Box {...props} ref={ref}>
45
+ <ChevronDownIcon />
46
+ </Box>
47
+ )
48
+ })
49
+
50
+ const ListMenuTrigger = ({item, name, isOpen, onOpen, onClose, hasItems}) => {
51
+ const theme = useTheme()
52
+ const {baseStyle} = theme.components.ListMenu
53
+
54
+ const keyMap = {
55
+ Escape: () => onClose(),
56
+ Enter: () => onOpen()
57
+ }
58
+
59
+ return (
60
+ <Box {...baseStyle.listMenuTriggerContainer}>
61
+ <Link
62
+ as={RouteLink}
63
+ to={categoryUrlBuilder(item)}
64
+ onMouseOver={onOpen}
65
+ {...baseStyle.listMenuTriggerLink}
66
+ {...(hasItems ? {name: name + ' __'} : {name: name})}
67
+ {...(isOpen ? baseStyle.listMenuTriggerLinkActive : {})}
68
+ >
69
+ {name}
70
+ </Link>
71
+
72
+ <Link
73
+ as={RouteLink}
74
+ to={'#'}
75
+ onMouseOver={onOpen}
76
+ onKeyDown={(e) => {
77
+ keyMap[e.key]?.(e)
78
+ }}
79
+ {...baseStyle.listMenuTriggerLinkIcon}
80
+ >
81
+ <PopoverTrigger>
82
+ <Fade in={hasItems}>
83
+ <ChevronIconTrigger {...baseStyle.selectedButtonIcon} />
84
+ </Fade>
85
+ </PopoverTrigger>
86
+ </Link>
87
+ </Box>
88
+ )
89
+ }
90
+ ListMenuTrigger.propTypes = {
91
+ item: PropTypes.object,
92
+ name: PropTypes.string,
93
+ isOpen: PropTypes.bool,
94
+ onOpen: PropTypes.func,
95
+ onClose: PropTypes.func,
96
+ hasItems: PropTypes.bool
97
+ }
98
+
99
+ const ListMenuContent = ({maxColumns, items, itemsKey, onClose, initialFocusRef}) => {
100
+ const theme = useTheme()
101
+ const {baseStyle} = theme.components.ListMenu
102
+ const {locale} = useIntl()
103
+
104
+ return (
105
+ <PopoverContent data-testid="popover-menu" {...baseStyle.popoverContent}>
106
+ <PopoverBody>
107
+ <Container as={Stack} {...baseStyle.popoverContainer}>
108
+ <SimpleGrid
109
+ spacing={8}
110
+ justifyContent={'left'}
111
+ gridTemplateColumns={`repeat(${
112
+ items.length > maxColumns ? maxColumns : items.length
113
+ }, minmax(0, 21%))`}
114
+ marginInlineStart={{lg: '68px', xl: '96px'}}
115
+ >
116
+ {items.map((item, index) => {
117
+ const {id, name} = item
118
+ const items = item[itemsKey]
119
+
120
+ const heading = {
121
+ href: categoryUrlBuilder(item, locale),
122
+ text: name,
123
+ styles: {
124
+ fontSize: 'md',
125
+ marginBottom: 2
126
+ }
127
+ }
128
+
129
+ const links = items
130
+ ? items.map((item) => {
131
+ const {name} = item
132
+ return {
133
+ href: categoryUrlBuilder(item, locale),
134
+ text: name,
135
+ styles: {
136
+ fontSize: 'md',
137
+ paddingTop: 3,
138
+ paddingBottom: 3
139
+ }
140
+ }
141
+ })
142
+ : []
143
+ return (
144
+ <LinksList
145
+ key={id}
146
+ heading={heading}
147
+ links={links}
148
+ color={'gray.900'}
149
+ onLinkClick={onClose}
150
+ {...(index === 0 ? {headingLinkRef: initialFocusRef} : {})}
151
+ />
152
+ )
153
+ })}
154
+ </SimpleGrid>
155
+ </Container>
156
+ </PopoverBody>
157
+ </PopoverContent>
158
+ )
159
+ }
160
+ ListMenuContent.propTypes = {
161
+ items: PropTypes.array,
162
+ maxColumns: PropTypes.number,
163
+ onClose: PropTypes.func,
164
+ initialFocusRef: PropTypes.object,
165
+ itemsKey: PropTypes.string
166
+ }
167
+
168
+ const ListMenuPopover = ({items, item, name, itemsKey, maxColumns}) => {
169
+ const initialFocusRef = useRef()
170
+ const {isOpen, onClose, onOpen} = useDisclosure()
171
+ return (
172
+ <Box onMouseLeave={onClose}>
173
+ <Popover
174
+ isLazy
175
+ placement={'bottom-start'}
176
+ initialFocusRef={initialFocusRef}
177
+ onOpen={onOpen}
178
+ onClose={onClose}
179
+ isOpen={isOpen}
180
+ variant="fullWidth"
181
+ >
182
+ <Fragment>
183
+ <ListMenuTrigger
184
+ item={item}
185
+ name={name}
186
+ isOpen={isOpen}
187
+ onOpen={onOpen}
188
+ onClose={onClose}
189
+ hasItems={!!items}
190
+ />
191
+ {items && (
192
+ <ListMenuContent
193
+ items={items}
194
+ itemsKey={itemsKey}
195
+ initialFocusRef={initialFocusRef}
196
+ onClose={onClose}
197
+ maxColumns={maxColumns}
198
+ />
199
+ )}
200
+ </Fragment>
201
+ </Popover>
202
+ </Box>
203
+ )
204
+ }
205
+
206
+ ListMenuPopover.propTypes = {
207
+ items: PropTypes.array,
208
+ item: PropTypes.object,
209
+ name: PropTypes.string,
210
+ maxColumns: PropTypes.number,
211
+ itemsKey: PropTypes.string
212
+ }
213
+
214
+ /**
215
+ * This is the navigation component used for desktop devices. Holds the site navigation,
216
+ * providing users with a way to access all product categories and other important pages.
217
+ * The submenus are open when the user moves the mouse over the trigger and for A11y when
218
+ * users use the keyboard Tab key to focus over the chevron icon and press Enter.
219
+ *
220
+ * @param maxColumns The maximum number of columns that we want to use per row inside the ListMenu.
221
+ * @param root
222
+ */
223
+ const ListMenu = ({root, maxColumns = MAXIMUM_NUMBER_COLUMNS}) => {
224
+ const itemsKey = 'categories'
225
+ const theme = useTheme()
226
+ const {baseStyle} = theme.components.ListMenu
227
+ const [ariaBusy, setAriaBusy] = useState(true)
228
+
229
+ useEffect(() => {
230
+ setAriaBusy(false)
231
+ }, [])
232
+
233
+ return (
234
+ <nav
235
+ id="list-menu"
236
+ aria-label="main"
237
+ aria-live="polite"
238
+ aria-busy={ariaBusy}
239
+ aria-atomic="true"
240
+ >
241
+ <Flex {...baseStyle.container}>
242
+ {root?.[itemsKey] ? (
243
+ <Stack direction={'row'} spacing={0} {...baseStyle.stackContainer}>
244
+ {root?.[itemsKey]?.map?.((item) => {
245
+ const {id, name} = item
246
+ return (
247
+ <Box key={id}>
248
+ <ListMenuPopover
249
+ key={id}
250
+ maxColumns={maxColumns}
251
+ item={item}
252
+ name={name}
253
+ items={item?.[itemsKey]}
254
+ itemsKey={itemsKey}
255
+ />
256
+ </Box>
257
+ )
258
+ })}
259
+ </Stack>
260
+ ) : (
261
+ <Center p="2">
262
+ <Spinner size="lg" />
263
+ </Center>
264
+ )}
265
+ </Flex>
266
+ </nav>
267
+ )
268
+ }
269
+
270
+ ListMenu.displayName = 'ListMenu'
271
+
272
+ ListMenu.propTypes = {
273
+ root: PropTypes.object,
274
+ /**
275
+ * The maximum number of columns that we want to use per row in the menu.
276
+ */
277
+ maxColumns: PropTypes.number
278
+ }
279
+
280
+ export default ListMenu
@@ -0,0 +1,44 @@
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 ListMenu from '@salesforce/retail-react-app/app/components/list-menu/index'
10
+ import {renderWithProviders} from '@salesforce/retail-react-app/app/utils/test-utils'
11
+ import {mockCategories} from '@salesforce/retail-react-app/app/mocks/mock-data'
12
+ import userEvent from '@testing-library/user-event'
13
+
14
+ describe('ListMenu', () => {
15
+ test('ListMenu renders without errors', async () => {
16
+ const user = userEvent.setup()
17
+ renderWithProviders(<ListMenu root={mockCategories.root} />)
18
+
19
+ const categoryTrigger = screen.getByText(/Mens/i)
20
+ await user.hover(categoryTrigger)
21
+ expect(categoryTrigger).toBeInTheDocument()
22
+ expect(screen.getByRole('navigation', {name: 'main'})).toBeInTheDocument()
23
+ const suit = screen.getByText(/suits/i)
24
+ expect(suit).toBeInTheDocument()
25
+ })
26
+ test('ListMenu renders Spinner without root categories', () => {
27
+ renderWithProviders(<ListMenu />, {
28
+ wrapperProps: {initialCategories: {}}
29
+ })
30
+
31
+ const spinner = document.querySelector('.chakra-spinner')
32
+
33
+ expect(spinner).toBeInTheDocument()
34
+ })
35
+ })
36
+
37
+ // Set up and clean up
38
+ beforeEach(() => {
39
+ jest.resetModules()
40
+ })
41
+ afterEach(() => {
42
+ localStorage.clear()
43
+ jest.clearAllMocks()
44
+ })
@@ -0,0 +1,46 @@
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 {Box, Spinner} from '@chakra-ui/react'
9
+ import PropTypes from 'prop-types'
10
+
11
+ const LoadingSpinner = ({wrapperStyles = {}, spinnerStyles = {}}) => {
12
+ return (
13
+ <Box
14
+ zIndex="overlay"
15
+ position="absolute"
16
+ top="0"
17
+ left="0"
18
+ right="0"
19
+ bottom="0"
20
+ background="whiteAlpha.800"
21
+ {...wrapperStyles}
22
+ >
23
+ <Spinner
24
+ data-testid="loading"
25
+ {...spinnerStyles}
26
+ position="absolute"
27
+ top="50%"
28
+ left="50%"
29
+ ml="-1.5em"
30
+ mt="-1.5em"
31
+ thickness="4px"
32
+ speed="0.65s"
33
+ emptyColor="gray.200"
34
+ color="blue.600"
35
+ size="xl"
36
+ />
37
+ </Box>
38
+ )
39
+ }
40
+
41
+ LoadingSpinner.propTypes = {
42
+ wrapperStyles: PropTypes.object,
43
+ spinnerStyles: PropTypes.object
44
+ }
45
+
46
+ export default LoadingSpinner
@@ -0,0 +1,124 @@
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
+ AccordionButton,
15
+ AccordionItem,
16
+ AccordionPanel,
17
+ Box,
18
+ Text,
19
+
20
+ // Hooks
21
+ useStyleConfig
22
+ } from '@chakra-ui/react'
23
+
24
+ // Icons
25
+ import {
26
+ CheckIcon,
27
+ ChevronDownIcon,
28
+ ChevronRightIcon,
29
+ FlagGBIcon,
30
+ FlagFRIcon,
31
+ FlagITIcon,
32
+ FlagCNIcon,
33
+ FlagJPIcon
34
+ } from '@salesforce/retail-react-app/app/components/icons'
35
+
36
+ import LocaleText from '@salesforce/retail-react-app/app/components/locale-text'
37
+
38
+ // NOTE: If you want to have flags shown next to a selectable locale, update this
39
+ // mapping object with the short code as the key for the desired icon.
40
+ const flags = {
41
+ 'en-GB': <FlagGBIcon />,
42
+ 'fr-FR': <FlagFRIcon />,
43
+ 'it-IT': <FlagITIcon />,
44
+ 'zh-CN': <FlagCNIcon />,
45
+ 'ja-JP': <FlagJPIcon />
46
+ }
47
+
48
+ /**
49
+ * The Locale Selector is a disclosure in the form of an accordion. It is
50
+ * populated with all the supported locales for the application allowing the
51
+ * user to change the current locale.
52
+ */
53
+ const LocaleSelector = ({selectedLocale = '', locales = [], onSelect = () => {}, ...props}) => {
54
+ const styles = useStyleConfig('LocaleSelector')
55
+ return (
56
+ <Box className="sf-locale-selector">
57
+ <Accordion allowToggle={true} {...props}>
58
+ <AccordionItem border="none">
59
+ {({isExpanded}) => (
60
+ <>
61
+ <AccordionButton {...styles.selectedButton}>
62
+ {/* Replace default expanded/collapsed icons. */}
63
+ {isExpanded ? (
64
+ <ChevronDownIcon {...styles.selectedButtonIcon} />
65
+ ) : (
66
+ <ChevronRightIcon {...styles.selectedButtonIcon} />
67
+ )}
68
+ {/* Display flag icon if one exists */}
69
+ {flags[selectedLocale]}
70
+ <Text {...styles.selectedText}>
71
+ <LocaleText shortCode={selectedLocale} />
72
+ </Text>
73
+ </AccordionButton>
74
+ <AccordionPanel>
75
+ <Accordion allowToggle={true} {...styles.accordion}>
76
+ {locales.map((locale) => (
77
+ <AccordionItem border="none" key={locale}>
78
+ <AccordionButton
79
+ {...styles.optionButton}
80
+ onClick={() => onSelect(locale)}
81
+ >
82
+ {/* Display flag icon if one exists */}
83
+ {flags[locale]}
84
+
85
+ {/* Locale name */}
86
+ <Text {...styles.optionText}>
87
+ <LocaleText shortCode={locale} />
88
+ </Text>
89
+
90
+ {/* Selection indicator */}
91
+ {selectedLocale === locale && (
92
+ <CheckIcon {...styles.selectedIcon} />
93
+ )}
94
+ </AccordionButton>
95
+ </AccordionItem>
96
+ ))}
97
+ </Accordion>
98
+ </AccordionPanel>
99
+ </>
100
+ )}
101
+ </AccordionItem>
102
+ </Accordion>
103
+ </Box>
104
+ )
105
+ }
106
+
107
+ LocaleSelector.displayName = 'LocaleSelector'
108
+
109
+ LocaleSelector.propTypes = {
110
+ /**
111
+ * A complete list of all the locales supported. This array must have content.
112
+ */
113
+ locales: PropTypes.arrayOf(PropTypes.string).isRequired,
114
+ /**
115
+ * The current locales shortcode.
116
+ */
117
+ selectedLocale: PropTypes.string.isRequired,
118
+ /**
119
+ * Function called when a locale is selected.
120
+ */
121
+ onSelect: PropTypes.func
122
+ }
123
+
124
+ export default LocaleSelector
@@ -0,0 +1,37 @@
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 {fireEvent} from '@testing-library/react'
9
+ import LocaleSelector from '@salesforce/retail-react-app/app/components/locale-selector/index'
10
+ import {renderWithProviders} from '@salesforce/retail-react-app/app/utils/test-utils'
11
+
12
+ const supportedLocales = ['en-GB', 'fr-FR', 'it-IT', 'zh-CN', 'ja-JP']
13
+
14
+ test('Renders LocaleSelector', () => {
15
+ renderWithProviders(<LocaleSelector selectedLocale="en-GB" locales={supportedLocales} />)
16
+ const accordion = document.querySelector('.chakra-accordion')
17
+ const selectedLocale = document.querySelector('button[aria-expanded="false"]')
18
+
19
+ expect(accordion).toBeInTheDocument()
20
+ expect(selectedLocale).toBeInTheDocument()
21
+ })
22
+
23
+ test('Renders LocaleSelector with event handlers', () => {
24
+ const onSelect = jest.fn()
25
+
26
+ renderWithProviders(
27
+ <LocaleSelector selectedLocale="fr-FR" locales={supportedLocales} onSelect={onSelect} />
28
+ )
29
+
30
+ const firstLocale = document.querySelector(
31
+ '.chakra-accordion .chakra-accordion button.chakra-accordion__button'
32
+ )
33
+
34
+ fireEvent.click(firstLocale)
35
+ expect(onSelect).toHaveBeenCalledTimes(1)
36
+ expect(onSelect).toHaveBeenCalledWith('en-GB')
37
+ })
@@ -0,0 +1,97 @@
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
+ import {defineMessages, useIntl} from 'react-intl'
11
+
12
+ const LocaleText = ({shortCode}) => {
13
+ const intl = useIntl()
14
+ const message = LOCALE_MESSAGES[shortCode]
15
+
16
+ if (!message) {
17
+ console.error(
18
+ `No locale message found for "${shortCode}". Please update the list accordingly.`
19
+ )
20
+ return <>Unknown {shortCode}</>
21
+ }
22
+
23
+ return <>{intl.formatMessage(message)}</>
24
+ }
25
+
26
+ LocaleText.displayName = 'LocaleText'
27
+
28
+ LocaleText.propTypes = {
29
+ /**
30
+ * The locale shortcode that you would like the localized text for.
31
+ */
32
+ shortCode: PropTypes.string.isRequired
33
+ }
34
+
35
+ export default LocaleText
36
+
37
+ /**
38
+ * Translations for names of the commonly-used locales.
39
+ * `locale` parameter format for OCAPI and Commerce API: <language code>-<country code>
40
+ * https://documentation.b2c.commercecloud.salesforce.com/DOC1/topic/com.demandware.dochelp/OCAPI/current/usage/Localization.html
41
+ */
42
+ // TODO: do we want to localize this?
43
+ const LOCALE_MESSAGES = defineMessages({
44
+ 'ar-SA': {id: 'locale_text.message.ar-SA', defaultMessage: 'Arabic (Saudi Arabia)'},
45
+ 'bn-BD': {id: 'locale_text.message.bn-BD', defaultMessage: 'Bangla (Bangladesh)'},
46
+ 'bn-IN': {id: 'locale_text.message.bn-IN', defaultMessage: 'Bangla (India)'},
47
+ 'cs-CZ': {id: 'locale_text.message.cs-CZ', defaultMessage: 'Czech (Czech Republic)'},
48
+ 'da-DK': {id: 'locale_text.message.da-DK', defaultMessage: 'Danish (Denmark)'},
49
+ 'de-AT': {id: 'locale_text.message.de-AT', defaultMessage: 'German (Austria)'},
50
+ 'de-CH': {id: 'locale_text.message.de-CH', defaultMessage: 'German (Switzerland)'},
51
+ 'de-DE': {id: 'locale_text.message.de-DE', defaultMessage: 'German (Germany)'},
52
+ 'el-GR': {id: 'locale_text.message.el-GR', defaultMessage: 'Greek (Greece)'},
53
+ 'en-AU': {id: 'locale_text.message.en-AU', defaultMessage: 'English (Australia)'},
54
+ 'en-CA': {id: 'locale_text.message.en-CA', defaultMessage: 'English (Canada)'},
55
+ 'en-GB': {id: 'locale_text.message.en-GB', defaultMessage: 'English (United Kingdom)'},
56
+ 'en-IE': {id: 'locale_text.message.en-IE', defaultMessage: 'English (Ireland)'},
57
+ 'en-IN': {id: 'locale_text.message.en-IN', defaultMessage: 'English (India)'},
58
+ 'en-NZ': {id: 'locale_text.message.en-NZ', defaultMessage: 'English (New Zealand)'},
59
+ 'en-US': {id: 'locale_text.message.en-US', defaultMessage: 'English (United States)'},
60
+ 'en-ZA': {id: 'locale_text.message.en-ZA', defaultMessage: 'English (South Africa)'},
61
+ 'es-AR': {id: 'locale_text.message.es-AR', defaultMessage: 'Spanish (Argentina)'},
62
+ 'es-CL': {id: 'locale_text.message.es-CL', defaultMessage: 'Spanish (Chile)'},
63
+ 'es-CO': {id: 'locale_text.message.es-CO', defaultMessage: 'Spanish (Columbia)'},
64
+ 'es-ES': {id: 'locale_text.message.es-ES', defaultMessage: 'Spanish (Spain)'},
65
+ 'es-MX': {id: 'locale_text.message.es-MX', defaultMessage: 'Spanish (Mexico)'},
66
+ 'es-US': {id: 'locale_text.message.es-US', defaultMessage: 'Spanish (United States)'},
67
+ 'fi-FI': {id: 'locale_text.message.fi-FI', defaultMessage: 'Finnish (Finland)'},
68
+ 'fr-BE': {id: 'locale_text.message.fr-BE', defaultMessage: 'French (Belgium)'},
69
+ 'fr-CA': {id: 'locale_text.message.fr-CA', defaultMessage: 'French (Canada)'},
70
+ 'fr-CH': {id: 'locale_text.message.fr-CH', defaultMessage: 'French (Switzerland)'},
71
+ 'fr-FR': {id: 'locale_text.message.fr-FR', defaultMessage: 'French (France)'},
72
+ 'he-IL': {id: 'locale_text.message.he-IL', defaultMessage: 'Hebrew (Israel)'},
73
+ 'hi-IN': {id: 'locale_text.message.hi-IN', defaultMessage: 'Hindi (India)'},
74
+ 'hu-HU': {id: 'locale_text.message.hu-HU', defaultMessage: 'Hungarian (Hungary)'},
75
+ 'id-ID': {id: 'locale_text.message.id-ID', defaultMessage: 'Indonesian (Indonesia)'},
76
+ 'it-CH': {id: 'locale_text.message.it-CH', defaultMessage: 'Italian (Switzerland)'},
77
+ 'it-IT': {id: 'locale_text.message.it-IT', defaultMessage: 'Italian (Italy)'},
78
+ 'ja-JP': {id: 'locale_text.message.ja-JP', defaultMessage: 'Japanese (Japan)'},
79
+ 'ko-KR': {id: 'locale_text.message.ko-KR', defaultMessage: 'Korean (Republic of Korea)'},
80
+ 'nl-BE': {id: 'locale_text.message.nl-BE', defaultMessage: 'Dutch (Belgium)'},
81
+ 'nl-NL': {id: 'locale_text.message.nl-NL', defaultMessage: 'Dutch (The Netherlands)'},
82
+ 'no-NO': {id: 'locale_text.message.no-NO', defaultMessage: 'Norwegian (Norway)'},
83
+ 'pl-PL': {id: 'locale_text.message.pl-PL', defaultMessage: 'Polish (Poland)'},
84
+ 'pt-BR': {id: 'locale_text.message.pt-BR', defaultMessage: 'Portuguese (Brazil)'},
85
+ 'pt-PT': {id: 'locale_text.message.pt-PT', defaultMessage: 'Portuguese (Portugal)'},
86
+ 'ro-RO': {id: 'locale_text.message.ro-RO', defaultMessage: 'Romanian (Romania)'},
87
+ 'ru-RU': {id: 'locale_text.message.ru-RU', defaultMessage: 'Russian (Russian Federation)'},
88
+ 'sk-SK': {id: 'locale_text.message.sk-SK', defaultMessage: 'Slovak (Slovakia)'},
89
+ 'sv-SE': {id: 'locale_text.message.sv-SE', defaultMessage: 'Swedish (Sweden)'},
90
+ 'ta-IN': {id: 'locale_text.message.ta-IN', defaultMessage: 'Tamil (India)'},
91
+ 'ta-LK': {id: 'locale_text.message.ta-LK', defaultMessage: 'Tamil (Sri Lanka)'},
92
+ 'th-TH': {id: 'locale_text.message.th-TH', defaultMessage: 'Thai (Thailand)'},
93
+ 'tr-TR': {id: 'locale_text.message.tr-TR', defaultMessage: 'Turkish (Turkey)'},
94
+ 'zh-CN': {id: 'locale_text.message.zh-CN', defaultMessage: 'Chinese (China)'},
95
+ 'zh-HK': {id: 'locale_text.message.zh-HK', defaultMessage: 'Chinese (Hong Kong)'},
96
+ 'zh-TW': {id: 'locale_text.message.zh-TW', defaultMessage: 'Chinese (Taiwan)'}
97
+ })
@@ -0,0 +1,36 @@
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 LocaleText from '@salesforce/retail-react-app/app/components/locale-text/index'
9
+ import {renderWithProviders} from '@salesforce/retail-react-app/app/utils/test-utils'
10
+
11
+ test('Renders LocaleText', () => {
12
+ renderWithProviders(
13
+ <div>
14
+ <LocaleText shortCode="en-GB" />
15
+ </div>
16
+ )
17
+ const el = document.querySelector('div')
18
+ expect(el.textContent).toBe('English (United Kingdom)')
19
+ })
20
+
21
+ test('Warns on missing shortCode message definition', () => {
22
+ jest.spyOn(console, 'error')
23
+
24
+ renderWithProviders(
25
+ <div>
26
+ <LocaleText shortCode="fa-KE" />
27
+ </div>
28
+ )
29
+
30
+ const el = document.querySelector('div')
31
+
32
+ expect(console.error.mock.calls[0][0]).toContain(
33
+ `No locale message found for "fa-KE". Please update the list accordingly.`
34
+ )
35
+ expect(el.textContent).toBe('Unknown fa-KE')
36
+ })