@faststore/core 4.9.3-dev.2 → 4.10.0-dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-generate.log +3 -3
- package/.turbo/turbo-test.log +139 -133
- package/CHANGELOG.md +6 -0
- package/cms/faststore/components/cms_component__bannernewsletter.jsonc +1 -1
- package/cms/faststore/components/cms_component__newsletter.jsonc +1 -1
- package/index.ts +3 -0
- package/package.json +6 -6
- package/src/components/ui/RichText/RichText.tsx +2 -0
- package/src/components/ui/RichText/RichTextImageNode.ts +163 -0
- package/test/components/ui/RichText/RichText.browser.test.tsx +321 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
|
|
2
|
-
> @faststore/core@4.9.3-dev.
|
|
2
|
+
> @faststore/core@4.9.3-dev.2 generate /home/runner/work/faststore/faststore/packages/core
|
|
3
3
|
> pnpm run gen-types && pnpm run cache-graphql
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
> @faststore/core@4.9.3-dev.
|
|
6
|
+
> @faststore/core@4.9.3-dev.2 gen-types /home/runner/work/faststore/faststore/packages/core
|
|
7
7
|
> node ../cli/bin/run generate-types .
|
|
8
8
|
|
|
9
9
|
[33m[STARTED][39m Parse Configuration
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
[32m[COMPLETED][39m Generate to @generated/
|
|
20
20
|
[32m[COMPLETED][39m Generate outputs
|
|
21
21
|
|
|
22
|
-
> @faststore/core@4.9.3-dev.
|
|
22
|
+
> @faststore/core@4.9.3-dev.2 cache-graphql /home/runner/work/faststore/faststore/packages/core
|
|
23
23
|
> node ../cli/bin/run cache-graphql --config=./discovery.config.default.js --queries=./@generated/persisted-documents.json
|
|
24
24
|
|
|
25
25
|
[Info] - Config file location: /home/runner/work/faststore/faststore/packages/core/discovery.config.default.js
|
package/.turbo/turbo-test.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @faststore/core@4.9.3-dev.
|
|
2
|
+
> @faststore/core@4.9.3-dev.2 test /home/runner/work/faststore/faststore/packages/core
|
|
3
3
|
> vitest run
|
|
4
4
|
|
|
5
5
|
|
|
@@ -7,27 +7,32 @@
|
|
|
7
7
|
|
|
8
8
|
Not implemented: navigation to another Document
|
|
9
9
|
Not implemented: navigation to another Document
|
|
10
|
+
[32m✓[39m [30m[46m browser [49m[39m test/sdk/ui/useScrollRestoration.browser.test.ts [2m([22m[2m43 tests[22m[2m)[22m[33m 1434[2mms[22m[39m
|
|
10
11
|
Browserslist: browsers data (caniuse-lite) is 8 months old. Please run:
|
|
11
12
|
npx update-browserslist-db@latest
|
|
12
13
|
Why you should do it regularly: https://github.com/browserslist/update-db#readme
|
|
13
|
-
[32m✓[39m [30m[46m browser [49m[39m test/
|
|
14
|
-
|
|
15
|
-
[33m[2m✓[22m[39m
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
[33m[2m✓[22m[39m
|
|
19
|
-
[33m[2m✓[22m[39m
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
[33m[2m✓[22m[39m opens the reject confirmation modal with
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
14
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/account/cards/MyAccountListCards.browser.test.tsx [2m([22m[2m16 tests[22m[2m)[22m[33m 2768[2mms[22m[39m
|
|
15
|
+
[33m[2m✓[22m[39m shows the tab bar and renders Personal cards by default [33m 1334[2mms[22m[39m
|
|
16
|
+
[33m[2m✓[22m[39m paginates when there are more than 25 cards [33m 315[2mms[22m[39m
|
|
17
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/account/ContractSwitcher.browser.test.tsx [2m([22m[2m22 tests[22m[2m)[22m[33m 3857[2mms[22m[39m
|
|
18
|
+
[33m[2m✓[22m[39m shows an error state when the list fails to load [33m 966[2mms[22m[39m
|
|
19
|
+
[33m[2m✓[22m[39m requires selecting a contract before Confirm is enabled, then switches (REQ-03) [33m 381[2mms[22m[39m
|
|
20
|
+
[33m[2m✓[22m[39m keeps Confirm disabled when the selected contract is filtered out [33m 377[2mms[22m[39m
|
|
21
|
+
[33m[2m✓[22m[39m honors CMS-provided labels for the header, current session, search, footer, and available count [33m 331[2mms[22m[39m
|
|
22
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/account/orders/BuyingPolicyAlert.browser.test.tsx [2m([22m[2m13 tests[22m[2m)[22m[33m 2749[2mms[22m[39m
|
|
23
|
+
[33m[2m✓[22m[39m opens the reject confirmation modal with the default English copy [33m 884[2mms[22m[39m
|
|
24
|
+
[33m[2m✓[22m[39m opens the reject confirmation modal with CMS-provided labels [33m 430[2mms[22m[39m
|
|
25
|
+
[33m[2m✓[22m[39m shows the default English toast when a policy is rejected [33m 330[2mms[22m[39m
|
|
26
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/CartRecommendationShelf/CartRecommendationShelf.browser.test.tsx [2m([22m[2m13 tests[22m[2m)[22m[33m 352[2mms[22m[39m
|
|
27
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/ui/RichText/RichText.browser.test.tsx [2m([22m[2m8 tests[22m[2m)[22m[33m 383[2mms[22m[39m
|
|
28
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/account/OrganizationDrawer.browser.test.tsx [2m([22m[2m10 tests[22m[2m)[22m[33m 2194[2mms[22m[39m
|
|
29
|
+
[33m[2m✓[22m[39m renders the menu view with contract details and manage footer [33m 1242[2mms[22m[39m
|
|
30
|
+
[33m[2m✓[22m[39m opens the contract switcher and returns to the menu on back [33m 388[2mms[22m[39m
|
|
31
|
+
[33m[2m✓[22m[39m resets to the menu when the drawer closes [33m 314[2mms[22m[39m
|
|
32
|
+
[32m✓[39m [30m[46m browser [49m[39m test/sdk/session/reconcileSessionLocale.browser.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m 21[2mms[22m[39m
|
|
33
|
+
[32m✓[39m [30m[46m browser [49m[39m test/sdk/localization/useBindingSelector.browser.test.tsx [2m([22m[2m9 tests[22m[2m)[22m[32m 72[2mms[22m[39m
|
|
34
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/ui/ProductGallery/GalleryPageHeightLock.browser.test.tsx [2m([22m[2m8 tests[22m[2m)[22m[32m 66[2mms[22m[39m
|
|
35
|
+
[32m✓[39m [30m[46m browser [49m[39m test/sdk/recommendations/useRecommendationShelf.browser.test.tsx [2m([22m[2m12 tests[22m[2m)[22m[32m 162[2mms[22m[39m
|
|
31
36
|
[90mstderr[2m | test/components/RecommendationShelf/RecommendationShelf.browser.test.tsx
|
|
32
37
|
[22m[39mError in optimistic validation: TypeError: Failed to parse URL from /api/graphql?operationName=ValidateCartMutation&operationHash=3c71b0d3fc2bade14df68abfa271858beb361b12
|
|
33
38
|
[90m at node:internal/deps/undici/undici:16416:13[39m
|
|
@@ -57,10 +62,10 @@ Browserslist: browsers data (caniuse-lite) is 8 months old. Please run:
|
|
|
57
62
|
[90mstderr[2m | test/components/RecommendationShelf/RecommendationShelf.browser.test.tsx[2m > [22m[2mRecommendationShelf[2m > [22m[2mrenders nothing when there is an error
|
|
58
63
|
[22m[39mError fetching recommendations [90mundefined[39m boom for campaign vrn:recommendations:acc:rec-top-items-v2:campaign-1
|
|
59
64
|
|
|
60
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/RecommendationShelf/RecommendationShelf.browser.test.tsx [2m([22m[2m8 tests[22m[2m)[22m[32m
|
|
61
|
-
[32m✓[39m [30m[46m browser [49m[39m test/
|
|
62
|
-
[32m✓[39m [30m[46m browser [49m[39m test/
|
|
63
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/sections/Account/AccountOrderDetails.browser.test.tsx [2m([22m[2m4 tests[22m[2m)[22m[32m
|
|
65
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/RecommendationShelf/RecommendationShelf.browser.test.tsx [2m([22m[2m8 tests[22m[2m)[22m[32m 86[2mms[22m[39m
|
|
66
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/CartSidebar/CartSidebar.browser.test.tsx [2m([22m[2m5 tests[22m[2m)[22m[32m 76[2mms[22m[39m
|
|
67
|
+
[32m✓[39m [30m[46m browser [49m[39m test/sdk/session/getInitialSession.browser.test.ts [2m([22m[2m7 tests[22m[2m)[22m[32m 19[2mms[22m[39m
|
|
68
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/sections/Account/AccountOrderDetails.browser.test.tsx [2m([22m[2m4 tests[22m[2m)[22m[32m 145[2mms[22m[39m
|
|
64
69
|
[90mstderr[2m | test/pages/password-protection.browser.test.tsx[2m > [22m[2mPasswordProtectionLogin[2m > [22m[2mposts the password and redirects to the requested return path
|
|
65
70
|
[22m[39mWarning: An update to PasswordProtectionLogin inside a test was not wrapped in act(...).
|
|
66
71
|
|
|
@@ -146,8 +151,6 @@ act(() => {
|
|
|
146
151
|
This ensures that you're testing the behavior the user would see in the browser. Learn more at https://reactjs.org/link/wrap-tests-with-act
|
|
147
152
|
at PasswordProtectionLogin (/home/runner/work/faststore/faststore/packages/core/src/pages/password-protection/index.tsx:19:69)
|
|
148
153
|
|
|
149
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/navigation/Navbar.browser.test.tsx [2m([22m[2m3 tests[22m[2m)[22m[32m 100[2mms[22m[39m
|
|
150
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/account/OrganizationDrawerFooter.browser.test.tsx [2m([22m[2m8 tests[22m[2m)[22m[33m 508[2mms[22m[39m
|
|
151
154
|
[90mstderr[2m | test/pages/password-protection.browser.test.tsx[2m > [22m[2mPasswordProtectionLogin[2m > [22m[2muses the fallback invalid-password message when API omits an error
|
|
152
155
|
[22m[39mWarning: An update to PasswordProtectionLogin inside a test was not wrapped in act(...).
|
|
153
156
|
|
|
@@ -292,8 +295,11 @@ act(() => {
|
|
|
292
295
|
This ensures that you're testing the behavior the user would see in the browser. Learn more at https://reactjs.org/link/wrap-tests-with-act
|
|
293
296
|
at PasswordProtectionLogin (/home/runner/work/faststore/faststore/packages/core/src/pages/password-protection/index.tsx:19:69)
|
|
294
297
|
|
|
295
|
-
[32m✓[39m [30m[46m browser [49m[39m test/pages/password-protection.browser.test.tsx [2m([22m[2m6 tests[22m[2m)[22m[33m
|
|
296
|
-
[33m[2m✓[22m[39m renders the password protection form [33m
|
|
298
|
+
[32m✓[39m [30m[46m browser [49m[39m test/pages/password-protection.browser.test.tsx [2m([22m[2m6 tests[22m[2m)[22m[33m 932[2mms[22m[39m
|
|
299
|
+
[33m[2m✓[22m[39m renders the password protection form [33m 488[2mms[22m[39m
|
|
300
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/navigation/Navbar.browser.test.tsx [2m([22m[2m3 tests[22m[2m)[22m[32m 70[2mms[22m[39m
|
|
301
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/account/OrganizationDrawerFooter.browser.test.tsx [2m([22m[2m8 tests[22m[2m)[22m[33m 488[2mms[22m[39m
|
|
302
|
+
[32m✓[39m [30m[46m browser [49m[39m test/sdk/account/useSwitchContract.browser.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m 45[2mms[22m[39m
|
|
297
303
|
[90mstderr[2m | test/components/cms/RenderSections.browser.test.tsx
|
|
298
304
|
[22m[39mError in optimistic validation: TypeError: Cannot read properties of undefined (reading 'read')
|
|
299
305
|
at waitForSessionValidated [90m(/home/runner/work/faststore/faststore/packages/core/[39msrc/sdk/cart/waitForSessionValidated.ts:16:32[90m)[39m
|
|
@@ -302,9 +308,9 @@ This ensures that you're testing the behavior the user would see in the browser.
|
|
|
302
308
|
at a (/home/runner/work/faststore/faststore/packages/sdk/dist/es/index.mjs:357:23)
|
|
303
309
|
[90m at processTicksAndRejections (node:internal/process/task_queues:103:5)[39m
|
|
304
310
|
|
|
305
|
-
[32m✓[39m [30m[46m browser [49m[39m test/
|
|
306
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/
|
|
307
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/
|
|
311
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/navigation/NavbarSlider.browser.test.tsx [2m([22m[2m2 tests[22m[2m)[22m[32m 31[2mms[22m[39m
|
|
312
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/cms/RenderSections.browser.test.tsx [2m([22m[2m5 tests[22m[2m)[22m[32m 81[2mms[22m[39m
|
|
313
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/account/Menu.browser.test.tsx [2m([22m[2m6 tests[22m[2m)[22m[33m 338[2mms[22m[39m
|
|
308
314
|
[90mstderr[2m | test/sdk/localization/store-url.browser.test.ts
|
|
309
315
|
[22m[39mError in optimistic validation: TypeError: Cannot read properties of undefined (reading 'read')
|
|
310
316
|
at waitForSessionValidated [90m(/home/runner/work/faststore/faststore/packages/core/[39msrc/sdk/cart/waitForSessionValidated.ts:16:32[90m)[39m
|
|
@@ -313,15 +319,14 @@ This ensures that you're testing the behavior the user would see in the browser.
|
|
|
313
319
|
at a (/home/runner/work/faststore/faststore/packages/sdk/dist/es/index.mjs:357:23)
|
|
314
320
|
[90m at processTicksAndRejections (node:internal/process/task_queues:103:5)[39m
|
|
315
321
|
|
|
316
|
-
[32m✓[39m [30m[46m browser [49m[39m test/sdk/localization/store-url.browser.test.ts [2m([22m[2m3 tests[22m[2m)[22m[32m
|
|
317
|
-
[32m✓[39m [30m[46m browser [49m[39m test/
|
|
318
|
-
[32m✓[39m [30m[46m browser [49m[39m test/
|
|
319
|
-
[32m✓[39m [30m[46m browser [49m[39m test/
|
|
320
|
-
[32m✓[39m [30m[46m browser [49m[39m test/
|
|
321
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/
|
|
322
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/
|
|
323
|
-
[32m✓[39m [30m[46m browser [49m[39m test/sdk/account/changeContractToken.browser.test.ts [2m([22m[2m9 tests[22m[2m)[22m[32m
|
|
324
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/CartRecommendationShelf/CartRecommendationProductCard.browser.test.tsx [2m([22m[2m3 tests[22m[2m)[22m[32m 54[2mms[22m[39m
|
|
322
|
+
[32m✓[39m [30m[46m browser [49m[39m test/sdk/localization/store-url.browser.test.ts [2m([22m[2m3 tests[22m[2m)[22m[32m 4[2mms[22m[39m
|
|
323
|
+
[32m✓[39m [30m[46m browser [49m[39m test/sdk/account/useAvailableContracts.browser.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m 37[2mms[22m[39m
|
|
324
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/templates/SearchPage/SearchWrapper.browser.test.tsx [2m([22m[2m3 tests[22m[2m)[22m[32m 36[2mms[22m[39m
|
|
325
|
+
[32m✓[39m [30m[46m browser [49m[39m test/sdk/recommendations/useRecommendationShelf.sessionFallback.browser.test.tsx [2m([22m[2m2 tests[22m[2m)[22m[32m 83[2mms[22m[39m
|
|
326
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/sections/Account/AccountListQuotes.browser.test.tsx [2m([22m[2m4 tests[22m[2m)[22m[32m 126[2mms[22m[39m
|
|
327
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/navigation/NavbarAccountArea.browser.test.tsx [2m([22m[2m4 tests[22m[2m)[22m[32m 72[2mms[22m[39m
|
|
328
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/CartRecommendationShelf/CartRecommendationProductCard.browser.test.tsx [2m([22m[2m3 tests[22m[2m)[22m[32m 73[2mms[22m[39m
|
|
329
|
+
[32m✓[39m [30m[46m browser [49m[39m test/sdk/account/changeContractToken.browser.test.ts [2m([22m[2m9 tests[22m[2m)[22m[32m 19[2mms[22m[39m
|
|
325
330
|
[90mstderr[2m | test/components/account/doLogout.browser.test.ts
|
|
326
331
|
[22m[39mError in optimistic validation: TypeError: Cannot read properties of undefined (reading 'read')
|
|
327
332
|
at waitForSessionValidated [90m(/home/runner/work/faststore/faststore/packages/core/[39msrc/sdk/cart/waitForSessionValidated.ts:16:32[90m)[39m
|
|
@@ -330,9 +335,9 @@ This ensures that you're testing the behavior the user would see in the browser.
|
|
|
330
335
|
at a (/home/runner/work/faststore/faststore/packages/sdk/dist/es/index.mjs:357:23)
|
|
331
336
|
[90m at processTicksAndRejections (node:internal/process/task_queues:103:5)[39m
|
|
332
337
|
|
|
333
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/account/doLogout.browser.test.ts [2m([22m[2m1 test[22m[2m)[22m[32m
|
|
334
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/ui/LocalizationButton.browser.test.tsx [2m([22m[2m3 tests[22m[2m)[22m[32m
|
|
335
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/account/OrganizationDrawerHeader.browser.test.tsx [2m([22m[2m5 tests[22m[2m)[22m[33m
|
|
338
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/account/doLogout.browser.test.ts [2m([22m[2m1 test[22m[2m)[22m[32m 25[2mms[22m[39m
|
|
339
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/ui/LocalizationButton.browser.test.tsx [2m([22m[2m3 tests[22m[2m)[22m[32m 56[2mms[22m[39m
|
|
340
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/account/OrganizationDrawerHeader.browser.test.tsx [2m([22m[2m5 tests[22m[2m)[22m[33m 378[2mms[22m[39m
|
|
336
341
|
[90mstderr[2m | test/sdk/account/clearPersistedSessionState.browser.test.ts
|
|
337
342
|
[22m[39mError in optimistic validation: TypeError: Cannot read properties of undefined (reading 'read')
|
|
338
343
|
at waitForSessionValidated [90m(/home/runner/work/faststore/faststore/packages/core/[39msrc/sdk/cart/waitForSessionValidated.ts:16:32[90m)[39m
|
|
@@ -341,14 +346,15 @@ This ensures that you're testing the behavior the user would see in the browser.
|
|
|
341
346
|
at a (/home/runner/work/faststore/faststore/packages/sdk/dist/es/index.mjs:357:23)
|
|
342
347
|
[90m at processTicksAndRejections (node:internal/process/task_queues:103:5)[39m
|
|
343
348
|
|
|
344
|
-
[32m✓[39m [30m[46m browser [49m[39m test/sdk/account/clearPersistedSessionState.browser.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m
|
|
345
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/
|
|
346
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/
|
|
347
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/sections/Account/AccountOrderStatus.browser.test.tsx [2m([22m[2m3 tests[22m[2m)[22m[32m
|
|
348
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/region/useRegion.browser.test.ts [2m([22m[2m1 test[22m[2m)[22m[32m
|
|
349
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/sections/Account/AccountListCards.browser.test.tsx [2m([22m[2m3 tests[22m[2m)[22m[32m
|
|
350
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/sections/Account/AccountOrdersList.browser.test.tsx [2m([22m[2m2 tests[22m[2m)[22m[32m
|
|
351
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/account/orders/SummaryCard.browser.test.tsx [2m([22m[2m2 tests[22m[2m)[22m[32m
|
|
349
|
+
[32m✓[39m [30m[46m browser [49m[39m test/sdk/account/clearPersistedSessionState.browser.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m 13[2mms[22m[39m
|
|
350
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/account/orders/DeliveryOptionAccordion.browser.test.tsx [2m([22m[2m2 tests[22m[2m)[22m[32m 90[2mms[22m[39m
|
|
351
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/sections/Account/AccountOrderDelivery.browser.test.tsx [2m([22m[2m2 tests[22m[2m)[22m[32m 87[2mms[22m[39m
|
|
352
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/sections/Account/AccountOrderStatus.browser.test.tsx [2m([22m[2m3 tests[22m[2m)[22m[32m 96[2mms[22m[39m
|
|
353
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/region/useRegion.browser.test.ts [2m([22m[2m1 test[22m[2m)[22m[32m 23[2mms[22m[39m
|
|
354
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/sections/Account/AccountListCards.browser.test.tsx [2m([22m[2m3 tests[22m[2m)[22m[32m 72[2mms[22m[39m
|
|
355
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/sections/Account/AccountOrdersList.browser.test.tsx [2m([22m[2m2 tests[22m[2m)[22m[32m 29[2mms[22m[39m
|
|
356
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/account/orders/SummaryCard.browser.test.tsx [2m([22m[2m2 tests[22m[2m)[22m[32m 89[2mms[22m[39m
|
|
357
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/account/OrganizationSignInButton.browser.test.tsx [2m([22m[2m2 tests[22m[2m)[22m[32m 242[2mms[22m[39m
|
|
352
358
|
[90mstderr[2m | test/sdk/session/sessionStore.browser.test.ts
|
|
353
359
|
[22m[39mError in optimistic validation: TypeError: Cannot read properties of undefined (reading 'read')
|
|
354
360
|
at waitForSessionValidated [90m(/home/runner/work/faststore/faststore/packages/core/[39msrc/sdk/cart/waitForSessionValidated.ts:16:32[90m)[39m
|
|
@@ -357,9 +363,7 @@ This ensures that you're testing the behavior the user would see in the browser.
|
|
|
357
363
|
at a (/home/runner/work/faststore/faststore/packages/sdk/dist/es/index.mjs:357:23)
|
|
358
364
|
[90m at processTicksAndRejections (node:internal/process/task_queues:103:5)[39m
|
|
359
365
|
|
|
360
|
-
[32m✓[39m [30m[46m browser [49m[39m test/sdk/session/sessionStore.browser.test.ts [2m([22m[2m2 tests[22m[2m)[22m[32m
|
|
361
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/account/OrganizationSignInButton.browser.test.tsx [2m([22m[2m2 tests[22m[2m)[22m[32m 270[2mms[22m[39m
|
|
362
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/account/orders/DeliveryOptionAccordionDeliveryInfo.browser.test.tsx [2m([22m[2m1 test[22m[2m)[22m[32m 31[2mms[22m[39m
|
|
366
|
+
[32m✓[39m [30m[46m browser [49m[39m test/sdk/session/sessionStore.browser.test.ts [2m([22m[2m2 tests[22m[2m)[22m[32m 7[2mms[22m[39m
|
|
363
367
|
[90mstderr[2m | test/sdk/session/validateSession.browser.test.ts
|
|
364
368
|
[22m[39mError in optimistic validation: TypeError: Cannot read properties of undefined (reading 'read')
|
|
365
369
|
at waitForSessionValidated [90m(/home/runner/work/faststore/faststore/packages/core/[39msrc/sdk/cart/waitForSessionValidated.ts:16:32[90m)[39m
|
|
@@ -368,14 +372,15 @@ This ensures that you're testing the behavior the user would see in the browser.
|
|
|
368
372
|
at a (/home/runner/work/faststore/faststore/packages/sdk/dist/es/index.mjs:357:23)
|
|
369
373
|
[90m at processTicksAndRejections (node:internal/process/task_queues:103:5)[39m
|
|
370
374
|
|
|
371
|
-
[32m✓[39m [30m[46m browser [49m[39m test/
|
|
372
|
-
[32m✓[39m [30m[46m browser [49m[39m test/
|
|
373
|
-
[32m✓[39m [30m[46m browser [49m[39m test/
|
|
374
|
-
[32m✓[39m [30m[46m browser [49m[39m test/
|
|
375
|
-
[32m✓[39m [30m[46m browser [49m[39m test/
|
|
376
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/account/orders/
|
|
377
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/
|
|
378
|
-
[32m✓[39m [30m[
|
|
375
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/account/orders/DeliveryOptionAccordionDeliveryInfo.browser.test.tsx [2m([22m[2m1 test[22m[2m)[22m[32m 62[2mms[22m[39m
|
|
376
|
+
[32m✓[39m [30m[46m browser [49m[39m test/sdk/session/validateSession.browser.test.ts [2m([22m[2m1 test[22m[2m)[22m[32m 6[2mms[22m[39m
|
|
377
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/account/orders/StatusCard.browser.test.tsx [2m([22m[2m2 tests[22m[2m)[22m[32m 106[2mms[22m[39m
|
|
378
|
+
[32m✓[39m [30m[46m browser [49m[39m test/utils/isLocalHost.browser.test.ts [2m([22m[2m3 tests[22m[2m)[22m[32m 5[2mms[22m[39m
|
|
379
|
+
[32m✓[39m [30m[46m browser [49m[39m test/sdk/session/reconcileSessionLocale.disabled.browser.test.ts [2m([22m[2m1 test[22m[2m)[22m[32m 4[2mms[22m[39m
|
|
380
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/account/orders/DeliveryCard.browser.test.tsx [2m([22m[2m1 test[22m[2m)[22m[32m 42[2mms[22m[39m
|
|
381
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/account/orders/DeliveryOptionAccordionProducts.browser.test.tsx [2m([22m[2m1 test[22m[2m)[22m[32m 50[2mms[22m[39m
|
|
382
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/skeletons/ProductGridSkeleton.browser.test.tsx [2m([22m[2m2 tests[22m[2m)[22m[32m 43[2mms[22m[39m
|
|
383
|
+
[32m✓[39m [30m[43m node [49m[39m test/utils/localization/bindingPaths.test.ts [2m([22m[2m71 tests[22m[2m)[22m[32m 32[2mms[22m[39m
|
|
379
384
|
[90mstderr[2m | test/sdk/account/refreshToken.browser.test.ts
|
|
380
385
|
[22m[39mError in optimistic validation: TypeError: Cannot read properties of undefined (reading 'read')
|
|
381
386
|
at waitForSessionValidated [90m(/home/runner/work/faststore/faststore/packages/core/[39msrc/sdk/cart/waitForSessionValidated.ts:16:32[90m)[39m
|
|
@@ -384,14 +389,14 @@ This ensures that you're testing the behavior the user would see in the browser.
|
|
|
384
389
|
at a (/home/runner/work/faststore/faststore/packages/sdk/dist/es/index.mjs:357:23)
|
|
385
390
|
[90m at processTicksAndRejections (node:internal/process/task_queues:103:5)[39m
|
|
386
391
|
|
|
387
|
-
[32m✓[39m [30m[46m browser [49m[39m test/sdk/account/refreshToken.browser.test.ts [2m([22m[2m1 test[22m[2m)[22m[32m
|
|
388
|
-
[32m✓[39m [30m[43m node [49m[39m test/server/password-protection-service.test.ts [2m([22m[2m22 tests[22m[2m)[22m[32m
|
|
389
|
-
[32m✓[39m [30m[43m node [49m[39m test/pages/api/switch-contract.test.ts [2m([22m[2m25 tests[22m[2m)[22m[32m
|
|
390
|
-
[32m✓[39m [30m[
|
|
391
|
-
[32m✓[39m [30m[
|
|
392
|
+
[32m✓[39m [30m[46m browser [49m[39m test/sdk/account/refreshToken.browser.test.ts [2m([22m[2m1 test[22m[2m)[22m[32m 5[2mms[22m[39m
|
|
393
|
+
[32m✓[39m [30m[43m node [49m[39m test/server/password-protection-service.test.ts [2m([22m[2m22 tests[22m[2m)[22m[32m 36[2mms[22m[39m
|
|
394
|
+
[32m✓[39m [30m[43m node [49m[39m test/pages/api/switch-contract.test.ts [2m([22m[2m25 tests[22m[2m)[22m[32m 80[2mms[22m[39m
|
|
395
|
+
[32m✓[39m [30m[43m node [49m[39m test/utils/match-url.test.ts [2m([22m[2m10 tests[22m[2m)[22m[32m 12[2mms[22m[39m
|
|
396
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/account/orders/FilterFacetPendingApproval.browser.test.tsx [2m([22m[2m1 test[22m[2m)[22m[32m 224[2mms[22m[39m
|
|
392
397
|
[32m✓[39m [30m[43m node [49m[39m test/sdk/localization/useBindingSelector.test.tsx [2m([22m[2m22 tests[22m[2m)[22m[32m 15[2mms[22m[39m
|
|
393
|
-
[32m✓[39m [30m[43m node [49m[39m test/pages/api/unlock.test.ts [2m([22m[2m15 tests[22m[2m)[22m[32m
|
|
394
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/session/syncSalesChannelFromOrderForm.test.ts [2m([22m[2m14 tests[22m[2m)[22m[32m
|
|
398
|
+
[32m✓[39m [30m[43m node [49m[39m test/pages/api/unlock.test.ts [2m([22m[2m15 tests[22m[2m)[22m[32m 125[2mms[22m[39m
|
|
399
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/session/syncSalesChannelFromOrderForm.test.ts [2m([22m[2m14 tests[22m[2m)[22m[32m 16[2mms[22m[39m
|
|
395
400
|
[90mstderr[2m | test/components/search/SearchInputComponent.test.tsx
|
|
396
401
|
[22m[39mWarning: forwardRef render functions accept exactly two parameters: props and ref. Did you forget to use the ref parameter?
|
|
397
402
|
|
|
@@ -455,24 +460,23 @@ Warning: React does not recognize the `providerProps` prop on a DOM element. If
|
|
|
455
460
|
at Suspense
|
|
456
461
|
at Wrapper (/home/runner/work/faststore/faststore/packages/core/test/components/search/SearchInputComponent.test.tsx:106:20)
|
|
457
462
|
|
|
458
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
459
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
460
|
-
[32m✓[39m [30m[43m node [49m[39m test/components/quotes/MyAccountListQuotesTable.test.tsx [2m([22m[2m15 tests[22m[2m)[22m[33m
|
|
461
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/search/useSearchHistory.test.ts [2m([22m[2m13 tests[22m[2m)[22m[32m
|
|
463
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/search/SearchInputComponent.test.tsx [2m([22m[2m6 tests[22m[2m)[22m[32m 86[2mms[22m[39m
|
|
464
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/localization/bindingSelector.test.ts [2m([22m[2m18 tests[22m[2m)[22m[32m 11[2mms[22m[39m
|
|
465
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/quotes/MyAccountListQuotesTable.test.tsx [2m([22m[2m15 tests[22m[2m)[22m[33m 440[2mms[22m[39m
|
|
466
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/search/useSearchHistory.test.ts [2m([22m[2m13 tests[22m[2m)[22m[32m 43[2mms[22m[39m
|
|
467
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/quotes/MyAccountListQuotes.test.tsx [2m([22m[2m11 tests[22m[2m)[22m[33m 834[2mms[22m[39m
|
|
468
|
+
[33m[2m✓[22m[39m navigates with the search term on blur [33m 361[2mms[22m[39m
|
|
469
|
+
[33m[2m✓[22m[39m navigates without a label param when the search is cleared [33m 365[2mms[22m[39m
|
|
462
470
|
[90mstderr[2m | test/pages/pvt/account/cards/index.test.ts[2m > [22m[2mCards page getServerSideProps[2m > [22m[2mredirects to /pvt/account/403 when the query fails with 401/403
|
|
463
471
|
[22m[39m{ extensions: { status: [33m401[39m } }
|
|
464
472
|
|
|
465
473
|
[90mstderr[2m | test/pages/pvt/account/cards/index.test.ts[2m > [22m[2mCards page getServerSideProps[2m > [22m[2mrenders the error state (no redirect) when the query fails with a non-auth status
|
|
466
474
|
[22m[39m{ extensions: { status: [33m502[39m } }
|
|
467
475
|
|
|
468
|
-
[32m✓[39m [30m[43m node [49m[39m test/pages/pvt/account/cards/index.test.ts [2m([22m[2m8 tests[22m[2m)[22m[32m
|
|
469
|
-
[32m✓[39m [30m[43m node [49m[39m test/components/quotes/
|
|
470
|
-
|
|
471
|
-
[33m[2m✓[22m[39m navigates without a label param when the search is cleared [33m 360[2mms[22m[39m
|
|
472
|
-
[32m✓[39m [30m[43m node [49m[39m test/components/quotes/quoteFilters.test.ts [2m([22m[2m26 tests[22m[2m)[22m[32m 29[2mms[22m[39m
|
|
476
|
+
[32m✓[39m [30m[43m node [49m[39m test/pages/pvt/account/cards/index.test.ts [2m([22m[2m8 tests[22m[2m)[22m[32m 12[2mms[22m[39m
|
|
477
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/quotes/quoteFilters.test.ts [2m([22m[2m26 tests[22m[2m)[22m[32m 38[2mms[22m[39m
|
|
478
|
+
[32m✓[39m [30m[43m node [49m[39m test/utils/cookieCacheBusting.test.ts [2m([22m[2m10 tests[22m[2m)[22m[32m 15[2mms[22m[39m
|
|
473
479
|
[32m✓[39m [30m[43m node [49m[39m test/utils/productJsonLd.test.ts [2m([22m[2m36 tests[22m[2m)[22m[32m 14[2mms[22m[39m
|
|
474
|
-
[32m✓[39m [30m[43m node [49m[39m test/utils/cookieCacheBusting.test.ts [2m([22m[2m10 tests[22m[2m)[22m[32m 17[2mms[22m[39m
|
|
475
|
-
[32m✓[39m [30m[43m node [49m[39m test/experimental/myAccountCmsServerSideProps.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m 22[2mms[22m[39m
|
|
476
480
|
[90mstderr[2m | test/pages/api/graphql.test.ts[2m > [22m[2m/api/graphql error status propagation[2m > [22m[2mpropagates the upstream 400 from a wrapped BadRequestError instead of 500
|
|
477
481
|
[22m[39mGraphql execution returned with error: [
|
|
478
482
|
{
|
|
@@ -582,73 +586,75 @@ Warning: React does not recognize the `providerProps` prop on a DOM element. If
|
|
|
582
586
|
at trace (file:///home/runner/work/faststore/faststore/node_modules/[4m.pnpm[24m/vitest@4.0.18_@opentelemetry+api@1.9.0_@types+node@20.19.13_jiti@2.6.1_jsdom@27.4.0_sas_13be941c57d55f08f06eeaf1c180ddfe/node_modules/[4mvitest[24m/dist/chunks/test.B8ej_ZHS.js:239:21)
|
|
583
587
|
at runTest (file:///home/runner/work/faststore/faststore/node_modules/[4m.pnpm[24m/@vitest+runner@4.0.18/node_modules/[4m@vitest/runner[24m/dist/index.js:1653:12)
|
|
584
588
|
|
|
585
|
-
[32m✓[39m [30m[43m node [49m[39m test/pages/api/graphql.test.ts [2m([22m[2m19 tests[22m[2m)[22m[32m
|
|
586
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
587
|
-
[32m✓[39m [30m[43m node [49m[39m test/utils/
|
|
589
|
+
[32m✓[39m [30m[43m node [49m[39m test/pages/api/graphql.test.ts [2m([22m[2m19 tests[22m[2m)[22m[32m 33[2mms[22m[39m
|
|
590
|
+
[32m✓[39m [30m[43m node [49m[39m test/experimental/myAccountCmsServerSideProps.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m 9[2mms[22m[39m
|
|
591
|
+
[32m✓[39m [30m[43m node [49m[39m test/utils/clearCookies.test.ts [2m([22m[2m20 tests[22m[2m)[22m[32m 20[2mms[22m[39m
|
|
592
|
+
[32m✓[39m [30m[43m node [49m[39m test/utils/multipleTemplates.test.ts [2m([22m[2m8 tests[22m[2m)[22m[32m 7[2mms[22m[39m
|
|
588
593
|
[90mstderr[2m | test/sdk/account/useSetPassword.test.ts[2m > [22m[2museSetPassword[2m > [22m[2mmaps wrongcredentials error responses to the existing message
|
|
589
594
|
[22m[39mSet password request failed: Bad Request
|
|
590
595
|
|
|
591
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/account/useSetPassword.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m
|
|
592
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/orderEntry/useOrderEntryOperation.test.ts [2m([22m[2m8 tests[22m[2m)[22m[32m
|
|
596
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/account/useSetPassword.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m 32[2mms[22m[39m
|
|
597
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/orderEntry/useOrderEntryOperation.test.ts [2m([22m[2m8 tests[22m[2m)[22m[32m 51[2mms[22m[39m
|
|
593
598
|
[32m✓[39m [30m[43m node [49m[39m test/utils/localization/localizeRedirectDestination.test.ts [2m([22m[2m11 tests[22m[2m)[22m[32m 7[2mms[22m[39m
|
|
594
|
-
[32m✓[39m [30m[43m node [49m[39m test/components/quotes/MyAccountQuotesFilterSlider.test.tsx [2m([22m[2m8 tests[22m[2m)[22m[32m
|
|
595
|
-
[32m✓[39m [30m[43m node [49m[39m test/components/quotes/MyAccountQuotesStatusSelector.test.tsx [2m([22m[2m14 tests[22m[2m)[22m[32m 190[2mms[22m[39m
|
|
599
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/quotes/MyAccountQuotesFilterSlider.test.tsx [2m([22m[2m8 tests[22m[2m)[22m[32m 160[2mms[22m[39m
|
|
596
600
|
[32m✓[39m [30m[43m node [49m[39m test/utils/localization/hreflang.test.ts [2m([22m[2m8 tests[22m[2m)[22m[32m 7[2mms[22m[39m
|
|
597
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
598
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
599
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
600
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/
|
|
601
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
602
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
601
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/quotes/MyAccountQuotesStatusSelector.test.tsx [2m([22m[2m14 tests[22m[2m)[22m[32m 209[2mms[22m[39m
|
|
602
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/account/getMyAccountRoutes.test.ts [2m([22m[2m13 tests[22m[2m)[22m[32m 9[2mms[22m[39m
|
|
603
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/quotes/MyAccountQuotesSelectedTags.test.tsx [2m([22m[2m10 tests[22m[2m)[22m[32m 106[2mms[22m[39m
|
|
604
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/redirects/index.test.ts [2m([22m[2m7 tests[22m[2m)[22m[32m 38[2mms[22m[39m
|
|
605
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/orderEntry/useOrderEntryUpload.test.ts [2m([22m[2m8 tests[22m[2m)[22m[32m 53[2mms[22m[39m
|
|
606
|
+
[32m✓[39m [30m[43m node [49m[39m test/proxy.localization.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m 45[2mms[22m[39m
|
|
607
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/orderEntry/useOrderEntry.test.ts [2m([22m[2m8 tests[22m[2m)[22m[32m 50[2mms[22m[39m
|
|
608
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/graphql/retryPolicy.test.ts [2m([22m[2m18 tests[22m[2m)[22m[32m 21[2mms[22m[39m
|
|
603
609
|
[32m✓[39m [30m[43m node [49m[39m test/components/account/orders/getDeliveryOptionLabel.test.ts [2m([22m[2m21 tests[22m[2m)[22m[32m 7[2mms[22m[39m
|
|
604
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/graphql/retryPolicy.test.ts [2m([22m[2m18 tests[22m[2m)[22m[32m 23[2mms[22m[39m
|
|
605
610
|
[32m✓[39m [30m[43m node [49m[39m test/server/cms/myAccountDefaultSections.test.ts [2m([22m[2m9 tests[22m[2m)[22m[32m 8[2mms[22m[39m
|
|
606
|
-
[32m✓[39m [30m[43m node [49m[39m test/utils/productJsonLdRendering.test.tsx [2m([22m[2m5 tests[22m[2m)[22m[32m
|
|
607
|
-
[32m✓[39m [30m[43m node [49m[39m test/utils/trustedForwardedHost.test.ts [2m([22m[2m27 tests[22m[2m)[22m[32m
|
|
608
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
609
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
610
|
-
|
|
611
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/
|
|
612
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
613
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
614
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
615
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/
|
|
616
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/
|
|
611
|
+
[32m✓[39m [30m[43m node [49m[39m test/utils/productJsonLdRendering.test.tsx [2m([22m[2m5 tests[22m[2m)[22m[32m 14[2mms[22m[39m
|
|
612
|
+
[32m✓[39m [30m[43m node [49m[39m test/utils/trustedForwardedHost.test.ts [2m([22m[2m27 tests[22m[2m)[22m[32m 6[2mms[22m[39m
|
|
613
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/analytics/useStartRecommendationSession.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m 37[2mms[22m[39m
|
|
614
|
+
[32m✓[39m [30m[43m node [49m[39m test/server/index.test.ts [2m([22m[2m7 tests[22m[2m)[22m[33m 1350[2mms[22m[39m
|
|
615
|
+
[33m[2m✓[22m[39m should handle options and execute [33m 765[2mms[22m[39m
|
|
616
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/orderEntry/useOrderFormItems.test.ts [2m([22m[2m7 tests[22m[2m)[22m[32m 50[2mms[22m[39m
|
|
617
|
+
[32m✓[39m [30m[43m node [49m[39m test/server/webops-api.test.ts [2m([22m[2m9 tests[22m[2m)[22m[32m 35[2mms[22m[39m
|
|
618
|
+
[32m✓[39m [30m[43m node [49m[39m test/proxy.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m 19[2mms[22m[39m
|
|
619
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/account/orders/StatusCard.test.ts [2m([22m[2m3 tests[22m[2m)[22m[32m 30[2mms[22m[39m
|
|
620
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/localization/store-url.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m 7[2mms[22m[39m
|
|
621
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/cart/waitForSessionValidated.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m 16[2mms[22m[39m
|
|
617
622
|
[32m✓[39m [30m[43m node [49m[39m test/server/content/service.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m 4[2mms[22m[39m
|
|
623
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/account/refreshToken.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m 7[2mms[22m[39m
|
|
618
624
|
[32m✓[39m [30m[43m node [49m[39m test/server/cms/global.test.ts [2m([22m[2m3 tests[22m[2m)[22m[32m 6[2mms[22m[39m
|
|
619
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/auth/useAuth.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m
|
|
620
|
-
[32m✓[39m [30m[43m node [49m[39m test/utils/getRequestHostname.test.ts [2m([22m[2m12 tests[22m[2m)[22m[32m
|
|
621
|
-
[32m✓[39m [30m[43m node [49m[39m test/components/account/Layout.test.tsx [2m([22m[2m6 tests[22m[2m)[22m[32m
|
|
622
|
-
[32m✓[39m [30m[43m node [49m[39m test/server/rootSpan.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m
|
|
625
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/auth/useAuth.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m 29[2mms[22m[39m
|
|
626
|
+
[32m✓[39m [30m[43m node [49m[39m test/utils/getRequestHostname.test.ts [2m([22m[2m12 tests[22m[2m)[22m[32m 7[2mms[22m[39m
|
|
627
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/account/Layout.test.tsx [2m([22m[2m6 tests[22m[2m)[22m[32m 87[2mms[22m[39m
|
|
628
|
+
[32m✓[39m [30m[43m node [49m[39m test/server/rootSpan.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m 45[2mms[22m[39m
|
|
623
629
|
[32m✓[39m [30m[43m node [49m[39m test/pages/api/preview.test.ts [2m([22m[2m2 tests[22m[2m)[22m[32m 9[2mms[22m[39m
|
|
624
|
-
[32m✓[39m [30m[43m node [49m[39m test/components/search/SearchInput.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m
|
|
625
|
-
[32m✓[39m [30m[43m node [49m[39m test/utils/validateSessionRefreshToken.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m
|
|
626
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/recommendations/vrn.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m
|
|
627
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
628
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
629
|
-
[32m✓[39m [30m[43m node [49m[39m test/utils/retry.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m
|
|
630
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/account/getB2BSessionClaims.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m
|
|
631
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
632
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
633
|
-
[32m✓[39m [30m[43m node [49m[39m test/utils/unlockResponse.test.ts [2m([22m[2m11 tests[22m[2m)[22m[32m
|
|
634
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/recommendations/useRecommendations.test.ts [2m([22m[2m2 tests[22m[2m)[22m[32m
|
|
635
|
-
[32m✓[39m [30m[43m node [49m[39m test/components/account/OrganizationDrawerBody.test.tsx [2m([22m[2m3 tests[22m[2m)[22m[32m
|
|
630
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/search/SearchInput.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m 7[2mms[22m[39m
|
|
631
|
+
[32m✓[39m [30m[43m node [49m[39m test/utils/validateSessionRefreshToken.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m 4[2mms[22m[39m
|
|
632
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/recommendations/vrn.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m 4[2mms[22m[39m
|
|
633
|
+
[32m✓[39m [30m[43m node [49m[39m test/server/cms/index.test.ts [2m([22m[2m2 tests[22m[2m)[22m[32m 6[2mms[22m[39m
|
|
634
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/region/useRegion.test.ts [2m([22m[2m1 test[22m[2m)[22m[32m 22[2mms[22m[39m
|
|
635
|
+
[32m✓[39m [30m[43m node [49m[39m test/utils/retry.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m 18[2mms[22m[39m
|
|
636
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/account/getB2BSessionClaims.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m 6[2mms[22m[39m
|
|
637
|
+
[32m✓[39m [30m[43m node [49m[39m test/utils/userOrderStatus.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m 4[2mms[22m[39m
|
|
638
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/recommendations/useRecommendationUserId.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m 198[2mms[22m[39m
|
|
639
|
+
[32m✓[39m [30m[43m node [49m[39m test/utils/unlockResponse.test.ts [2m([22m[2m11 tests[22m[2m)[22m[32m 8[2mms[22m[39m
|
|
640
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/recommendations/useRecommendations.test.ts [2m([22m[2m2 tests[22m[2m)[22m[32m 5[2mms[22m[39m
|
|
641
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/account/OrganizationDrawerBody.test.tsx [2m([22m[2m3 tests[22m[2m)[22m[32m 41[2mms[22m[39m
|
|
636
642
|
[32m✓[39m [30m[43m node [49m[39m test/utils/isLocalHost.test.ts [2m([22m[2m7 tests[22m[2m)[22m[32m 5[2mms[22m[39m
|
|
637
643
|
[32m✓[39m [30m[43m node [49m[39m test/sdk/session/toSessionInput.test.ts [2m([22m[2m3 tests[22m[2m)[22m[32m 5[2mms[22m[39m
|
|
638
|
-
[32m✓[39m [30m[43m node [49m[39m test/components/quotes/MyAccountQuoteStatusBadge.test.tsx [2m([22m[2m4 tests[22m[2m)[22m[32m
|
|
639
|
-
[32m✓[39m [30m[43m node [49m[39m test/components/account/orders/
|
|
640
|
-
[32m✓[39m [30m[43m node [49m[39m test/components/account/orders/
|
|
641
|
-
[32m✓[39m [30m[43m node [49m[39m test/utils/getCookie.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m 5[2mms[22m[39m
|
|
644
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/quotes/MyAccountQuoteStatusBadge.test.tsx [2m([22m[2m4 tests[22m[2m)[22m[32m 36[2mms[22m[39m
|
|
645
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/account/orders/listOrdersLabels.test.ts [2m([22m[2m2 tests[22m[2m)[22m[32m 4[2mms[22m[39m
|
|
646
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/account/orders/getOrderTotalLabel.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m 3[2mms[22m[39m
|
|
642
647
|
[32m✓[39m [30m[43m node [49m[39m test/sdk/session/isSignInAreaResolved.test.ts [2m([22m[2m3 tests[22m[2m)[22m[32m 4[2mms[22m[39m
|
|
643
|
-
[32m✓[39m [30m[43m node [49m[39m test/utils/
|
|
644
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
645
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
646
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/analytics/utils.test.ts [2m([22m[2m2 tests[22m[2m)[22m[32m
|
|
648
|
+
[32m✓[39m [30m[43m node [49m[39m test/utils/getCookie.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m 5[2mms[22m[39m
|
|
649
|
+
[32m✓[39m [30m[43m node [49m[39m test/utils/filterChannel.test.ts [2m([22m[2m2 tests[22m[2m)[22m[32m 5[2mms[22m[39m
|
|
650
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/auth/ProfileChallenge.test.tsx [2m([22m[2m3 tests[22m[2m)[22m[32m 33[2mms[22m[39m
|
|
651
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/analytics/utils.test.ts [2m([22m[2m2 tests[22m[2m)[22m[32m 4[2mms[22m[39m
|
|
652
|
+
[32m✓[39m [30m[43m node [49m[39m test/instrumentation.test.ts [2m([22m[2m3 tests[22m[2m)[22m[32m 6[2mms[22m[39m
|
|
647
653
|
[32m✓[39m [30m[43m node [49m[39m test/components/account/orders/orderDetailsLabels.test.ts [2m([22m[2m1 test[22m[2m)[22m[32m 4[2mms[22m[39m
|
|
648
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/account/clearPersistedSessionState.test.ts [2m([22m[2m1 test[22m[2m)[22m[32m
|
|
654
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/account/clearPersistedSessionState.test.ts [2m([22m[2m1 test[22m[2m)[22m[32m 10[2mms[22m[39m
|
|
649
655
|
|
|
650
|
-
[2m Test Files [22m [1m[
|
|
651
|
-
[2m Tests [22m [1m[
|
|
652
|
-
[2m Start at [22m
|
|
653
|
-
[2m Duration [22m
|
|
656
|
+
[2m Test Files [22m [1m[32m131 passed[39m[22m[90m (131)[39m
|
|
657
|
+
[2m Tests [22m [1m[32m1040 passed[39m[22m[90m (1040)[39m
|
|
658
|
+
[2m Start at [22m 16:50:57
|
|
659
|
+
[2m Duration [22m 64.14s[2m (transform 16.34s, setup 0ms, import 57.63s, tests 23.46s, environment 79.54s)[22m
|
|
654
660
|
|
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,12 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [4.10.0-dev.0](https://github.com/vtex/faststore/compare/v4.9.3-dev.2...v4.10.0-dev.0) (2026-10-08)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
- render images in RichText via a custom Lexical image node ([#3448](https://github.com/vtex/faststore/issues/3448)) ([a7c85b8](https://github.com/vtex/faststore/commit/a7c85b8478a64994b123f81ee08add594daa7b2f))
|
|
11
|
+
|
|
6
12
|
## [4.9.3-dev.2](https://github.com/vtex/faststore/compare/v4.9.3-dev.1...v4.9.3-dev.2) (2026-10-07)
|
|
7
13
|
|
|
8
14
|
### Bug Fixes
|
package/index.ts
CHANGED
|
@@ -12,6 +12,9 @@ export * from './src/typings/overrides'
|
|
|
12
12
|
export { getOverriddenSection } from './src/sdk/overrides/getOverriddenSection'
|
|
13
13
|
export { getMyAccountRoutes } from './src/sdk/account/getMyAccountRoutes'
|
|
14
14
|
|
|
15
|
+
export { RichText } from './src/components/ui/RichText'
|
|
16
|
+
export type { RichTextProps } from './src/components/ui/RichText'
|
|
17
|
+
|
|
15
18
|
// Overridable Sections
|
|
16
19
|
export { default as AlertSection } from './src/components/sections/Alert'
|
|
17
20
|
export { default as BannerTextSection } from './src/components/sections/BannerText'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@faststore/core",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.10.0-dev.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -71,11 +71,11 @@
|
|
|
71
71
|
"style-loader": "^3.3.1",
|
|
72
72
|
"swr": "^2.2.5",
|
|
73
73
|
"use-sync-external-store": "^1.6.0",
|
|
74
|
-
"@faststore/api": "4.
|
|
75
|
-
"@faststore/diagnostics": "4.
|
|
76
|
-
"@faststore/lighthouse": "4.
|
|
77
|
-
"@faststore/
|
|
78
|
-
"@faststore/
|
|
74
|
+
"@faststore/api": "4.10.0-dev.0",
|
|
75
|
+
"@faststore/diagnostics": "4.10.0-dev.0",
|
|
76
|
+
"@faststore/lighthouse": "4.10.0-dev.0",
|
|
77
|
+
"@faststore/ui": "4.10.0-dev.0",
|
|
78
|
+
"@faststore/sdk": "4.10.0-dev.0"
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
81
|
"@cypress/code-coverage": "^3.12.1",
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
} from 'lexical'
|
|
27
27
|
import { RichText as UIRichText } from '@faststore/ui'
|
|
28
28
|
import { isContentPlatformSource } from 'src/server/content/utils'
|
|
29
|
+
import { RichTextImageNode } from './RichTextImageNode'
|
|
29
30
|
|
|
30
31
|
export interface RichTextProps {
|
|
31
32
|
/**
|
|
@@ -124,6 +125,7 @@ function lexicalToHtml(content: string) {
|
|
|
124
125
|
ListItemNode,
|
|
125
126
|
CodeNode,
|
|
126
127
|
HorizontalRuleNode,
|
|
128
|
+
RichTextImageNode,
|
|
127
129
|
],
|
|
128
130
|
onError: (error) => {
|
|
129
131
|
throw error
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DecoratorNode,
|
|
3
|
+
type DOMExportOutput,
|
|
4
|
+
type EditorConfig,
|
|
5
|
+
type LexicalEditor,
|
|
6
|
+
type NodeKey,
|
|
7
|
+
type SerializedLexicalNode,
|
|
8
|
+
type Spread,
|
|
9
|
+
} from 'lexical'
|
|
10
|
+
|
|
11
|
+
export type ImageAlignment = 'left' | 'center' | 'right'
|
|
12
|
+
|
|
13
|
+
export type SerializedRichTextImageNode = Spread<
|
|
14
|
+
{
|
|
15
|
+
type: 'image'
|
|
16
|
+
version: 1
|
|
17
|
+
src: string
|
|
18
|
+
altText: string
|
|
19
|
+
alignment: ImageAlignment
|
|
20
|
+
widthPercent: number
|
|
21
|
+
},
|
|
22
|
+
SerializedLexicalNode
|
|
23
|
+
>
|
|
24
|
+
|
|
25
|
+
const VALID_ALIGNMENTS = new Set<ImageAlignment>(['left', 'center', 'right'])
|
|
26
|
+
const DEFAULT_ALIGNMENT: ImageAlignment = 'left'
|
|
27
|
+
const DEFAULT_WIDTH_PERCENT = 100
|
|
28
|
+
const RICH_TEXT_CONTENT_MAX_WIDTH = 720
|
|
29
|
+
const DEFAULT_IMAGE_QUALITY = 8
|
|
30
|
+
|
|
31
|
+
function resolveAlignment(alignment: unknown): ImageAlignment {
|
|
32
|
+
return VALID_ALIGNMENTS.has(alignment as ImageAlignment)
|
|
33
|
+
? (alignment as ImageAlignment)
|
|
34
|
+
: DEFAULT_ALIGNMENT
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function resolveWidthPercent(widthPercent: unknown): number {
|
|
38
|
+
if (typeof widthPercent !== 'number' || widthPercent <= 0) {
|
|
39
|
+
return DEFAULT_WIDTH_PERCENT
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return Math.min(widthPercent, DEFAULT_WIDTH_PERCENT)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function withVtexResizeParams(src: string, widthPercent: number): string {
|
|
46
|
+
if (!src.includes('vtexassets') || !src.includes('/assets')) {
|
|
47
|
+
return src
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
const url = new URL(src)
|
|
52
|
+
const targetWidth = Math.max(
|
|
53
|
+
1,
|
|
54
|
+
Math.round((RICH_TEXT_CONTENT_MAX_WIDTH * widthPercent) / 100)
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
url.searchParams.set('width', targetWidth.toString())
|
|
58
|
+
url.searchParams.set('aspect', 'true')
|
|
59
|
+
url.searchParams.set('quality', DEFAULT_IMAGE_QUALITY.toString())
|
|
60
|
+
|
|
61
|
+
return url.toString()
|
|
62
|
+
} catch {
|
|
63
|
+
return src
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export class RichTextImageNode extends DecoratorNode<null> {
|
|
68
|
+
__src: string
|
|
69
|
+
__altText: string
|
|
70
|
+
__alignment: ImageAlignment
|
|
71
|
+
__widthPercent: number
|
|
72
|
+
|
|
73
|
+
constructor(
|
|
74
|
+
src: string,
|
|
75
|
+
altText: string,
|
|
76
|
+
alignment: ImageAlignment = DEFAULT_ALIGNMENT,
|
|
77
|
+
widthPercent: number = DEFAULT_WIDTH_PERCENT,
|
|
78
|
+
key?: NodeKey
|
|
79
|
+
) {
|
|
80
|
+
super(key)
|
|
81
|
+
this.__src = src
|
|
82
|
+
this.__altText = altText
|
|
83
|
+
this.__alignment = resolveAlignment(alignment)
|
|
84
|
+
this.__widthPercent = resolveWidthPercent(widthPercent)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
static getType(): string {
|
|
88
|
+
return 'image'
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
static clone(node: RichTextImageNode): RichTextImageNode {
|
|
92
|
+
return new RichTextImageNode(
|
|
93
|
+
node.__src,
|
|
94
|
+
node.__altText,
|
|
95
|
+
node.__alignment,
|
|
96
|
+
node.__widthPercent,
|
|
97
|
+
node.__key
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
static importDOM(): null {
|
|
102
|
+
return null
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
static importJSON(
|
|
106
|
+
serializedNode: SerializedRichTextImageNode
|
|
107
|
+
): RichTextImageNode {
|
|
108
|
+
return new RichTextImageNode(
|
|
109
|
+
typeof serializedNode.src === 'string' ? serializedNode.src : '',
|
|
110
|
+
typeof serializedNode.altText === 'string' ? serializedNode.altText : '',
|
|
111
|
+
serializedNode.alignment,
|
|
112
|
+
serializedNode.widthPercent
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
exportJSON(): SerializedRichTextImageNode {
|
|
117
|
+
return {
|
|
118
|
+
type: 'image',
|
|
119
|
+
version: 1,
|
|
120
|
+
src: this.__src,
|
|
121
|
+
altText: this.__altText,
|
|
122
|
+
alignment: this.__alignment,
|
|
123
|
+
widthPercent: this.__widthPercent,
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
isInline(): boolean {
|
|
128
|
+
return false
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
createDOM(_config: EditorConfig, _editor: LexicalEditor): HTMLElement {
|
|
132
|
+
return document.createElement('div')
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
updateDOM(): boolean {
|
|
136
|
+
return false
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
decorate(): null {
|
|
140
|
+
return null
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
exportDOM(_editor: LexicalEditor): DOMExportOutput {
|
|
144
|
+
if (!this.__src) {
|
|
145
|
+
return { element: null }
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const wrapper = document.createElement('div')
|
|
149
|
+
wrapper.dataset.fsRichTextImageWrapper = ''
|
|
150
|
+
wrapper.dataset.fsRichTextImageAlignment = this.__alignment
|
|
151
|
+
|
|
152
|
+
const img = document.createElement('img')
|
|
153
|
+
img.dataset.fsRichTextImage = ''
|
|
154
|
+
img.src = withVtexResizeParams(this.__src, this.__widthPercent)
|
|
155
|
+
img.alt = this.__altText
|
|
156
|
+
img.setAttribute('loading', 'lazy')
|
|
157
|
+
img.style.width = `${this.__widthPercent}%`
|
|
158
|
+
|
|
159
|
+
wrapper.append(img)
|
|
160
|
+
|
|
161
|
+
return { element: wrapper }
|
|
162
|
+
}
|
|
163
|
+
}
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vitest-environment jsdom
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { render } from '@testing-library/react'
|
|
6
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
7
|
+
|
|
8
|
+
const isContentPlatformSourceMock = vi.hoisted(() => vi.fn(() => true))
|
|
9
|
+
|
|
10
|
+
vi.mock('src/server/content/utils', () => ({
|
|
11
|
+
isContentPlatformSource: isContentPlatformSourceMock,
|
|
12
|
+
}))
|
|
13
|
+
|
|
14
|
+
import { RichText } from '../../../../src/components/ui/RichText/RichText'
|
|
15
|
+
|
|
16
|
+
function textNode(text: string) {
|
|
17
|
+
return {
|
|
18
|
+
detail: 0,
|
|
19
|
+
format: 0,
|
|
20
|
+
mode: 'normal',
|
|
21
|
+
style: '',
|
|
22
|
+
text,
|
|
23
|
+
type: 'text',
|
|
24
|
+
version: 1,
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function paragraphNode(children: unknown[]) {
|
|
29
|
+
return {
|
|
30
|
+
children,
|
|
31
|
+
direction: 'ltr',
|
|
32
|
+
format: '',
|
|
33
|
+
indent: 0,
|
|
34
|
+
type: 'paragraph',
|
|
35
|
+
version: 1,
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function headingNode(text: string, tag = 'h2') {
|
|
40
|
+
return {
|
|
41
|
+
children: [textNode(text)],
|
|
42
|
+
direction: 'ltr',
|
|
43
|
+
format: '',
|
|
44
|
+
indent: 0,
|
|
45
|
+
type: 'heading',
|
|
46
|
+
version: 1,
|
|
47
|
+
tag,
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function linkNode(url: string, text: string) {
|
|
52
|
+
return {
|
|
53
|
+
children: [textNode(text)],
|
|
54
|
+
direction: 'ltr',
|
|
55
|
+
format: '',
|
|
56
|
+
indent: 0,
|
|
57
|
+
type: 'link',
|
|
58
|
+
version: 1,
|
|
59
|
+
rel: null,
|
|
60
|
+
target: null,
|
|
61
|
+
title: null,
|
|
62
|
+
url,
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function listNode(itemText: string) {
|
|
67
|
+
return {
|
|
68
|
+
children: [
|
|
69
|
+
{
|
|
70
|
+
children: [textNode(itemText)],
|
|
71
|
+
direction: 'ltr',
|
|
72
|
+
format: '',
|
|
73
|
+
indent: 0,
|
|
74
|
+
type: 'listitem',
|
|
75
|
+
version: 1,
|
|
76
|
+
value: 1,
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
direction: 'ltr',
|
|
80
|
+
format: '',
|
|
81
|
+
indent: 0,
|
|
82
|
+
type: 'list',
|
|
83
|
+
version: 1,
|
|
84
|
+
listType: 'bullet',
|
|
85
|
+
start: 1,
|
|
86
|
+
tag: 'ul',
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function imageNode(overrides: Record<string, unknown> = {}) {
|
|
91
|
+
return {
|
|
92
|
+
type: 'image',
|
|
93
|
+
version: 1,
|
|
94
|
+
src: 'https://storeaccount.vtexassets.com/assets/vtex.file-manager-graphql/images/abc123.png',
|
|
95
|
+
altText: 'A nice picture',
|
|
96
|
+
alignment: 'center',
|
|
97
|
+
widthPercent: 60,
|
|
98
|
+
...overrides,
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function lexicalContent(children: unknown[]) {
|
|
103
|
+
return JSON.stringify({
|
|
104
|
+
root: {
|
|
105
|
+
children,
|
|
106
|
+
direction: 'ltr',
|
|
107
|
+
format: '',
|
|
108
|
+
indent: 0,
|
|
109
|
+
type: 'root',
|
|
110
|
+
version: 1,
|
|
111
|
+
},
|
|
112
|
+
})
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function draftJsContent(text: string) {
|
|
116
|
+
return JSON.stringify({
|
|
117
|
+
blocks: [
|
|
118
|
+
{
|
|
119
|
+
key: '1',
|
|
120
|
+
text,
|
|
121
|
+
type: 'unstyled',
|
|
122
|
+
depth: 0,
|
|
123
|
+
inlineStyleRanges: [],
|
|
124
|
+
entityRanges: [],
|
|
125
|
+
data: {},
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
entityMap: {},
|
|
129
|
+
})
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
describe('RichText', () => {
|
|
133
|
+
beforeEach(() => {
|
|
134
|
+
isContentPlatformSourceMock.mockReturnValue(true)
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
it('renders an image node with the correct src, alt, alignment and width', () => {
|
|
138
|
+
const { container } = render(
|
|
139
|
+
<RichText content={lexicalContent([imageNode()])} />
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
const wrapper = container.querySelector('[data-fs-rich-text-image-wrapper]')
|
|
143
|
+
const img = container.querySelector<HTMLImageElement>(
|
|
144
|
+
'[data-fs-rich-text-image]'
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
expect(wrapper?.getAttribute('data-fs-rich-text-image-alignment')).toBe(
|
|
148
|
+
'center'
|
|
149
|
+
)
|
|
150
|
+
expect(img?.getAttribute('alt')).toBe('A nice picture')
|
|
151
|
+
expect(img?.getAttribute('loading')).toBe('lazy')
|
|
152
|
+
expect(img?.getAttribute('style')).toBe('width: 60%;')
|
|
153
|
+
|
|
154
|
+
const src = img?.getAttribute('src') ?? ''
|
|
155
|
+
expect(src).toContain('width=432')
|
|
156
|
+
expect(src).toContain('aspect=true')
|
|
157
|
+
expect(src).toContain('quality=8')
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
it('renders images together with text, headings, links and lists in document order', () => {
|
|
161
|
+
const { container } = render(
|
|
162
|
+
<RichText
|
|
163
|
+
content={lexicalContent([
|
|
164
|
+
headingNode('Title'),
|
|
165
|
+
paragraphNode([
|
|
166
|
+
textNode('See '),
|
|
167
|
+
linkNode('https://example.com', 'this link'),
|
|
168
|
+
]),
|
|
169
|
+
listNode('An item'),
|
|
170
|
+
imageNode(),
|
|
171
|
+
])}
|
|
172
|
+
/>
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
const html = container.innerHTML
|
|
176
|
+
|
|
177
|
+
expect(container.querySelector('h2')?.textContent).toBe('Title')
|
|
178
|
+
expect(
|
|
179
|
+
container.querySelector('a[href="https://example.com"]')
|
|
180
|
+
).toBeTruthy()
|
|
181
|
+
expect(
|
|
182
|
+
container.querySelector('[data-fs-rich-text-list="true"]')
|
|
183
|
+
).toBeTruthy()
|
|
184
|
+
expect(container.querySelector('[data-fs-rich-text-image]')).toBeTruthy()
|
|
185
|
+
|
|
186
|
+
const headingIndex = html.indexOf('<h2')
|
|
187
|
+
const linkIndex = html.indexOf('href="https://example.com"')
|
|
188
|
+
const listIndex = html.indexOf('data-fs-rich-text-list')
|
|
189
|
+
const imageIndex = html.indexOf('data-fs-rich-text-image-wrapper')
|
|
190
|
+
|
|
191
|
+
expect(headingIndex).toBeLessThan(linkIndex)
|
|
192
|
+
expect(linkIndex).toBeLessThan(listIndex)
|
|
193
|
+
expect(listIndex).toBeLessThan(imageIndex)
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
it('drops an image node with a missing src without breaking the rest of the content', () => {
|
|
197
|
+
const { container } = render(
|
|
198
|
+
<RichText
|
|
199
|
+
content={lexicalContent([
|
|
200
|
+
paragraphNode([textNode('Before')]),
|
|
201
|
+
imageNode({ src: '' }),
|
|
202
|
+
paragraphNode([textNode('After')]),
|
|
203
|
+
])}
|
|
204
|
+
/>
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
expect(container.querySelector('[data-fs-rich-text-image]')).toBeNull()
|
|
208
|
+
expect(
|
|
209
|
+
container.querySelector('[data-fs-rich-text-image-wrapper]')
|
|
210
|
+
).toBeNull()
|
|
211
|
+
expect(container.textContent).toContain('Before')
|
|
212
|
+
expect(container.textContent).toContain('After')
|
|
213
|
+
})
|
|
214
|
+
|
|
215
|
+
it('does not throw and skips an image node with an unsupported/unexpected shape', () => {
|
|
216
|
+
expect(() =>
|
|
217
|
+
render(
|
|
218
|
+
<RichText
|
|
219
|
+
content={lexicalContent([
|
|
220
|
+
paragraphNode([textNode('Still here')]),
|
|
221
|
+
{
|
|
222
|
+
type: 'image',
|
|
223
|
+
version: 2,
|
|
224
|
+
imageUrl: 'https://storeaccount.vtexassets.com/assets/x.png',
|
|
225
|
+
},
|
|
226
|
+
])}
|
|
227
|
+
/>
|
|
228
|
+
)
|
|
229
|
+
).not.toThrow()
|
|
230
|
+
|
|
231
|
+
const { container } = render(
|
|
232
|
+
<RichText
|
|
233
|
+
content={lexicalContent([
|
|
234
|
+
paragraphNode([textNode('Still here')]),
|
|
235
|
+
{
|
|
236
|
+
type: 'image',
|
|
237
|
+
version: 2,
|
|
238
|
+
imageUrl: 'https://storeaccount.vtexassets.com/assets/x.png',
|
|
239
|
+
},
|
|
240
|
+
])}
|
|
241
|
+
/>
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
expect(container.querySelector('[data-fs-rich-text-image]')).toBeNull()
|
|
245
|
+
expect(container.textContent).toContain('Still here')
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
it('renders multiple images, defaulting alignment/width when omitted and passing through non-VTEX URLs unmodified', () => {
|
|
249
|
+
const { container } = render(
|
|
250
|
+
<RichText
|
|
251
|
+
content={lexicalContent([
|
|
252
|
+
imageNode({ alignment: 'right', widthPercent: 30 }),
|
|
253
|
+
imageNode({
|
|
254
|
+
src: 'https://storeaccount.vtexassets.com/assets/vtex.file-manager-graphql/images/no-layout.png',
|
|
255
|
+
alignment: undefined,
|
|
256
|
+
widthPercent: undefined,
|
|
257
|
+
}),
|
|
258
|
+
imageNode({
|
|
259
|
+
src: 'https://cdn.example.com/external.png',
|
|
260
|
+
alignment: 'center',
|
|
261
|
+
widthPercent: 80,
|
|
262
|
+
}),
|
|
263
|
+
])}
|
|
264
|
+
/>
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
const wrappers = container.querySelectorAll(
|
|
268
|
+
'[data-fs-rich-text-image-wrapper]'
|
|
269
|
+
)
|
|
270
|
+
expect(wrappers).toHaveLength(3)
|
|
271
|
+
|
|
272
|
+
expect(wrappers[0].getAttribute('data-fs-rich-text-image-alignment')).toBe(
|
|
273
|
+
'right'
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
expect(wrappers[1].getAttribute('data-fs-rich-text-image-alignment')).toBe(
|
|
277
|
+
'left'
|
|
278
|
+
)
|
|
279
|
+
expect(
|
|
280
|
+
wrappers[1]
|
|
281
|
+
.querySelector('[data-fs-rich-text-image]')
|
|
282
|
+
?.getAttribute('style')
|
|
283
|
+
).toBe('width: 100%;')
|
|
284
|
+
|
|
285
|
+
const externalImg = wrappers[2].querySelector('[data-fs-rich-text-image]')
|
|
286
|
+
expect(externalImg?.getAttribute('src')).toBe(
|
|
287
|
+
'https://cdn.example.com/external.png'
|
|
288
|
+
)
|
|
289
|
+
})
|
|
290
|
+
|
|
291
|
+
it('clamps widthPercent to 100 so the image never overflows its container', () => {
|
|
292
|
+
const { container } = render(
|
|
293
|
+
<RichText content={lexicalContent([imageNode({ widthPercent: 150 })])} />
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
const img = container.querySelector('[data-fs-rich-text-image]')
|
|
297
|
+
expect(img?.getAttribute('style')).toBe('width: 100%;')
|
|
298
|
+
})
|
|
299
|
+
|
|
300
|
+
it('keeps rendering existing hCMS Draft.js content unaffected', () => {
|
|
301
|
+
isContentPlatformSourceMock.mockReturnValue(false)
|
|
302
|
+
|
|
303
|
+
const { container } = render(
|
|
304
|
+
<RichText content={draftJsContent('Hello legacy content')} />
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
expect(container.textContent).toContain('Hello legacy content')
|
|
308
|
+
expect(container.querySelector('[data-fs-rich-text-image]')).toBeNull()
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
it('keeps rendering existing Lexical content without images unaffected', () => {
|
|
312
|
+
const { container } = render(
|
|
313
|
+
<RichText
|
|
314
|
+
content={lexicalContent([paragraphNode([textNode('No images here')])])}
|
|
315
|
+
/>
|
|
316
|
+
)
|
|
317
|
+
|
|
318
|
+
expect(container.textContent).toContain('No images here')
|
|
319
|
+
expect(container.querySelector('[data-fs-rich-text-image]')).toBeNull()
|
|
320
|
+
})
|
|
321
|
+
})
|