@faststore/core 4.7.0-dev.7 → 4.7.0-dev.9
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 +101 -100
- package/@generated/gql.ts +3 -3
- package/@generated/graphql.ts +10 -2
- package/@generated/persisted-documents.json +1 -1
- package/@generated/schema.graphql +8 -0
- package/CHANGELOG.md +10 -0
- package/package.json +6 -6
- package/src/components/ui/LocalizationButton/LocalizationButton.tsx +5 -3
- package/src/pages/[slug]/p.tsx +6 -1
- package/src/sdk/localization/LocalizedProductContext.tsx +14 -2
- package/src/sdk/localization/bindingSelector.ts +38 -0
- package/src/sdk/localization/useBindingSelector.ts +17 -22
- package/test/components/ui/LocalizationButton.browser.test.tsx +87 -0
- package/test/sdk/localization/useBindingSelector.browser.test.tsx +252 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
|
|
2
|
-
> @faststore/core@4.7.0-dev.
|
|
2
|
+
> @faststore/core@4.7.0-dev.8 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.7.0-dev.
|
|
6
|
+
> @faststore/core@4.7.0-dev.8 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 /home/runner/work/faststore/faststore/packages/core/@generated/
|
|
20
20
|
[32m[COMPLETED][39m Generate outputs
|
|
21
21
|
|
|
22
|
-
> @faststore/core@4.7.0-dev.
|
|
22
|
+
> @faststore/core@4.7.0-dev.8 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.7.0-dev.
|
|
2
|
+
> @faststore/core@4.7.0-dev.8 test /home/runner/work/faststore/faststore/packages/core
|
|
3
3
|
> vitest run
|
|
4
4
|
|
|
5
5
|
|
|
@@ -7,19 +7,20 @@
|
|
|
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
|
|
10
|
+
[32m✓[39m [30m[46m browser [49m[39m test/sdk/ui/useScrollRestoration.browser.test.ts [2m([22m[2m43 tests[22m[2m)[22m[33m 1147[2mms[22m[39m
|
|
11
11
|
Browserslist: browsers data (caniuse-lite) is 6 months old. Please run:
|
|
12
12
|
npx update-browserslist-db@latest
|
|
13
13
|
Why you should do it regularly: https://github.com/browserslist/update-db#readme
|
|
14
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/account/cards/MyAccountListCards.browser.test.tsx [2m([22m[2m14 tests[22m[2m)[22m[33m
|
|
15
|
-
[33m[2m✓[22m[39m shows the tab bar and renders Personal cards by default [33m
|
|
16
|
-
[33m[2m✓[22m[39m paginates when there are more than 25 cards [33m
|
|
17
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/account/ContractSwitcher.browser.test.tsx [2m([22m[2m13 tests[22m[2m)[22m[33m
|
|
18
|
-
[33m[2m✓[22m[39m shows an error state when the list fails to load [33m
|
|
19
|
-
[33m[2m✓[22m[39m requires selecting a contract before Confirm is enabled, then switches (REQ-03) [33m
|
|
20
|
-
[32m✓[39m [30m[46m browser [49m[39m test/
|
|
21
|
-
[32m✓[39m [30m[46m browser [49m[39m test/sdk/session/reconcileSessionLocale.browser.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m
|
|
22
|
-
[32m✓[39m [30m[46m browser [49m[39m test/
|
|
14
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/account/cards/MyAccountListCards.browser.test.tsx [2m([22m[2m14 tests[22m[2m)[22m[33m 1965[2mms[22m[39m
|
|
15
|
+
[33m[2m✓[22m[39m shows the tab bar and renders Personal cards by default [33m 771[2mms[22m[39m
|
|
16
|
+
[33m[2m✓[22m[39m paginates when there are more than 25 cards [33m 352[2mms[22m[39m
|
|
17
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/account/ContractSwitcher.browser.test.tsx [2m([22m[2m13 tests[22m[2m)[22m[33m 2079[2mms[22m[39m
|
|
18
|
+
[33m[2m✓[22m[39m shows an error state when the list fails to load [33m 553[2mms[22m[39m
|
|
19
|
+
[33m[2m✓[22m[39m requires selecting a contract before Confirm is enabled, then switches (REQ-03) [33m 305[2mms[22m[39m
|
|
20
|
+
[32m✓[39m [30m[46m browser [49m[39m test/sdk/localization/useBindingSelector.browser.test.tsx [2m([22m[2m9 tests[22m[2m)[22m[32m 106[2mms[22m[39m
|
|
21
|
+
[32m✓[39m [30m[46m browser [49m[39m test/sdk/session/reconcileSessionLocale.browser.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m 33[2mms[22m[39m
|
|
22
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/ui/ProductGallery/GalleryPageHeightLock.browser.test.tsx [2m([22m[2m8 tests[22m[2m)[22m[32m 82[2mms[22m[39m
|
|
23
|
+
[32m✓[39m [30m[46m browser [49m[39m test/sdk/recommendations/useRecommendationShelf.browser.test.tsx [2m([22m[2m12 tests[22m[2m)[22m[32m 161[2mms[22m[39m
|
|
23
24
|
[90mstderr[2m | test/components/RecommendationShelf/RecommendationShelf.browser.test.tsx
|
|
24
25
|
[22m[39mError in optimistic validation: TypeError: Failed to parse URL from /api/graphql?operationName=ValidateCartMutation&operationHash=3c71b0d3fc2bade14df68abfa271858beb361b12
|
|
25
26
|
[90m at node:internal/deps/undici/undici:16416:13[39m
|
|
@@ -49,7 +50,7 @@ Browserslist: browsers data (caniuse-lite) is 6 months old. Please run:
|
|
|
49
50
|
[90mstderr[2m | test/components/RecommendationShelf/RecommendationShelf.browser.test.tsx[2m > [22m[2mRecommendationShelf[2m > [22m[2mrenders nothing when there is an error
|
|
50
51
|
[22m[39mError fetching recommendations [90mundefined[39m boom for campaign vrn:recommendations:acc:rec-top-items-v2:campaign-1
|
|
51
52
|
|
|
52
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/RecommendationShelf/RecommendationShelf.browser.test.tsx [2m([22m[2m7 tests[22m[2m)[22m[32m
|
|
53
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/RecommendationShelf/RecommendationShelf.browser.test.tsx [2m([22m[2m7 tests[22m[2m)[22m[32m 270[2mms[22m[39m
|
|
53
54
|
[90mstderr[2m | test/pages/password-protection.browser.test.tsx[2m > [22m[2mPasswordProtectionLogin[2m > [22m[2mposts the password and redirects to the requested return path
|
|
54
55
|
[22m[39mWarning: An update to PasswordProtectionLogin inside a test was not wrapped in act(...).
|
|
55
56
|
|
|
@@ -135,7 +136,6 @@ act(() => {
|
|
|
135
136
|
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
|
|
136
137
|
at PasswordProtectionLogin (/home/runner/work/faststore/faststore/packages/core/src/pages/password-protection/index.tsx:19:69)
|
|
137
138
|
|
|
138
|
-
[32m✓[39m [30m[46m browser [49m[39m test/sdk/session/getInitialSession.browser.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m 32[2mms[22m[39m
|
|
139
139
|
[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
|
|
140
140
|
[22m[39mWarning: An update to PasswordProtectionLogin inside a test was not wrapped in act(...).
|
|
141
141
|
|
|
@@ -184,8 +184,6 @@ act(() => {
|
|
|
184
184
|
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
|
|
185
185
|
at PasswordProtectionLogin (/home/runner/work/faststore/faststore/packages/core/src/pages/password-protection/index.tsx:19:69)
|
|
186
186
|
|
|
187
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/account/OrganizationDrawer.browser.test.tsx [2m([22m[2m5 tests[22m[2m)[22m[33m 1658[2mms[22m[39m
|
|
188
|
-
[33m[2m✓[22m[39m renders the menu view with contract details and manage footer [33m 988[2mms[22m[39m
|
|
189
187
|
[90mstderr[2m | test/pages/password-protection.browser.test.tsx[2m > [22m[2mPasswordProtectionLogin[2m > [22m[2mshows service unavailable when the response is not a login payload
|
|
190
188
|
[22m[39mWarning: An update to PasswordProtectionLogin inside a test was not wrapped in act(...).
|
|
191
189
|
|
|
@@ -282,9 +280,12 @@ act(() => {
|
|
|
282
280
|
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
|
|
283
281
|
at PasswordProtectionLogin (/home/runner/work/faststore/faststore/packages/core/src/pages/password-protection/index.tsx:19:69)
|
|
284
282
|
|
|
285
|
-
[32m✓[39m [30m[46m browser [49m[39m test/pages/password-protection.browser.test.tsx [2m([22m[2m6 tests[22m[2m)[22m[33m
|
|
286
|
-
[33m[2m✓[22m[39m renders the password protection form [33m
|
|
287
|
-
[32m✓[39m [30m[46m browser [49m[39m test/sdk/
|
|
283
|
+
[32m✓[39m [30m[46m browser [49m[39m test/pages/password-protection.browser.test.tsx [2m([22m[2m6 tests[22m[2m)[22m[33m 1334[2mms[22m[39m
|
|
284
|
+
[33m[2m✓[22m[39m renders the password protection form [33m 554[2mms[22m[39m
|
|
285
|
+
[32m✓[39m [30m[46m browser [49m[39m test/sdk/session/getInitialSession.browser.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m 16[2mms[22m[39m
|
|
286
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/account/OrganizationDrawer.browser.test.tsx [2m([22m[2m5 tests[22m[2m)[22m[33m 1072[2mms[22m[39m
|
|
287
|
+
[33m[2m✓[22m[39m renders the menu view with contract details and manage footer [33m 692[2mms[22m[39m
|
|
288
|
+
[32m✓[39m [30m[46m browser [49m[39m test/sdk/account/changeContractToken.browser.test.ts [2m([22m[2m9 tests[22m[2m)[22m[32m 17[2mms[22m[39m
|
|
288
289
|
[90mstderr[2m | test/sdk/localization/store-url.browser.test.ts
|
|
289
290
|
[22m[39mError in optimistic validation: TypeError: Cannot read properties of undefined (reading 'read')
|
|
290
291
|
at waitForSessionValidated [90m(/home/runner/work/faststore/faststore/packages/core/[39msrc/sdk/cart/waitForSessionValidated.ts:16:32[90m)[39m
|
|
@@ -293,7 +294,7 @@ This ensures that you're testing the behavior the user would see in the browser.
|
|
|
293
294
|
at a (/home/runner/work/faststore/faststore/packages/sdk/dist/es/index.mjs:354:23)
|
|
294
295
|
[90m at processTicksAndRejections (node:internal/process/task_queues:103:5)[39m
|
|
295
296
|
|
|
296
|
-
[32m✓[39m [30m[46m browser [49m[39m test/sdk/localization/store-url.browser.test.ts [2m([22m[2m3 tests[22m[2m)[22m[32m
|
|
297
|
+
[32m✓[39m [30m[46m browser [49m[39m test/sdk/localization/store-url.browser.test.ts [2m([22m[2m3 tests[22m[2m)[22m[32m 5[2mms[22m[39m
|
|
297
298
|
[90mstderr[2m | test/components/cms/RenderSections.browser.test.tsx
|
|
298
299
|
[22m[39mError in optimistic validation: TypeError: Cannot read properties of undefined (reading 'read')
|
|
299
300
|
at waitForSessionValidated [90m(/home/runner/work/faststore/faststore/packages/core/[39msrc/sdk/cart/waitForSessionValidated.ts:16:32[90m)[39m
|
|
@@ -302,11 +303,11 @@ This ensures that you're testing the behavior the user would see in the browser.
|
|
|
302
303
|
at a (/home/runner/work/faststore/faststore/packages/sdk/dist/es/index.mjs:354:23)
|
|
303
304
|
[90m at processTicksAndRejections (node:internal/process/task_queues:103:5)[39m
|
|
304
305
|
|
|
305
|
-
[32m✓[39m [30m[46m browser [49m[39m test/
|
|
306
|
-
[32m✓[39m [30m[46m browser [49m[39m test/
|
|
307
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/templates/SearchPage/SearchWrapper.browser.test.tsx [2m([22m[2m3 tests[22m[2m)[22m[32m
|
|
308
|
-
[32m✓[39m [30m[46m browser [49m[39m test/sdk/recommendations/useRecommendationShelf.sessionFallback.browser.test.tsx [2m([22m[2m2 tests[22m[2m)[22m[32m
|
|
309
|
-
[32m✓[39m [30m[46m browser [49m[39m test/sdk/account/useSwitchContract.browser.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m
|
|
306
|
+
[32m✓[39m [30m[46m browser [49m[39m test/sdk/account/useAvailableContracts.browser.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m 41[2mms[22m[39m
|
|
307
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/cms/RenderSections.browser.test.tsx [2m([22m[2m5 tests[22m[2m)[22m[32m 77[2mms[22m[39m
|
|
308
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/templates/SearchPage/SearchWrapper.browser.test.tsx [2m([22m[2m3 tests[22m[2m)[22m[32m 38[2mms[22m[39m
|
|
309
|
+
[32m✓[39m [30m[46m browser [49m[39m test/sdk/recommendations/useRecommendationShelf.sessionFallback.browser.test.tsx [2m([22m[2m2 tests[22m[2m)[22m[32m 132[2mms[22m[39m
|
|
310
|
+
[32m✓[39m [30m[46m browser [49m[39m test/sdk/account/useSwitchContract.browser.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m 30[2mms[22m[39m
|
|
310
311
|
[90mstderr[2m | test/components/account/doLogout.browser.test.ts
|
|
311
312
|
[22m[39mError in optimistic validation: TypeError: Cannot read properties of undefined (reading 'read')
|
|
312
313
|
at waitForSessionValidated [90m(/home/runner/work/faststore/faststore/packages/core/[39msrc/sdk/cart/waitForSessionValidated.ts:16:32[90m)[39m
|
|
@@ -315,10 +316,11 @@ This ensures that you're testing the behavior the user would see in the browser.
|
|
|
315
316
|
at a (/home/runner/work/faststore/faststore/packages/sdk/dist/es/index.mjs:354:23)
|
|
316
317
|
[90m at processTicksAndRejections (node:internal/process/task_queues:103:5)[39m
|
|
317
318
|
|
|
318
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/account/doLogout.browser.test.ts [2m([22m[2m1 test[22m[2m)[22m[32m
|
|
319
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/
|
|
320
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/
|
|
321
|
-
[32m✓[39m [30m[46m browser [49m[39m test/components/account/
|
|
319
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/account/doLogout.browser.test.ts [2m([22m[2m1 test[22m[2m)[22m[32m 38[2mms[22m[39m
|
|
320
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/ui/LocalizationButton.browser.test.tsx [2m([22m[2m3 tests[22m[2m)[22m[32m 47[2mms[22m[39m
|
|
321
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/sections/Account/AccountListCards.browser.test.tsx [2m([22m[2m3 tests[22m[2m)[22m[32m 78[2mms[22m[39m
|
|
322
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/account/OrganizationDrawerHeader.browser.test.tsx [2m([22m[2m3 tests[22m[2m)[22m[32m 278[2mms[22m[39m
|
|
323
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/account/OrganizationDrawerFooter.browser.test.tsx [2m([22m[2m3 tests[22m[2m)[22m[32m 296[2mms[22m[39m
|
|
322
324
|
[90mstderr[2m | test/sdk/account/clearPersistedSessionState.browser.test.ts
|
|
323
325
|
[22m[39mError in optimistic validation: TypeError: Cannot read properties of undefined (reading 'read')
|
|
324
326
|
at waitForSessionValidated [90m(/home/runner/work/faststore/faststore/packages/core/[39msrc/sdk/cart/waitForSessionValidated.ts:16:32[90m)[39m
|
|
@@ -327,10 +329,11 @@ This ensures that you're testing the behavior the user would see in the browser.
|
|
|
327
329
|
at a (/home/runner/work/faststore/faststore/packages/sdk/dist/es/index.mjs:354:23)
|
|
328
330
|
[90m at processTicksAndRejections (node:internal/process/task_queues:103:5)[39m
|
|
329
331
|
|
|
330
|
-
[32m✓[39m [30m[46m browser [49m[39m test/sdk/account/clearPersistedSessionState.browser.test.ts [2m([22m[2m1 test[22m[2m)[22m[32m
|
|
331
|
-
[32m✓[39m [30m[46m browser [49m[39m test/utils/isLocalHost.browser.test.ts [2m([22m[2m3 tests[22m[2m)[22m[32m
|
|
332
|
+
[32m✓[39m [30m[46m browser [49m[39m test/sdk/account/clearPersistedSessionState.browser.test.ts [2m([22m[2m1 test[22m[2m)[22m[32m 8[2mms[22m[39m
|
|
333
|
+
[32m✓[39m [30m[46m browser [49m[39m test/utils/isLocalHost.browser.test.ts [2m([22m[2m3 tests[22m[2m)[22m[32m 4[2mms[22m[39m
|
|
332
334
|
[32m✓[39m [30m[46m browser [49m[39m test/sdk/session/reconcileSessionLocale.disabled.browser.test.ts [2m([22m[2m1 test[22m[2m)[22m[32m 3[2mms[22m[39m
|
|
333
|
-
[32m✓[39m [30m[43m node [49m[39m test/utils/localization/bindingPaths.test.ts [2m([22m[2m71 tests[22m[2m)[22m[32m
|
|
335
|
+
[32m✓[39m [30m[43m node [49m[39m test/utils/localization/bindingPaths.test.ts [2m([22m[2m71 tests[22m[2m)[22m[32m 29[2mms[22m[39m
|
|
336
|
+
[32m✓[39m [30m[46m browser [49m[39m test/components/skeletons/ProductGridSkeleton.browser.test.tsx [2m([22m[2m2 tests[22m[2m)[22m[32m 29[2mms[22m[39m
|
|
334
337
|
[90mstderr[2m | test/sdk/account/refreshToken.browser.test.ts
|
|
335
338
|
[22m[39mError in optimistic validation: TypeError: Cannot read properties of undefined (reading 'read')
|
|
336
339
|
at waitForSessionValidated [90m(/home/runner/work/faststore/faststore/packages/core/[39msrc/sdk/cart/waitForSessionValidated.ts:16:32[90m)[39m
|
|
@@ -339,12 +342,11 @@ This ensures that you're testing the behavior the user would see in the browser.
|
|
|
339
342
|
at a (/home/runner/work/faststore/faststore/packages/sdk/dist/es/index.mjs:354:23)
|
|
340
343
|
[90m at processTicksAndRejections (node:internal/process/task_queues:103:5)[39m
|
|
341
344
|
|
|
342
|
-
[32m✓[39m [30m[43m node [49m[39m test/server/password-protection-service.test.ts [2m([22m[2m22 tests[22m[2m)[22m[32m 38[2mms[22m[39m
|
|
343
345
|
[32m✓[39m [30m[46m browser [49m[39m test/sdk/account/refreshToken.browser.test.ts [2m([22m[2m1 test[22m[2m)[22m[32m 6[2mms[22m[39m
|
|
344
|
-
[32m✓[39m [30m[
|
|
346
|
+
[32m✓[39m [30m[43m node [49m[39m test/server/password-protection-service.test.ts [2m([22m[2m22 tests[22m[2m)[22m[32m 32[2mms[22m[39m
|
|
345
347
|
[32m✓[39m [30m[43m node [49m[39m test/utils/match-url.test.ts [2m([22m[2m10 tests[22m[2m)[22m[32m 9[2mms[22m[39m
|
|
346
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
347
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
348
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/localization/useBindingSelector.test.tsx [2m([22m[2m22 tests[22m[2m)[22m[32m 13[2mms[22m[39m
|
|
349
|
+
[32m✓[39m [30m[43m node [49m[39m test/pages/api/unlock.test.ts [2m([22m[2m15 tests[22m[2m)[22m[32m 159[2mms[22m[39m
|
|
348
350
|
[32m✓[39m [30m[43m node [49m[39m test/sdk/localization/bindingSelector.test.ts [2m([22m[2m18 tests[22m[2m)[22m[32m 9[2mms[22m[39m
|
|
349
351
|
[90mstderr[2m | test/components/search/SearchInputComponent.test.tsx
|
|
350
352
|
[22m[39mWarning: forwardRef render functions accept exactly two parameters: props and ref. Did you forget to use the ref parameter?
|
|
@@ -409,19 +411,19 @@ Warning: React does not recognize the `providerProps` prop on a DOM element. If
|
|
|
409
411
|
at Suspense
|
|
410
412
|
at Wrapper (/home/runner/work/faststore/faststore/packages/core/test/components/search/SearchInputComponent.test.tsx:106:20)
|
|
411
413
|
|
|
412
|
-
[32m✓[39m [30m[43m node [49m[39m test/components/search/SearchInputComponent.test.tsx [2m([22m[2m6 tests[22m[2m)[22m[32m
|
|
413
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/search/useSearchHistory.test.ts [2m([22m[2m13 tests[22m[2m)[22m[32m
|
|
414
|
-
[32m✓[39m [30m[43m node [49m[39m test/utils/cookieCacheBusting.test.ts [2m([22m[2m10 tests[22m[2m)[22m[32m
|
|
414
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/search/SearchInputComponent.test.tsx [2m([22m[2m6 tests[22m[2m)[22m[32m 72[2mms[22m[39m
|
|
415
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/search/useSearchHistory.test.ts [2m([22m[2m13 tests[22m[2m)[22m[32m 53[2mms[22m[39m
|
|
416
|
+
[32m✓[39m [30m[43m node [49m[39m test/utils/cookieCacheBusting.test.ts [2m([22m[2m10 tests[22m[2m)[22m[32m 11[2mms[22m[39m
|
|
415
417
|
[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
|
|
416
418
|
[22m[39m{ extensions: { status: [33m401[39m } }
|
|
417
419
|
|
|
418
420
|
[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
|
|
419
421
|
[22m[39m{ extensions: { status: [33m502[39m } }
|
|
420
422
|
|
|
421
|
-
[32m✓[39m [30m[43m node [49m[39m test/pages/pvt/account/cards/index.test.ts [2m([22m[2m8 tests[22m[2m)[22m[32m
|
|
422
|
-
[32m✓[39m [30m[43m node [49m[39m test/utils/clearCookies.test.ts [2m([22m[2m20 tests[22m[2m)[22m[32m
|
|
423
|
-
[32m✓[39m [30m[43m node [49m[39m test/experimental/myAccountCmsServerSideProps.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m
|
|
424
|
-
[32m✓[39m [30m[43m node [49m[39m test/components/quotes/MyAccountListQuotesTable.test.tsx [2m([22m[2m12 tests[22m[2m)[22m[33m
|
|
423
|
+
[32m✓[39m [30m[43m node [49m[39m test/pages/pvt/account/cards/index.test.ts [2m([22m[2m8 tests[22m[2m)[22m[32m 8[2mms[22m[39m
|
|
424
|
+
[32m✓[39m [30m[43m node [49m[39m test/utils/clearCookies.test.ts [2m([22m[2m20 tests[22m[2m)[22m[32m 21[2mms[22m[39m
|
|
425
|
+
[32m✓[39m [30m[43m node [49m[39m test/experimental/myAccountCmsServerSideProps.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m 9[2mms[22m[39m
|
|
426
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/quotes/MyAccountListQuotesTable.test.tsx [2m([22m[2m12 tests[22m[2m)[22m[33m 385[2mms[22m[39m
|
|
425
427
|
[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
|
|
426
428
|
[22m[39mGraphql execution returned with error: [
|
|
427
429
|
{
|
|
@@ -470,7 +472,7 @@ Warning: React does not recognize the `providerProps` prop on a DOM element. If
|
|
|
470
472
|
|
|
471
473
|
[90mstderr[2m | test/pages/api/graphql.test.ts[2m > [22m[2m/api/graphql request handling[2m > [22m[2mmaps BadRequestError thrown by execute to its status
|
|
472
474
|
[22m[39mSomething unexpected occurred querying Graphql endpoint:
|
|
473
|
-
|
|
475
|
+
T [FastStoreError]: malformed
|
|
474
476
|
at [90m/home/runner/work/faststore/faststore/packages/core/[39mtest/pages/api/graphql.test.ts:190:31
|
|
475
477
|
at [90m/home/runner/work/faststore/faststore/packages/core/[39mtest/pages/api/graphql.test.ts:196:39
|
|
476
478
|
at 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:1024:60
|
|
@@ -514,68 +516,67 @@ Warning: React does not recognize the `providerProps` prop on a DOM element. If
|
|
|
514
516
|
at 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:37
|
|
515
517
|
at Traces.$ (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/traces.CCmnQaNT.js:142:27)
|
|
516
518
|
|
|
517
|
-
[32m✓[39m [30m[43m node [49m[39m test/pages/api/graphql.test.ts [2m([22m[2m17 tests[22m[2m)[22m[32m
|
|
518
|
-
[32m✓[39m [30m[43m node [49m[39m test/components/quotes/MyAccountListQuotes.test.tsx [2m([22m[2m9 tests[22m[2m)[22m[33m
|
|
519
|
-
[33m[2m✓[22m[39m navigates with the search term on blur [33m
|
|
520
|
-
[33m[2m✓[22m[39m navigates without a label param when the search is cleared [33m
|
|
519
|
+
[32m✓[39m [30m[43m node [49m[39m test/pages/api/graphql.test.ts [2m([22m[2m17 tests[22m[2m)[22m[32m 25[2mms[22m[39m
|
|
520
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/quotes/MyAccountListQuotes.test.tsx [2m([22m[2m9 tests[22m[2m)[22m[33m 828[2mms[22m[39m
|
|
521
|
+
[33m[2m✓[22m[39m navigates with the search term on blur [33m 362[2mms[22m[39m
|
|
522
|
+
[33m[2m✓[22m[39m navigates without a label param when the search is cleared [33m 361[2mms[22m[39m
|
|
521
523
|
[90mstderr[2m | test/sdk/account/useSetPassword.test.ts[2m > [22m[2museSetPassword[2m > [22m[2mmaps wrongcredentials error responses to the existing message
|
|
522
524
|
[22m[39mSet password request failed: Bad Request
|
|
523
525
|
|
|
524
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/account/useSetPassword.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m
|
|
525
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
526
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
527
|
-
[32m✓[39m [30m[43m node [49m[39m test/utils/multipleTemplates.test.ts [2m([22m[2m8 tests[22m[2m)[22m[32m
|
|
528
|
-
[32m✓[39m [30m[43m node [49m[39m test/utils/localization/localizeRedirectDestination.test.ts [2m([22m[2m11 tests[22m[2m)[22m[32m
|
|
529
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/account/getMyAccountRoutes.test.ts [2m([22m[2m12 tests[22m[2m)[22m[32m
|
|
530
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/orderEntry/useOrderEntryUpload.test.ts [2m([22m[2m8 tests[22m[2m)[22m[32m
|
|
531
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/redirects/index.test.ts [2m([22m[2m7 tests[22m[2m)[22m[32m
|
|
532
|
-
[32m✓[39m [30m[43m node [49m[39m test/components/quotes/MyAccountQuotesFilterSlider.test.tsx [2m([22m[2m5 tests[22m[2m)[22m[32m
|
|
533
|
-
[32m✓[39m [30m[43m node [49m[39m test/utils/productJsonLd.test.ts [2m([22m[2m17 tests[22m[2m)[22m[32m
|
|
534
|
-
[32m✓[39m [30m[43m node [49m[39m test/proxy.localization.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m
|
|
535
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
[33m[2m✓[22m[39m should handle options and execute [33m 689[2mms[22m[39m
|
|
526
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/account/useSetPassword.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m 45[2mms[22m[39m
|
|
527
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/quotes/quoteFilters.test.ts [2m([22m[2m23 tests[22m[2m)[22m[32m 39[2mms[22m[39m
|
|
528
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/orderEntry/useOrderEntryOperation.test.ts [2m([22m[2m8 tests[22m[2m)[22m[32m 37[2mms[22m[39m
|
|
529
|
+
[32m✓[39m [30m[43m node [49m[39m test/utils/multipleTemplates.test.ts [2m([22m[2m8 tests[22m[2m)[22m[32m 6[2mms[22m[39m
|
|
530
|
+
[32m✓[39m [30m[43m node [49m[39m test/utils/localization/localizeRedirectDestination.test.ts [2m([22m[2m11 tests[22m[2m)[22m[32m 9[2mms[22m[39m
|
|
531
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/account/getMyAccountRoutes.test.ts [2m([22m[2m12 tests[22m[2m)[22m[32m 8[2mms[22m[39m
|
|
532
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/orderEntry/useOrderEntryUpload.test.ts [2m([22m[2m8 tests[22m[2m)[22m[32m 55[2mms[22m[39m
|
|
533
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/redirects/index.test.ts [2m([22m[2m7 tests[22m[2m)[22m[32m 59[2mms[22m[39m
|
|
534
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/quotes/MyAccountQuotesFilterSlider.test.tsx [2m([22m[2m5 tests[22m[2m)[22m[32m 148[2mms[22m[39m
|
|
535
|
+
[32m✓[39m [30m[43m node [49m[39m test/utils/productJsonLd.test.ts [2m([22m[2m17 tests[22m[2m)[22m[32m 11[2mms[22m[39m
|
|
536
|
+
[32m✓[39m [30m[43m node [49m[39m test/proxy.localization.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m 35[2mms[22m[39m
|
|
537
|
+
[32m✓[39m [30m[43m node [49m[39m test/server/index.test.ts [2m([22m[2m7 tests[22m[2m)[22m[33m 846[2mms[22m[39m
|
|
538
|
+
[33m[2m✓[22m[39m should return a valid merged GraphQL schema [33m 313[2mms[22m[39m
|
|
539
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/orderEntry/useOrderEntry.test.ts [2m([22m[2m8 tests[22m[2m)[22m[32m 59[2mms[22m[39m
|
|
539
540
|
[32m✓[39m [30m[43m node [49m[39m test/sdk/session/syncSalesChannelFromOrderForm.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m 7[2mms[22m[39m
|
|
540
|
-
[32m✓[39m [30m[43m node [49m[39m test/components/quotes/MyAccountQuotesSelectedTags.test.tsx [2m([22m[2m8 tests[22m[2m)[22m[32m
|
|
541
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/analytics/useStartRecommendationSession.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m
|
|
542
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
543
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
544
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/
|
|
545
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
546
|
-
[32m✓[39m [30m[43m node [49m[39m test/server/
|
|
547
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
548
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/account/refreshToken.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m
|
|
549
|
-
[32m✓[39m [30m[43m node [49m[39m test/utils/productJsonLdRendering.test.tsx [2m([22m[2m4 tests[22m[2m)[22m[32m
|
|
550
|
-
[32m✓[39m [30m[43m node [49m[39m test/server/cms/global.test.ts [2m([22m[2m3 tests[22m[2m)[22m[32m
|
|
551
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/localization/store-url.test.ts [2m([22m[2m1 test[22m[2m)[22m[32m
|
|
552
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/auth/useAuth.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m
|
|
553
|
-
[32m✓[39m [30m[43m node [49m[39m test/components/quotes/MyAccountQuotesStatusSelector.test.tsx [2m([22m[2m6 tests[22m[2m)[22m[32m
|
|
541
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/quotes/MyAccountQuotesSelectedTags.test.tsx [2m([22m[2m8 tests[22m[2m)[22m[32m 88[2mms[22m[39m
|
|
542
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/analytics/useStartRecommendationSession.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m 42[2mms[22m[39m
|
|
543
|
+
[32m✓[39m [30m[43m node [49m[39m test/proxy.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m 20[2mms[22m[39m
|
|
544
|
+
[32m✓[39m [30m[43m node [49m[39m test/server/webops-api.test.ts [2m([22m[2m9 tests[22m[2m)[22m[32m 18[2mms[22m[39m
|
|
545
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/orderEntry/useOrderFormItems.test.ts [2m([22m[2m7 tests[22m[2m)[22m[32m 36[2mms[22m[39m
|
|
546
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/cart/waitForSessionValidated.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m 10[2mms[22m[39m
|
|
547
|
+
[32m✓[39m [30m[43m node [49m[39m test/server/cms/myAccountDefaultSections.test.ts [2m([22m[2m7 tests[22m[2m)[22m[32m 5[2mms[22m[39m
|
|
548
|
+
[32m✓[39m [30m[43m node [49m[39m test/server/content/service.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m 5[2mms[22m[39m
|
|
549
|
+
[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
|
|
550
|
+
[32m✓[39m [30m[43m node [49m[39m test/utils/productJsonLdRendering.test.tsx [2m([22m[2m4 tests[22m[2m)[22m[32m 12[2mms[22m[39m
|
|
551
|
+
[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
|
|
552
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/localization/store-url.test.ts [2m([22m[2m1 test[22m[2m)[22m[32m 4[2mms[22m[39m
|
|
553
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/auth/useAuth.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m 34[2mms[22m[39m
|
|
554
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/quotes/MyAccountQuotesStatusSelector.test.tsx [2m([22m[2m6 tests[22m[2m)[22m[32m 127[2mms[22m[39m
|
|
554
555
|
[32m✓[39m [30m[43m node [49m[39m test/utils/getRequestHostname.test.ts [2m([22m[2m12 tests[22m[2m)[22m[32m 7[2mms[22m[39m
|
|
555
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
556
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
557
|
-
[32m✓[39m [30m[43m node [49m[39m test/utils/validateSessionRefreshToken.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m
|
|
558
|
-
[32m✓[39m [30m[43m node [49m[39m test/components/
|
|
559
|
-
[32m✓[39m [30m[43m node [49m[39m test/components/
|
|
560
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/recommendations/vrn.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m
|
|
561
|
-
[32m✓[39m [30m[43m node [49m[39m test/utils/retry.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m
|
|
562
|
-
[32m✓[39m [30m[43m node [49m[39m test/server/cms/index.test.ts [2m([22m[2m2 tests[22m[2m)[22m[32m
|
|
556
|
+
[32m✓[39m [30m[43m node [49m[39m test/server/rootSpan.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m 41[2mms[22m[39m
|
|
557
|
+
[32m✓[39m [30m[43m node [49m[39m test/pages/api/preview.test.ts [2m([22m[2m2 tests[22m[2m)[22m[32m 8[2mms[22m[39m
|
|
558
|
+
[32m✓[39m [30m[43m node [49m[39m test/utils/validateSessionRefreshToken.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m 5[2mms[22m[39m
|
|
559
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/account/Layout.test.tsx [2m([22m[2m6 tests[22m[2m)[22m[32m 61[2mms[22m[39m
|
|
560
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/search/SearchInput.test.ts [2m([22m[2m6 tests[22m[2m)[22m[32m 8[2mms[22m[39m
|
|
561
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/recommendations/vrn.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m 6[2mms[22m[39m
|
|
562
|
+
[32m✓[39m [30m[43m node [49m[39m test/utils/retry.test.ts [2m([22m[2m5 tests[22m[2m)[22m[32m 14[2mms[22m[39m
|
|
563
|
+
[32m✓[39m [30m[43m node [49m[39m test/server/cms/index.test.ts [2m([22m[2m2 tests[22m[2m)[22m[32m 5[2mms[22m[39m
|
|
563
564
|
[32m✓[39m [30m[43m node [49m[39m test/sdk/account/getB2BSessionClaims.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m 5[2mms[22m[39m
|
|
564
|
-
[32m✓[39m [30m[43m node [49m[39m test/utils/unlockResponse.test.ts [2m([22m[2m11 tests[22m[2m)[22m[32m
|
|
565
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/recommendations/useRecommendations.test.ts [2m([22m[2m2 tests[22m[2m)[22m[32m
|
|
566
|
-
[32m✓[39m [30m[43m node [49m[39m test/sdk/recommendations/useRecommendationUserId.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m
|
|
567
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
568
|
-
[32m✓[39m [30m[43m node [49m[39m test/utils/
|
|
569
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
565
|
+
[32m✓[39m [30m[43m node [49m[39m test/utils/unlockResponse.test.ts [2m([22m[2m11 tests[22m[2m)[22m[32m 7[2mms[22m[39m
|
|
566
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/recommendations/useRecommendations.test.ts [2m([22m[2m2 tests[22m[2m)[22m[32m 3[2mms[22m[39m
|
|
567
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/recommendations/useRecommendationUserId.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m 185[2mms[22m[39m
|
|
568
|
+
[32m✓[39m [30m[43m node [49m[39m test/utils/isLocalHost.test.ts [2m([22m[2m7 tests[22m[2m)[22m[32m 5[2mms[22m[39m
|
|
569
|
+
[32m✓[39m [30m[43m node [49m[39m test/utils/userOrderStatus.test.ts [2m([22m[2m3 tests[22m[2m)[22m[32m 4[2mms[22m[39m
|
|
570
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/account/OrganizationDrawerBody.test.tsx [2m([22m[2m3 tests[22m[2m)[22m[32m 44[2mms[22m[39m
|
|
570
571
|
[32m✓[39m [30m[43m node [49m[39m test/utils/getCookie.test.ts [2m([22m[2m4 tests[22m[2m)[22m[32m 5[2mms[22m[39m
|
|
571
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
572
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
573
|
-
[32m✓[39m [30m[43m node [49m[39m test/instrumentation.test.ts [2m([22m[2m3 tests[22m[2m)[22m[32m
|
|
574
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
575
|
-
[32m✓[39m [30m[43m node [49m[39m test/
|
|
576
|
-
|
|
577
|
-
[2m Test Files [22m [1m[
|
|
578
|
-
[2m Tests [22m [1m[
|
|
579
|
-
[2m Start at [22m
|
|
580
|
-
[2m Duration [22m
|
|
572
|
+
[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
|
|
573
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/auth/ProfileChallenge.test.tsx [2m([22m[2m3 tests[22m[2m)[22m[32m 32[2mms[22m[39m
|
|
574
|
+
[32m✓[39m [30m[43m node [49m[39m test/instrumentation.test.ts [2m([22m[2m3 tests[22m[2m)[22m[32m 6[2mms[22m[39m
|
|
575
|
+
[32m✓[39m [30m[43m node [49m[39m test/sdk/account/clearPersistedSessionState.test.ts [2m([22m[2m1 test[22m[2m)[22m[32m 11[2mms[22m[39m
|
|
576
|
+
[32m✓[39m [30m[43m node [49m[39m test/components/quotes/MyAccountQuoteStatusBadge.test.tsx [2m([22m[2m2 tests[22m[2m)[22m[32m 24[2mms[22m[39m
|
|
577
|
+
|
|
578
|
+
[2m Test Files [22m [1m[32m93 passed[39m[22m[90m (93)[39m
|
|
579
|
+
[2m Tests [22m [1m[32m742 passed[39m[22m[90m (742)[39m
|
|
580
|
+
[2m Start at [22m 13:03:37
|
|
581
|
+
[2m Duration [22m 44.11s[2m (transform 12.29s, setup 0ms, import 41.01s, tests 13.32s, environment 54.59s)[22m
|
|
581
582
|
|
package/@generated/gql.ts
CHANGED
|
@@ -30,7 +30,7 @@ type Documents = {
|
|
|
30
30
|
"\n fragment ServerProduct on Query {\n product(locator: $locator) {\n id: productID\n }\n }\n": typeof types.ServerProductFragmentDoc,
|
|
31
31
|
"\n query ServerAccountPageQuery {\n accountProfile {\n name\n }\n }\n": typeof types.ServerAccountPageQueryDocument,
|
|
32
32
|
"\n query ServerCollectionPageQuery($slug: String!) {\n ...ServerCollectionPage\n collection(slug: $slug) {\n seo {\n title\n description\n }\n breadcrumbList {\n itemListElement {\n item\n name\n position\n }\n }\n meta {\n selectedFacets {\n key\n value\n }\n }\n otherLocales {\n locale\n slug\n }\n }\n }\n": typeof types.ServerCollectionPageQueryDocument,
|
|
33
|
-
"\n query ServerProductQuery($locator: [IStoreSelectedFacet!]!) {\n ...ServerProduct\n product(locator: $locator) {\n id: productID\n\n seo {\n title\n description\n canonical\n }\n\n brand {\n name\n }\n\n sku\n gtin\n mpn\n name\n description\n releaseDate\n\n breadcrumbList {\n itemListElement {\n item\n name\n position\n }\n }\n\n image {\n url\n alternateName\n }\n\n offers {\n lowPrice\n highPrice\n lowPriceWithTaxes\n priceCurrency\n offers {\n availability\n price\n priceValidUntil\n priceCurrency\n itemCondition\n priceToken\n seller {\n identifier\n }\n }\n }\n\n isVariantOf {\n productGroupID\n }\n\n otherLocales {\n locale\n slug\n }\n\n ...ProductDetailsFragment_product\n }\n }\n": typeof types.ServerProductQueryDocument,
|
|
33
|
+
"\n query ServerProductQuery($locator: [IStoreSelectedFacet!]!) {\n ...ServerProduct\n product(locator: $locator) {\n id: productID\n\n seo {\n title\n description\n canonical\n }\n\n brand {\n name\n }\n\n sku\n gtin\n mpn\n name\n description\n releaseDate\n\n breadcrumbList {\n itemListElement {\n item\n name\n position\n }\n }\n\n image {\n url\n alternateName\n }\n\n offers {\n lowPrice\n highPrice\n lowPriceWithTaxes\n priceCurrency\n offers {\n availability\n price\n priceValidUntil\n priceCurrency\n itemCondition\n priceToken\n seller {\n identifier\n }\n }\n }\n\n isVariantOf {\n productGroupID\n }\n\n otherLocales {\n locale\n slug\n }\n\n defaultLocaleSlug\n\n ...ProductDetailsFragment_product\n }\n }\n": typeof types.ServerProductQueryDocument,
|
|
34
34
|
"\n query ServerListCardsQuery {\n listCreditCards {\n list {\n accountId\n bin\n cardNumber\n cardLabel\n paymentSystem\n paymentSystemName\n isDefault\n isActive\n origin\n }\n }\n accountProfile {\n name\n }\n hasAdHocCardAccess\n }\n": typeof types.ServerListCardsQueryDocument,
|
|
35
35
|
"\n fragment UserOrderItemsFragment on UserOrderItems {\n id\n name\n quantity\n sellingPrice\n unitMultiplier\n measurementUnit\n imageUrl\n detailUrl\n refId\n rewardValue\n }\n": typeof types.UserOrderItemsFragmentFragmentDoc,
|
|
36
36
|
"\n query ServerOrderDetailsQuery($orderId: String!) {\n userOrder(orderId: $orderId) {\n orderId\n creationDate\n status\n canProcessOrderAuthorization\n statusDescription\n allowCancellation\n ruleForAuthorization {\n orderAuthorizationId\n dimensionId\n rule {\n id\n name\n status\n doId\n authorizedEmails\n priority\n trigger {\n condition {\n conditionType\n description\n lessThan\n greatherThan\n expression\n }\n effect {\n description\n effectType\n funcPath\n }\n }\n timeout\n notification\n scoreInterval {\n accept\n deny\n }\n authorizationData {\n requireAllApprovals\n authorizers {\n id\n email\n type\n authorizationDate\n }\n }\n isUserAuthorized\n isUserNextAuthorizer\n }\n }\n storePreferencesData {\n currencyCode\n }\n clientProfileData {\n firstName\n lastName\n email\n phone\n corporateName\n isCorporate\n }\n customFields {\n type\n id\n fields {\n name\n value\n refId\n }\n }\n deliveryOptionsData {\n deliveryOptions {\n selectedSla\n deliveryChannel\n deliveryCompany\n deliveryWindow {\n startDateUtc\n endDateUtc\n price\n }\n shippingEstimate\n shippingEstimateDate\n friendlyShippingEstimate\n friendlyDeliveryOptionName\n seller\n address {\n addressType\n receiverName\n addressId\n versionId\n entityId\n postalCode\n city\n state\n country\n street\n number\n neighborhood\n complement\n reference\n geoCoordinates\n }\n pickupStoreInfo {\n additionalInfo\n address {\n addressType\n receiverName\n addressId\n versionId\n entityId\n postalCode\n city\n state\n country\n street\n number\n neighborhood\n complement\n reference\n geoCoordinates\n }\n dockId\n friendlyName\n isPickupStore\n }\n quantityOfDifferentItems\n total\n items {\n id\n uniqueId\n name\n quantity\n price\n sellingPrice\n imageUrl\n tax\n taxPriceTagsTotal\n total\n }\n }\n contact {\n email\n phone\n name\n }\n }\n paymentData {\n transactions {\n isActive\n payments {\n id\n paymentSystemName\n value\n installments\n referenceValue\n lastDigits\n url\n group\n tid\n connectorResponses {\n authId\n }\n bankIssuedInvoiceIdentificationNumber\n redemptionCode\n paymentOrigin\n }\n }\n }\n totals {\n id\n name\n value\n }\n shopper {\n firstName\n lastName\n email\n phone\n }\n budgetData {\n budgets {\n id\n name\n balance {\n remaining\n }\n allocations {\n id\n linkedEntity {\n id\n }\n reservations\n }\n }\n }\n }\n accountProfile {\n name\n }\n }\n": typeof types.ServerOrderDetailsQueryDocument,
|
|
@@ -83,7 +83,7 @@ const documents: Documents = {
|
|
|
83
83
|
"\n fragment ServerProduct on Query {\n product(locator: $locator) {\n id: productID\n }\n }\n": types.ServerProductFragmentDoc,
|
|
84
84
|
"\n query ServerAccountPageQuery {\n accountProfile {\n name\n }\n }\n": types.ServerAccountPageQueryDocument,
|
|
85
85
|
"\n query ServerCollectionPageQuery($slug: String!) {\n ...ServerCollectionPage\n collection(slug: $slug) {\n seo {\n title\n description\n }\n breadcrumbList {\n itemListElement {\n item\n name\n position\n }\n }\n meta {\n selectedFacets {\n key\n value\n }\n }\n otherLocales {\n locale\n slug\n }\n }\n }\n": types.ServerCollectionPageQueryDocument,
|
|
86
|
-
"\n query ServerProductQuery($locator: [IStoreSelectedFacet!]!) {\n ...ServerProduct\n product(locator: $locator) {\n id: productID\n\n seo {\n title\n description\n canonical\n }\n\n brand {\n name\n }\n\n sku\n gtin\n mpn\n name\n description\n releaseDate\n\n breadcrumbList {\n itemListElement {\n item\n name\n position\n }\n }\n\n image {\n url\n alternateName\n }\n\n offers {\n lowPrice\n highPrice\n lowPriceWithTaxes\n priceCurrency\n offers {\n availability\n price\n priceValidUntil\n priceCurrency\n itemCondition\n priceToken\n seller {\n identifier\n }\n }\n }\n\n isVariantOf {\n productGroupID\n }\n\n otherLocales {\n locale\n slug\n }\n\n ...ProductDetailsFragment_product\n }\n }\n": types.ServerProductQueryDocument,
|
|
86
|
+
"\n query ServerProductQuery($locator: [IStoreSelectedFacet!]!) {\n ...ServerProduct\n product(locator: $locator) {\n id: productID\n\n seo {\n title\n description\n canonical\n }\n\n brand {\n name\n }\n\n sku\n gtin\n mpn\n name\n description\n releaseDate\n\n breadcrumbList {\n itemListElement {\n item\n name\n position\n }\n }\n\n image {\n url\n alternateName\n }\n\n offers {\n lowPrice\n highPrice\n lowPriceWithTaxes\n priceCurrency\n offers {\n availability\n price\n priceValidUntil\n priceCurrency\n itemCondition\n priceToken\n seller {\n identifier\n }\n }\n }\n\n isVariantOf {\n productGroupID\n }\n\n otherLocales {\n locale\n slug\n }\n\n defaultLocaleSlug\n\n ...ProductDetailsFragment_product\n }\n }\n": types.ServerProductQueryDocument,
|
|
87
87
|
"\n query ServerListCardsQuery {\n listCreditCards {\n list {\n accountId\n bin\n cardNumber\n cardLabel\n paymentSystem\n paymentSystemName\n isDefault\n isActive\n origin\n }\n }\n accountProfile {\n name\n }\n hasAdHocCardAccess\n }\n": types.ServerListCardsQueryDocument,
|
|
88
88
|
"\n fragment UserOrderItemsFragment on UserOrderItems {\n id\n name\n quantity\n sellingPrice\n unitMultiplier\n measurementUnit\n imageUrl\n detailUrl\n refId\n rewardValue\n }\n": types.UserOrderItemsFragmentFragmentDoc,
|
|
89
89
|
"\n query ServerOrderDetailsQuery($orderId: String!) {\n userOrder(orderId: $orderId) {\n orderId\n creationDate\n status\n canProcessOrderAuthorization\n statusDescription\n allowCancellation\n ruleForAuthorization {\n orderAuthorizationId\n dimensionId\n rule {\n id\n name\n status\n doId\n authorizedEmails\n priority\n trigger {\n condition {\n conditionType\n description\n lessThan\n greatherThan\n expression\n }\n effect {\n description\n effectType\n funcPath\n }\n }\n timeout\n notification\n scoreInterval {\n accept\n deny\n }\n authorizationData {\n requireAllApprovals\n authorizers {\n id\n email\n type\n authorizationDate\n }\n }\n isUserAuthorized\n isUserNextAuthorizer\n }\n }\n storePreferencesData {\n currencyCode\n }\n clientProfileData {\n firstName\n lastName\n email\n phone\n corporateName\n isCorporate\n }\n customFields {\n type\n id\n fields {\n name\n value\n refId\n }\n }\n deliveryOptionsData {\n deliveryOptions {\n selectedSla\n deliveryChannel\n deliveryCompany\n deliveryWindow {\n startDateUtc\n endDateUtc\n price\n }\n shippingEstimate\n shippingEstimateDate\n friendlyShippingEstimate\n friendlyDeliveryOptionName\n seller\n address {\n addressType\n receiverName\n addressId\n versionId\n entityId\n postalCode\n city\n state\n country\n street\n number\n neighborhood\n complement\n reference\n geoCoordinates\n }\n pickupStoreInfo {\n additionalInfo\n address {\n addressType\n receiverName\n addressId\n versionId\n entityId\n postalCode\n city\n state\n country\n street\n number\n neighborhood\n complement\n reference\n geoCoordinates\n }\n dockId\n friendlyName\n isPickupStore\n }\n quantityOfDifferentItems\n total\n items {\n id\n uniqueId\n name\n quantity\n price\n sellingPrice\n imageUrl\n tax\n taxPriceTagsTotal\n total\n }\n }\n contact {\n email\n phone\n name\n }\n }\n paymentData {\n transactions {\n isActive\n payments {\n id\n paymentSystemName\n value\n installments\n referenceValue\n lastDigits\n url\n group\n tid\n connectorResponses {\n authId\n }\n bankIssuedInvoiceIdentificationNumber\n redemptionCode\n paymentOrigin\n }\n }\n }\n totals {\n id\n name\n value\n }\n shopper {\n firstName\n lastName\n email\n phone\n }\n budgetData {\n budgets {\n id\n name\n balance {\n remaining\n }\n allocations {\n id\n linkedEntity {\n id\n }\n reservations\n }\n }\n }\n }\n accountProfile {\n name\n }\n }\n": types.ServerOrderDetailsQueryDocument,
|
|
@@ -184,7 +184,7 @@ export function gql(source: "\n query ServerCollectionPageQuery($slug: String!)
|
|
|
184
184
|
/**
|
|
185
185
|
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
|
186
186
|
*/
|
|
187
|
-
export function gql(source: "\n query ServerProductQuery($locator: [IStoreSelectedFacet!]!) {\n ...ServerProduct\n product(locator: $locator) {\n id: productID\n\n seo {\n title\n description\n canonical\n }\n\n brand {\n name\n }\n\n sku\n gtin\n mpn\n name\n description\n releaseDate\n\n breadcrumbList {\n itemListElement {\n item\n name\n position\n }\n }\n\n image {\n url\n alternateName\n }\n\n offers {\n lowPrice\n highPrice\n lowPriceWithTaxes\n priceCurrency\n offers {\n availability\n price\n priceValidUntil\n priceCurrency\n itemCondition\n priceToken\n seller {\n identifier\n }\n }\n }\n\n isVariantOf {\n productGroupID\n }\n\n otherLocales {\n locale\n slug\n }\n\n ...ProductDetailsFragment_product\n }\n }\n"): typeof import('./graphql').ServerProductQueryDocument;
|
|
187
|
+
export function gql(source: "\n query ServerProductQuery($locator: [IStoreSelectedFacet!]!) {\n ...ServerProduct\n product(locator: $locator) {\n id: productID\n\n seo {\n title\n description\n canonical\n }\n\n brand {\n name\n }\n\n sku\n gtin\n mpn\n name\n description\n releaseDate\n\n breadcrumbList {\n itemListElement {\n item\n name\n position\n }\n }\n\n image {\n url\n alternateName\n }\n\n offers {\n lowPrice\n highPrice\n lowPriceWithTaxes\n priceCurrency\n offers {\n availability\n price\n priceValidUntil\n priceCurrency\n itemCondition\n priceToken\n seller {\n identifier\n }\n }\n }\n\n isVariantOf {\n productGroupID\n }\n\n otherLocales {\n locale\n slug\n }\n\n defaultLocaleSlug\n\n ...ProductDetailsFragment_product\n }\n }\n"): typeof import('./graphql').ServerProductQueryDocument;
|
|
188
188
|
/**
|
|
189
189
|
* The gql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
|
190
190
|
*/
|
package/@generated/graphql.ts
CHANGED
|
@@ -1681,6 +1681,14 @@ export type StoreProduct = {
|
|
|
1681
1681
|
brand: StoreBrand;
|
|
1682
1682
|
/** List of items consisting of chain linked web pages, ending with the current page. */
|
|
1683
1683
|
breadcrumbList: StoreBreadcrumbList;
|
|
1684
|
+
/**
|
|
1685
|
+
* Slug for the store's default locale, including the SKU ID suffix.
|
|
1686
|
+
* Navigation fallback for the locale selector when the target locale is absent
|
|
1687
|
+
* from `otherLocales`. Best-effort: it may point at a slug the catalog has not
|
|
1688
|
+
* registered for the default locale, so it must never be used to build hreflang
|
|
1689
|
+
* annotations. Only populated when localization is enabled.
|
|
1690
|
+
*/
|
|
1691
|
+
defaultLocaleSlug: Maybe<Scalars['String']['output']>;
|
|
1684
1692
|
/** Delivery Promise product's badge. */
|
|
1685
1693
|
deliveryPromiseBadges: Maybe<Array<Maybe<DeliveryPromiseBadge>>>;
|
|
1686
1694
|
/** Product description. */
|
|
@@ -2819,7 +2827,7 @@ export type ServerProductQueryQueryVariables = Exact<{
|
|
|
2819
2827
|
}>;
|
|
2820
2828
|
|
|
2821
2829
|
|
|
2822
|
-
export type ServerProductQueryQuery = { product: { sku: string, gtin: string, mpn: string, name: string, description: string, releaseDate: string, unitMultiplier: number | null, id: string, seo: { title: string, description: string, canonical: string }, brand: { name: string }, breadcrumbList: { itemListElement: Array<{ item: string, name: string, position: number }> }, image: Array<{ url: string, alternateName: string }>, offers: { lowPrice: number, highPrice: number, lowPriceWithTaxes: number, priceCurrency: string, offers: Array<{ availability: string, price: number, priceValidUntil: string, priceCurrency: string, itemCondition: string, priceToken: string | null, priceWithTaxes: number, listPrice: number, listPriceWithTaxes: number, quantity: number, seller: { identifier: string } }> }, isVariantOf: { name: string, productGroupID: string, skuVariants: { activeVariations: any | null, slugsMap: any | null, availableVariations: any | null, allVariantProducts: Array<{ name: string, productID: string }> | null } | null }, otherLocales: Array<{ locale: string, slug: string }> | null, additionalProperty: Array<{ propertyID: string, name: string, value: any, valueReference: any }> } };
|
|
2830
|
+
export type ServerProductQueryQuery = { product: { sku: string, gtin: string, mpn: string, name: string, description: string, releaseDate: string, defaultLocaleSlug: string | null, unitMultiplier: number | null, id: string, seo: { title: string, description: string, canonical: string }, brand: { name: string }, breadcrumbList: { itemListElement: Array<{ item: string, name: string, position: number }> }, image: Array<{ url: string, alternateName: string }>, offers: { lowPrice: number, highPrice: number, lowPriceWithTaxes: number, priceCurrency: string, offers: Array<{ availability: string, price: number, priceValidUntil: string, priceCurrency: string, itemCondition: string, priceToken: string | null, priceWithTaxes: number, listPrice: number, listPriceWithTaxes: number, quantity: number, seller: { identifier: string } }> }, isVariantOf: { name: string, productGroupID: string, skuVariants: { activeVariations: any | null, slugsMap: any | null, availableVariations: any | null, allVariantProducts: Array<{ name: string, productID: string }> | null } | null }, otherLocales: Array<{ locale: string, slug: string }> | null, additionalProperty: Array<{ propertyID: string, name: string, value: any, valueReference: any }> } };
|
|
2823
2831
|
|
|
2824
2832
|
export type ServerListCardsQueryQueryVariables = Exact<{ [key: string]: never; }>;
|
|
2825
2833
|
|
|
@@ -3617,7 +3625,7 @@ export const SearchEvent_MetadataFragmentDoc = new TypedDocumentString(`
|
|
|
3617
3625
|
`, {"fragmentName":"SearchEvent_metadata"}) as unknown as TypedDocumentString<SearchEvent_MetadataFragment, unknown>;
|
|
3618
3626
|
export const ServerAccountPageQueryDocument = {"__meta__":{"operationName":"ServerAccountPageQuery","operationHash":"9baae331b75848a310fecb457e8c971ae27897ff"}} as unknown as TypedDocumentString<ServerAccountPageQueryQuery, ServerAccountPageQueryQueryVariables>;
|
|
3619
3627
|
export const ServerCollectionPageQueryDocument = {"__meta__":{"operationName":"ServerCollectionPageQuery","operationHash":"d46841b30ae1f6350021b5cf02f253d56c848664"}} as unknown as TypedDocumentString<ServerCollectionPageQueryQuery, ServerCollectionPageQueryQueryVariables>;
|
|
3620
|
-
export const ServerProductQueryDocument = {"__meta__":{"operationName":"ServerProductQuery","operationHash":"
|
|
3628
|
+
export const ServerProductQueryDocument = {"__meta__":{"operationName":"ServerProductQuery","operationHash":"13fc9efa8628b91971e3a8aa985e6cdbed70adae"}} as unknown as TypedDocumentString<ServerProductQueryQuery, ServerProductQueryQueryVariables>;
|
|
3621
3629
|
export const ServerListCardsQueryDocument = {"__meta__":{"operationName":"ServerListCardsQuery","operationHash":"392cf85d18d66b94d6ea8d6b2a3c6ffb5c94683d"}} as unknown as TypedDocumentString<ServerListCardsQueryQuery, ServerListCardsQueryQueryVariables>;
|
|
3622
3630
|
export const ServerOrderDetailsQueryDocument = {"__meta__":{"operationName":"ServerOrderDetailsQuery","operationHash":"bdf677bbccce12186a5ef15aebdce46585a99782"}} as unknown as TypedDocumentString<ServerOrderDetailsQueryQuery, ServerOrderDetailsQueryQueryVariables>;
|
|
3623
3631
|
export const ServerListOrdersQueryDocument = {"__meta__":{"operationName":"ServerListOrdersQuery","operationHash":"70d06de1da9c11f10ebde31b66fd74eccd456af5"}} as unknown as TypedDocumentString<ServerListOrdersQueryQuery, ServerListOrdersQueryQueryVariables>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"9baae331b75848a310fecb457e8c971ae27897ff": "query ServerAccountPageQuery { accountProfile { name } }",
|
|
3
3
|
"d46841b30ae1f6350021b5cf02f253d56c848664": "fragment ServerCollectionPage on Query { collection(slug: $slug) { id } } query ServerCollectionPageQuery($slug: String!) { collection(slug: $slug) { breadcrumbList { itemListElement { item name position } } meta { selectedFacets { key value } } otherLocales { locale slug } seo { description title } } ...ServerCollectionPage }",
|
|
4
|
-
"
|
|
4
|
+
"13fc9efa8628b91971e3a8aa985e6cdbed70adae": "fragment CartProductItem on StoreProduct { additionalProperty { name propertyID value valueReference } brand { name } gtin image { alternateName url } isVariantOf { name productGroupID skuVariants { activeVariations availableVariations slugsMap } } name sku unitMultiplier } fragment ProductDetailsFragment_product on StoreProduct { additionalProperty { name propertyID value valueReference } brand { name } description gtin image { alternateName url } isVariantOf { name productGroupID skuVariants { activeVariations allVariantProducts { name productID } availableVariations slugsMap } } name offers { lowPrice lowPriceWithTaxes offers { availability listPrice listPriceWithTaxes price priceToken priceWithTaxes quantity seller { identifier } } } id: productID sku unitMultiplier ...CartProductItem } fragment ServerProduct on Query { product(locator: $locator) { id: productID } } query ServerProductQuery($locator: [IStoreSelectedFacet!]!) { product(locator: $locator) { brand { name } breadcrumbList { itemListElement { item name position } } defaultLocaleSlug description gtin image { alternateName url } isVariantOf { productGroupID } mpn name offers { highPrice lowPrice lowPriceWithTaxes offers { availability itemCondition price priceCurrency priceToken priceValidUntil seller { identifier } } priceCurrency } otherLocales { locale slug } id: productID releaseDate seo { canonical description title } sku ...ProductDetailsFragment_product } ...ServerProduct }",
|
|
5
5
|
"392cf85d18d66b94d6ea8d6b2a3c6ffb5c94683d": "query ServerListCardsQuery { accountProfile { name } hasAdHocCardAccess listCreditCards { list { accountId bin cardLabel cardNumber isActive isDefault origin paymentSystem paymentSystemName } } }",
|
|
6
6
|
"bdf677bbccce12186a5ef15aebdce46585a99782": "query ServerOrderDetailsQuery($orderId: String!) { accountProfile { name } userOrder(orderId: $orderId) { allowCancellation budgetData { budgets { allocations { id linkedEntity { id } reservations } balance { remaining } id name } } canProcessOrderAuthorization clientProfileData { corporateName email firstName isCorporate lastName phone } creationDate customFields { fields { name refId value } id type } deliveryOptionsData { contact { email name phone } deliveryOptions { address { addressId addressType city complement country entityId geoCoordinates neighborhood number postalCode receiverName reference state street versionId } deliveryChannel deliveryCompany deliveryWindow { endDateUtc price startDateUtc } friendlyDeliveryOptionName friendlyShippingEstimate items { id imageUrl name price quantity sellingPrice tax taxPriceTagsTotal total uniqueId } pickupStoreInfo { additionalInfo address { addressId addressType city complement country entityId geoCoordinates neighborhood number postalCode receiverName reference state street versionId } dockId friendlyName isPickupStore } quantityOfDifferentItems selectedSla seller shippingEstimate shippingEstimateDate total } } orderId paymentData { transactions { isActive payments { bankIssuedInvoiceIdentificationNumber connectorResponses { authId } group id installments lastDigits paymentOrigin paymentSystemName redemptionCode referenceValue tid url value } } } ruleForAuthorization { dimensionId orderAuthorizationId rule { authorizationData { authorizers { authorizationDate email id type } requireAllApprovals } authorizedEmails doId id isUserAuthorized isUserNextAuthorizer name notification priority scoreInterval { accept deny } status timeout trigger { condition { conditionType description expression greatherThan lessThan } effect { description effectType funcPath } } } } shopper { email firstName lastName phone } status statusDescription storePreferencesData { currencyCode } totals { id name value } } }",
|
|
7
7
|
"70d06de1da9c11f10ebde31b66fd74eccd456af5": "query ServerListOrdersQuery($clientEmail: String, $dateFinal: String, $dateInitial: String, $page: Int, $pendingMyApproval: Boolean, $perPage: Int, $status: [String], $text: String) { accountProfile { name } listUserOrders( page: $page perPage: $perPage status: $status dateInitial: $dateInitial dateFinal: $dateFinal text: $text clientEmail: $clientEmail pendingMyApproval: $pendingMyApproval ) { list { ShippingEstimatedDate clientName creationDate currencyCode customFields { type value } items { description ean id price productId quantity refId seller sellingPrice } orderId status statusDescription totalValue } paging { currentPage pages perPage total } } }",
|
|
@@ -1735,6 +1735,14 @@ type StoreProduct {
|
|
|
1735
1735
|
Only populated when localization is enabled.
|
|
1736
1736
|
"""
|
|
1737
1737
|
otherLocales: [StoreProductLocale!]
|
|
1738
|
+
"""
|
|
1739
|
+
Slug for the store's default locale, including the SKU ID suffix.
|
|
1740
|
+
Navigation fallback for the locale selector when the target locale is absent
|
|
1741
|
+
from `otherLocales`. Best-effort: it may point at a slug the catalog has not
|
|
1742
|
+
registered for the default locale, so it must never be used to build hreflang
|
|
1743
|
+
annotations. Only populated when localization is enabled.
|
|
1744
|
+
"""
|
|
1745
|
+
defaultLocaleSlug: String
|
|
1738
1746
|
}
|
|
1739
1747
|
|
|
1740
1748
|
"""
|
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,16 @@
|
|
|
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.7.0-dev.9](https://github.com/vtex/faststore/compare/v4.7.0-dev.8...v4.7.0-dev.9) (2026-08-31)
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
- **api:** separate hreflang slugs from locale-switch navigation ([#3462](https://github.com/vtex/faststore/issues/3462)) ([3091a46](https://github.com/vtex/faststore/commit/3091a46031f387d1e11e5747dd0f4ac6bef358e2))
|
|
11
|
+
|
|
12
|
+
# [4.7.0-dev.8](https://github.com/vtex/faststore/compare/v4.7.0-dev.7...v4.7.0-dev.8) (2026-08-28)
|
|
13
|
+
|
|
14
|
+
**Note:** Version bump only for package @faststore/core
|
|
15
|
+
|
|
6
16
|
# [4.7.0-dev.7](https://github.com/vtex/faststore/compare/v4.7.0-dev.6...v4.7.0-dev.7) (2026-08-28)
|
|
7
17
|
|
|
8
18
|
### Bug Fixes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@faststore/core",
|
|
3
|
-
"version": "4.7.0-dev.
|
|
3
|
+
"version": "4.7.0-dev.9",
|
|
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.7.0-dev.
|
|
75
|
-
"@faststore/
|
|
76
|
-
"@faststore/
|
|
77
|
-
"@faststore/
|
|
78
|
-
"@faststore/
|
|
74
|
+
"@faststore/api": "4.7.0-dev.9",
|
|
75
|
+
"@faststore/lighthouse": "4.7.0-dev.9",
|
|
76
|
+
"@faststore/sdk": "4.7.0-dev.9",
|
|
77
|
+
"@faststore/ui": "4.7.0-dev.9",
|
|
78
|
+
"@faststore/diagnostics": "4.7.0-dev.9"
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
81
|
"@cypress/code-coverage": "^3.12.1",
|
|
@@ -42,8 +42,10 @@ const LocalizationButton = ({
|
|
|
42
42
|
const [isSelectorOpen, setIsSelectorOpen] = useState(false)
|
|
43
43
|
const buttonRef = useRef<HTMLButtonElement>(null)
|
|
44
44
|
|
|
45
|
-
const
|
|
46
|
-
const
|
|
45
|
+
const localizedProduct = useLocalizedProduct()
|
|
46
|
+
const otherLocales = localizedProduct?.otherLocales ?? undefined
|
|
47
|
+
const urlSuffix = localizedProduct?.urlSuffix ?? '/p'
|
|
48
|
+
const defaultLocaleSlug = localizedProduct?.defaultLocaleSlug ?? undefined
|
|
47
49
|
|
|
48
50
|
const {
|
|
49
51
|
languages,
|
|
@@ -56,7 +58,7 @@ const LocalizationButton = ({
|
|
|
56
58
|
reset,
|
|
57
59
|
isSaveEnabled,
|
|
58
60
|
error,
|
|
59
|
-
} = useBindingSelector(otherLocales, urlSuffix)
|
|
61
|
+
} = useBindingSelector(otherLocales, urlSuffix, defaultLocaleSlug)
|
|
60
62
|
|
|
61
63
|
const { locale: sessionLocale, currency: sessionCurrency } = useSession()
|
|
62
64
|
|
package/src/pages/[slug]/p.tsx
CHANGED
|
@@ -352,7 +352,10 @@ function Page({
|
|
|
352
352
|
If needed, wrap your component in a <Section /> component
|
|
353
353
|
(not the HTML tag) before rendering it here.
|
|
354
354
|
*/}
|
|
355
|
-
<LocalizedProductProvider
|
|
355
|
+
<LocalizedProductProvider
|
|
356
|
+
otherLocales={server.product.otherLocales}
|
|
357
|
+
defaultLocaleSlug={server.product.defaultLocaleSlug}
|
|
358
|
+
>
|
|
356
359
|
<PageProvider context={context}>
|
|
357
360
|
<RenderSections
|
|
358
361
|
sections={sections}
|
|
@@ -428,6 +431,8 @@ const query = gql(`
|
|
|
428
431
|
slug
|
|
429
432
|
}
|
|
430
433
|
|
|
434
|
+
defaultLocaleSlug
|
|
435
|
+
|
|
431
436
|
...ProductDetailsFragment_product
|
|
432
437
|
}
|
|
433
438
|
}
|
|
@@ -12,6 +12,12 @@ interface LocalizedProductData {
|
|
|
12
12
|
* Null when localization is disabled or the page type does not support it.
|
|
13
13
|
*/
|
|
14
14
|
otherLocales: LocalizedProductLocale[] | null
|
|
15
|
+
/**
|
|
16
|
+
* Slug for the store's default locale, used to navigate to a locale that is
|
|
17
|
+
* absent from `otherLocales`. Null outside PDPs, where the API does not
|
|
18
|
+
* provide one.
|
|
19
|
+
*/
|
|
20
|
+
defaultLocaleSlug: string | null
|
|
15
21
|
/**
|
|
16
22
|
* Suffix appended after the localized slug when building the redirect URL.
|
|
17
23
|
* Use '/p' for product pages (PDP), '' for collection/PLP pages.
|
|
@@ -24,6 +30,7 @@ const LocalizedProductContext = createContext<LocalizedProductData | null>(null)
|
|
|
24
30
|
type LocalizedProductProviderProps = Readonly<
|
|
25
31
|
PropsWithChildren<{
|
|
26
32
|
otherLocales: LocalizedProductLocale[] | null | undefined
|
|
33
|
+
defaultLocaleSlug?: string | null
|
|
27
34
|
/**
|
|
28
35
|
* Suffix to append to the localized slug when building the redirect URL.
|
|
29
36
|
* Defaults to '/p' (product pages). Pass '' for collection/PLP pages.
|
|
@@ -41,12 +48,17 @@ type LocalizedProductProviderProps = Readonly<
|
|
|
41
48
|
*/
|
|
42
49
|
export function LocalizedProductProvider({
|
|
43
50
|
otherLocales,
|
|
51
|
+
defaultLocaleSlug,
|
|
44
52
|
urlSuffix = '/p',
|
|
45
53
|
children,
|
|
46
54
|
}: LocalizedProductProviderProps) {
|
|
47
55
|
const value = useMemo(
|
|
48
|
-
() => ({
|
|
49
|
-
|
|
56
|
+
() => ({
|
|
57
|
+
otherLocales: otherLocales ?? null,
|
|
58
|
+
defaultLocaleSlug: defaultLocaleSlug ?? null,
|
|
59
|
+
urlSuffix,
|
|
60
|
+
}),
|
|
61
|
+
[otherLocales, defaultLocaleSlug, urlSuffix]
|
|
50
62
|
)
|
|
51
63
|
|
|
52
64
|
return (
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { LocalizedProductLocale } from './LocalizedProductContext'
|
|
1
2
|
import type { Binding, Locale } from './types'
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -74,6 +75,43 @@ export function resolveBinding(
|
|
|
74
75
|
return matches.find((b) => b.isDefault) ?? matches[0]
|
|
75
76
|
}
|
|
76
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Resolves which product slug the locale selector should navigate to.
|
|
80
|
+
*
|
|
81
|
+
* Falls back to the default locale's slug rather than to any other entry, so a
|
|
82
|
+
* translated slug is never carried across locales (e.g. an Italian slug served
|
|
83
|
+
* under an es-ES prefix).
|
|
84
|
+
*
|
|
85
|
+
* `otherLocales` only carries locales the catalog has a registered slug for, so
|
|
86
|
+
* an untranslated product has no entry at all — not even for the default
|
|
87
|
+
* locale. `defaultLocaleSlug` covers that gap: the API resolves it best-effort
|
|
88
|
+
* so navigation lands on the product page instead of the locale root.
|
|
89
|
+
*
|
|
90
|
+
* @param otherLocales - Registered localized slugs for the current product
|
|
91
|
+
* @param targetLocale - Locale the shopper is switching to
|
|
92
|
+
* @param defaultLocale - The store's default locale
|
|
93
|
+
* @param defaultLocaleSlug - Best-effort default-locale slug, PDP only
|
|
94
|
+
* @returns The slug to redirect to, or null when none is available
|
|
95
|
+
*/
|
|
96
|
+
export function resolveTargetSlug({
|
|
97
|
+
otherLocales,
|
|
98
|
+
targetLocale,
|
|
99
|
+
defaultLocale,
|
|
100
|
+
defaultLocaleSlug,
|
|
101
|
+
}: {
|
|
102
|
+
otherLocales: LocalizedProductLocale[] | null | undefined
|
|
103
|
+
targetLocale: string
|
|
104
|
+
defaultLocale: string
|
|
105
|
+
defaultLocaleSlug?: string | null
|
|
106
|
+
}): string | null {
|
|
107
|
+
return (
|
|
108
|
+
otherLocales?.find((e) => e.locale === targetLocale)?.slug ??
|
|
109
|
+
otherLocales?.find((e) => e.locale === defaultLocale)?.slug ??
|
|
110
|
+
defaultLocaleSlug ??
|
|
111
|
+
null
|
|
112
|
+
)
|
|
113
|
+
}
|
|
114
|
+
|
|
77
115
|
/**
|
|
78
116
|
* Validates that a URL is non-empty and appears to be valid.
|
|
79
117
|
*
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
getCurrenciesForLocale,
|
|
9
9
|
isValidUrl,
|
|
10
10
|
resolveBinding,
|
|
11
|
+
resolveTargetSlug,
|
|
11
12
|
} from './bindingSelector'
|
|
12
13
|
import type { LocalizedProductLocale } from './LocalizedProductContext'
|
|
13
14
|
import type { BindingSelectorError, Locale } from './types'
|
|
@@ -147,11 +148,14 @@ export interface UseBindingSelectorReturn {
|
|
|
147
148
|
* localized page URL instead of preserving the current page path verbatim.
|
|
148
149
|
* @param urlSuffix - Suffix appended after the slug when building the redirect URL.
|
|
149
150
|
* Use '/p' for product pages (default) and '' for collection/PLP pages.
|
|
151
|
+
* @param defaultLocaleSlug - Slug for the store's default locale, used when the
|
|
152
|
+
* target locale is absent from `otherLocales`. PDP only; PLPs pass nothing.
|
|
150
153
|
* @returns Object with languages, currencies, selections, and actions
|
|
151
154
|
*/
|
|
152
155
|
export function useBindingSelector(
|
|
153
156
|
otherLocales?: Array<{ locale: string; slug: string }> | null,
|
|
154
|
-
urlSuffix = '/p'
|
|
157
|
+
urlSuffix = '/p',
|
|
158
|
+
defaultLocaleSlug?: string | null
|
|
155
159
|
): UseBindingSelectorReturn {
|
|
156
160
|
const { locale: currentLocale, currency: currentCurrency } = useSession()
|
|
157
161
|
const localizationConfig = storeConfig.localization as LocalizationConfig
|
|
@@ -284,27 +288,17 @@ export function useBindingSelector(
|
|
|
284
288
|
? otherLocales
|
|
285
289
|
: recoverOtherLocales()
|
|
286
290
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
(e) => e.locale === localizationConfig.defaultLocale
|
|
299
|
-
)
|
|
300
|
-
|
|
301
|
-
const entry = localizedEntry ?? fallbackEntry
|
|
302
|
-
|
|
303
|
-
if (entry) {
|
|
304
|
-
const baseUrl = binding.url.replace(/\/$/, '')
|
|
305
|
-
globalThis.location.href = `${baseUrl}/${entry.slug}${urlSuffix}${globalThis.location.search}${globalThis.location.hash}`
|
|
306
|
-
return
|
|
307
|
-
}
|
|
291
|
+
const slug = resolveTargetSlug({
|
|
292
|
+
otherLocales: effectiveOtherLocales,
|
|
293
|
+
targetLocale: localeCode,
|
|
294
|
+
defaultLocale: localizationConfig.defaultLocale,
|
|
295
|
+
defaultLocaleSlug,
|
|
296
|
+
})
|
|
297
|
+
|
|
298
|
+
if (slug) {
|
|
299
|
+
const baseUrl = binding.url.replace(/\/$/, '')
|
|
300
|
+
globalThis.location.href = `${baseUrl}/${slug}${urlSuffix}${globalThis.location.search}${globalThis.location.hash}`
|
|
301
|
+
return
|
|
308
302
|
}
|
|
309
303
|
|
|
310
304
|
// otherLocales is empty/null but we're still on a PDP: strip the stale slug.
|
|
@@ -329,6 +323,7 @@ export function useBindingSelector(
|
|
|
329
323
|
localizationConfig.defaultLocale,
|
|
330
324
|
otherLocales,
|
|
331
325
|
urlSuffix,
|
|
326
|
+
defaultLocaleSlug,
|
|
332
327
|
])
|
|
333
328
|
|
|
334
329
|
const isSaveEnabled = Boolean(localeCode && currencyCode && !error)
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { cleanup, render } from '@testing-library/react'
|
|
2
|
+
import { afterEach, describe, expect, it, vi } from 'vitest'
|
|
3
|
+
|
|
4
|
+
const mockUseBindingSelector = vi.hoisted(() =>
|
|
5
|
+
vi.fn(() => ({
|
|
6
|
+
languages: { 'en-US': 'English' },
|
|
7
|
+
currencies: { USD: 'USD' },
|
|
8
|
+
localeCode: 'en-US',
|
|
9
|
+
currencyCode: 'USD',
|
|
10
|
+
setLocaleCode: vi.fn(),
|
|
11
|
+
setCurrencyCode: vi.fn(),
|
|
12
|
+
save: vi.fn(),
|
|
13
|
+
reset: vi.fn(),
|
|
14
|
+
isSaveEnabled: true,
|
|
15
|
+
error: null,
|
|
16
|
+
}))
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
vi.mock('src/sdk/localization', () => ({
|
|
20
|
+
useBindingSelector: mockUseBindingSelector,
|
|
21
|
+
}))
|
|
22
|
+
|
|
23
|
+
vi.mock('src/sdk/session', () => ({
|
|
24
|
+
useSession: () => ({ locale: 'pt-BR', currency: { code: 'BRL' } }),
|
|
25
|
+
}))
|
|
26
|
+
|
|
27
|
+
vi.mock('discovery.config', async (importOriginal) => {
|
|
28
|
+
const original = await importOriginal<{ default: Record<string, unknown> }>()
|
|
29
|
+
|
|
30
|
+
return { default: { ...original.default, localization: { enabled: true } } }
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
import LocalizationButton from 'src/components/ui/LocalizationButton'
|
|
34
|
+
import { LocalizedProductProvider } from 'src/sdk/localization/LocalizedProductContext'
|
|
35
|
+
|
|
36
|
+
const OTHER_LOCALES = [
|
|
37
|
+
{ locale: 'en-US', slug: 'roshe-tenis-76' },
|
|
38
|
+
{ locale: 'pt-BR', slug: 'tenis-roshe-76' },
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
afterEach(() => {
|
|
42
|
+
cleanup()
|
|
43
|
+
mockUseBindingSelector.mockClear()
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
describe('LocalizationButton', () => {
|
|
47
|
+
it('forwards both slug sources from the product context to the selector', () => {
|
|
48
|
+
render(
|
|
49
|
+
<LocalizedProductProvider
|
|
50
|
+
otherLocales={OTHER_LOCALES}
|
|
51
|
+
defaultLocaleSlug="roshe-tenis-76"
|
|
52
|
+
>
|
|
53
|
+
<LocalizationButton />
|
|
54
|
+
</LocalizedProductProvider>
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
expect(mockUseBindingSelector).toHaveBeenCalledWith(
|
|
58
|
+
OTHER_LOCALES,
|
|
59
|
+
'/p',
|
|
60
|
+
'roshe-tenis-76'
|
|
61
|
+
)
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
it('passes no default-locale slug on collection pages', () => {
|
|
65
|
+
render(
|
|
66
|
+
<LocalizedProductProvider otherLocales={OTHER_LOCALES} urlSuffix="">
|
|
67
|
+
<LocalizationButton />
|
|
68
|
+
</LocalizedProductProvider>
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
expect(mockUseBindingSelector).toHaveBeenCalledWith(
|
|
72
|
+
OTHER_LOCALES,
|
|
73
|
+
'',
|
|
74
|
+
undefined
|
|
75
|
+
)
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
it('falls back to product-page defaults outside a provider', () => {
|
|
79
|
+
render(<LocalizationButton />)
|
|
80
|
+
|
|
81
|
+
expect(mockUseBindingSelector).toHaveBeenCalledWith(
|
|
82
|
+
undefined,
|
|
83
|
+
'/p',
|
|
84
|
+
undefined
|
|
85
|
+
)
|
|
86
|
+
})
|
|
87
|
+
})
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { act, renderHook } from '@testing-library/react'
|
|
2
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
3
|
+
|
|
4
|
+
vi.mock(import('../../../discovery.config.js'), async (original) => ({
|
|
5
|
+
default: {
|
|
6
|
+
...((await original()).default ?? (await original())),
|
|
7
|
+
localization: {
|
|
8
|
+
enabled: true,
|
|
9
|
+
defaultLocale: 'en-US',
|
|
10
|
+
regions: {
|
|
11
|
+
US: {
|
|
12
|
+
code: 'US',
|
|
13
|
+
name: 'United States',
|
|
14
|
+
dateFormat: 'MM/DD/YYYY',
|
|
15
|
+
timeFormat: '12h',
|
|
16
|
+
timeFormatMask: 'hh:mm a',
|
|
17
|
+
unitSystem: 'imperial',
|
|
18
|
+
defaultTimezone: 'GMT-5',
|
|
19
|
+
},
|
|
20
|
+
BR: {
|
|
21
|
+
code: 'BR',
|
|
22
|
+
name: 'Brazil',
|
|
23
|
+
dateFormat: 'DD/MM/YYYY',
|
|
24
|
+
timeFormat: '24h',
|
|
25
|
+
timeFormatMask: 'HH:mm',
|
|
26
|
+
unitSystem: 'metric',
|
|
27
|
+
defaultTimezone: 'GMT-3',
|
|
28
|
+
},
|
|
29
|
+
IT: {
|
|
30
|
+
code: 'IT',
|
|
31
|
+
name: 'Italy',
|
|
32
|
+
dateFormat: 'DD/MM/YYYY',
|
|
33
|
+
timeFormat: '24h',
|
|
34
|
+
timeFormatMask: 'HH:mm',
|
|
35
|
+
unitSystem: 'metric',
|
|
36
|
+
defaultTimezone: 'GMT+1',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
locales: {
|
|
40
|
+
'en-US': {
|
|
41
|
+
code: 'en-US',
|
|
42
|
+
name: 'English',
|
|
43
|
+
languageCode: 'en',
|
|
44
|
+
languageName: 'English',
|
|
45
|
+
script: 'Latn',
|
|
46
|
+
textDirection: 'ltr',
|
|
47
|
+
regionCode: 'US',
|
|
48
|
+
bindings: [
|
|
49
|
+
{
|
|
50
|
+
currencyCode: 'USD',
|
|
51
|
+
url: 'https://store.example.com',
|
|
52
|
+
salesChannel: '1',
|
|
53
|
+
isDefault: true,
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
},
|
|
57
|
+
'pt-BR': {
|
|
58
|
+
code: 'pt-BR',
|
|
59
|
+
name: 'português',
|
|
60
|
+
languageCode: 'pt',
|
|
61
|
+
languageName: 'Portuguese',
|
|
62
|
+
script: 'Latn',
|
|
63
|
+
textDirection: 'ltr',
|
|
64
|
+
regionCode: 'BR',
|
|
65
|
+
bindings: [
|
|
66
|
+
{
|
|
67
|
+
currencyCode: 'BRL',
|
|
68
|
+
url: 'https://store.example.com/pt-BR',
|
|
69
|
+
salesChannel: '2',
|
|
70
|
+
isDefault: true,
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
},
|
|
74
|
+
'it-IT': {
|
|
75
|
+
code: 'it-IT',
|
|
76
|
+
name: 'italiano',
|
|
77
|
+
languageCode: 'it',
|
|
78
|
+
languageName: 'Italian',
|
|
79
|
+
script: 'Latn',
|
|
80
|
+
textDirection: 'ltr',
|
|
81
|
+
regionCode: 'IT',
|
|
82
|
+
bindings: [
|
|
83
|
+
{
|
|
84
|
+
currencyCode: 'EUR',
|
|
85
|
+
url: 'https://store.example.com/it-IT',
|
|
86
|
+
salesChannel: '3',
|
|
87
|
+
isDefault: true,
|
|
88
|
+
},
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
currencies: {
|
|
93
|
+
USD: { code: 'USD', name: 'US Dollar', symbol: '$' },
|
|
94
|
+
BRL: { code: 'BRL', name: 'Brazilian Real', symbol: 'R$' },
|
|
95
|
+
EUR: { code: 'EUR', name: 'Euro', symbol: '€' },
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
}))
|
|
100
|
+
|
|
101
|
+
vi.mock('../../../src/sdk/session', () => ({
|
|
102
|
+
useSession: () => ({
|
|
103
|
+
locale: 'en-US',
|
|
104
|
+
currency: { code: 'USD', symbol: '$' },
|
|
105
|
+
}),
|
|
106
|
+
}))
|
|
107
|
+
|
|
108
|
+
import { useBindingSelector } from '../../../src/sdk/localization/useBindingSelector'
|
|
109
|
+
|
|
110
|
+
const TRANSLATED = [
|
|
111
|
+
{ locale: 'en-US', slug: 'roshe-tenis-76' },
|
|
112
|
+
{ locale: 'pt-BR', slug: 'tenis-roshe-76' },
|
|
113
|
+
]
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Replaces `globalThis.location` with a plain object so the redirect can be
|
|
117
|
+
* asserted. jsdom throws on a real `href` assignment.
|
|
118
|
+
*/
|
|
119
|
+
function stubLocation(pathname: string, search = '', hash = '') {
|
|
120
|
+
const location = { pathname, search, hash, href: '' }
|
|
121
|
+
vi.stubGlobal('location', location)
|
|
122
|
+
|
|
123
|
+
return location
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/** Drives the selector to a locale/currency pair and triggers the redirect. */
|
|
127
|
+
function switchTo(
|
|
128
|
+
locale: string,
|
|
129
|
+
currency: string,
|
|
130
|
+
otherLocales?: Array<{ locale: string; slug: string }> | null,
|
|
131
|
+
defaultLocaleSlug?: string | null,
|
|
132
|
+
urlSuffix = '/p'
|
|
133
|
+
) {
|
|
134
|
+
const { result } = renderHook(() =>
|
|
135
|
+
useBindingSelector(otherLocales, urlSuffix, defaultLocaleSlug)
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
act(() => result.current.setLocaleCode(locale))
|
|
139
|
+
act(() => result.current.setCurrencyCode(currency))
|
|
140
|
+
act(() => result.current.save())
|
|
141
|
+
|
|
142
|
+
return result
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
describe('useBindingSelector redirect', () => {
|
|
146
|
+
beforeEach(() => {
|
|
147
|
+
globalThis.sessionStorage.clear()
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
afterEach(() => {
|
|
151
|
+
vi.unstubAllGlobals()
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
it('navigates to the slug the catalog registered for the target locale', () => {
|
|
155
|
+
const location = stubLocation('/roshe-tenis-76/p')
|
|
156
|
+
|
|
157
|
+
switchTo('pt-BR', 'BRL', TRANSLATED)
|
|
158
|
+
|
|
159
|
+
expect(location.href).toBe(
|
|
160
|
+
'https://store.example.com/pt-BR/tenis-roshe-76/p'
|
|
161
|
+
)
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
it('falls back to the default locale slug registered in the map when the target has none', () => {
|
|
165
|
+
const location = stubLocation('/tenis-roshe-76/p')
|
|
166
|
+
|
|
167
|
+
switchTo('it-IT', 'EUR', TRANSLATED)
|
|
168
|
+
|
|
169
|
+
expect(location.href).toBe(
|
|
170
|
+
'https://store.example.com/it-IT/roshe-tenis-76/p'
|
|
171
|
+
)
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
it('navigates to the product page via defaultLocaleSlug when the target locale has no registered slug', () => {
|
|
175
|
+
const location = stubLocation('/roshe-tenis-76/p')
|
|
176
|
+
|
|
177
|
+
switchTo(
|
|
178
|
+
'it-IT',
|
|
179
|
+
'EUR',
|
|
180
|
+
[{ locale: 'pt-BR', slug: 'tenis-roshe-76' }],
|
|
181
|
+
'roshe-tenis-76'
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
// The Italian binding with the default-locale slug: an untranslated product
|
|
185
|
+
// page, which the agreed behavior prefers over the locale root.
|
|
186
|
+
expect(location.href).toBe(
|
|
187
|
+
'https://store.example.com/it-IT/roshe-tenis-76/p'
|
|
188
|
+
)
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
it('uses defaultLocaleSlug for a product with no registered translations at all', () => {
|
|
192
|
+
const location = stubLocation('/side-by-side-refrigerator-14/p')
|
|
193
|
+
|
|
194
|
+
switchTo('pt-BR', 'BRL', [], 'side-by-side-refrigerator-14')
|
|
195
|
+
|
|
196
|
+
expect(location.href).toBe(
|
|
197
|
+
'https://store.example.com/pt-BR/side-by-side-refrigerator-14/p'
|
|
198
|
+
)
|
|
199
|
+
})
|
|
200
|
+
|
|
201
|
+
it('never carries a slug registered for a third locale into the target locale', () => {
|
|
202
|
+
const location = stubLocation('/roshe-tenis-76/p')
|
|
203
|
+
|
|
204
|
+
switchTo(
|
|
205
|
+
'it-IT',
|
|
206
|
+
'EUR',
|
|
207
|
+
[{ locale: 'pt-BR', slug: 'tenis-roshe-76' }],
|
|
208
|
+
'roshe-tenis-76'
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
expect(location.href).not.toContain('tenis-roshe-76')
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
it('falls back to the binding root on a PDP with no slug available', () => {
|
|
215
|
+
const location = stubLocation('/roshe-tenis-76/p')
|
|
216
|
+
|
|
217
|
+
switchTo('pt-BR', 'BRL', [], null)
|
|
218
|
+
|
|
219
|
+
expect(location.href).toBe('https://store.example.com/pt-BR')
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
it('preserves the query string and hash across the switch', () => {
|
|
223
|
+
const location = stubLocation('/roshe-tenis-76/p', '?skuId=76', '#reviews')
|
|
224
|
+
|
|
225
|
+
switchTo('pt-BR', 'BRL', TRANSLATED)
|
|
226
|
+
|
|
227
|
+
expect(location.href).toBe(
|
|
228
|
+
'https://store.example.com/pt-BR/tenis-roshe-76/p?skuId=76#reviews'
|
|
229
|
+
)
|
|
230
|
+
})
|
|
231
|
+
|
|
232
|
+
it('omits the /p suffix for collection pages', () => {
|
|
233
|
+
const location = stubLocation('/apparel')
|
|
234
|
+
|
|
235
|
+
switchTo('pt-BR', 'BRL', [{ locale: 'pt-BR', slug: 'vestuario' }], null, '')
|
|
236
|
+
|
|
237
|
+
expect(location.href).toBe('https://store.example.com/pt-BR/vestuario')
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
it('reports an error instead of redirecting when the locale has no binding for the currency', () => {
|
|
241
|
+
const location = stubLocation('/roshe-tenis-76/p')
|
|
242
|
+
|
|
243
|
+
const result = switchTo('pt-BR', 'JPY', TRANSLATED)
|
|
244
|
+
|
|
245
|
+
expect(result.current.error).toEqual({
|
|
246
|
+
type: 'no-binding-found',
|
|
247
|
+
locale: 'pt-BR',
|
|
248
|
+
currency: 'JPY',
|
|
249
|
+
})
|
|
250
|
+
expect(location.href).toBe('')
|
|
251
|
+
})
|
|
252
|
+
})
|