@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
@@ -2,6 +2,7 @@
2
2
  * @vitest-environment jsdom
3
3
  */
4
4
 
5
+ import '@testing-library/jest-dom/vitest'
5
6
  import { fireEvent, render, screen, waitFor } from '@testing-library/react'
6
7
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
7
8
 
@@ -117,6 +118,47 @@ describe('ContractSwitcher', () => {
117
118
  expect(options.length).toBe(2)
118
119
  })
119
120
 
121
+ it('marks the default contract with a star and lists it first (Design QA 00:02:00)', async () => {
122
+ // Note: id 'a' is pinned to the current session (this file mocks
123
+ // useSession with b2b.customerId: 'a'), so it must stay on the active
124
+ // contract for it to resolve as the current one; Alpha (the default)
125
+ // and Aardvark get other ids and land in the alternatives list, which
126
+ // is what this test exercises.
127
+ mockUseAvailableContracts.mockReturnValue({
128
+ contracts: [
129
+ { id: 'a', corporateName: 'Beta', isActive: true, isDefault: false },
130
+ { id: 'b', corporateName: 'Alpha', isActive: false, isDefault: true },
131
+ {
132
+ id: 'c',
133
+ corporateName: 'Aardvark',
134
+ isActive: false,
135
+ isDefault: false,
136
+ },
137
+ ],
138
+ loading: false,
139
+ error: null,
140
+ })
141
+
142
+ const { container } = render(
143
+ <ContractSwitcher onBack={vi.fn()} onClose={vi.fn()} />
144
+ )
145
+
146
+ await screen.findByText('Alpha')
147
+ expect(
148
+ container.querySelectorAll('[data-fs-contract-switcher-default]')
149
+ ).toHaveLength(1)
150
+ expect(
151
+ container.querySelector('[data-fs-contract-switcher-default]')
152
+ ).toHaveAttribute('aria-label', 'Default contract')
153
+
154
+ const names = Array.from(
155
+ container.querySelectorAll(
156
+ '[data-fs-contract-switcher-option] [data-fs-contract-switcher-option-name]'
157
+ )
158
+ ).map((el) => el.textContent)
159
+ expect(names[0]).toBe('Alpha') // default first, then alphabetical ('Aardvark')
160
+ })
161
+
120
162
  it('requires selecting a contract before Confirm is enabled, then switches (REQ-03)', async () => {
121
163
  render(<ContractSwitcher onBack={vi.fn()} onClose={vi.fn()} />)
122
164
 
@@ -0,0 +1,123 @@
1
+ /**
2
+ * @vitest-environment jsdom
3
+ */
4
+
5
+ import '@testing-library/jest-dom/vitest'
6
+ import { act, fireEvent, render, screen } from '@testing-library/react'
7
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
8
+
9
+ const mockUseSession = vi.hoisted(() => vi.fn())
10
+ const mockUseScreenResize = vi.hoisted(() => vi.fn())
11
+ const mockOrganizationDrawer = vi.hoisted(() => vi.fn())
12
+
13
+ vi.mock('src/sdk/session', () => ({ useSession: mockUseSession }))
14
+
15
+ vi.mock('src/sdk/account/accountPageContext', () => ({
16
+ useAccountNavigationLabels: () => ({ switchLabel: 'Switch' }),
17
+ }))
18
+
19
+ vi.mock('src/sdk/ui/useScreenResize', () => ({
20
+ default: mockUseScreenResize,
21
+ }))
22
+
23
+ vi.mock('next/router', () => ({
24
+ useRouter: () => ({ pathname: '/pvt/account' }),
25
+ }))
26
+
27
+ vi.mock(
28
+ '../../../src/components/account/Drawer/OrganizationDrawer/OrganizationDrawer',
29
+ () => ({
30
+ OrganizationDrawer: (props: Record<string, unknown>) => {
31
+ mockOrganizationDrawer(props)
32
+ return <div data-testid="organization-drawer" />
33
+ },
34
+ })
35
+ )
36
+
37
+ import Menu from '../../../src/components/account/Menu/Menu'
38
+
39
+ const items = [{ title: 'Orders', route: '/pvt/account/orders' }]
40
+
41
+ describe('Menu', () => {
42
+ beforeEach(() => {
43
+ mockUseScreenResize.mockReturnValue({ isDesktop: true })
44
+ })
45
+
46
+ afterEach(() => {
47
+ vi.clearAllMocks()
48
+ })
49
+
50
+ it('does not render the Switch button without an organization unit', () => {
51
+ mockUseSession.mockReturnValue({ b2b: {} })
52
+
53
+ render(<Menu accountName="Jane" items={items} />)
54
+
55
+ expect(screen.queryByRole('button', { name: 'Switch' })).toBeNull()
56
+ })
57
+
58
+ it('renders the Switch button when the buyer has an organization unit', () => {
59
+ mockUseSession.mockReturnValue({ b2b: { unitId: 'unit-1' } })
60
+
61
+ render(<Menu accountName="Jane" items={items} />)
62
+
63
+ expect(screen.getByRole('button', { name: 'Switch' })).toBeTruthy()
64
+ })
65
+
66
+ it('mounts the OrganizationDrawer with initialView "switch" when Switch is clicked', () => {
67
+ mockUseSession.mockReturnValue({
68
+ b2b: { unitId: 'unit-1', isRepresentative: true },
69
+ })
70
+
71
+ render(<Menu accountName="Jane" items={items} />)
72
+
73
+ expect(screen.queryByTestId('organization-drawer')).toBeNull()
74
+
75
+ fireEvent.click(screen.getByRole('button', { name: 'Switch' }))
76
+
77
+ expect(screen.getByTestId('organization-drawer')).toBeTruthy()
78
+ expect(mockOrganizationDrawer).toHaveBeenCalledWith(
79
+ expect.objectContaining({
80
+ isOpen: true,
81
+ initialView: 'switch',
82
+ isRepresentative: true,
83
+ })
84
+ )
85
+ })
86
+
87
+ it('passes isRepresentative as a boolean even when b2b.isRepresentative is undefined', () => {
88
+ mockUseSession.mockReturnValue({ b2b: { unitId: 'unit-1' } })
89
+
90
+ render(<Menu accountName="Jane" items={items} />)
91
+ fireEvent.click(screen.getByRole('button', { name: 'Switch' }))
92
+
93
+ expect(mockOrganizationDrawer).toHaveBeenCalledWith(
94
+ expect.objectContaining({ isRepresentative: false })
95
+ )
96
+ })
97
+
98
+ it('unmounts the OrganizationDrawer when closeDrawer is invoked', () => {
99
+ mockUseSession.mockReturnValue({ b2b: { unitId: 'unit-1' } })
100
+
101
+ render(<Menu accountName="Jane" items={items} />)
102
+ fireEvent.click(screen.getByRole('button', { name: 'Switch' }))
103
+ expect(screen.getByTestId('organization-drawer')).toBeTruthy()
104
+
105
+ const closeDrawer = mockOrganizationDrawer.mock.calls[0][0]
106
+ .closeDrawer as () => void
107
+ act(() => {
108
+ closeDrawer()
109
+ })
110
+
111
+ expect(screen.queryByTestId('organization-drawer')).toBeNull()
112
+ })
113
+
114
+ it('renders only the nav list on mobile (no account/switch area)', () => {
115
+ mockUseScreenResize.mockReturnValue({ isDesktop: false })
116
+ mockUseSession.mockReturnValue({ b2b: { unitId: 'unit-1' } })
117
+
118
+ render(<Menu accountName="Jane" items={items} />)
119
+
120
+ expect(screen.queryByRole('button', { name: 'Switch' })).toBeNull()
121
+ expect(screen.getByText('Orders')).toBeTruthy()
122
+ })
123
+ })
@@ -2,6 +2,7 @@
2
2
  * @vitest-environment jsdom
3
3
  */
4
4
 
5
+ import '@testing-library/jest-dom/vitest'
5
6
  import { fireEvent, render, screen } from '@testing-library/react'
6
7
  import type { ReactNode } from 'react'
7
8
  import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
@@ -9,6 +10,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
9
10
  const mockFadeOut = vi.hoisted(() => vi.fn())
10
11
  const mockUseSession = vi.hoisted(() => vi.fn())
11
12
  const mockCloseDrawer = vi.hoisted(() => vi.fn())
13
+ const mockUseAvailableContracts = vi.hoisted(() => vi.fn())
12
14
 
13
15
  vi.mock('@faststore/ui', async (importOriginal) => {
14
16
  const actual = await importOriginal<typeof import('@faststore/ui')>()
@@ -38,6 +40,10 @@ vi.mock('@faststore/ui', async (importOriginal) => {
38
40
 
39
41
  vi.mock('src/sdk/session', () => ({ useSession: mockUseSession }))
40
42
 
43
+ vi.mock('src/sdk/account/useAvailableContracts', () => ({
44
+ useAvailableContracts: mockUseAvailableContracts,
45
+ }))
46
+
41
47
  vi.mock(
42
48
  '../../../src/components/account/Drawer/OrganizationDrawer/ContractSwitcher',
43
49
  () => ({
@@ -82,6 +88,11 @@ describe('OrganizationDrawer', () => {
82
88
  },
83
89
  person: { givenName: 'Jane' },
84
90
  })
91
+ mockUseAvailableContracts.mockReturnValue({
92
+ contracts: [],
93
+ loading: false,
94
+ error: null,
95
+ })
85
96
  })
86
97
 
87
98
  afterEach(() => {
@@ -194,4 +205,141 @@ describe('OrganizationDrawer', () => {
194
205
  screen.getByRole('heading', { name: 'Organization', level: 1 })
195
206
  ).toBeTruthy()
196
207
  })
208
+
209
+ it('opens directly in the switcher when initialView is "switch"', () => {
210
+ render(
211
+ <OrganizationDrawer
212
+ isOpen
213
+ closeDrawer={vi.fn()}
214
+ isRepresentative
215
+ initialView="switch"
216
+ />
217
+ )
218
+ expect(screen.getByTestId('contract-switcher')).toBeInTheDocument()
219
+ })
220
+
221
+ it('shows the default-contract star in the header when the active contract is the unit default', () => {
222
+ mockUseAvailableContracts.mockReturnValue({
223
+ contracts: [
224
+ {
225
+ id: 'unit-1',
226
+ corporateName: 'Acme Contract',
227
+ isActive: true,
228
+ isDefault: true,
229
+ },
230
+ {
231
+ id: 'other',
232
+ corporateName: 'Other Contract',
233
+ isActive: false,
234
+ isDefault: false,
235
+ },
236
+ ],
237
+ loading: false,
238
+ error: null,
239
+ })
240
+ mockUseSession.mockReturnValue({
241
+ b2b: {
242
+ unitId: 'unit-1',
243
+ unitName: 'Stellar Global',
244
+ contractName: 'Acme Contract',
245
+ customerId: 'unit-1',
246
+ userName: 'Jane Buyer',
247
+ userEmail: 'jane@example.com',
248
+ organizationManager: true,
249
+ },
250
+ person: { givenName: 'Jane' },
251
+ })
252
+
253
+ render(
254
+ <OrganizationDrawer
255
+ isOpen
256
+ closeDrawer={mockCloseDrawer}
257
+ isRepresentative={false}
258
+ />
259
+ )
260
+
261
+ expect(screen.getByLabelText('Default contract')).toBeTruthy()
262
+ })
263
+
264
+ it('does not show the default-contract star when the active contract is not the unit default', () => {
265
+ mockUseAvailableContracts.mockReturnValue({
266
+ contracts: [
267
+ {
268
+ id: 'unit-1',
269
+ corporateName: 'Acme Contract',
270
+ isActive: true,
271
+ isDefault: false,
272
+ },
273
+ {
274
+ id: 'other',
275
+ corporateName: 'Other Contract',
276
+ isActive: false,
277
+ isDefault: true,
278
+ },
279
+ ],
280
+ loading: false,
281
+ error: null,
282
+ })
283
+ mockUseSession.mockReturnValue({
284
+ b2b: {
285
+ unitId: 'unit-1',
286
+ unitName: 'Stellar Global',
287
+ contractName: 'Acme Contract',
288
+ customerId: 'unit-1',
289
+ userName: 'Jane Buyer',
290
+ userEmail: 'jane@example.com',
291
+ organizationManager: true,
292
+ },
293
+ person: { givenName: 'Jane' },
294
+ })
295
+
296
+ render(
297
+ <OrganizationDrawer
298
+ isOpen
299
+ closeDrawer={mockCloseDrawer}
300
+ isRepresentative={false}
301
+ />
302
+ )
303
+
304
+ expect(screen.queryByLabelText('Default contract')).toBeNull()
305
+ })
306
+
307
+ it('fetches the contract list only while open for an org member', () => {
308
+ const { rerender } = render(
309
+ <OrganizationDrawer
310
+ isOpen={false}
311
+ closeDrawer={mockCloseDrawer}
312
+ isRepresentative={false}
313
+ />
314
+ )
315
+
316
+ expect(mockUseAvailableContracts).toHaveBeenLastCalledWith(false)
317
+
318
+ rerender(
319
+ <OrganizationDrawer
320
+ isOpen
321
+ closeDrawer={mockCloseDrawer}
322
+ isRepresentative={false}
323
+ />
324
+ )
325
+
326
+ expect(mockUseAvailableContracts).toHaveBeenLastCalledWith(true)
327
+ })
328
+
329
+ it('never fetches the contract list when the buyer has no organization unit', () => {
330
+ mockUseSession.mockReturnValue({
331
+ b2b: { userName: 'Jane Buyer' },
332
+ person: null,
333
+ })
334
+
335
+ render(
336
+ <OrganizationDrawer
337
+ isOpen
338
+ closeDrawer={mockCloseDrawer}
339
+ isRepresentative={false}
340
+ />
341
+ )
342
+
343
+ expect(mockUseAvailableContracts).toHaveBeenLastCalledWith(false)
344
+ })
197
345
  })
@@ -6,6 +6,7 @@ import { fireEvent, render, screen } from '@testing-library/react'
6
6
  import { describe, expect, it, vi } from 'vitest'
7
7
 
8
8
  import { OrganizationDrawerFooter } from '../../../src/components/account/Drawer/OrganizationDrawer/OrganizationDrawerFooter'
9
+ import PageProvider from '../../../src/sdk/overrides/PageProvider'
9
10
 
10
11
  describe('OrganizationDrawerFooter', () => {
11
12
  it('renders org and user details with optional email', () => {
@@ -48,7 +49,100 @@ describe('OrganizationDrawerFooter', () => {
48
49
  />
49
50
  )
50
51
 
51
- fireEvent.click(screen.getByRole('button', { name: /log out/i }))
52
+ fireEvent.click(screen.getByRole('button', { name: /logout/i }))
52
53
  expect(onLogoutClick).toHaveBeenCalledTimes(1)
53
54
  })
55
+
56
+ it('uses the default English manage/logout labels when rendered outside a My Account page context', () => {
57
+ render(
58
+ <OrganizationDrawerFooter
59
+ orgName="Stellar Global"
60
+ userName="Jane Buyer"
61
+ showManageLink
62
+ manageUrl="/pvt/organization-account/org-unit/unit-1"
63
+ />
64
+ )
65
+
66
+ expect(screen.getByText('Manage')).toBeTruthy()
67
+ expect(screen.getByRole('button', { name: 'Logout' })).toBeTruthy()
68
+ })
69
+
70
+ it('uses the default labels inside a non-account page context', () => {
71
+ render(
72
+ <PageProvider context={{ globalSettings: {} }}>
73
+ <OrganizationDrawerFooter
74
+ orgName="Stellar Global"
75
+ userName="Jane Buyer"
76
+ showManageLink
77
+ manageUrl="/pvt/organization-account/org-unit/unit-1"
78
+ />
79
+ </PageProvider>
80
+ )
81
+
82
+ expect(screen.getByText('Manage')).toBeTruthy()
83
+ expect(screen.getByRole('button', { name: 'Logout' })).toBeTruthy()
84
+ })
85
+
86
+ it('uses the CMS-provided navigation labels when rendered inside a My Account page', () => {
87
+ render(
88
+ <PageProvider
89
+ context={{
90
+ accountPageData: {},
91
+ navigationLabels: {
92
+ manageLabel: 'Gerenciar',
93
+ logoutLabel: 'Sair',
94
+ },
95
+ }}
96
+ >
97
+ <OrganizationDrawerFooter
98
+ orgName="Stellar Global"
99
+ userName="Jane Buyer"
100
+ showManageLink
101
+ manageUrl="/pvt/organization-account/org-unit/unit-1"
102
+ />
103
+ </PageProvider>
104
+ )
105
+
106
+ expect(screen.getByText('Gerenciar')).toBeTruthy()
107
+ expect(screen.getByRole('button', { name: 'Sair' })).toBeTruthy()
108
+ })
109
+
110
+ it('lets an explicit label prop win over the CMS-provided navigation labels', () => {
111
+ render(
112
+ <PageProvider
113
+ context={{
114
+ accountPageData: {},
115
+ navigationLabels: {
116
+ manageLabel: 'Gerenciar',
117
+ logoutLabel: 'Sair',
118
+ },
119
+ }}
120
+ >
121
+ <OrganizationDrawerFooter
122
+ orgName="Stellar Global"
123
+ userName="Jane Buyer"
124
+ showManageLink
125
+ manageUrl="/pvt/organization-account/org-unit/unit-1"
126
+ manageLabel="Manage account"
127
+ logoutLabel="Sign out"
128
+ />
129
+ </PageProvider>
130
+ )
131
+
132
+ expect(screen.getByText('Manage account')).toBeTruthy()
133
+ expect(screen.getByRole('button', { name: 'Sign out' })).toBeTruthy()
134
+ })
135
+
136
+ it('does not render the manage link when showManageLink is false', () => {
137
+ render(
138
+ <OrganizationDrawerFooter
139
+ orgName="Stellar Global"
140
+ userName="Jane Buyer"
141
+ showManageLink={false}
142
+ manageUrl="/pvt/organization-account/org-unit/unit-1"
143
+ />
144
+ )
145
+
146
+ expect(screen.queryByText('Manage')).toBeNull()
147
+ })
54
148
  })
@@ -36,6 +36,8 @@ describe('OrganizationDrawerHeader', () => {
36
36
  />
37
37
  )
38
38
 
39
+ expect(screen.getByLabelText('Default contract')).toBeTruthy()
40
+
39
41
  fireEvent.click(screen.getByRole('button', { name: /change/i }))
40
42
  expect(onChangeContract).toHaveBeenCalledTimes(1)
41
43
  })
@@ -0,0 +1,49 @@
1
+ /**
2
+ * @vitest-environment jsdom
3
+ */
4
+ import '@testing-library/jest-dom/vitest'
5
+ import { render, screen } from '@testing-library/react'
6
+ import { describe, expect, it, vi } from 'vitest'
7
+
8
+ const mockUseSession = vi.hoisted(() => vi.fn())
9
+ vi.mock('src/sdk/session', () => ({ useSession: mockUseSession }))
10
+ vi.mock('src/sdk/account/accountPageContext', () => ({
11
+ useAccountNavigationLabels: () => ({
12
+ companyLabel: 'Company',
13
+ contractLabel: 'Contract',
14
+ }),
15
+ }))
16
+ vi.mock(
17
+ 'src/components/account/Drawer/OrganizationDrawer/OrganizationDrawer',
18
+ () => ({
19
+ OrganizationDrawer: () => null,
20
+ })
21
+ )
22
+
23
+ import { OrganizationSignInButton } from '../../../src/components/account/Drawer/OrganizationSignInButton/OrganizationSignInButton'
24
+
25
+ const icon = { alt: 'account', icon: 'User' }
26
+
27
+ describe('OrganizationSignInButton', () => {
28
+ it('shows the active contract name when the session has one (Design QA 00:02:55)', () => {
29
+ mockUseSession.mockReturnValue({
30
+ person: { id: 'p1' },
31
+ b2b: { contractName: ' Caetano Corp ' },
32
+ })
33
+ render(<OrganizationSignInButton icon={icon} isRepresentative />)
34
+ expect(screen.getByRole('button', { name: 'account' })).toHaveTextContent(
35
+ 'Caetano Corp'
36
+ )
37
+ })
38
+
39
+ it('falls back to the company label without a contract name', () => {
40
+ mockUseSession.mockReturnValue({
41
+ person: { id: 'p1' },
42
+ b2b: { contractName: '' },
43
+ })
44
+ render(<OrganizationSignInButton icon={icon} isRepresentative />)
45
+ expect(screen.getByRole('button', { name: 'account' })).toHaveTextContent(
46
+ 'Company'
47
+ )
48
+ })
49
+ })