@faststore/core 4.8.1-dev.0 → 4.8.1-dev.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/.turbo/turbo-generate.log +3 -3
  2. package/.turbo/turbo-test.log +146 -105
  3. package/@generated/gql.ts +3 -3
  4. package/@generated/graphql.ts +4 -2
  5. package/@generated/persisted-documents.json +1 -1
  6. package/@generated/schema.graphql +4 -0
  7. package/CHANGELOG.md +16 -0
  8. package/cms/faststore/my-account/components/cms_component__accountnavigation.jsonc +10 -0
  9. package/cms/faststore/my-account/components/cms_component__accountorderdelivery.jsonc +80 -0
  10. package/cms/faststore/my-account/components/cms_component__accountorderdetails.jsonc +25 -0
  11. package/cms/faststore/my-account/components/cms_component__accountorderslist.jsonc +10 -0
  12. package/cms/faststore/my-account/components/cms_component__accountorderstatus.jsonc +90 -0
  13. package/cms/faststore/my-account/components/cms_component__accountordersummary.jsonc +25 -0
  14. package/package.json +6 -6
  15. package/src/components/account/Drawer/OrganizationDrawer/ContractSwitcher/ContractSwitcher.tsx +4 -6
  16. package/src/components/account/Drawer/OrganizationDrawer/OrganizationDrawer.tsx +18 -3
  17. package/src/components/account/Drawer/OrganizationDrawer/OrganizationDrawerFooter.tsx +13 -2
  18. package/src/components/account/Drawer/OrganizationDrawer/OrganizationDrawerHeader.tsx +1 -0
  19. package/src/components/account/Drawer/OrganizationDrawer/section.module.scss +7 -0
  20. package/src/components/account/Drawer/OrganizationSignInButton/OrganizationSignInButton.tsx +7 -9
  21. package/src/components/account/Menu/Menu.tsx +24 -7
  22. package/src/components/account/orders/ListOrders/FilterSlider/FilterFacetPendingApproval/FilterFacetPendingApproval.tsx +8 -3
  23. package/src/components/account/orders/ListOrders/FilterSlider/FilterSlider.tsx +1 -0
  24. package/src/components/account/orders/ListOrders/ListOrders.tsx +2 -2
  25. package/src/components/account/orders/ListOrders/listOrdersLabels.ts +4 -0
  26. package/src/components/account/orders/OrderDetails/BuyingPolicyAlert/BuyingPolicyAlert.tsx +45 -9
  27. package/src/components/account/orders/OrderDetails/DeliveryCard/DeliveryCard.tsx +14 -3
  28. package/src/components/account/orders/OrderDetails/DeliveryOptionAccordion/DeliveryOptionAccordion.tsx +4 -1
  29. package/src/components/account/orders/OrderDetails/DeliveryOptionAccordion/DeliveryOptionAccordionDeliveryInfo.tsx +14 -7
  30. package/src/components/account/orders/OrderDetails/DeliveryOptionAccordion/DeliveryOptionAccordionProducts.tsx +8 -5
  31. package/src/components/account/orders/OrderDetails/OrderDetailsHeader.tsx +5 -0
  32. package/src/components/account/orders/OrderDetails/StatusCard/StatusCard.tsx +26 -89
  33. package/src/components/account/orders/OrderDetails/StatusCard/statusCardLocalization.ts +114 -0
  34. package/src/components/account/orders/OrderDetails/SummaryCard/SummaryCard.tsx +2 -1
  35. package/src/components/account/orders/OrderDetails/SummaryCard/getOrderTotalLabel.ts +19 -0
  36. package/src/components/account/orders/OrderDetails/getDeliveryOptionLabel.ts +135 -0
  37. package/src/components/account/orders/OrderDetails/orderDetailsLabels.ts +73 -0
  38. package/src/components/navigation/Navbar/Navbar.tsx +17 -19
  39. package/src/components/navigation/Navbar/NavbarAccountArea.tsx +57 -0
  40. package/src/components/navigation/NavbarSlider/NavbarSlider.tsx +16 -18
  41. package/src/components/sections/Account/AccountOrderDelivery.tsx +3 -1
  42. package/src/components/sections/Account/AccountOrderDetails.tsx +16 -0
  43. package/src/components/sections/Account/AccountOrderStatus.tsx +27 -3
  44. package/src/components/sections/Account/AccountOrdersList.tsx +4 -0
  45. package/src/pages/api/fs/switch-contract.ts +194 -0
  46. package/src/pages/api/graphql.ts +108 -69
  47. package/src/sdk/account/accountPageContext.ts +14 -3
  48. package/src/sdk/account/changeContractToken.ts +19 -63
  49. package/src/sdk/account/clearPersistedSessionState.ts +13 -7
  50. package/src/sdk/account/getMyAccountRoutes.ts +2 -0
  51. package/src/sdk/account/useAvailableContracts.ts +1 -0
  52. package/src/sdk/account/useSwitchContract.ts +11 -3
  53. package/src/sdk/overrides/PageProvider.tsx +1 -1
  54. package/src/sdk/session/index.ts +2 -1
  55. package/src/sdk/session/isSignInAreaResolved.ts +12 -0
  56. package/test/components/account/ContractSwitcher.browser.test.tsx +42 -0
  57. package/test/components/account/Menu.browser.test.tsx +123 -0
  58. package/test/components/account/OrganizationDrawer.browser.test.tsx +148 -0
  59. package/test/components/account/OrganizationDrawerFooter.browser.test.tsx +95 -1
  60. package/test/components/account/OrganizationDrawerHeader.browser.test.tsx +2 -0
  61. package/test/components/account/OrganizationSignInButton.browser.test.tsx +49 -0
  62. package/test/components/account/orders/BuyingPolicyAlert.browser.test.tsx +342 -0
  63. package/test/components/account/orders/DeliveryCard.browser.test.tsx +36 -0
  64. package/test/components/account/orders/DeliveryOptionAccordion.browser.test.tsx +76 -0
  65. package/test/components/account/orders/DeliveryOptionAccordionDeliveryInfo.browser.test.tsx +41 -0
  66. package/test/components/account/orders/DeliveryOptionAccordionProducts.browser.test.tsx +35 -0
  67. package/test/components/account/orders/FilterFacetPendingApproval.browser.test.tsx +25 -0
  68. package/test/components/account/orders/StatusCard.browser.test.tsx +37 -0
  69. package/test/components/account/orders/StatusCard.test.ts +101 -0
  70. package/test/components/account/orders/SummaryCard.browser.test.tsx +59 -0
  71. package/test/components/account/orders/getDeliveryOptionLabel.test.ts +129 -0
  72. package/test/components/account/orders/getOrderTotalLabel.test.ts +35 -0
  73. package/test/components/account/orders/listOrdersLabels.test.ts +23 -0
  74. package/test/components/account/orders/orderDetailsLabels.test.ts +13 -0
  75. package/test/components/navigation/Navbar.browser.test.tsx +183 -0
  76. package/test/components/navigation/NavbarAccountArea.browser.test.tsx +115 -0
  77. package/test/components/navigation/NavbarSlider.browser.test.tsx +143 -0
  78. package/test/components/sections/Account/AccountOrderDelivery.browser.test.tsx +72 -0
  79. package/test/components/sections/Account/AccountOrderDetails.browser.test.tsx +151 -0
  80. package/test/components/sections/Account/AccountOrderStatus.browser.test.tsx +59 -0
  81. package/test/components/sections/Account/AccountOrdersList.browser.test.tsx +67 -0
  82. package/test/pages/api/graphql.test.ts +27 -1
  83. package/test/pages/api/switch-contract.test.ts +385 -0
  84. package/test/sdk/account/changeContractToken.browser.test.ts +23 -71
  85. package/test/sdk/account/clearPersistedSessionState.browser.test.ts +24 -0
  86. package/test/sdk/account/getMyAccountRoutes.test.ts +11 -1
  87. package/test/sdk/account/useSwitchContract.browser.test.ts +21 -0
  88. package/test/sdk/session/isSignInAreaResolved.test.ts +22 -0
  89. package/test/utils/userOrderStatus.test.ts +22 -0
@@ -0,0 +1,59 @@
1
+ /**
2
+ * @vitest-environment jsdom
3
+ */
4
+
5
+ import { render, screen } from '@testing-library/react'
6
+ import { describe, expect, it, vi } from 'vitest'
7
+
8
+ import SummaryCard from '../../../../src/components/account/orders/OrderDetails/SummaryCard'
9
+
10
+ vi.mock('next/router', () => ({
11
+ useRouter: () => ({ locale: 'en-US' }),
12
+ }))
13
+
14
+ describe('SummaryCard', () => {
15
+ it('renders localized totals, interest, and the final total', () => {
16
+ render(
17
+ <SummaryCard
18
+ totals={[
19
+ { id: 'Items', name: 'Items from OMS', value: 1_000 },
20
+ { id: 'FutureTotal', name: 'Future total from OMS', value: 100 },
21
+ ]}
22
+ currencyCode="USD"
23
+ transactions={[
24
+ {
25
+ isActive: true,
26
+ payments: [{ value: 1_200, referenceValue: 1_100 }],
27
+ },
28
+ ]}
29
+ labels={{
30
+ itemsTotalLabel: 'Products',
31
+ interestLabel: 'Financing',
32
+ totalLabel: 'Grand total',
33
+ }}
34
+ />
35
+ )
36
+
37
+ expect(screen.getByText('Products')).toBeTruthy()
38
+ expect(screen.getByText('Future total from OMS')).toBeTruthy()
39
+ expect(screen.getByText('Financing')).toBeTruthy()
40
+ expect(screen.getByText('Grand total')).toBeTruthy()
41
+ })
42
+
43
+ it('does not add interest for inactive transactions', () => {
44
+ render(
45
+ <SummaryCard
46
+ totals={[{ id: 'Items', name: 'Items from OMS', value: 1_000 }]}
47
+ currencyCode="USD"
48
+ transactions={[
49
+ {
50
+ isActive: false,
51
+ payments: [{ value: 1_200, referenceValue: 1_000 }],
52
+ },
53
+ ]}
54
+ />
55
+ )
56
+
57
+ expect(screen.queryByText('Interest')).toBeNull()
58
+ })
59
+ })
@@ -0,0 +1,129 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import {
4
+ getDeliveryOptionKey,
5
+ getDeliveryOptionLabel,
6
+ } from '../../../../src/components/account/orders/OrderDetails/getDeliveryOptionLabel'
7
+ import { resolveOrderDeliveryLabels } from '../../../../src/components/account/orders/OrderDetails/orderDetailsLabels'
8
+
9
+ const labels = resolveOrderDeliveryLabels({
10
+ deliveryChannelLabel: 'Entrega',
11
+ pickupChannelLabel: 'Retirada',
12
+ takeAwayChannelLabel: 'Levar',
13
+ businessDaysZeroTemplate: 'bd-0',
14
+ businessDaysOneTemplate: 'bd-1',
15
+ businessDaysOtherTemplate: 'bd-{count}',
16
+ daysZeroTemplate: 'd-0',
17
+ daysOneTemplate: 'd-1',
18
+ daysOtherTemplate: 'd-{count}',
19
+ hoursZeroTemplate: 'h-0',
20
+ hoursOneTemplate: 'h-1',
21
+ hoursOtherTemplate: 'h-{count}',
22
+ minutesZeroTemplate: 'm-0',
23
+ minutesOneTemplate: 'm-1',
24
+ minutesOtherTemplate: 'm-{count}',
25
+ toNeighborhoodTemplate: 'para {neighborhood}',
26
+ })
27
+
28
+ describe('getDeliveryOptionLabel', () => {
29
+ it.each([
30
+ ['0bd', 'bd-0'],
31
+ ['1bd', 'bd-1'],
32
+ ['5bd', 'bd-5'],
33
+ ['0d', 'd-0'],
34
+ ['1d', 'd-1'],
35
+ ['5d', 'd-5'],
36
+ ['0h', 'h-0'],
37
+ ['1h', 'h-1'],
38
+ ['5h', 'h-5'],
39
+ ['0m', 'm-0'],
40
+ ['1m', 'm-1'],
41
+ ['5m', 'm-5'],
42
+ ])('localizes shipping estimate %s', (shippingEstimate, expected) => {
43
+ expect(
44
+ getDeliveryOptionLabel({ deliveryChannel: '', shippingEstimate }, labels)
45
+ ).toBe(expected)
46
+ })
47
+
48
+ it.each([
49
+ ['delivery', 'Entrega'],
50
+ ['pickup', 'Retirada'],
51
+ ['pickup-in-point', 'Retirada'],
52
+ ['take-away', 'Levar'],
53
+ ])('localizes the %s channel', (deliveryChannel, expected) => {
54
+ expect(
55
+ getDeliveryOptionLabel(
56
+ { deliveryChannel, shippingEstimate: '1d' },
57
+ labels
58
+ )
59
+ ).toBe(`${expected} d-1`)
60
+ })
61
+
62
+ it('localizes the neighborhood connector while preserving its value', () => {
63
+ expect(
64
+ getDeliveryOptionLabel(
65
+ {
66
+ deliveryChannel: 'delivery',
67
+ shippingEstimate: '5bd',
68
+ address: { neighborhood: 'Botafogo' },
69
+ },
70
+ labels
71
+ )
72
+ ).toBe('Entrega bd-5 para Botafogo')
73
+ })
74
+
75
+ it('treats padded one-unit estimates the same way as the API parser', () => {
76
+ expect(
77
+ getDeliveryOptionLabel(
78
+ { deliveryChannel: '', shippingEstimate: '01bd' },
79
+ labels
80
+ )
81
+ ).toBe('bd-1')
82
+ })
83
+
84
+ it('builds a stable key from the same grouping fields as the API', () => {
85
+ expect(
86
+ getDeliveryOptionKey({
87
+ selectedSla: 'Normal',
88
+ deliveryChannel: 'delivery',
89
+ deliveryCompany: 'Correios',
90
+ seller: '1',
91
+ shippingEstimate: '5bd',
92
+ shippingEstimateDate: '2026-08-05T00:00:00Z',
93
+ address: { addressId: 'addr-1' },
94
+ deliveryWindow: {
95
+ startDateUtc: '2026-08-05T10:00:00Z',
96
+ endDateUtc: '2026-08-05T18:00:00Z',
97
+ },
98
+ })
99
+ ).toBe(
100
+ 'Normal|delivery|Correios|1|5bd|2026-08-05T00:00:00Z|addr-1|2026-08-05T10:00:00Z|2026-08-05T18:00:00Z'
101
+ )
102
+ })
103
+
104
+ it('keeps a recognized channel localized when the estimate is unavailable', () => {
105
+ expect(
106
+ getDeliveryOptionLabel(
107
+ {
108
+ deliveryChannel: 'delivery',
109
+ shippingEstimate: 'someday',
110
+ friendlyDeliveryOptionName: 'Delivery someday',
111
+ },
112
+ labels
113
+ )
114
+ ).toBe('Entrega')
115
+ })
116
+
117
+ it('preserves the API fallback for unsupported raw values', () => {
118
+ expect(
119
+ getDeliveryOptionLabel(
120
+ {
121
+ deliveryChannel: 'future-channel',
122
+ shippingEstimate: 'someday',
123
+ friendlyDeliveryOptionName: 'Existing API label',
124
+ },
125
+ labels
126
+ )
127
+ ).toBe('Existing API label')
128
+ })
129
+ })
@@ -0,0 +1,35 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import { getOrderTotalLabel } from '../../../../src/components/account/orders/OrderDetails/SummaryCard/getOrderTotalLabel'
4
+ import { resolveOrderSummaryLabels } from '../../../../src/components/account/orders/OrderDetails/orderDetailsLabels'
5
+
6
+ const labels = resolveOrderSummaryLabels({
7
+ itemsTotalLabel: 'Produtos',
8
+ discountsTotalLabel: 'Descontos',
9
+ shippingTotalLabel: 'Frete',
10
+ taxTotalLabel: 'Impostos',
11
+ changeTotalLabel: 'Alterações',
12
+ })
13
+
14
+ describe('getOrderTotalLabel', () => {
15
+ it.each([
16
+ ['Items', 'Produtos'],
17
+ ['Discounts', 'Descontos'],
18
+ ['Shipping', 'Frete'],
19
+ ['Tax', 'Impostos'],
20
+ ['Change', 'Alterações'],
21
+ ])('localizes the documented OMS %s total', (id, expected) => {
22
+ expect(getOrderTotalLabel({ id, name: `${id} from OMS` }, labels)).toBe(
23
+ expected
24
+ )
25
+ })
26
+
27
+ it('falls back to the OMS name for an unknown total id', () => {
28
+ expect(
29
+ getOrderTotalLabel(
30
+ { id: 'FutureTotal', name: 'Future total from OMS' },
31
+ labels
32
+ )
33
+ ).toBe('Future total from OMS')
34
+ })
35
+ })
@@ -0,0 +1,23 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import {
4
+ defaultListOrdersLabels,
5
+ resolveListOrdersLabels,
6
+ } from '../../../../src/components/account/orders/ListOrders/listOrdersLabels'
7
+
8
+ describe('list orders labels', () => {
9
+ it('provides English defaults for filter group labels', () => {
10
+ expect(defaultListOrdersLabels.statusFilterLabel).toBe('Status')
11
+ expect(defaultListOrdersLabels.orderDateFilterLabel).toBe('Order Date')
12
+ })
13
+
14
+ it('resolves localized filter group labels', () => {
15
+ const labels = resolveListOrdersLabels({
16
+ statusFilterLabel: 'Situação',
17
+ orderDateFilterLabel: 'Data do pedido',
18
+ })
19
+
20
+ expect(labels.statusFilterLabel).toBe('Situação')
21
+ expect(labels.orderDateFilterLabel).toBe('Data do pedido')
22
+ })
23
+ })
@@ -0,0 +1,13 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import {
4
+ defaultOrderDeliveryLabels,
5
+ resolveOrderDeliveryLabels,
6
+ } from '../../../../src/components/account/orders/OrderDetails/orderDetailsLabels'
7
+
8
+ describe('order details labels', () => {
9
+ it('uses English delivery labels by default', () => {
10
+ expect(resolveOrderDeliveryLabels()).toEqual(defaultOrderDeliveryLabels)
11
+ expect(defaultOrderDeliveryLabels.eachLabel).toBe('Each')
12
+ })
13
+ })
@@ -0,0 +1,183 @@
1
+ /**
2
+ * @vitest-environment jsdom
3
+ */
4
+
5
+ import '@testing-library/jest-dom/vitest'
6
+ import { render, screen } from '@testing-library/react'
7
+ import { forwardRef } from 'react'
8
+ import { describe, expect, it, vi } from 'vitest'
9
+
10
+ const mockUseSession = vi.hoisted(() => vi.fn())
11
+ const mockUseScreenResize = vi.hoisted(() => vi.fn())
12
+ const mockNavbarAccountArea = vi.hoisted(() => vi.fn())
13
+ const mockStoreConfig = vi.hoisted(() => ({
14
+ experimental: { enableFaststoreMyAccount: false },
15
+ localization: { enabled: false },
16
+ }))
17
+
18
+ vi.mock('next/dynamic', () => ({
19
+ default: () => () => null,
20
+ }))
21
+
22
+ vi.mock('@faststore/ui', () => ({
23
+ Icon: () => null,
24
+ Skeleton: () => null,
25
+ useScrollDirection: () => 'up',
26
+ useUI: () => ({ openNavbar: vi.fn(), navbar: false }),
27
+ }))
28
+
29
+ vi.mock('discovery.config', () => ({ default: mockStoreConfig }))
30
+
31
+ vi.mock('src/components/account/Drawer/OrganizationSignInButton', () => ({
32
+ OrganizationSignInButton: () => null,
33
+ }))
34
+
35
+ vi.mock('src/components/cart/CartToggle', () => ({
36
+ default: () => <div data-testid="cart-toggle" />,
37
+ }))
38
+
39
+ vi.mock('src/components/search/SearchInput', () => ({
40
+ default: forwardRef(function SearchInputStub(_props, _ref) {
41
+ return <div data-testid="search-input" />
42
+ }),
43
+ }))
44
+
45
+ vi.mock('src/components/ui/Link', () => ({
46
+ default: ({ children }: { children?: React.ReactNode }) => (
47
+ <a href="/">{children}</a>
48
+ ),
49
+ }))
50
+
51
+ vi.mock('src/components/ui/LocalizationButton', () => ({
52
+ default: () => <div data-testid="localization-button" />,
53
+ }))
54
+
55
+ vi.mock('src/components/ui/Logo', () => ({
56
+ default: () => <div data-testid="logo" />,
57
+ }))
58
+
59
+ vi.mock('../../../src/components/navigation/Navbar/NavbarAccountArea', () => ({
60
+ NavbarAccountArea: (props: Record<string, unknown>) => {
61
+ mockNavbarAccountArea(props)
62
+ return <div data-testid="navbar-account-area" />
63
+ },
64
+ }))
65
+
66
+ vi.mock('src/sdk/overrides/OverrideContext', () => ({
67
+ useOverrideComponents: () => ({
68
+ Navbar: {
69
+ Component: ({ children }: React.PropsWithChildren) => (
70
+ <div data-testid="navbar-wrapper">{children}</div>
71
+ ),
72
+ props: {},
73
+ },
74
+ NavbarHeader: {
75
+ Component: ({ children }: React.PropsWithChildren) => (
76
+ <header>{children}</header>
77
+ ),
78
+ props: {},
79
+ },
80
+ NavbarRow: {
81
+ Component: ({ children }: React.PropsWithChildren) => (
82
+ <div>{children}</div>
83
+ ),
84
+ props: {},
85
+ },
86
+ NavbarButtons: {
87
+ Component: ({ children }: React.PropsWithChildren) => (
88
+ <div>{children}</div>
89
+ ),
90
+ props: {},
91
+ },
92
+ IconButton: {
93
+ Component: (props: Record<string, unknown>) => <button {...props} />,
94
+ props: { 'aria-label': 'menu' },
95
+ },
96
+ _experimentalButtonSignIn: { Component: () => null },
97
+ }),
98
+ }))
99
+
100
+ vi.mock('src/sdk/session', () => ({ useSession: mockUseSession }))
101
+
102
+ vi.mock('src/sdk/ui/useScreenResize', () => ({
103
+ default: mockUseScreenResize,
104
+ }))
105
+
106
+ import Navbar from '../../../src/components/navigation/Navbar/Navbar'
107
+
108
+ const baseProps = {
109
+ logo: {
110
+ src: '/logo.png',
111
+ alt: 'Logo',
112
+ link: { url: '/', title: 'Home' },
113
+ },
114
+ searchInput: { sort: 'score_desc' },
115
+ cart: { alt: 'cart', icon: 'ShoppingCart' },
116
+ signIn: {
117
+ button: {
118
+ icon: { alt: 'account', icon: 'User' },
119
+ label: 'Sign in',
120
+ myAccountLabel: 'My Account',
121
+ },
122
+ },
123
+ region: { icon: 'MapPin', label: 'Region', shouldDisplayRegion: false },
124
+ links: [],
125
+ home: { label: 'Home' },
126
+ menu: { icon: { icon: 'List', alt: 'Menu' } },
127
+ }
128
+
129
+ describe('Navbar', () => {
130
+ it('renders the account area (desktop) and forwards isSignInResolved=false before the session validates', () => {
131
+ mockUseScreenResize.mockReturnValue({ isDesktop: true })
132
+ mockUseSession.mockReturnValue({
133
+ b2b: {},
134
+ isSessionReady: false,
135
+ hasValidated: false,
136
+ })
137
+
138
+ render(<Navbar {...baseProps} />)
139
+
140
+ expect(screen.getByTestId('navbar-account-area')).toBeTruthy()
141
+ expect(mockNavbarAccountArea).toHaveBeenCalledWith(
142
+ expect.objectContaining({
143
+ isSignInResolved: false,
144
+ skeletonAttr: 'data-fs-navbar-signin-skeleton',
145
+ })
146
+ )
147
+ })
148
+
149
+ it('forwards isSignInResolved=true and isOrganizationEnabled for a resolved B2B representative session', () => {
150
+ mockStoreConfig.experimental.enableFaststoreMyAccount = true
151
+ mockUseScreenResize.mockReturnValue({ isDesktop: true })
152
+ mockUseSession.mockReturnValue({
153
+ b2b: { isRepresentative: true },
154
+ isSessionReady: true,
155
+ hasValidated: true,
156
+ })
157
+
158
+ render(<Navbar {...baseProps} />)
159
+
160
+ expect(mockNavbarAccountArea).toHaveBeenCalledWith(
161
+ expect.objectContaining({
162
+ isSignInResolved: true,
163
+ isOrganizationEnabled: true,
164
+ isRepresentative: true,
165
+ })
166
+ )
167
+
168
+ mockStoreConfig.experimental.enableFaststoreMyAccount = false
169
+ })
170
+
171
+ it('does not render the account area on mobile', () => {
172
+ mockUseScreenResize.mockReturnValue({ isDesktop: false })
173
+ mockUseSession.mockReturnValue({
174
+ b2b: {},
175
+ isSessionReady: true,
176
+ hasValidated: true,
177
+ })
178
+
179
+ render(<Navbar {...baseProps} />)
180
+
181
+ expect(screen.queryByTestId('navbar-account-area')).toBeNull()
182
+ })
183
+ })
@@ -0,0 +1,115 @@
1
+ /**
2
+ * @vitest-environment jsdom
3
+ */
4
+
5
+ import '@testing-library/jest-dom/vitest'
6
+ import { render, screen } from '@testing-library/react'
7
+ import { describe, expect, it, vi } from 'vitest'
8
+
9
+ vi.mock(
10
+ '../../../src/components/account/Drawer/OrganizationSignInButton',
11
+ () => ({
12
+ OrganizationSignInButton: ({
13
+ icon,
14
+ isRepresentative,
15
+ }: {
16
+ icon: { alt: string; icon: string }
17
+ isRepresentative?: boolean
18
+ }) => (
19
+ <button
20
+ type="button"
21
+ data-testid="organization-signin"
22
+ data-icon={icon.alt}
23
+ >
24
+ {isRepresentative ? 'Representative' : 'Not representative'}
25
+ </button>
26
+ ),
27
+ })
28
+ )
29
+
30
+ import { NavbarAccountArea } from '../../../src/components/navigation/Navbar/NavbarAccountArea'
31
+
32
+ const signInButton = {
33
+ icon: { alt: 'account', icon: 'User' },
34
+ label: 'Sign in',
35
+ myAccountLabel: 'My Account',
36
+ }
37
+
38
+ const ButtonSignInStub = {
39
+ Component: ({ label }: { label: string }) => (
40
+ <button type="button" data-testid="storefront-signin">
41
+ {label}
42
+ </button>
43
+ ),
44
+ props: undefined,
45
+ }
46
+
47
+ describe('NavbarAccountArea', () => {
48
+ it('renders the loading skeleton with the Navbar attribute while sign-in is not resolved', () => {
49
+ const { container } = render(
50
+ <NavbarAccountArea
51
+ isSignInResolved={false}
52
+ isOrganizationEnabled={false}
53
+ signInButton={signInButton}
54
+ ButtonSignIn={ButtonSignInStub}
55
+ skeletonAttr="data-fs-navbar-signin-skeleton"
56
+ />
57
+ )
58
+
59
+ expect(
60
+ container.querySelector('[data-fs-navbar-signin-skeleton]')
61
+ ).toBeTruthy()
62
+ expect(
63
+ container.querySelector('[data-fs-navbar-slider-signin-skeleton]')
64
+ ).toBeNull()
65
+ })
66
+
67
+ it('renders the loading skeleton with the NavbarSlider attribute while sign-in is not resolved', () => {
68
+ const { container } = render(
69
+ <NavbarAccountArea
70
+ isSignInResolved={false}
71
+ isOrganizationEnabled={false}
72
+ signInButton={signInButton}
73
+ ButtonSignIn={ButtonSignInStub}
74
+ skeletonAttr="data-fs-navbar-slider-signin-skeleton"
75
+ />
76
+ )
77
+
78
+ expect(
79
+ container.querySelector('[data-fs-navbar-slider-signin-skeleton]')
80
+ ).toBeTruthy()
81
+ })
82
+
83
+ it('renders the OrganizationSignInButton when the organization area is enabled', () => {
84
+ render(
85
+ <NavbarAccountArea
86
+ isSignInResolved
87
+ isOrganizationEnabled
88
+ isRepresentative
89
+ signInButton={signInButton}
90
+ ButtonSignIn={ButtonSignInStub}
91
+ skeletonAttr="data-fs-navbar-signin-skeleton"
92
+ />
93
+ )
94
+
95
+ expect(screen.getByTestId('organization-signin')).toHaveTextContent(
96
+ 'Representative'
97
+ )
98
+ expect(screen.queryByTestId('storefront-signin')).toBeNull()
99
+ })
100
+
101
+ it('renders the storefront ButtonSignIn override when the organization area is not enabled', () => {
102
+ render(
103
+ <NavbarAccountArea
104
+ isSignInResolved
105
+ isOrganizationEnabled={false}
106
+ signInButton={signInButton}
107
+ ButtonSignIn={ButtonSignInStub}
108
+ skeletonAttr="data-fs-navbar-signin-skeleton"
109
+ />
110
+ )
111
+
112
+ expect(screen.getByTestId('storefront-signin')).toHaveTextContent('Sign in')
113
+ expect(screen.queryByTestId('organization-signin')).toBeNull()
114
+ })
115
+ })