@faststore/core 4.8.0 → 4.8.1-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-generate.log +3 -3
- package/.turbo/turbo-test.log +146 -108
- package/CHANGELOG.md +14 -0
- package/cms/faststore/my-account/components/cms_component__accountnavigation.jsonc +10 -0
- package/cms/faststore/my-account/components/cms_component__accountorderdelivery.jsonc +80 -0
- package/cms/faststore/my-account/components/cms_component__accountorderdetails.jsonc +25 -0
- package/cms/faststore/my-account/components/cms_component__accountorderslist.jsonc +10 -0
- package/cms/faststore/my-account/components/cms_component__accountorderstatus.jsonc +90 -0
- package/cms/faststore/my-account/components/cms_component__accountordersummary.jsonc +25 -0
- package/package.json +6 -6
- package/src/components/account/Drawer/OrganizationDrawer/OrganizationDrawerFooter.tsx +13 -2
- package/src/components/account/orders/ListOrders/FilterSlider/FilterFacetPendingApproval/FilterFacetPendingApproval.tsx +8 -3
- package/src/components/account/orders/ListOrders/FilterSlider/FilterSlider.tsx +1 -0
- package/src/components/account/orders/ListOrders/ListOrders.tsx +2 -2
- package/src/components/account/orders/ListOrders/listOrdersLabels.ts +4 -0
- package/src/components/account/orders/OrderDetails/BuyingPolicyAlert/BuyingPolicyAlert.tsx +45 -9
- package/src/components/account/orders/OrderDetails/DeliveryCard/DeliveryCard.tsx +14 -3
- package/src/components/account/orders/OrderDetails/DeliveryOptionAccordion/DeliveryOptionAccordion.tsx +4 -1
- package/src/components/account/orders/OrderDetails/DeliveryOptionAccordion/DeliveryOptionAccordionDeliveryInfo.tsx +14 -7
- package/src/components/account/orders/OrderDetails/DeliveryOptionAccordion/DeliveryOptionAccordionProducts.tsx +8 -5
- package/src/components/account/orders/OrderDetails/OrderDetailsHeader.tsx +5 -0
- package/src/components/account/orders/OrderDetails/StatusCard/StatusCard.tsx +26 -89
- package/src/components/account/orders/OrderDetails/StatusCard/statusCardLocalization.ts +114 -0
- package/src/components/account/orders/OrderDetails/SummaryCard/SummaryCard.tsx +2 -1
- package/src/components/account/orders/OrderDetails/SummaryCard/getOrderTotalLabel.ts +19 -0
- package/src/components/account/orders/OrderDetails/getDeliveryOptionLabel.ts +135 -0
- package/src/components/account/orders/OrderDetails/orderDetailsLabels.ts +73 -0
- package/src/components/sections/Account/AccountOrderDelivery.tsx +3 -1
- package/src/components/sections/Account/AccountOrderDetails.tsx +16 -0
- package/src/components/sections/Account/AccountOrderStatus.tsx +27 -3
- package/src/components/sections/Account/AccountOrdersList.tsx +4 -0
- package/src/pages/api/graphql.ts +108 -69
- package/src/sdk/account/accountPageContext.ts +14 -3
- package/src/sdk/account/getMyAccountRoutes.ts +2 -0
- package/src/sdk/overrides/PageProvider.tsx +1 -1
- package/test/components/account/OrganizationDrawerFooter.browser.test.tsx +95 -1
- package/test/components/account/orders/BuyingPolicyAlert.browser.test.tsx +342 -0
- package/test/components/account/orders/DeliveryCard.browser.test.tsx +36 -0
- package/test/components/account/orders/DeliveryOptionAccordion.browser.test.tsx +76 -0
- package/test/components/account/orders/DeliveryOptionAccordionDeliveryInfo.browser.test.tsx +41 -0
- package/test/components/account/orders/DeliveryOptionAccordionProducts.browser.test.tsx +35 -0
- package/test/components/account/orders/FilterFacetPendingApproval.browser.test.tsx +25 -0
- package/test/components/account/orders/StatusCard.browser.test.tsx +37 -0
- package/test/components/account/orders/StatusCard.test.ts +101 -0
- package/test/components/account/orders/SummaryCard.browser.test.tsx +59 -0
- package/test/components/account/orders/getDeliveryOptionLabel.test.ts +129 -0
- package/test/components/account/orders/getOrderTotalLabel.test.ts +35 -0
- package/test/components/account/orders/listOrdersLabels.test.ts +23 -0
- package/test/components/account/orders/orderDetailsLabels.test.ts +13 -0
- package/test/components/sections/Account/AccountOrderDelivery.browser.test.tsx +72 -0
- package/test/components/sections/Account/AccountOrderDetails.browser.test.tsx +151 -0
- package/test/components/sections/Account/AccountOrderStatus.browser.test.tsx +59 -0
- package/test/components/sections/Account/AccountOrdersList.browser.test.tsx +67 -0
- package/test/pages/api/graphql.test.ts +27 -1
- package/test/sdk/account/getMyAccountRoutes.test.ts +11 -1
- package/test/utils/userOrderStatus.test.ts +22 -0
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vitest-environment jsdom
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { UIProvider, useUI } from '@faststore/ui'
|
|
6
|
+
import { fireEvent, render, screen, within } from '@testing-library/react'
|
|
7
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
8
|
+
|
|
9
|
+
import type { ProcessOrderAuthorizationRule } from '@generated/graphql'
|
|
10
|
+
|
|
11
|
+
const mockProcessOrderAuthorization = vi.hoisted(() => vi.fn())
|
|
12
|
+
const mockOrderAuthorizationData = vi.hoisted(() => ({
|
|
13
|
+
current: null as { isPendingForOtherAuthorizer?: boolean } | null,
|
|
14
|
+
}))
|
|
15
|
+
|
|
16
|
+
vi.mock('src/sdk/account/useOrderAuthorization', () => ({
|
|
17
|
+
useOrderAuthorization: () => ({
|
|
18
|
+
processOrderAuthorization: mockProcessOrderAuthorization,
|
|
19
|
+
data: mockOrderAuthorizationData.current,
|
|
20
|
+
error: null,
|
|
21
|
+
loading: false,
|
|
22
|
+
}),
|
|
23
|
+
}))
|
|
24
|
+
|
|
25
|
+
import BuyingPolicyAlert from 'src/components/account/orders/OrderDetails/BuyingPolicyAlert'
|
|
26
|
+
|
|
27
|
+
const ruleForAuthorization = {
|
|
28
|
+
orderAuthorizationId: 'auth-1',
|
|
29
|
+
dimensionId: 'dim-1',
|
|
30
|
+
rule: { id: 'rule-1', name: 'Approval Policy' },
|
|
31
|
+
} as unknown as ProcessOrderAuthorizationRule
|
|
32
|
+
|
|
33
|
+
/** Renders the last pushed toast message so tests can assert on it. */
|
|
34
|
+
function ToastPreview() {
|
|
35
|
+
const { toasts } = useUI()
|
|
36
|
+
const lastToast = toasts[toasts.length - 1]
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<div data-testid="toast-preview" data-toast-status={lastToast?.status}>
|
|
40
|
+
{lastToast?.message}
|
|
41
|
+
</div>
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function openRejectModal() {
|
|
46
|
+
fireEvent.click(screen.getByText('Reject'))
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function confirmRejectModal() {
|
|
50
|
+
const dialog = within(screen.getByRole('dialog'))
|
|
51
|
+
fireEvent.click(dialog.getByRole('button', { name: /reject/i }))
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function getModalTitle() {
|
|
55
|
+
return document.querySelector('[data-fs-modal-header-title]')?.textContent
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function getModalMessage() {
|
|
59
|
+
return document.querySelector('[data-fs-order-details-action-modal-message]')
|
|
60
|
+
?.textContent
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
describe('BuyingPolicyAlert', () => {
|
|
64
|
+
beforeEach(() => {
|
|
65
|
+
mockProcessOrderAuthorization.mockReset()
|
|
66
|
+
mockOrderAuthorizationData.current = null
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('opens the reject confirmation modal with the default English copy', () => {
|
|
70
|
+
render(
|
|
71
|
+
<UIProvider>
|
|
72
|
+
<BuyingPolicyAlert ruleForAuthorization={ruleForAuthorization} />
|
|
73
|
+
</UIProvider>
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
openRejectModal()
|
|
77
|
+
|
|
78
|
+
expect(getModalTitle()).toBe('Reject approval request')
|
|
79
|
+
expect(getModalMessage()).toContain(
|
|
80
|
+
"You're about to reject this approval request, triggered by the Approval Policy policy."
|
|
81
|
+
)
|
|
82
|
+
})
|
|
83
|
+
|
|
84
|
+
it('opens the reject confirmation modal with CMS-provided labels', () => {
|
|
85
|
+
render(
|
|
86
|
+
<UIProvider>
|
|
87
|
+
<BuyingPolicyAlert
|
|
88
|
+
ruleForAuthorization={ruleForAuthorization}
|
|
89
|
+
labels={{
|
|
90
|
+
rejectModalTitle: 'Rejeitar solicitação de aprovação',
|
|
91
|
+
rejectModalMessage: 'Você está rejeitando a política {policy}.',
|
|
92
|
+
rejectModalConfirmText: 'Confirmar rejeição',
|
|
93
|
+
}}
|
|
94
|
+
/>
|
|
95
|
+
</UIProvider>
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
openRejectModal()
|
|
99
|
+
|
|
100
|
+
expect(getModalTitle()).toBe('Rejeitar solicitação de aprovação')
|
|
101
|
+
expect(getModalMessage()).toBe(
|
|
102
|
+
'Você está rejeitando a política Approval Policy.'
|
|
103
|
+
)
|
|
104
|
+
expect(
|
|
105
|
+
screen.getByRole('button', { name: 'Confirmar rejeição' })
|
|
106
|
+
).toBeTruthy()
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
it('shows the default English toast when a policy is approved', async () => {
|
|
110
|
+
mockProcessOrderAuthorization.mockResolvedValueOnce({})
|
|
111
|
+
|
|
112
|
+
render(
|
|
113
|
+
<UIProvider>
|
|
114
|
+
<BuyingPolicyAlert ruleForAuthorization={ruleForAuthorization} />
|
|
115
|
+
<ToastPreview />
|
|
116
|
+
</UIProvider>
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
fireEvent.click(screen.getByText('Approve'))
|
|
120
|
+
|
|
121
|
+
expect(
|
|
122
|
+
await screen.findByText('Approval Policy policy approved successfully.')
|
|
123
|
+
).toBeTruthy()
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
it('shows the CMS-provided toast when a policy is approved', async () => {
|
|
127
|
+
mockProcessOrderAuthorization.mockResolvedValueOnce({})
|
|
128
|
+
|
|
129
|
+
render(
|
|
130
|
+
<UIProvider>
|
|
131
|
+
<BuyingPolicyAlert
|
|
132
|
+
ruleForAuthorization={ruleForAuthorization}
|
|
133
|
+
labels={{
|
|
134
|
+
approveSuccessToast: 'Política {policy} aprovada com sucesso.',
|
|
135
|
+
}}
|
|
136
|
+
/>
|
|
137
|
+
<ToastPreview />
|
|
138
|
+
</UIProvider>
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
fireEvent.click(screen.getByText('Approve'))
|
|
142
|
+
|
|
143
|
+
expect(
|
|
144
|
+
await screen.findByText('Política Approval Policy aprovada com sucesso.')
|
|
145
|
+
).toBeTruthy()
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
it('replaces every policy placeholder without interpreting replacement patterns', async () => {
|
|
149
|
+
mockProcessOrderAuthorization.mockResolvedValueOnce({})
|
|
150
|
+
const policyName = '$& Policy'
|
|
151
|
+
|
|
152
|
+
render(
|
|
153
|
+
<UIProvider>
|
|
154
|
+
<BuyingPolicyAlert
|
|
155
|
+
ruleForAuthorization={
|
|
156
|
+
{
|
|
157
|
+
...ruleForAuthorization,
|
|
158
|
+
rule: { ...ruleForAuthorization.rule, name: policyName },
|
|
159
|
+
} as ProcessOrderAuthorizationRule
|
|
160
|
+
}
|
|
161
|
+
labels={{
|
|
162
|
+
approveSuccessToast: '{policy} approved by {policy}.',
|
|
163
|
+
}}
|
|
164
|
+
/>
|
|
165
|
+
<ToastPreview />
|
|
166
|
+
</UIProvider>
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
fireEvent.click(screen.getByText('Approve'))
|
|
170
|
+
|
|
171
|
+
expect(
|
|
172
|
+
await screen.findByText('$& Policy approved by $& Policy.')
|
|
173
|
+
).toBeTruthy()
|
|
174
|
+
})
|
|
175
|
+
|
|
176
|
+
it('shows the default English error toast when approving a policy fails', async () => {
|
|
177
|
+
mockProcessOrderAuthorization.mockRejectedValueOnce(new Error('failure'))
|
|
178
|
+
|
|
179
|
+
render(
|
|
180
|
+
<UIProvider>
|
|
181
|
+
<BuyingPolicyAlert ruleForAuthorization={ruleForAuthorization} />
|
|
182
|
+
<ToastPreview />
|
|
183
|
+
</UIProvider>
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
fireEvent.click(screen.getByText('Approve'))
|
|
187
|
+
|
|
188
|
+
expect(
|
|
189
|
+
await screen.findByText(
|
|
190
|
+
"Policy couldn't be approved due to a technical issue."
|
|
191
|
+
)
|
|
192
|
+
).toBeTruthy()
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
it('shows the CMS-provided error toast when approving a policy fails', async () => {
|
|
196
|
+
mockProcessOrderAuthorization.mockRejectedValueOnce(new Error('failure'))
|
|
197
|
+
|
|
198
|
+
render(
|
|
199
|
+
<UIProvider>
|
|
200
|
+
<BuyingPolicyAlert
|
|
201
|
+
ruleForAuthorization={ruleForAuthorization}
|
|
202
|
+
labels={{
|
|
203
|
+
approveErrorToast: 'Não foi possível aprovar a política.',
|
|
204
|
+
}}
|
|
205
|
+
/>
|
|
206
|
+
<ToastPreview />
|
|
207
|
+
</UIProvider>
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
fireEvent.click(screen.getByText('Approve'))
|
|
211
|
+
|
|
212
|
+
expect(
|
|
213
|
+
await screen.findByText('Não foi possível aprovar a política.')
|
|
214
|
+
).toBeTruthy()
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
it('shows the default English toast when a policy is rejected', async () => {
|
|
218
|
+
mockProcessOrderAuthorization.mockResolvedValueOnce({})
|
|
219
|
+
|
|
220
|
+
render(
|
|
221
|
+
<UIProvider>
|
|
222
|
+
<BuyingPolicyAlert ruleForAuthorization={ruleForAuthorization} />
|
|
223
|
+
<ToastPreview />
|
|
224
|
+
</UIProvider>
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
openRejectModal()
|
|
228
|
+
confirmRejectModal()
|
|
229
|
+
|
|
230
|
+
expect(
|
|
231
|
+
await screen.findByText(
|
|
232
|
+
'Approval Policy policy rejected successfully. Order denied.'
|
|
233
|
+
)
|
|
234
|
+
).toBeTruthy()
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
it('shows the CMS-provided toast when a policy is rejected', async () => {
|
|
238
|
+
mockProcessOrderAuthorization.mockResolvedValueOnce({})
|
|
239
|
+
|
|
240
|
+
render(
|
|
241
|
+
<UIProvider>
|
|
242
|
+
<BuyingPolicyAlert
|
|
243
|
+
ruleForAuthorization={ruleForAuthorization}
|
|
244
|
+
labels={{
|
|
245
|
+
rejectSuccessToast: 'Política {policy} rejeitada. Pedido negado.',
|
|
246
|
+
}}
|
|
247
|
+
/>
|
|
248
|
+
<ToastPreview />
|
|
249
|
+
</UIProvider>
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
openRejectModal()
|
|
253
|
+
confirmRejectModal()
|
|
254
|
+
|
|
255
|
+
expect(
|
|
256
|
+
await screen.findByText(
|
|
257
|
+
'Política Approval Policy rejeitada. Pedido negado.'
|
|
258
|
+
)
|
|
259
|
+
).toBeTruthy()
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
it('shows the default English error toast when rejecting a policy fails', async () => {
|
|
263
|
+
mockProcessOrderAuthorization.mockRejectedValueOnce(new Error('failure'))
|
|
264
|
+
|
|
265
|
+
render(
|
|
266
|
+
<UIProvider>
|
|
267
|
+
<BuyingPolicyAlert ruleForAuthorization={ruleForAuthorization} />
|
|
268
|
+
<ToastPreview />
|
|
269
|
+
</UIProvider>
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
openRejectModal()
|
|
273
|
+
confirmRejectModal()
|
|
274
|
+
|
|
275
|
+
expect(
|
|
276
|
+
await screen.findByText(
|
|
277
|
+
"Policy couldn't be rejected due to a technical issue."
|
|
278
|
+
)
|
|
279
|
+
).toBeTruthy()
|
|
280
|
+
})
|
|
281
|
+
|
|
282
|
+
it('shows the CMS-provided error toast when rejecting a policy fails', async () => {
|
|
283
|
+
mockProcessOrderAuthorization.mockRejectedValueOnce(new Error('failure'))
|
|
284
|
+
|
|
285
|
+
render(
|
|
286
|
+
<UIProvider>
|
|
287
|
+
<BuyingPolicyAlert
|
|
288
|
+
ruleForAuthorization={ruleForAuthorization}
|
|
289
|
+
labels={{
|
|
290
|
+
rejectErrorToast: 'Não foi possível rejeitar a política.',
|
|
291
|
+
}}
|
|
292
|
+
/>
|
|
293
|
+
<ToastPreview />
|
|
294
|
+
</UIProvider>
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
openRejectModal()
|
|
298
|
+
confirmRejectModal()
|
|
299
|
+
|
|
300
|
+
expect(
|
|
301
|
+
await screen.findByText('Não foi possível rejeitar a política.')
|
|
302
|
+
).toBeTruthy()
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
it('shows the default English pending-approvals alert', () => {
|
|
306
|
+
mockOrderAuthorizationData.current = { isPendingForOtherAuthorizer: true }
|
|
307
|
+
|
|
308
|
+
render(
|
|
309
|
+
<UIProvider>
|
|
310
|
+
<BuyingPolicyAlert ruleForAuthorization={ruleForAuthorization} />
|
|
311
|
+
</UIProvider>
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
expect(
|
|
315
|
+
screen.getByText(
|
|
316
|
+
'Your approval is recorded. This order is still pending further approvals.'
|
|
317
|
+
)
|
|
318
|
+
).toBeTruthy()
|
|
319
|
+
})
|
|
320
|
+
|
|
321
|
+
it('shows the CMS-provided pending-approvals alert', () => {
|
|
322
|
+
mockOrderAuthorizationData.current = { isPendingForOtherAuthorizer: true }
|
|
323
|
+
|
|
324
|
+
render(
|
|
325
|
+
<UIProvider>
|
|
326
|
+
<BuyingPolicyAlert
|
|
327
|
+
ruleForAuthorization={ruleForAuthorization}
|
|
328
|
+
labels={{
|
|
329
|
+
pendingFurtherApprovalsAlert:
|
|
330
|
+
'Sua aprovação foi registrada. O pedido ainda aguarda outras aprovações.',
|
|
331
|
+
}}
|
|
332
|
+
/>
|
|
333
|
+
</UIProvider>
|
|
334
|
+
)
|
|
335
|
+
|
|
336
|
+
expect(
|
|
337
|
+
screen.getByText(
|
|
338
|
+
'Sua aprovação foi registrada. O pedido ainda aguarda outras aprovações.'
|
|
339
|
+
)
|
|
340
|
+
).toBeTruthy()
|
|
341
|
+
})
|
|
342
|
+
})
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vitest-environment jsdom
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { UserOrderDeliveryOptionsData } from '@generated/graphql'
|
|
6
|
+
import { render, screen } from '@testing-library/react'
|
|
7
|
+
import { describe, expect, it } from 'vitest'
|
|
8
|
+
|
|
9
|
+
import DeliveryCard from '../../../../src/components/account/orders/OrderDetails/DeliveryCard'
|
|
10
|
+
|
|
11
|
+
describe('DeliveryCard', () => {
|
|
12
|
+
it('renders delivery options with localized CMS labels', () => {
|
|
13
|
+
render(
|
|
14
|
+
<DeliveryCard
|
|
15
|
+
deliveryOptionsData={
|
|
16
|
+
{
|
|
17
|
+
deliveryOptions: [
|
|
18
|
+
{
|
|
19
|
+
selectedSla: 'Normal',
|
|
20
|
+
deliveryChannel: 'delivery',
|
|
21
|
+
shippingEstimate: '2bd',
|
|
22
|
+
friendlyDeliveryOptionName: 'Delivery Up to 2 business days',
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
} as UserOrderDeliveryOptionsData
|
|
26
|
+
}
|
|
27
|
+
labels={{
|
|
28
|
+
deliveryChannelLabel: 'Entrega',
|
|
29
|
+
businessDaysOtherTemplate: 'Em até {count} dias úteis',
|
|
30
|
+
}}
|
|
31
|
+
/>
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
expect(screen.getByText('Entrega Em até 2 dias úteis')).toBeTruthy()
|
|
35
|
+
})
|
|
36
|
+
})
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vitest-environment jsdom
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { UserOrderDeliveryOption } from '@generated/graphql'
|
|
6
|
+
import { render, screen } from '@testing-library/react'
|
|
7
|
+
import { describe, expect, it, vi } from 'vitest'
|
|
8
|
+
|
|
9
|
+
import { DeliveryOptionAccordion } from '../../../../src/components/account/orders/OrderDetails/DeliveryOptionAccordion'
|
|
10
|
+
|
|
11
|
+
vi.mock('next/router', () => ({
|
|
12
|
+
useRouter: () => ({ locale: 'pt-BR' }),
|
|
13
|
+
}))
|
|
14
|
+
|
|
15
|
+
const deliveryOption = {
|
|
16
|
+
selectedSla: 'Normal',
|
|
17
|
+
deliveryChannel: 'delivery',
|
|
18
|
+
shippingEstimate: '2bd',
|
|
19
|
+
friendlyDeliveryOptionName: 'Delivery Up to 2 business days',
|
|
20
|
+
quantityOfDifferentItems: 1,
|
|
21
|
+
total: 1100,
|
|
22
|
+
address: {
|
|
23
|
+
city: 'Rio de Janeiro',
|
|
24
|
+
street: 'Rua Um',
|
|
25
|
+
postalCode: '20000-000',
|
|
26
|
+
state: 'RJ',
|
|
27
|
+
country: 'BRA',
|
|
28
|
+
},
|
|
29
|
+
items: [
|
|
30
|
+
{
|
|
31
|
+
uniqueId: 'item-1',
|
|
32
|
+
name: 'Produto',
|
|
33
|
+
imageUrl: '',
|
|
34
|
+
quantity: 1,
|
|
35
|
+
sellingPrice: 1000,
|
|
36
|
+
tax: 100,
|
|
37
|
+
total: 1100,
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
} as unknown as UserOrderDeliveryOption
|
|
41
|
+
|
|
42
|
+
describe('DeliveryOptionAccordion', () => {
|
|
43
|
+
it('renders the localized delivery option title and summary', () => {
|
|
44
|
+
render(
|
|
45
|
+
<DeliveryOptionAccordion
|
|
46
|
+
deliveryOption={deliveryOption}
|
|
47
|
+
currencyCode="BRL"
|
|
48
|
+
labels={{
|
|
49
|
+
deliveryChannelLabel: 'Entrega',
|
|
50
|
+
businessDaysOtherTemplate: 'Em até {count} dias úteis',
|
|
51
|
+
itemCountTemplate: '{count} item',
|
|
52
|
+
totalLabel: 'Total traduzido',
|
|
53
|
+
}}
|
|
54
|
+
/>
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
expect(screen.getByText('Entrega Em até 2 dias úteis')).toBeTruthy()
|
|
58
|
+
expect(
|
|
59
|
+
screen.getByText(/1 item – Total traduzido/, { exact: false })
|
|
60
|
+
).toBeTruthy()
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
it('forwards the resolved labels to the delivery info and product panels', () => {
|
|
64
|
+
render(
|
|
65
|
+
<DeliveryOptionAccordion
|
|
66
|
+
deliveryOption={deliveryOption}
|
|
67
|
+
contact={{ name: 'Maria' }}
|
|
68
|
+
currencyCode="BRL"
|
|
69
|
+
labels={{ recipientLabel: 'Destinatário', eachLabel: 'Cada' }}
|
|
70
|
+
/>
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
expect(screen.getByText('Destinatário')).toBeTruthy()
|
|
74
|
+
expect(screen.getByText('Cada')).toBeTruthy()
|
|
75
|
+
})
|
|
76
|
+
})
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vitest-environment jsdom
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { UserOrderDeliveryOption } from '@generated/graphql'
|
|
6
|
+
import { render, screen } from '@testing-library/react'
|
|
7
|
+
import { describe, expect, it } from 'vitest'
|
|
8
|
+
|
|
9
|
+
import DeliveryOptionAccordionDeliveryInfo from '../../../../src/components/account/orders/OrderDetails/DeliveryOptionAccordion/DeliveryOptionAccordionDeliveryInfo'
|
|
10
|
+
import { resolveOrderDeliveryLabels } from '../../../../src/components/account/orders/OrderDetails/orderDetailsLabels'
|
|
11
|
+
|
|
12
|
+
const labels = resolveOrderDeliveryLabels({
|
|
13
|
+
recipientLabel: 'Destinatário',
|
|
14
|
+
deliveryAddressLabel: 'Endereço de entrega',
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
describe('DeliveryOptionAccordionDeliveryInfo', () => {
|
|
18
|
+
it('renders localized recipient and delivery address labels', () => {
|
|
19
|
+
render(
|
|
20
|
+
<DeliveryOptionAccordionDeliveryInfo
|
|
21
|
+
deliveryOption={
|
|
22
|
+
{
|
|
23
|
+
deliveryChannel: 'delivery',
|
|
24
|
+
address: {
|
|
25
|
+
city: 'Rio de Janeiro',
|
|
26
|
+
street: 'Rua Um',
|
|
27
|
+
postalCode: '20000-000',
|
|
28
|
+
state: 'RJ',
|
|
29
|
+
country: 'BRA',
|
|
30
|
+
},
|
|
31
|
+
} as UserOrderDeliveryOption
|
|
32
|
+
}
|
|
33
|
+
contact={{ name: 'Maria' }}
|
|
34
|
+
labels={labels}
|
|
35
|
+
/>
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
expect(screen.getByText('Destinatário')).toBeTruthy()
|
|
39
|
+
expect(screen.getByText('Endereço de entrega')).toBeTruthy()
|
|
40
|
+
})
|
|
41
|
+
})
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @vitest-environment jsdom
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { render, screen } from '@testing-library/react'
|
|
6
|
+
import { describe, expect, it } from 'vitest'
|
|
7
|
+
|
|
8
|
+
import { DeliveryOptionAccordionProduct } from '../../../../src/components/account/orders/OrderDetails/DeliveryOptionAccordion/DeliveryOptionAccordionProducts'
|
|
9
|
+
import { resolveOrderDeliveryLabels } from '../../../../src/components/account/orders/OrderDetails/orderDetailsLabels'
|
|
10
|
+
|
|
11
|
+
const labels = resolveOrderDeliveryLabels({
|
|
12
|
+
eachLabel: 'Cada',
|
|
13
|
+
taxesLabel: 'Impostos',
|
|
14
|
+
totalLabel: 'Total traduzido',
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
describe('DeliveryOptionAccordionProduct', () => {
|
|
18
|
+
it('renders localized product price labels', () => {
|
|
19
|
+
render(
|
|
20
|
+
<DeliveryOptionAccordionProduct
|
|
21
|
+
image=""
|
|
22
|
+
quantity={1}
|
|
23
|
+
name="Produto"
|
|
24
|
+
price="R$ 10,00"
|
|
25
|
+
tax="R$ 1,00"
|
|
26
|
+
total="R$ 11,00"
|
|
27
|
+
labels={labels}
|
|
28
|
+
/>
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
expect(screen.getByText('Cada')).toBeTruthy()
|
|
32
|
+
expect(screen.getByText('Impostos')).toBeTruthy()
|
|
33
|
+
expect(screen.getByText('Total traduzido')).toBeTruthy()
|
|
34
|
+
})
|
|
35
|
+
})
|
|
@@ -0,0 +1,25 @@
|
|
|
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 FilterFacetPendingApproval from '../../../../src/components/account/orders/ListOrders/FilterSlider/FilterFacetPendingApproval'
|
|
9
|
+
|
|
10
|
+
describe('FilterFacetPendingApproval', () => {
|
|
11
|
+
it('uses the localized label for visible and accessible text', () => {
|
|
12
|
+
render(
|
|
13
|
+
<FilterFacetPendingApproval
|
|
14
|
+
label="Aguardando minha aprovação"
|
|
15
|
+
selected={[]}
|
|
16
|
+
dispatch={vi.fn()}
|
|
17
|
+
/>
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
expect(screen.getByText('Aguardando minha aprovação')).toBeTruthy()
|
|
21
|
+
expect(
|
|
22
|
+
screen.getByRole('switch', { name: 'Aguardando minha aprovação' })
|
|
23
|
+
).toBeTruthy()
|
|
24
|
+
})
|
|
25
|
+
})
|
|
@@ -0,0 +1,37 @@
|
|
|
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 StatusCard from '../../../../src/components/account/orders/OrderDetails/StatusCard'
|
|
9
|
+
import { formatDate } from '../../../../src/components/account/orders/OrderDetails/StatusCard/statusCardLocalization'
|
|
10
|
+
|
|
11
|
+
vi.mock('next/router', () => ({
|
|
12
|
+
useRouter: () => ({ locale: 'pt-BR' }),
|
|
13
|
+
}))
|
|
14
|
+
|
|
15
|
+
describe('StatusCard', () => {
|
|
16
|
+
it('renders timeline dates with the page locale', () => {
|
|
17
|
+
const creationDate = '2026-08-05T18:30:00.000Z'
|
|
18
|
+
|
|
19
|
+
render(<StatusCard status="payment-approved" creationDate={creationDate} />)
|
|
20
|
+
|
|
21
|
+
const formatted = formatDate(creationDate, 'pt-BR')
|
|
22
|
+
expect(screen.getByText(formatted.date)).toBeTruthy()
|
|
23
|
+
expect(screen.getByText(formatted.time)).toBeTruthy()
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('renders the CMS status label for canceled orders', () => {
|
|
27
|
+
render(
|
|
28
|
+
<StatusCard
|
|
29
|
+
status="canceled"
|
|
30
|
+
creationDate="2026-08-05T18:30:00.000Z"
|
|
31
|
+
statusLabels={{ canceledStatus: 'Cancelado' }}
|
|
32
|
+
/>
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
expect(screen.getByText('Cancelado')).toBeTruthy()
|
|
36
|
+
})
|
|
37
|
+
})
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
defaultOrderStatusLabels,
|
|
5
|
+
resolveOrderStatusLabels,
|
|
6
|
+
} from '../../../../src/components/account/orders/OrderDetails/orderDetailsLabels'
|
|
7
|
+
import {
|
|
8
|
+
formatDate,
|
|
9
|
+
getDisplayStepLabel,
|
|
10
|
+
getStepLabel,
|
|
11
|
+
type StepKey,
|
|
12
|
+
type StepStatus,
|
|
13
|
+
} from '../../../../src/components/account/orders/OrderDetails/StatusCard/statusCardLocalization'
|
|
14
|
+
|
|
15
|
+
describe('StatusCard localization', () => {
|
|
16
|
+
it('resolves every timeline state from configurable labels', () => {
|
|
17
|
+
const labels = resolveOrderStatusLabels(
|
|
18
|
+
Object.fromEntries(
|
|
19
|
+
Object.keys(defaultOrderStatusLabels).map((key) => [key, `i18n:${key}`])
|
|
20
|
+
)
|
|
21
|
+
)
|
|
22
|
+
const combinations: [StepKey, StepStatus, string][] = [
|
|
23
|
+
['order', 'completed', 'orderPlacedStep'],
|
|
24
|
+
['approval', 'completed', 'approvedStep'],
|
|
25
|
+
['approval', 'loading', 'pendingApprovalStep'],
|
|
26
|
+
['approval', 'failed', 'deniedStep'],
|
|
27
|
+
['payment', 'completed', 'paymentApprovedStep'],
|
|
28
|
+
['payment', 'loading', 'paymentPendingStep'],
|
|
29
|
+
['payment', 'not-started', 'paymentAuthorizationStep'],
|
|
30
|
+
['payment', 'failed', 'paymentDeniedStep'],
|
|
31
|
+
['processing', 'completed', 'readyForDeliveryStep'],
|
|
32
|
+
['processing', 'loading', 'handlingStep'],
|
|
33
|
+
['processing', 'failed', 'canceledStep'],
|
|
34
|
+
['shipping', 'completed', 'invoicedStep'],
|
|
35
|
+
['shipping', 'loading', 'deliveredStep'],
|
|
36
|
+
['shipping', 'not-started', 'shipOrderStep'],
|
|
37
|
+
['shipping', 'failed', 'canceledStep'],
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
for (const [step, status, labelKey] of combinations) {
|
|
41
|
+
expect(getStepLabel(step, status, labels)).toBe(`i18n:${labelKey}`)
|
|
42
|
+
}
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('uses CMS status labels for canceled and failed timeline copy', () => {
|
|
46
|
+
const labels = resolveOrderStatusLabels()
|
|
47
|
+
const statusLabels = {
|
|
48
|
+
canceledStatus: 'Cancelado',
|
|
49
|
+
paymentDeniedStatus: 'Pagamento recusado',
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
expect(
|
|
53
|
+
getDisplayStepLabel({
|
|
54
|
+
stepKey: 'payment',
|
|
55
|
+
stepStatus: 'failed',
|
|
56
|
+
labels,
|
|
57
|
+
status: 'canceled',
|
|
58
|
+
statusLabels,
|
|
59
|
+
isCanceled: true,
|
|
60
|
+
})
|
|
61
|
+
).toBe('Cancelado')
|
|
62
|
+
|
|
63
|
+
expect(
|
|
64
|
+
getDisplayStepLabel({
|
|
65
|
+
stepKey: 'shipping',
|
|
66
|
+
stepStatus: 'failed',
|
|
67
|
+
labels,
|
|
68
|
+
status: 'canceled',
|
|
69
|
+
statusLabels,
|
|
70
|
+
isCanceled: false,
|
|
71
|
+
})
|
|
72
|
+
).toBe('Cancelado')
|
|
73
|
+
|
|
74
|
+
expect(
|
|
75
|
+
getDisplayStepLabel({
|
|
76
|
+
stepKey: 'payment',
|
|
77
|
+
stepStatus: 'failed',
|
|
78
|
+
labels,
|
|
79
|
+
status: 'payment-denied',
|
|
80
|
+
statusLabels,
|
|
81
|
+
isCanceled: false,
|
|
82
|
+
})
|
|
83
|
+
).toBe('Pagamento recusado')
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
it('formats timeline dates and times using the active locale', () => {
|
|
87
|
+
const timestamp = '2026-08-05T18:30:00.000Z'
|
|
88
|
+
|
|
89
|
+
expect(formatDate(timestamp, 'pt-BR')).toEqual({
|
|
90
|
+
date: new Intl.DateTimeFormat('pt-BR', {
|
|
91
|
+
month: '2-digit',
|
|
92
|
+
day: '2-digit',
|
|
93
|
+
year: 'numeric',
|
|
94
|
+
}).format(new Date(timestamp)),
|
|
95
|
+
time: new Intl.DateTimeFormat('pt-BR', {
|
|
96
|
+
hour: 'numeric',
|
|
97
|
+
minute: '2-digit',
|
|
98
|
+
}).format(new Date(timestamp)),
|
|
99
|
+
})
|
|
100
|
+
})
|
|
101
|
+
})
|