@faststore/core 4.8.0-dev.6 → 4.8.0-dev.8

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.
@@ -1,9 +1,9 @@
1
1
 
2
- > @faststore/core@4.8.0-dev.5 generate /home/runner/work/faststore/faststore/packages/core
2
+ > @faststore/core@4.8.0-dev.7 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.8.0-dev.5 gen-types /home/runner/work/faststore/faststore/packages/core
6
+ > @faststore/core@4.8.0-dev.7 gen-types /home/runner/work/faststore/faststore/packages/core
7
7
  > node ../cli/bin/run generate-types .
8
8
 
9
9
  [STARTED] Parse Configuration
@@ -19,7 +19,7 @@
19
19
  [COMPLETED] Generate to @generated/
20
20
  [COMPLETED] Generate outputs
21
21
 
22
- > @faststore/core@4.8.0-dev.5 cache-graphql /home/runner/work/faststore/faststore/packages/core
22
+ > @faststore/core@4.8.0-dev.7 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
@@ -1,5 +1,5 @@
1
1
 
2
- > @faststore/core@4.8.0-dev.5 test /home/runner/work/faststore/faststore/packages/core
2
+ > @faststore/core@4.8.0-dev.7 test /home/runner/work/faststore/faststore/packages/core
3
3
  > vitest run
4
4
 
5
5
 
@@ -10,17 +10,17 @@ Not implemented: navigation to another Document
10
10
  Browserslist: browsers data (caniuse-lite) is 7 months old. Please run:
11
11
  npx update-browserslist-db@latest
12
12
  Why you should do it regularly: https://github.com/browserslist/update-db#readme
13
- ✓  browser  test/sdk/ui/useScrollRestoration.browser.test.ts (43 tests) 910ms
14
- ✓  browser  test/components/CartRecommendationShelf/CartRecommendationShelf.browser.test.tsx (13 tests) 510ms
15
- ✓  browser  test/components/account/cards/MyAccountListCards.browser.test.tsx (14 tests) 2388ms
16
- ✓ shows the tab bar and renders Personal cards by default  1027ms
17
- ✓ paginates when there are more than 25 cards  389ms
18
- ✓  browser  test/sdk/localization/useBindingSelector.browser.test.tsx (9 tests) 224ms
19
- ✓  browser  test/components/account/ContractSwitcher.browser.test.tsx (13 tests) 2328ms
20
- ✓ shows an error state when the list fails to load  514ms
21
- ✓ requires selecting a contract before Confirm is enabled, then switches (REQ-03)  304ms
22
- ✓  browser  test/components/ui/ProductGallery/GalleryPageHeightLock.browser.test.tsx (8 tests) 212ms
23
- ✓  browser  test/sdk/session/reconcileSessionLocale.browser.test.ts (5 tests) 27ms
13
+ ✓  browser  test/sdk/ui/useScrollRestoration.browser.test.ts (43 tests) 1248ms
14
+ ✓  browser  test/components/CartRecommendationShelf/CartRecommendationShelf.browser.test.tsx (13 tests) 572ms
15
+ ✓  browser  test/components/account/cards/MyAccountListCards.browser.test.tsx (16 tests) 2754ms
16
+ ✓ shows the tab bar and renders Personal cards by default  832ms
17
+ ✓ paginates when there are more than 25 cards  601ms
18
+ ✓  browser  test/sdk/localization/useBindingSelector.browser.test.tsx (9 tests) 222ms
19
+ ✓  browser  test/components/ui/ProductGallery/GalleryPageHeightLock.browser.test.tsx (8 tests) 264ms
20
+ ✓  browser  test/components/account/ContractSwitcher.browser.test.tsx (13 tests) 2747ms
21
+ ✓ shows an error state when the list fails to load  636ms
22
+ ✓ requires selecting a contract before Confirm is enabled, then switches (REQ-03)  386ms
23
+ ✓ keeps Confirm disabled when switching is unavailable  369ms
24
24
  stderr | test/components/RecommendationShelf/RecommendationShelf.browser.test.tsx
25
25
  Error in optimistic validation: TypeError: Failed to parse URL from /api/graphql?operationName=ValidateCartMutation&operationHash=3c71b0d3fc2bade14df68abfa271858beb361b12
26
26
   at node:internal/deps/undici/undici:16416:13
@@ -47,12 +47,13 @@ Browserslist: browsers data (caniuse-lite) is 7 months old. Please run:
47
47
  }
48
48
  }
49
49
 
50
+ ✓  browser  test/sdk/session/reconcileSessionLocale.browser.test.ts (5 tests) 19ms
50
51
  stderr | test/components/RecommendationShelf/RecommendationShelf.browser.test.tsx > RecommendationShelf > renders nothing when there is an error
51
52
  Error fetching recommendations undefined boom for campaign vrn:recommendations:acc:rec-top-items-v2:campaign-1
52
53
 
53
- ✓  browser  test/components/RecommendationShelf/RecommendationShelf.browser.test.tsx (8 tests) 291ms
54
- ✓  browser  test/sdk/recommendations/useRecommendationShelf.browser.test.tsx (12 tests) 136ms
55
- ✓  browser  test/components/CartSidebar/CartSidebar.browser.test.tsx (5 tests) 119ms
54
+ ✓  browser  test/components/RecommendationShelf/RecommendationShelf.browser.test.tsx (8 tests) 268ms
55
+ ✓  browser  test/sdk/recommendations/useRecommendationShelf.browser.test.tsx (12 tests) 143ms
56
+ ✓  browser  test/components/CartSidebar/CartSidebar.browser.test.tsx (5 tests) 117ms
56
57
  stderr | test/pages/password-protection.browser.test.tsx > PasswordProtectionLogin > posts the password and redirects to the requested return path
57
58
  Warning: An update to PasswordProtectionLogin inside a test was not wrapped in act(...).
58
59
 
@@ -234,6 +235,8 @@ act(() => {
234
235
  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
235
236
  at PasswordProtectionLogin (/home/runner/work/faststore/faststore/packages/core/src/pages/password-protection/index.tsx:19:69)
236
237
 
238
+ ✓  browser  test/components/account/OrganizationDrawer.browser.test.tsx (5 tests) 1005ms
239
+ ✓ renders the menu view with contract details and manage footer  538ms
237
240
  stderr | test/pages/password-protection.browser.test.tsx > PasswordProtectionLogin > shows service unavailable when the login request fails
238
241
  Warning: An update to PasswordProtectionLogin inside a test was not wrapped in act(...).
239
242
 
@@ -282,12 +285,10 @@ act(() => {
282
285
  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
286
  at PasswordProtectionLogin (/home/runner/work/faststore/faststore/packages/core/src/pages/password-protection/index.tsx:19:69)
284
287
 
285
- ✓  browser  test/pages/password-protection.browser.test.tsx (6 tests) 936ms
286
- ✓ renders the password protection form  331ms
287
- ✓  browser  test/components/account/OrganizationDrawer.browser.test.tsx (5 tests) 750ms
288
- ✓ renders the menu view with contract details and manage footer  378ms
289
- ✓  browser  test/sdk/session/getInitialSession.browser.test.ts (6 tests) 15ms
290
- ✓  browser  test/sdk/account/changeContractToken.browser.test.ts (9 tests) 45ms
288
+ ✓  browser  test/pages/password-protection.browser.test.tsx (6 tests) 1068ms
289
+ ✓ renders the password protection form  418ms
290
+ ✓  browser  test/sdk/session/getInitialSession.browser.test.ts (6 tests) 16ms
291
+ ✓  browser  test/sdk/account/changeContractToken.browser.test.ts (9 tests) 23ms
291
292
  stderr | test/sdk/localization/store-url.browser.test.ts
292
293
  Error in optimistic validation: TypeError: Cannot read properties of undefined (reading 'read')
293
294
  at waitForSessionValidated (/home/runner/work/faststore/faststore/packages/core/src/sdk/cart/waitForSessionValidated.ts:16:32)
@@ -296,7 +297,6 @@ This ensures that you're testing the behavior the user would see in the browser.
296
297
  at a (/home/runner/work/faststore/faststore/packages/sdk/dist/es/index.mjs:354:23)
297
298
   at processTicksAndRejections (node:internal/process/task_queues:103:5)
298
299
 
299
- ✓  browser  test/sdk/localization/store-url.browser.test.ts (3 tests) 4ms
300
300
  stderr | test/components/cms/RenderSections.browser.test.tsx
301
301
  Error in optimistic validation: TypeError: Cannot read properties of undefined (reading 'read')
302
302
  at waitForSessionValidated (/home/runner/work/faststore/faststore/packages/core/src/sdk/cart/waitForSessionValidated.ts:16:32)
@@ -305,12 +305,13 @@ This ensures that you're testing the behavior the user would see in the browser.
305
305
  at a (/home/runner/work/faststore/faststore/packages/sdk/dist/es/index.mjs:354:23)
306
306
   at processTicksAndRejections (node:internal/process/task_queues:103:5)
307
307
 
308
- ✓  browser  test/sdk/account/useAvailableContracts.browser.test.ts (6 tests) 30ms
309
- ✓  browser  test/components/cms/RenderSections.browser.test.tsx (5 tests) 77ms
310
- ✓  browser  test/components/templates/SearchPage/SearchWrapper.browser.test.tsx (3 tests) 37ms
311
- ✓  browser  test/sdk/recommendations/useRecommendationShelf.sessionFallback.browser.test.tsx (2 tests) 75ms
312
- ✓  browser  test/sdk/account/useSwitchContract.browser.test.ts (4 tests) 28ms
313
- ✓  browser  test/components/CartRecommendationShelf/CartRecommendationProductCard.browser.test.tsx (3 tests) 48ms
308
+ ✓  browser  test/sdk/localization/store-url.browser.test.ts (3 tests) 6ms
309
+ ✓  browser  test/components/cms/RenderSections.browser.test.tsx (5 tests) 94ms
310
+ ✓  browser  test/sdk/account/useAvailableContracts.browser.test.ts (6 tests) 33ms
311
+ ✓  browser  test/components/templates/SearchPage/SearchWrapper.browser.test.tsx (3 tests) 41ms
312
+ ✓  browser  test/sdk/account/useSwitchContract.browser.test.ts (4 tests) 35ms
313
+ ✓  browser  test/sdk/recommendations/useRecommendationShelf.sessionFallback.browser.test.tsx (2 tests) 136ms
314
+ ✓  browser  test/components/CartRecommendationShelf/CartRecommendationProductCard.browser.test.tsx (3 tests) 71ms
314
315
  stderr | test/components/account/doLogout.browser.test.ts
315
316
  Error in optimistic validation: TypeError: Cannot read properties of undefined (reading 'read')
316
317
  at waitForSessionValidated (/home/runner/work/faststore/faststore/packages/core/src/sdk/cart/waitForSessionValidated.ts:16:32)
@@ -319,11 +320,11 @@ This ensures that you're testing the behavior the user would see in the browser.
319
320
  at a (/home/runner/work/faststore/faststore/packages/sdk/dist/es/index.mjs:354:23)
320
321
   at processTicksAndRejections (node:internal/process/task_queues:103:5)
321
322
 
322
- ✓  browser  test/components/account/doLogout.browser.test.ts (1 test) 30ms
323
- ✓  browser  test/components/ui/LocalizationButton.browser.test.tsx (3 tests) 45ms
324
- ✓  browser  test/components/sections/Account/AccountListCards.browser.test.tsx (3 tests) 83ms
325
- ✓  browser  test/components/account/OrganizationDrawerHeader.browser.test.tsx (3 tests) 279ms
326
- ✓  browser  test/components/account/OrganizationDrawerFooter.browser.test.tsx (3 tests) 273ms
323
+ ✓  browser  test/components/account/doLogout.browser.test.ts (1 test) 45ms
324
+ ✓  browser  test/components/ui/LocalizationButton.browser.test.tsx (3 tests) 51ms
325
+ ✓  browser  test/components/sections/Account/AccountListCards.browser.test.tsx (3 tests) 87ms
326
+ ✓  browser  test/components/account/OrganizationDrawerHeader.browser.test.tsx (3 tests) 292ms
327
+ ✓  browser  test/components/account/OrganizationDrawerFooter.browser.test.tsx (3 tests) 270ms
327
328
  stderr | test/sdk/account/clearPersistedSessionState.browser.test.ts
328
329
  Error in optimistic validation: TypeError: Cannot read properties of undefined (reading 'read')
329
330
  at waitForSessionValidated (/home/runner/work/faststore/faststore/packages/core/src/sdk/cart/waitForSessionValidated.ts:16:32)
@@ -332,10 +333,12 @@ This ensures that you're testing the behavior the user would see in the browser.
332
333
  at a (/home/runner/work/faststore/faststore/packages/sdk/dist/es/index.mjs:354:23)
333
334
   at processTicksAndRejections (node:internal/process/task_queues:103:5)
334
335
 
335
- ✓  browser  test/utils/isLocalHost.browser.test.ts (3 tests) 4ms
336
- ✓  browser  test/sdk/account/clearPersistedSessionState.browser.test.ts (1 test) 12ms
337
- ✓  browser  test/sdk/session/reconcileSessionLocale.disabled.browser.test.ts (1 test) 3ms
338
- ✓  node  test/utils/localization/bindingPaths.test.ts (71 tests) 32ms
336
+ ✓  browser  test/sdk/account/clearPersistedSessionState.browser.test.ts (1 test) 9ms
337
+ ✓  browser  test/utils/isLocalHost.browser.test.ts (3 tests) 5ms
338
+ ✓  browser  test/sdk/session/reconcileSessionLocale.disabled.browser.test.ts (1 test) 4ms
339
+ ✓  node  test/utils/localization/bindingPaths.test.ts (71 tests) 25ms
340
+ ✓  browser  test/components/skeletons/ProductGridSkeleton.browser.test.tsx (2 tests) 44ms
341
+ ✓  node  test/server/password-protection-service.test.ts (22 tests) 36ms
339
342
  stderr | test/sdk/account/refreshToken.browser.test.ts
340
343
  Error in optimistic validation: TypeError: Cannot read properties of undefined (reading 'read')
341
344
  at waitForSessionValidated (/home/runner/work/faststore/faststore/packages/core/src/sdk/cart/waitForSessionValidated.ts:16:32)
@@ -344,13 +347,11 @@ This ensures that you're testing the behavior the user would see in the browser.
344
347
  at a (/home/runner/work/faststore/faststore/packages/sdk/dist/es/index.mjs:354:23)
345
348
   at processTicksAndRejections (node:internal/process/task_queues:103:5)
346
349
 
347
- ✓  browser  test/sdk/account/refreshToken.browser.test.ts (1 test) 4ms
348
- ✓  browser  test/components/skeletons/ProductGridSkeleton.browser.test.tsx (2 tests) 36ms
349
- ✓  node  test/server/password-protection-service.test.ts (22 tests) 36ms
350
- ✓  node  test/utils/match-url.test.ts (10 tests) 8ms
351
- ✓  node  test/sdk/localization/useBindingSelector.test.tsx (22 tests) 15ms
352
- ✓  node  test/pages/api/unlock.test.ts (15 tests) 152ms
353
- ✓  node  test/sdk/localization/bindingSelector.test.ts (18 tests) 7ms
350
+ ✓  browser  test/sdk/account/refreshToken.browser.test.ts (1 test) 6ms
351
+ ✓  node  test/utils/match-url.test.ts (10 tests) 10ms
352
+ ✓  node  test/sdk/localization/useBindingSelector.test.tsx (22 tests) 18ms
353
+ ✓  node  test/pages/api/unlock.test.ts (15 tests) 175ms
354
+ ✓  node  test/sdk/localization/bindingSelector.test.ts (18 tests) 12ms
354
355
  stderr | test/components/search/SearchInputComponent.test.tsx
355
356
  Warning: forwardRef render functions accept exactly two parameters: props and ref. Did you forget to use the ref parameter?
356
357
 
@@ -414,19 +415,19 @@ Warning: React does not recognize the `providerProps` prop on a DOM element. If
414
415
  at Suspense
415
416
  at Wrapper (/home/runner/work/faststore/faststore/packages/core/test/components/search/SearchInputComponent.test.tsx:106:20)
416
417
 
417
- ✓  node  test/components/search/SearchInputComponent.test.tsx (6 tests) 73ms
418
- ✓  node  test/sdk/search/useSearchHistory.test.ts (13 tests) 55ms
419
- ✓  node  test/utils/cookieCacheBusting.test.ts (10 tests) 14ms
418
+ ✓  node  test/components/search/SearchInputComponent.test.tsx (6 tests) 80ms
419
+ ✓  node  test/sdk/search/useSearchHistory.test.ts (13 tests) 59ms
420
+ ✓  node  test/utils/cookieCacheBusting.test.ts (10 tests) 13ms
420
421
  stderr | test/pages/pvt/account/cards/index.test.ts > Cards page getServerSideProps > redirects to /pvt/account/403 when the query fails with 401/403
421
422
  { extensions: { status: 401 } }
422
423
 
423
424
  stderr | test/pages/pvt/account/cards/index.test.ts > Cards page getServerSideProps > renders the error state (no redirect) when the query fails with a non-auth status
424
425
  { extensions: { status: 502 } }
425
426
 
426
- ✓  node  test/pages/pvt/account/cards/index.test.ts (8 tests) 12ms
427
- ✓  node  test/utils/clearCookies.test.ts (20 tests) 19ms
428
- ✓  node  test/experimental/myAccountCmsServerSideProps.test.ts (5 tests) 7ms
429
- ✓  node  test/components/quotes/MyAccountListQuotesTable.test.tsx (12 tests) 372ms
427
+ ✓  node  test/pages/pvt/account/cards/index.test.ts (8 tests) 9ms
428
+ ✓  node  test/utils/clearCookies.test.ts (20 tests) 28ms
429
+ ✓  node  test/experimental/myAccountCmsServerSideProps.test.ts (5 tests) 11ms
430
+ ✓  node  test/components/quotes/MyAccountListQuotesTable.test.tsx (12 tests) 456ms
430
431
  stderr | test/pages/api/graphql.test.ts > /api/graphql error status propagation > propagates the upstream 400 from a wrapped BadRequestError instead of 500
431
432
  Graphql execution returned with error: [
432
433
  {
@@ -519,69 +520,70 @@ Warning: React does not recognize the `providerProps` prop on a DOM element. If
519
520
  at file:///home/runner/work/faststore/faststore/node_modules/.pnpm/@vitest+runner@4.0.18/node_modules/@vitest/runner/dist/index.js:1653:37
520
521
  at Traces.$ (file:///home/runner/work/faststore/faststore/node_modules/.pnpm/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/vitest/dist/chunks/traces.CCmnQaNT.js:142:27)
521
522
 
522
- ✓  node  test/pages/api/graphql.test.ts (17 tests) 28ms
523
- ✓  node  test/components/quotes/MyAccountListQuotes.test.tsx (9 tests) 802ms
524
- ✓ navigates with the search term on blur  360ms
525
- ✓ navigates without a label param when the search is cleared  357ms
523
+ ✓  node  test/pages/api/graphql.test.ts (17 tests) 25ms
524
+ ✓  node  test/components/quotes/MyAccountListQuotes.test.tsx (9 tests) 840ms
525
+ ✓ navigates with the search term on blur  364ms
526
+ ✓ navigates without a label param when the search is cleared  359ms
526
527
  stderr | test/sdk/account/useSetPassword.test.ts > useSetPassword > maps wrongcredentials error responses to the existing message
527
528
  Set password request failed: Bad Request
528
529
 
529
- ✓  node  test/sdk/account/useSetPassword.test.ts (6 tests) 31ms
530
- ✓  node  test/utils/multipleTemplates.test.ts (8 tests) 7ms
531
- ✓  node  test/sdk/orderEntry/useOrderEntryOperation.test.ts (8 tests) 30ms
532
- ✓  node  test/components/quotes/quoteFilters.test.ts (23 tests) 35ms
533
- ✓  node  test/utils/localization/localizeRedirectDestination.test.ts (11 tests) 8ms
534
- ✓  node  test/utils/localization/hreflang.test.ts (8 tests) 5ms
535
- ✓  node  test/sdk/account/getMyAccountRoutes.test.ts (12 tests) 6ms
536
- ✓  node  test/sdk/orderEntry/useOrderEntryUpload.test.ts (8 tests) 51ms
537
- ✓  node  test/sdk/redirects/index.test.ts (7 tests) 56ms
538
- ✓  node  test/components/quotes/MyAccountQuotesFilterSlider.test.tsx (5 tests) 135ms
539
- ✓  node  test/utils/productJsonLd.test.ts (17 tests) 6ms
540
- ✓  node  test/proxy.localization.test.ts (5 tests) 36ms
541
- ✓  node  test/sdk/orderEntry/useOrderEntry.test.ts (8 tests) 28ms
542
- ✓  node  test/server/index.test.ts (7 tests) 984ms
543
- ✓ should return a valid merged GraphQL schema  318ms
544
- ✓ should handle options and execute  373ms
545
- ✓  node  test/sdk/session/syncSalesChannelFromOrderForm.test.ts (6 tests) 6ms
546
- ✓  node  test/components/quotes/MyAccountQuotesSelectedTags.test.tsx (8 tests) 112ms
547
- ✓  node  test/sdk/analytics/useStartRecommendationSession.test.ts (6 tests) 38ms
548
- ✓  node  test/proxy.test.ts (4 tests) 16ms
549
- ✓  node  test/server/webops-api.test.ts (9 tests) 15ms
530
+ ✓  node  test/sdk/account/useSetPassword.test.ts (6 tests) 30ms
531
+ ✓  node  test/components/quotes/quoteFilters.test.ts (23 tests) 41ms
532
+ ✓  node  test/sdk/orderEntry/useOrderEntryOperation.test.ts (8 tests) 41ms
533
+ ✓  node  test/utils/multipleTemplates.test.ts (8 tests) 8ms
534
+ ✓  node  test/utils/localization/localizeRedirectDestination.test.ts (11 tests) 7ms
535
+ ✓  node  test/utils/localization/hreflang.test.ts (8 tests) 7ms
536
+ ✓  node  test/sdk/account/getMyAccountRoutes.test.ts (12 tests) 10ms
537
+ ✓  node  test/sdk/orderEntry/useOrderEntryUpload.test.ts (8 tests) 62ms
538
+ ✓  node  test/sdk/redirects/index.test.ts (7 tests) 51ms
539
+ ✓  node  test/components/quotes/MyAccountQuotesFilterSlider.test.tsx (5 tests) 161ms
540
+ ✓  node  test/utils/productJsonLd.test.ts (17 tests) 12ms
541
+ ✓  node  test/proxy.localization.test.ts (5 tests) 43ms
542
+ ✓  node  test/sdk/orderEntry/useOrderEntry.test.ts (8 tests) 31ms
543
+ ✓  node  test/sdk/graphql/retryPolicy.test.ts (18 tests) 17ms
544
+ ✓  node  test/server/index.test.ts (7 tests) 1124ms
545
+ ✓ should return a valid merged GraphQL schema  359ms
546
+ ✓ should handle options and execute  479ms
547
+ ✓  node  test/sdk/session/syncSalesChannelFromOrderForm.test.ts (6 tests) 10ms
548
+ ✓  node  test/sdk/analytics/useStartRecommendationSession.test.ts (6 tests) 67ms
549
+ ✓  node  test/components/quotes/MyAccountQuotesSelectedTags.test.tsx (8 tests) 120ms
550
+ ✓  node  test/server/webops-api.test.ts (9 tests) 18ms
550
551
  ✓  node  test/sdk/orderEntry/useOrderFormItems.test.ts (7 tests) 37ms
551
- ✓  node  test/sdk/localization/store-url.test.ts (4 tests) 4ms
552
+ ✓  node  test/proxy.test.ts (4 tests) 33ms
552
553
  ✓  node  test/sdk/cart/waitForSessionValidated.test.ts (5 tests) 12ms
553
- ✓  node  test/server/cms/myAccountDefaultSections.test.ts (7 tests) 4ms
554
- ✓  node  test/server/content/service.test.ts (5 tests) 8ms
555
- ✓  node  test/utils/productJsonLdRendering.test.tsx (4 tests) 10ms
554
+ ✓  node  test/sdk/localization/store-url.test.ts (4 tests) 8ms
555
+ ✓  node  test/server/content/service.test.ts (5 tests) 6ms
556
+ ✓  node  test/server/cms/myAccountDefaultSections.test.ts (7 tests) 6ms
557
+ ✓  node  test/utils/productJsonLdRendering.test.tsx (4 tests) 13ms
556
558
  ✓  node  test/sdk/account/refreshToken.test.ts (5 tests) 8ms
557
- ✓  node  test/server/cms/global.test.ts (3 tests) 5ms
558
- ✓  node  test/sdk/auth/useAuth.test.ts (5 tests) 66ms
559
- ✓  node  test/components/quotes/MyAccountQuotesStatusSelector.test.tsx (6 tests) 132ms
560
- ✓  node  test/utils/getRequestHostname.test.ts (12 tests) 5ms
561
- ✓  node  test/server/rootSpan.test.ts (4 tests) 51ms
562
- ✓  node  test/pages/api/preview.test.ts (2 tests) 11ms
559
+ ✓  node  test/server/cms/global.test.ts (3 tests) 6ms
560
+ ✓  node  test/sdk/auth/useAuth.test.ts (5 tests) 32ms
561
+ ✓  node  test/components/quotes/MyAccountQuotesStatusSelector.test.tsx (6 tests) 143ms
562
+ ✓  node  test/utils/getRequestHostname.test.ts (12 tests) 7ms
563
+ ✓  node  test/server/rootSpan.test.ts (4 tests) 41ms
564
+ ✓  node  test/pages/api/preview.test.ts (2 tests) 7ms
563
565
  ✓  node  test/components/search/SearchInput.test.ts (6 tests) 8ms
564
- ✓  node  test/utils/validateSessionRefreshToken.test.ts (6 tests) 4ms
565
- ✓  node  test/components/account/Layout.test.tsx (6 tests) 54ms
566
- ✓  node  test/sdk/recommendations/vrn.test.ts (5 tests) 7ms
567
- ✓  node  test/utils/retry.test.ts (5 tests) 13ms
566
+ ✓  node  test/utils/validateSessionRefreshToken.test.ts (6 tests) 6ms
567
+ ✓  node  test/sdk/recommendations/vrn.test.ts (5 tests) 5ms
568
+ ✓  node  test/components/account/Layout.test.tsx (6 tests) 67ms
569
+ ✓  node  test/utils/retry.test.ts (5 tests) 15ms
568
570
  ✓  node  test/server/cms/index.test.ts (2 tests) 5ms
569
- ✓  node  test/sdk/account/getB2BSessionClaims.test.ts (4 tests) 5ms
570
- ✓  node  test/utils/unlockResponse.test.ts (11 tests) 6ms
571
- ✓  node  test/sdk/recommendations/useRecommendations.test.ts (2 tests) 3ms
572
- ✓  node  test/sdk/recommendations/useRecommendationUserId.test.ts (4 tests) 187ms
573
- ✓  node  test/utils/isLocalHost.test.ts (7 tests) 4ms
574
- ✓  node  test/components/account/OrganizationDrawerBody.test.tsx (3 tests) 52ms
571
+ ✓  node  test/sdk/account/getB2BSessionClaims.test.ts (4 tests) 6ms
572
+ ✓  node  test/utils/unlockResponse.test.ts (11 tests) 7ms
573
+ ✓  node  test/sdk/recommendations/useRecommendations.test.ts (2 tests) 4ms
574
+ ✓  node  test/sdk/recommendations/useRecommendationUserId.test.ts (4 tests) 182ms
575
+ ✓  node  test/utils/isLocalHost.test.ts (7 tests) 5ms
575
576
  ✓  node  test/utils/userOrderStatus.test.ts (3 tests) 4ms
576
- ✓  node  test/utils/getCookie.test.ts (4 tests) 4ms
577
- ✓  node  test/sdk/analytics/utils.test.ts (2 tests) 4ms
578
- ✓  node  test/components/auth/ProfileChallenge.test.tsx (3 tests) 27ms
579
- ✓  node  test/instrumentation.test.ts (3 tests) 6ms
580
- ✓  node  test/sdk/account/clearPersistedSessionState.test.ts (1 test) 17ms
581
- ✓  node  test/components/quotes/MyAccountQuoteStatusBadge.test.tsx (2 tests) 24ms
582
-
583
-  Test Files  97 passed (97)
584
-  Tests  775 passed (775)
585
-  Start at  16:35:24
586
-  Duration  47.08s (transform 13.69s, setup 0ms, import 42.13s, tests 13.98s, environment 58.37s)
577
+ ✓  node  test/components/account/OrganizationDrawerBody.test.tsx (3 tests) 45ms
578
+ ✓  node  test/utils/getCookie.test.ts (4 tests) 6ms
579
+ ✓  node  test/sdk/analytics/utils.test.ts (2 tests) 6ms
580
+ ✓  node  test/instrumentation.test.ts (3 tests) 5ms
581
+ ✓  node  test/components/auth/ProfileChallenge.test.tsx (3 tests) 29ms
582
+ ✓  node  test/sdk/account/clearPersistedSessionState.test.ts (1 test) 15ms
583
+ ✓  node  test/components/quotes/MyAccountQuoteStatusBadge.test.tsx (2 tests) 25ms
584
+
585
+  Test Files  98 passed (98)
586
+  Tests  795 passed (795)
587
+  Start at  23:27:58
588
+  Duration  50.91s (transform 12.87s, setup 0ms, import 46.91s, tests 16.15s, environment 62.03s)
587
589
 
package/CHANGELOG.md CHANGED
@@ -3,6 +3,18 @@
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.8.0-dev.8](https://github.com/vtex/faststore/compare/v4.8.0-dev.7...v4.8.0-dev.8) (2026-09-14)
7
+
8
+ ### Bug Fixes
9
+
10
+ - **core:** align the saved-cards list with the design reference ([#3487](https://github.com/vtex/faststore/issues/3487)) ([0e0d3ea](https://github.com/vtex/faststore/commit/0e0d3eacc23f5d2027ef5f933b03cd8a0338885c))
11
+
12
+ # [4.8.0-dev.7](https://github.com/vtex/faststore/compare/v4.8.0-dev.6...v4.8.0-dev.7) (2026-09-14)
13
+
14
+ ### Bug Fixes
15
+
16
+ - stop retrying upstream 429 responses ([#3453](https://github.com/vtex/faststore/issues/3453)) ([a142258](https://github.com/vtex/faststore/commit/a14225863578965609aa5012cc1ca9f0132959b2)), closes [#3379](https://github.com/vtex/faststore/issues/3379) [#3420](https://github.com/vtex/faststore/issues/3420) [#1629](https://github.com/vtex/faststore/issues/1629) [/github.com/vtex/faststore/pull/3453#issuecomment-5433632179](https://github.com//github.com/vtex/faststore/pull/3453/issues/issuecomment-5433632179)
17
+
6
18
  # [4.8.0-dev.6](https://github.com/vtex/faststore/compare/v4.8.0-dev.5...v4.8.0-dev.6) (2026-09-11)
7
19
 
8
20
  **Note:** Version bump only for package @faststore/core
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@faststore/core",
3
- "version": "4.8.0-dev.6",
3
+ "version": "4.8.0-dev.8",
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.8.0-dev.6",
75
- "@faststore/lighthouse": "4.8.0-dev.6",
76
- "@faststore/diagnostics": "4.8.0-dev.6",
77
- "@faststore/sdk": "4.8.0-dev.6",
78
- "@faststore/ui": "4.8.0-dev.6"
74
+ "@faststore/api": "4.8.0-dev.8",
75
+ "@faststore/diagnostics": "4.8.0-dev.8",
76
+ "@faststore/lighthouse": "4.8.0-dev.8",
77
+ "@faststore/ui": "4.8.0-dev.8",
78
+ "@faststore/sdk": "4.8.0-dev.8"
79
79
  },
80
80
  "devDependencies": {
81
81
  "@cypress/code-coverage": "^3.12.1",
@@ -350,6 +350,7 @@ export default function MyAccountListCards({
350
350
  />
351
351
 
352
352
  <div
353
+ data-fs-list-cards-panel
353
354
  role={sharedOnly ? undefined : 'tabpanel'}
354
355
  id={sharedOnly ? undefined : PANEL_ID}
355
356
  aria-labelledby={sharedOnly ? undefined : activeTabId}
@@ -52,6 +52,16 @@
52
52
  color: var(--fs-text-link, #0632c1);
53
53
  }
54
54
 
55
+ // The tabpanel wrapper sits between .page and the controls/grid pair, so
56
+ // .page's column gap stops at this element and never separates the search
57
+ // row from the list below it. Carry the same rhythm down one level rather
58
+ // than dropping the wrapper, which owns the tabpanel role the tabs point at.
59
+ [data-fs-list-cards-panel] {
60
+ display: flex;
61
+ flex-direction: column;
62
+ gap: var(--fs-spacing-4, 1.5rem);
63
+ }
64
+
55
65
  [data-fs-list-cards-controls] {
56
66
  display: flex;
57
67
  flex-wrap: wrap;
@@ -84,14 +94,25 @@
84
94
 
85
95
  [data-fs-list-cards-item] {
86
96
  display: flex;
97
+
98
+ // Square tile, per the design reference: brand mark at the top, label and
99
+ // number at the bottom, with the slack between them. `aspect-ratio` sets
100
+ // the preferred box only — a long label still grows the card rather than
101
+ // overflowing it, since `min-height` stays `auto`.
87
102
  flex-direction: column;
88
103
  gap: var(--fs-spacing-1, 0.5rem);
104
+ aspect-ratio: 1;
89
105
  padding: var(--fs-spacing-2, 1rem);
90
106
  border: 1px solid var(--fs-border-color, #d9d9d9);
91
107
  border-radius: var(--fs-border-radius, 0.25rem);
92
108
  }
93
109
 
94
110
  [data-fs-list-cards-item-brand] {
111
+ // Pins the brand mark to the top edge and lets the label and number stay
112
+ // grouped at the bottom, as the design reference has them. `space-between`
113
+ // on the parent cannot express this: with three children it spreads all
114
+ // three evenly and strands the label in the middle of the tile.
115
+ margin-bottom: auto;
95
116
  font-size: 0.875rem;
96
117
  font-weight: 700;
97
118
  }
@@ -0,0 +1,49 @@
1
+ const MAX_BACKOFF_EXPONENT = 8
2
+ const TOO_MANY_REQUESTS = 429
3
+
4
+ /** Mirrors SWR's `RevalidatorOptions`. */
5
+ type RetryOptions = { retryCount: number; dedupe?: boolean }
6
+
7
+ /** Mirrors the subset of SWR's resolved config that the retry policy reads. */
8
+ type RetryConfig = { errorRetryCount?: number; errorRetryInterval: number }
9
+
10
+ /**
11
+ * SWR retry policy: never retry an upstream rate limit, retry everything else
12
+ * exactly as SWR would.
13
+ *
14
+ * A 429 means an upstream is already shedding load, so retrying multiplies the
15
+ * traffic it is trying to reject. Providing `onErrorRetry` replaces SWR's
16
+ * default implementation entirely, so the fall-through branch mirrors
17
+ * swr@2.4.0's default (ceiling check plus jittered exponential backoff) to keep
18
+ * every other status behaving as it did before. Revisit on an SWR upgrade.
19
+ *
20
+ * SWR writes the truncation as `~~`; `Math.trunc` is used here instead because
21
+ * the values stay far below 2^31, where the two are equivalent.
22
+ */
23
+ export const onErrorRetry = (
24
+ error: unknown,
25
+ _key: string,
26
+ config: RetryConfig,
27
+ revalidate: (opts: RetryOptions) => void,
28
+ opts: RetryOptions
29
+ ) => {
30
+ if (
31
+ (error as { status?: number } | undefined)?.status === TOO_MANY_REQUESTS
32
+ ) {
33
+ return
34
+ }
35
+
36
+ const maxRetryCount = config.errorRetryCount
37
+ const { retryCount } = opts
38
+
39
+ const timeout =
40
+ Math.trunc(
41
+ (Math.random() + 0.5) * (1 << Math.min(retryCount, MAX_BACKOFF_EXPONENT))
42
+ ) * config.errorRetryInterval
43
+
44
+ if (maxRetryCount !== undefined && retryCount > maxRetryCount) {
45
+ return
46
+ }
47
+
48
+ setTimeout(revalidate, timeout, opts)
49
+ }
@@ -5,6 +5,7 @@ import { getClientCacheBustingValue } from 'src/utils/cookieCacheBusting'
5
5
 
6
6
  import type { Operation, RequestOptions } from './request'
7
7
  import { request } from './request'
8
+ import { onErrorRetry } from './retryPolicy'
8
9
 
9
10
  export type QueryOptions = SWRConfiguration &
10
11
  RequestOptions & { doNotRun?: boolean }
@@ -34,6 +35,7 @@ export const DEFAULT_OPTIONS = {
34
35
  revalidateOnFocus: false,
35
36
  revalidateOnReconnect: false,
36
37
  shouldRetryOnError: true,
38
+ onErrorRetry,
37
39
  }
38
40
 
39
41
  export const useQuery = <Data, Variables = Record<string, unknown>>(
@@ -298,4 +298,42 @@ describe('MyAccountListCards', () => {
298
298
  fireEvent.click(screen.getByRole('button', { name: 'Try again' }))
299
299
  expect(mockReload).toHaveBeenCalledTimes(1)
300
300
  })
301
+
302
+ // Regression guard for the search/list spacing fix. The stylesheet hangs the
303
+ // column gap off this attribute because .page's own gap stops at this
304
+ // wrapper and never separates the controls row from the list below it.
305
+ // Dropping the attribute collapses that gap back to zero, silently.
306
+ it('marks the panel wrapper that carries the spacing between controls and list', () => {
307
+ const { container } = render(
308
+ <MyAccountListCards
309
+ personalCards={[VISA_PERSONAL]}
310
+ sharedCards={[AMEX_SHARED]}
311
+ hasOrgAssociation
312
+ canViewPersonalCards
313
+ />
314
+ )
315
+
316
+ const panel = container.querySelector('[data-fs-list-cards-panel]')
317
+
318
+ expect(panel).not.toBeNull()
319
+ expect(panel).toHaveAttribute('role', 'tabpanel')
320
+ expect(panel?.querySelector('[data-fs-list-cards-controls]')).not.toBeNull()
321
+ expect(panel?.querySelector('[data-fs-list-cards-grid]')).not.toBeNull()
322
+ })
323
+
324
+ it('keeps the panel marker in the shared-only rendering, which has no tabpanel role', () => {
325
+ const { container } = render(
326
+ <MyAccountListCards
327
+ personalCards={[]}
328
+ sharedCards={[AMEX_SHARED]}
329
+ hasOrgAssociation
330
+ canViewPersonalCards={false}
331
+ />
332
+ )
333
+
334
+ const panel = container.querySelector('[data-fs-list-cards-panel]')
335
+
336
+ expect(panel).not.toBeNull()
337
+ expect(panel).not.toHaveAttribute('role')
338
+ })
301
339
  })
@@ -0,0 +1,135 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
2
+
3
+ import { onErrorRetry } from '../../../src/sdk/graphql/retryPolicy'
4
+
5
+ const ERROR_RETRY_INTERVAL = 5000
6
+
7
+ type RetryConfig = Parameters<typeof onErrorRetry>[2]
8
+
9
+ const createConfig = (overrides: Partial<RetryConfig> = {}): RetryConfig => ({
10
+ errorRetryCount: 3,
11
+ errorRetryInterval: ERROR_RETRY_INTERVAL,
12
+ ...overrides,
13
+ })
14
+
15
+ // The client throws the object built by `baseRequest` in `request.ts`, which
16
+ // carries the HTTP status — not an Error instance.
17
+ const clientError = (status?: number) => ({
18
+ status,
19
+ message: 'upstream failure',
20
+ })
21
+
22
+ const runRetry = ({
23
+ error,
24
+ retryCount = 0,
25
+ config = createConfig(),
26
+ }: {
27
+ error: unknown
28
+ retryCount?: number
29
+ config?: RetryConfig
30
+ }) => {
31
+ const revalidate = vi.fn()
32
+
33
+ onErrorRetry(error, 'a-key', config, revalidate, {
34
+ retryCount,
35
+ dedupe: false,
36
+ })
37
+
38
+ vi.runAllTimers()
39
+
40
+ return revalidate
41
+ }
42
+
43
+ describe('useQuery retry policy', () => {
44
+ beforeEach(() => {
45
+ vi.useFakeTimers()
46
+ // Pins SWR's jitter so the backoff assertions are deterministic.
47
+ vi.spyOn(Math, 'random').mockReturnValue(0.5)
48
+ })
49
+
50
+ afterEach(() => {
51
+ // `restoreAllMocks` must run first: the `setTimeout` spy is installed while
52
+ // timers are faked, so restoring it after `useRealTimers` would put the
53
+ // faked timer back onto `globalThis`.
54
+ vi.restoreAllMocks()
55
+ vi.useRealTimers()
56
+ })
57
+
58
+ it('never retries an upstream rate limit (429)', () => {
59
+ expect(runRetry({ error: clientError(429) })).not.toHaveBeenCalled()
60
+ })
61
+
62
+ it('does not retry a 429 even on the first attempt of a fresh key', () => {
63
+ const revalidate = runRetry({ error: clientError(429), retryCount: 0 })
64
+
65
+ expect(revalidate).not.toHaveBeenCalled()
66
+ })
67
+
68
+ it.each([400, 401, 403, 404, 409, 422, 500, 502, 503])(
69
+ 'still retries status %i',
70
+ (status) => {
71
+ expect(runRetry({ error: clientError(status) })).toHaveBeenCalledTimes(1)
72
+ }
73
+ )
74
+
75
+ it('still retries an error carrying no status (e.g. network failure)', () => {
76
+ expect(runRetry({ error: clientError(undefined) })).toHaveBeenCalledTimes(1)
77
+ })
78
+
79
+ it('retries while at the errorRetryCount ceiling', () => {
80
+ expect(
81
+ runRetry({ error: clientError(500), retryCount: 3 })
82
+ ).toHaveBeenCalledTimes(1)
83
+ })
84
+
85
+ it('stops retrying once errorRetryCount is exceeded', () => {
86
+ expect(
87
+ runRetry({ error: clientError(500), retryCount: 4 })
88
+ ).not.toHaveBeenCalled()
89
+ })
90
+
91
+ it.each([
92
+ [0, 1 * ERROR_RETRY_INTERVAL],
93
+ [2, 4 * ERROR_RETRY_INTERVAL],
94
+ [3, 8 * ERROR_RETRY_INTERVAL],
95
+ ])(
96
+ 'mirrors SWR exponential backoff for retryCount %i',
97
+ (retryCount, expectedTimeout) => {
98
+ const setTimeoutSpy = vi.spyOn(globalThis, 'setTimeout')
99
+ const revalidate = vi.fn()
100
+
101
+ onErrorRetry(
102
+ clientError(500),
103
+ 'a-key',
104
+ createConfig({ errorRetryCount: 10 }),
105
+ revalidate,
106
+ { retryCount, dedupe: false }
107
+ )
108
+
109
+ expect(setTimeoutSpy).toHaveBeenCalledWith(
110
+ revalidate,
111
+ expectedTimeout,
112
+ expect.objectContaining({ retryCount })
113
+ )
114
+ }
115
+ )
116
+
117
+ it('caps the backoff exponent at 8, as SWR does', () => {
118
+ const setTimeoutSpy = vi.spyOn(globalThis, 'setTimeout')
119
+ const revalidate = vi.fn()
120
+
121
+ onErrorRetry(
122
+ clientError(500),
123
+ 'a-key',
124
+ createConfig({ errorRetryCount: 100 }),
125
+ revalidate,
126
+ { retryCount: 12, dedupe: false }
127
+ )
128
+
129
+ expect(setTimeoutSpy).toHaveBeenCalledWith(
130
+ revalidate,
131
+ 256 * ERROR_RETRY_INTERVAL,
132
+ expect.objectContaining({ retryCount: 12 })
133
+ )
134
+ })
135
+ })