@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,143 @@
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
+ const mockUseSession = vi.hoisted(() => vi.fn())
10
+ const mockNavbarAccountArea = vi.hoisted(() => vi.fn())
11
+ const mockStoreConfig = vi.hoisted(() => ({
12
+ experimental: { enableFaststoreMyAccount: false },
13
+ localization: { enabled: false },
14
+ }))
15
+
16
+ vi.mock('@faststore/ui', () => ({
17
+ useFadeEffect: () => ({ fade: 'in', fadeOut: vi.fn() }),
18
+ useUI: () => ({ closeNavbar: vi.fn() }),
19
+ }))
20
+
21
+ vi.mock('discovery.config', () => ({ default: mockStoreConfig }))
22
+
23
+ vi.mock('src/components/navigation/NavbarLinks', () => ({
24
+ default: () => <nav data-testid="navbar-links" />,
25
+ }))
26
+
27
+ vi.mock('src/components/ui/Button', () => ({
28
+ ButtonSignInFallback: () => null,
29
+ }))
30
+
31
+ vi.mock('src/components/ui/Link', () => ({
32
+ default: ({ children }: { children?: React.ReactNode }) => (
33
+ <a href="/">{children}</a>
34
+ ),
35
+ }))
36
+
37
+ vi.mock('src/components/ui/LocalizationButton', () => ({
38
+ default: () => <div data-testid="localization-button" />,
39
+ }))
40
+
41
+ vi.mock('src/components/ui/Logo', () => ({
42
+ default: () => <div data-testid="logo" />,
43
+ }))
44
+
45
+ vi.mock('../../../src/components/navigation/Navbar/NavbarAccountArea', () => ({
46
+ NavbarAccountArea: (props: Record<string, unknown>) => {
47
+ mockNavbarAccountArea(props)
48
+ return <div data-testid="navbar-account-area" />
49
+ },
50
+ }))
51
+
52
+ vi.mock('src/sdk/overrides/OverrideContext', () => ({
53
+ useOverrideComponents: () => ({
54
+ NavbarSlider: {
55
+ Component: ({ children }: React.PropsWithChildren) => (
56
+ <div data-testid="navbar-slider-wrapper">{children}</div>
57
+ ),
58
+ props: {},
59
+ },
60
+ NavbarSliderHeader: {
61
+ Component: ({ children }: React.PropsWithChildren) => (
62
+ <header>{children}</header>
63
+ ),
64
+ props: {},
65
+ },
66
+ NavbarSliderContent: {
67
+ Component: ({ children }: React.PropsWithChildren) => (
68
+ <div>{children}</div>
69
+ ),
70
+ props: {},
71
+ },
72
+ NavbarSliderFooter: {
73
+ Component: ({ children }: React.PropsWithChildren) => (
74
+ <footer>{children}</footer>
75
+ ),
76
+ props: {},
77
+ },
78
+ _experimentalButtonSignIn: { Component: () => null },
79
+ }),
80
+ }))
81
+
82
+ vi.mock('src/sdk/session', () => ({ useSession: mockUseSession }))
83
+
84
+ import NavbarSlider from '../../../src/components/navigation/NavbarSlider/NavbarSlider'
85
+
86
+ const baseProps = {
87
+ logo: {
88
+ src: '/logo.png',
89
+ alt: 'Logo',
90
+ link: { url: '/', title: 'Home' },
91
+ },
92
+ home: { label: 'Home' },
93
+ links: [],
94
+ region: { icon: 'MapPin', label: 'Region', shouldDisplayRegion: false },
95
+ signIn: {
96
+ button: {
97
+ icon: { alt: 'account', icon: 'User' },
98
+ label: 'Sign in',
99
+ myAccountLabel: 'My Account',
100
+ },
101
+ },
102
+ }
103
+
104
+ describe('NavbarSlider', () => {
105
+ it('resolves the sign-in area and forwards isSignInResolved=false while the session has not validated', () => {
106
+ mockUseSession.mockReturnValue({
107
+ b2b: {},
108
+ isSessionReady: false,
109
+ hasValidated: false,
110
+ })
111
+
112
+ render(<NavbarSlider {...baseProps} />)
113
+
114
+ expect(screen.getByTestId('navbar-account-area')).toBeTruthy()
115
+ expect(mockNavbarAccountArea).toHaveBeenCalledWith(
116
+ expect.objectContaining({
117
+ isSignInResolved: false,
118
+ skeletonAttr: 'data-fs-navbar-slider-signin-skeleton',
119
+ })
120
+ )
121
+ })
122
+
123
+ it('forwards isSignInResolved=true and isOrganizationEnabled once the B2B representative session resolves', () => {
124
+ mockStoreConfig.experimental.enableFaststoreMyAccount = true
125
+ mockUseSession.mockReturnValue({
126
+ b2b: { isRepresentative: true },
127
+ isSessionReady: true,
128
+ hasValidated: true,
129
+ })
130
+
131
+ render(<NavbarSlider {...baseProps} />)
132
+
133
+ expect(mockNavbarAccountArea).toHaveBeenCalledWith(
134
+ expect.objectContaining({
135
+ isSignInResolved: true,
136
+ isOrganizationEnabled: true,
137
+ isRepresentative: true,
138
+ })
139
+ )
140
+
141
+ mockStoreConfig.experimental.enableFaststoreMyAccount = false
142
+ })
143
+ })
@@ -0,0 +1,72 @@
1
+ import '@testing-library/jest-dom/vitest'
2
+ import { cleanup, render, screen } from '@testing-library/react'
3
+ import { afterEach, describe, expect, it, vi } from 'vitest'
4
+
5
+ const mockUseAccountPageData = vi.hoisted(() => vi.fn())
6
+
7
+ vi.mock('next/router', () => ({ useRouter: () => ({ locale: 'pt-BR' }) }))
8
+ vi.mock('src/sdk/account/accountPageContext', () => ({
9
+ useAccountPageData: mockUseAccountPageData,
10
+ }))
11
+
12
+ import AccountOrderDelivery from 'src/components/sections/Account/AccountOrderDelivery'
13
+
14
+ const order = {
15
+ storePreferencesData: { currencyCode: 'BRL' },
16
+ customFields: [],
17
+ deliveryOptionsData: {
18
+ contact: { name: 'Maria' },
19
+ deliveryOptions: [
20
+ {
21
+ selectedSla: 'Normal',
22
+ deliveryChannel: 'delivery',
23
+ shippingEstimate: '2bd',
24
+ friendlyDeliveryOptionName: 'Delivery Up to 2 business days',
25
+ quantityOfDifferentItems: 1,
26
+ total: 1100,
27
+ items: [],
28
+ address: {
29
+ city: 'Rio de Janeiro',
30
+ street: 'Rua Um',
31
+ postalCode: '20000-000',
32
+ state: 'RJ',
33
+ country: 'BRA',
34
+ },
35
+ },
36
+ ],
37
+ },
38
+ }
39
+
40
+ afterEach(() => {
41
+ cleanup()
42
+ mockUseAccountPageData.mockReset()
43
+ })
44
+
45
+ describe('AccountOrderDelivery', () => {
46
+ it('forwards the CMS labels to the delivery card and accordions', () => {
47
+ mockUseAccountPageData.mockReturnValue({ order })
48
+
49
+ render(
50
+ <AccountOrderDelivery
51
+ deliveryTitle="Entrega do pedido"
52
+ deliveryChannelLabel="Entrega"
53
+ businessDaysOtherTemplate="Em até {count} dias úteis"
54
+ recipientLabel="Destinatário"
55
+ />
56
+ )
57
+
58
+ expect(screen.getByText('Entrega do pedido')).toBeInTheDocument()
59
+ expect(screen.getAllByText('Entrega Em até 2 dias úteis')).toHaveLength(2)
60
+ expect(screen.getByText('Destinatário')).toBeInTheDocument()
61
+ })
62
+
63
+ it('renders nothing when the order has no delivery data', () => {
64
+ mockUseAccountPageData.mockReturnValue({
65
+ order: { ...order, deliveryOptionsData: null },
66
+ })
67
+
68
+ const { container } = render(<AccountOrderDelivery />)
69
+
70
+ expect(container).toBeEmptyDOMElement()
71
+ })
72
+ })
@@ -0,0 +1,151 @@
1
+ /**
2
+ * @vitest-environment jsdom
3
+ */
4
+
5
+ import '@testing-library/jest-dom/vitest'
6
+ import { cleanup, render, screen } from '@testing-library/react'
7
+ import { afterEach, describe, expect, it, vi } from 'vitest'
8
+
9
+ const mockUseAccountPageData = vi.hoisted(() => vi.fn())
10
+
11
+ vi.mock('src/sdk/account/accountPageContext', () => ({
12
+ useAccountPageData: mockUseAccountPageData,
13
+ }))
14
+
15
+ vi.mock(
16
+ 'src/components/account/orders/OrderDetails/OrderDetailsHeader',
17
+ () => ({
18
+ OrderDetailsHeader: ({
19
+ labels,
20
+ }: {
21
+ labels: Record<string, string | undefined>
22
+ }) => (
23
+ <div data-testid="order-details-header">
24
+ <span data-testid="reject-modal-title">{labels.rejectModalTitle}</span>
25
+ <span data-testid="reject-modal-message">
26
+ {labels.rejectModalMessage}
27
+ </span>
28
+ <span data-testid="reject-modal-confirm">
29
+ {labels.rejectModalConfirmText}
30
+ </span>
31
+ <span data-testid="approve-success-toast">
32
+ {labels.approveSuccessToast}
33
+ </span>
34
+ <span data-testid="approve-error-toast">
35
+ {labels.approveErrorToast}
36
+ </span>
37
+ <span data-testid="reject-success-toast">
38
+ {labels.rejectSuccessToast}
39
+ </span>
40
+ <span data-testid="reject-error-toast">{labels.rejectErrorToast}</span>
41
+ <span data-testid="pending-further-approvals-alert">
42
+ {labels.pendingFurtherApprovalsAlert}
43
+ </span>
44
+ </div>
45
+ ),
46
+ })
47
+ )
48
+
49
+ import AccountOrderDetails from 'src/components/sections/Account/AccountOrderDetails'
50
+ import { defaultOrderDetailsHeaderLabels } from 'src/components/account/orders/OrderDetails/orderDetailsLabels'
51
+
52
+ const order = { orderId: '123' }
53
+
54
+ afterEach(cleanup)
55
+
56
+ describe('AccountOrderDetails', () => {
57
+ it('forwards the default English reject modal labels when the CMS has no override', () => {
58
+ mockUseAccountPageData.mockReturnValueOnce({ order })
59
+
60
+ render(<AccountOrderDetails />)
61
+
62
+ expect(screen.getByTestId('reject-modal-title')).toHaveTextContent(
63
+ defaultOrderDetailsHeaderLabels.rejectModalTitle
64
+ )
65
+ expect(screen.getByTestId('reject-modal-message').textContent).toBe(
66
+ defaultOrderDetailsHeaderLabels.rejectModalMessage
67
+ )
68
+ expect(screen.getByTestId('reject-modal-confirm')).toHaveTextContent(
69
+ defaultOrderDetailsHeaderLabels.rejectModalConfirmText
70
+ )
71
+ expect(screen.getByTestId('approve-success-toast')).toHaveTextContent(
72
+ defaultOrderDetailsHeaderLabels.approveSuccessToast
73
+ )
74
+ expect(screen.getByTestId('approve-error-toast')).toHaveTextContent(
75
+ defaultOrderDetailsHeaderLabels.approveErrorToast
76
+ )
77
+ expect(screen.getByTestId('reject-success-toast')).toHaveTextContent(
78
+ defaultOrderDetailsHeaderLabels.rejectSuccessToast
79
+ )
80
+ expect(screen.getByTestId('reject-error-toast')).toHaveTextContent(
81
+ defaultOrderDetailsHeaderLabels.rejectErrorToast
82
+ )
83
+ expect(
84
+ screen.getByTestId('pending-further-approvals-alert')
85
+ ).toHaveTextContent(
86
+ defaultOrderDetailsHeaderLabels.pendingFurtherApprovalsAlert
87
+ )
88
+ })
89
+
90
+ it('forwards CMS-provided reject modal labels to the order details header', () => {
91
+ mockUseAccountPageData.mockReturnValueOnce({ order })
92
+
93
+ render(
94
+ <AccountOrderDetails
95
+ rejectModalTitle="Rejeitar solicitação de aprovação"
96
+ rejectModalMessage="Você está rejeitando a política {policy}."
97
+ rejectModalConfirmText="Confirmar rejeição"
98
+ />
99
+ )
100
+
101
+ expect(screen.getByTestId('reject-modal-title')).toHaveTextContent(
102
+ 'Rejeitar solicitação de aprovação'
103
+ )
104
+ expect(screen.getByTestId('reject-modal-message')).toHaveTextContent(
105
+ 'Você está rejeitando a política {policy}.'
106
+ )
107
+ expect(screen.getByTestId('reject-modal-confirm')).toHaveTextContent(
108
+ 'Confirmar rejeição'
109
+ )
110
+ })
111
+
112
+ it('forwards CMS-provided buying policy toast labels to the order details header', () => {
113
+ mockUseAccountPageData.mockReturnValueOnce({ order })
114
+
115
+ render(
116
+ <AccountOrderDetails
117
+ approveSuccessToast="Política {policy} aprovada com sucesso."
118
+ approveErrorToast="Não foi possível aprovar a política."
119
+ rejectSuccessToast="Política {policy} rejeitada. Pedido negado."
120
+ rejectErrorToast="Não foi possível rejeitar a política."
121
+ pendingFurtherApprovalsAlert="Sua aprovação foi registrada. O pedido ainda aguarda outras aprovações."
122
+ />
123
+ )
124
+
125
+ expect(screen.getByTestId('approve-success-toast')).toHaveTextContent(
126
+ 'Política {policy} aprovada com sucesso.'
127
+ )
128
+ expect(screen.getByTestId('approve-error-toast')).toHaveTextContent(
129
+ 'Não foi possível aprovar a política.'
130
+ )
131
+ expect(screen.getByTestId('reject-success-toast')).toHaveTextContent(
132
+ 'Política {policy} rejeitada. Pedido negado.'
133
+ )
134
+ expect(screen.getByTestId('reject-error-toast')).toHaveTextContent(
135
+ 'Não foi possível rejeitar a política.'
136
+ )
137
+ expect(
138
+ screen.getByTestId('pending-further-approvals-alert')
139
+ ).toHaveTextContent(
140
+ 'Sua aprovação foi registrada. O pedido ainda aguarda outras aprovações.'
141
+ )
142
+ })
143
+
144
+ it('renders nothing when the page data has no order', () => {
145
+ mockUseAccountPageData.mockReturnValueOnce({ order: null })
146
+
147
+ const { container } = render(<AccountOrderDetails />)
148
+
149
+ expect(container).toBeEmptyDOMElement()
150
+ })
151
+ })
@@ -0,0 +1,59 @@
1
+ import '@testing-library/jest-dom/vitest'
2
+ import { cleanup, render, screen } from '@testing-library/react'
3
+ import { afterEach, describe, expect, it, vi } from 'vitest'
4
+
5
+ const mockUseAccountPageData = vi.hoisted(() => vi.fn())
6
+
7
+ vi.mock('next/router', () => ({ useRouter: () => ({ locale: 'pt-BR' }) }))
8
+ vi.mock('src/sdk/account/accountPageContext', () => ({
9
+ useAccountPageData: mockUseAccountPageData,
10
+ }))
11
+
12
+ import AccountOrderStatus from 'src/components/sections/Account/AccountOrderStatus'
13
+
14
+ const order = {
15
+ status: 'payment-approved',
16
+ creationDate: '2026-08-05T18:30:00.000Z',
17
+ }
18
+
19
+ afterEach(cleanup)
20
+
21
+ describe('AccountOrderStatus', () => {
22
+ it('renders the timeline with the default labels', () => {
23
+ mockUseAccountPageData.mockReturnValueOnce({ order })
24
+
25
+ render(<AccountOrderStatus />)
26
+
27
+ expect(screen.getByText('Status')).toBeInTheDocument()
28
+ expect(screen.getByText('Order placed')).toBeInTheDocument()
29
+ expect(screen.getByText('Handling order')).toBeInTheDocument()
30
+ })
31
+
32
+ it('forwards the CMS labels to the status card', () => {
33
+ mockUseAccountPageData.mockReturnValueOnce({ order })
34
+
35
+ render(
36
+ <AccountOrderStatus
37
+ statusTitle="Status do pedido"
38
+ orderPlacedStep="Pedido realizado"
39
+ approvedStep="Aprovado"
40
+ handlingStep="Em separação"
41
+ shipOrderStep="Enviar pedido"
42
+ />
43
+ )
44
+
45
+ expect(screen.getByText('Status do pedido')).toBeInTheDocument()
46
+ expect(screen.getByText('Pedido realizado')).toBeInTheDocument()
47
+ expect(screen.getByText('Aprovado')).toBeInTheDocument()
48
+ expect(screen.getByText('Em separação')).toBeInTheDocument()
49
+ expect(screen.getByText('Enviar pedido')).toBeInTheDocument()
50
+ })
51
+
52
+ it('renders nothing when the page data has no order', () => {
53
+ mockUseAccountPageData.mockReturnValueOnce({ order: null })
54
+
55
+ const { container } = render(<AccountOrderStatus />)
56
+
57
+ expect(container).toBeEmptyDOMElement()
58
+ })
59
+ })
@@ -0,0 +1,67 @@
1
+ import '@testing-library/jest-dom/vitest'
2
+ import { cleanup, render } from '@testing-library/react'
3
+ import { afterEach, describe, expect, it, vi } from 'vitest'
4
+
5
+ import type { ListOrdersProps } from 'src/components/account/orders/ListOrders/ListOrders'
6
+
7
+ const mockUseAccountPageData = vi.hoisted(() => vi.fn())
8
+ const mockListOrders = vi.hoisted(() =>
9
+ vi.fn((_props: ListOrdersProps) => null)
10
+ )
11
+
12
+ vi.mock('src/sdk/account/accountPageContext', () => ({
13
+ useAccountPageData: mockUseAccountPageData,
14
+ }))
15
+ vi.mock('src/components/account/orders/ListOrders', () => ({
16
+ ListOrders: mockListOrders,
17
+ }))
18
+
19
+ import AccountOrdersList from 'src/components/sections/Account/AccountOrdersList'
20
+
21
+ const pageData = {
22
+ listOrders: { list: [] },
23
+ total: 0,
24
+ perPage: 10,
25
+ filters: {
26
+ page: 1,
27
+ status: [],
28
+ dateInitial: '',
29
+ dateFinal: '',
30
+ text: '',
31
+ clientEmail: '',
32
+ },
33
+ }
34
+
35
+ afterEach(() => {
36
+ cleanup()
37
+ mockListOrders.mockClear()
38
+ })
39
+
40
+ describe('AccountOrdersList', () => {
41
+ it('forwards the default filter group labels', () => {
42
+ mockUseAccountPageData.mockReturnValueOnce(pageData)
43
+
44
+ render(<AccountOrdersList />)
45
+
46
+ expect(mockListOrders.mock.calls[0][0].labels).toMatchObject({
47
+ statusFilterLabel: 'Status',
48
+ orderDateFilterLabel: 'Order Date',
49
+ })
50
+ })
51
+
52
+ it('forwards the CMS filter group labels', () => {
53
+ mockUseAccountPageData.mockReturnValueOnce(pageData)
54
+
55
+ render(
56
+ <AccountOrdersList
57
+ statusFilterLabel="Situação"
58
+ orderDateFilterLabel="Data do pedido"
59
+ />
60
+ )
61
+
62
+ expect(mockListOrders.mock.calls[0][0].labels).toMatchObject({
63
+ statusFilterLabel: 'Situação',
64
+ orderDateFilterLabel: 'Data do pedido',
65
+ })
66
+ })
67
+ })
@@ -18,12 +18,13 @@ vi.mock('../../../src/server', () => ({
18
18
 
19
19
  const mockedExecute = vi.mocked(execute)
20
20
 
21
- const createResponse = () => {
21
+ const createResponse = ({ headersSent = false } = {}) => {
22
22
  const res = {
23
23
  status: vi.fn().mockReturnThis(),
24
24
  setHeader: vi.fn().mockReturnThis(),
25
25
  send: vi.fn().mockReturnThis(),
26
26
  end: vi.fn().mockReturnThis(),
27
+ headersSent,
27
28
  }
28
29
 
29
30
  return res as unknown as NextApiResponse & typeof res
@@ -122,6 +123,7 @@ describe('/api/graphql error status propagation', () => {
122
123
  expect(res.status).toHaveBeenCalledWith(500)
123
124
  expect(res.end).toHaveBeenCalled()
124
125
  expect(res.send).not.toHaveBeenCalled()
126
+ expect(res.setHeader).toHaveBeenCalledWith('cache-control', 'no-store')
125
127
  })
126
128
 
127
129
  it('exposes type, status and message in the body outside production', async () => {
@@ -168,6 +170,15 @@ describe('/api/graphql error status propagation', () => {
168
170
 
169
171
  expect(res.status).toHaveBeenCalledWith(404)
170
172
  })
173
+
174
+ it('sets cache-control: no-store on error responses so a bare 404/410 is not cached by intermediaries', async () => {
175
+ mockExecuteWithErrors([maskedError(new NotFoundError('missing'))])
176
+
177
+ const res = createResponse()
178
+ await handler(createRequest(), res)
179
+
180
+ expect(res.setHeader).toHaveBeenCalledWith('cache-control', 'no-store')
181
+ })
171
182
  })
172
183
 
173
184
  describe('/api/graphql request handling', () => {
@@ -200,6 +211,21 @@ describe('/api/graphql request handling', () => {
200
211
 
201
212
  expect(res.status).toHaveBeenCalledWith(status)
202
213
  expect(res.end).toHaveBeenCalled()
214
+ expect(res.setHeader).toHaveBeenCalledWith('cache-control', 'no-store')
203
215
  }
204
216
  )
217
+
218
+ it('skips the cache-control header when headers were already sent', async () => {
219
+ mockedExecute.mockRejectedValue(new Error('boom after flush'))
220
+
221
+ const res = createResponse({ headersSent: true })
222
+ await handler(createRequest(), res)
223
+
224
+ expect(res.setHeader).not.toHaveBeenCalledWith(
225
+ 'cache-control',
226
+ expect.anything()
227
+ )
228
+ expect(res.status).toHaveBeenCalledWith(500)
229
+ expect(res.end).toHaveBeenCalled()
230
+ })
205
231
  })