@faststore/core 4.8.1-dev.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 +152 -114
- package/CHANGELOG.md +10 -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
|
@@ -7,20 +7,34 @@ import {
|
|
|
7
7
|
type AccountOrderDetailsPageData,
|
|
8
8
|
useAccountPageData,
|
|
9
9
|
} from 'src/sdk/account/accountPageContext'
|
|
10
|
-
import type {
|
|
10
|
+
import type {
|
|
11
|
+
OrderStatusCmsLabels,
|
|
12
|
+
OrderStatusKey,
|
|
13
|
+
} from 'src/utils/userOrderStatus'
|
|
11
14
|
import Section from '../Section'
|
|
12
15
|
|
|
13
|
-
export type AccountOrderStatusProps = OrderStatusSectionLabels
|
|
16
|
+
export type AccountOrderStatusProps = OrderStatusSectionLabels &
|
|
17
|
+
OrderStatusCmsLabels
|
|
14
18
|
|
|
15
19
|
const AccountOrderStatus = ({
|
|
16
20
|
statusTitle = defaultOrderStatusLabels.statusTitle,
|
|
17
21
|
orderPlacedStep = defaultOrderStatusLabels.orderPlacedStep,
|
|
22
|
+
approvedStep = defaultOrderStatusLabels.approvedStep,
|
|
23
|
+
pendingApprovalStep = defaultOrderStatusLabels.pendingApprovalStep,
|
|
24
|
+
deniedStep = defaultOrderStatusLabels.deniedStep,
|
|
25
|
+
paymentApprovedStep = defaultOrderStatusLabels.paymentApprovedStep,
|
|
18
26
|
paymentPendingStep = defaultOrderStatusLabels.paymentPendingStep,
|
|
27
|
+
paymentAuthorizationStep = defaultOrderStatusLabels.paymentAuthorizationStep,
|
|
28
|
+
paymentDeniedStep = defaultOrderStatusLabels.paymentDeniedStep,
|
|
29
|
+
readyForDeliveryStep = defaultOrderStatusLabels.readyForDeliveryStep,
|
|
19
30
|
handlingStep = defaultOrderStatusLabels.handlingStep,
|
|
31
|
+
canceledStep = defaultOrderStatusLabels.canceledStep,
|
|
20
32
|
invoicedStep = defaultOrderStatusLabels.invoicedStep,
|
|
21
33
|
deliveredStep = defaultOrderStatusLabels.deliveredStep,
|
|
34
|
+
shipOrderStep = defaultOrderStatusLabels.shipOrderStep,
|
|
22
35
|
}: AccountOrderStatusProps) => {
|
|
23
|
-
const { order } =
|
|
36
|
+
const { order, orderStatusLabels } =
|
|
37
|
+
useAccountPageData<AccountOrderDetailsPageData>()
|
|
24
38
|
|
|
25
39
|
if (!order) {
|
|
26
40
|
return null
|
|
@@ -31,13 +45,23 @@ const AccountOrderStatus = ({
|
|
|
31
45
|
<StatusCard
|
|
32
46
|
status={order.status as OrderStatusKey}
|
|
33
47
|
creationDate={order.creationDate}
|
|
48
|
+
statusLabels={orderStatusLabels}
|
|
34
49
|
labels={{
|
|
35
50
|
statusTitle,
|
|
36
51
|
orderPlacedStep,
|
|
52
|
+
approvedStep,
|
|
53
|
+
pendingApprovalStep,
|
|
54
|
+
deniedStep,
|
|
55
|
+
paymentApprovedStep,
|
|
37
56
|
paymentPendingStep,
|
|
57
|
+
paymentAuthorizationStep,
|
|
58
|
+
paymentDeniedStep,
|
|
59
|
+
readyForDeliveryStep,
|
|
38
60
|
handlingStep,
|
|
61
|
+
canceledStep,
|
|
39
62
|
invoicedStep,
|
|
40
63
|
deliveredStep,
|
|
64
|
+
shipOrderStep,
|
|
41
65
|
}}
|
|
42
66
|
/>
|
|
43
67
|
</Section>
|
|
@@ -21,6 +21,8 @@ const AccountOrdersList = ({
|
|
|
21
21
|
placedOnLabel = defaultListOrdersLabels.placedOnLabel,
|
|
22
22
|
deliveryByLabel = defaultListOrdersLabels.deliveryByLabel,
|
|
23
23
|
pendingApprovalLabel = defaultListOrdersLabels.pendingApprovalLabel,
|
|
24
|
+
statusFilterLabel = defaultListOrdersLabels.statusFilterLabel,
|
|
25
|
+
orderDateFilterLabel = defaultListOrdersLabels.orderDateFilterLabel,
|
|
24
26
|
paginationOfLabel = defaultListOrdersLabels.paginationOfLabel,
|
|
25
27
|
previousPageLabel = defaultListOrdersLabels.previousPageLabel,
|
|
26
28
|
nextPageLabel = defaultListOrdersLabels.nextPageLabel,
|
|
@@ -61,6 +63,8 @@ const AccountOrdersList = ({
|
|
|
61
63
|
placedOnLabel,
|
|
62
64
|
deliveryByLabel,
|
|
63
65
|
pendingApprovalLabel,
|
|
66
|
+
statusFilterLabel,
|
|
67
|
+
orderDateFilterLabel,
|
|
64
68
|
paginationOfLabel,
|
|
65
69
|
previousPageLabel,
|
|
66
70
|
nextPageLabel,
|
package/src/pages/api/graphql.ts
CHANGED
|
@@ -150,6 +150,112 @@ const hasVtexIdclientAutCookie = (request: NextApiRequest): boolean => {
|
|
|
150
150
|
)
|
|
151
151
|
}
|
|
152
152
|
|
|
153
|
+
/**
|
|
154
|
+
* Responds to a GraphQL execution that returned errors: recovers the
|
|
155
|
+
* upstream status from a FastStoreError when possible instead of collapsing
|
|
156
|
+
* everything to 500, and logs every error for observability.
|
|
157
|
+
*/
|
|
158
|
+
const respondWithGraphqlErrors = (
|
|
159
|
+
errors: readonly unknown[],
|
|
160
|
+
response: Parameters<NextApiHandler>[1]
|
|
161
|
+
) => {
|
|
162
|
+
// After error masking, entries are GraphQLError instances whose `name` is
|
|
163
|
+
// "GraphQLError" — the original FastStoreError (carrying the upstream
|
|
164
|
+
// status) is nested in `originalError`. Recover it so the BFF propagates
|
|
165
|
+
// the real status instead of collapsing everything to 500.
|
|
166
|
+
const fastStoreError = errors.map(recoverFastStoreError).find(Boolean)
|
|
167
|
+
const reportedErrors = errors.map((graphqlError) => {
|
|
168
|
+
const fsError = recoverFastStoreError(graphqlError)
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
message: (graphqlError as { message?: string })?.message,
|
|
172
|
+
status: fsError?.extensions.status,
|
|
173
|
+
type: fsError?.extensions.type,
|
|
174
|
+
}
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
console.error('Graphql execution returned with error: ', reportedErrors)
|
|
178
|
+
OTELLogger(
|
|
179
|
+
'error',
|
|
180
|
+
'Graphql execution returned with error: %o',
|
|
181
|
+
reportedErrors
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
const status = fastStoreError?.extensions.status ?? 500
|
|
185
|
+
|
|
186
|
+
// Error responses are never cacheable: some upstream statuses (404, 410,
|
|
187
|
+
// ...) are heuristically cacheable by intermediaries per RFC 9111 §4.2.2,
|
|
188
|
+
// which would let a CDN cache an error for this operation.
|
|
189
|
+
response.setHeader('cache-control', 'no-store')
|
|
190
|
+
|
|
191
|
+
// No recoverable FastStoreError: keep the masked, body-less 500.
|
|
192
|
+
if (!fastStoreError) {
|
|
193
|
+
response.status(status).end()
|
|
194
|
+
return
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Only FastStoreError-derived details are exposed. `type`/`status` are a
|
|
198
|
+
// closed enum (safe everywhere); the free-text `message` may echo raw
|
|
199
|
+
// upstream text, so it is restricted to non-production responses. The
|
|
200
|
+
// full message is still available server-side via the log above.
|
|
201
|
+
const responseError = {
|
|
202
|
+
extensions: {
|
|
203
|
+
type: fastStoreError.extensions.type,
|
|
204
|
+
status: fastStoreError.extensions.status,
|
|
205
|
+
},
|
|
206
|
+
...(process.env.NODE_ENV === 'production'
|
|
207
|
+
? {}
|
|
208
|
+
: { message: fastStoreError.message }),
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
response.status(status)
|
|
212
|
+
response.setHeader('content-type', 'application/json')
|
|
213
|
+
response.send(JSON.stringify({ errors: [responseError] }))
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Responds to an error thrown out of the main handler try-block (a rejected
|
|
218
|
+
* `parseRequest`/`execute`, or anything else unexpected).
|
|
219
|
+
*/
|
|
220
|
+
const respondToUnexpectedError = (
|
|
221
|
+
err: unknown,
|
|
222
|
+
response: Parameters<NextApiHandler>[1]
|
|
223
|
+
) => {
|
|
224
|
+
// Same rationale as `respondWithGraphqlErrors`: a 400/401/500 here must
|
|
225
|
+
// never be cached. This path can run after the success branch has already
|
|
226
|
+
// set a cacheable cache-control (e.g. `setHeader('set-cookie', ...)`
|
|
227
|
+
// rejecting a malformed upstream cookie, or `JSON.stringify` throwing
|
|
228
|
+
// after cache-control was set but before `send` completed). Guarded by
|
|
229
|
+
// `headersSent`: if the throw came from `send()` itself after headers were
|
|
230
|
+
// already flushed, `setHeader` would throw ERR_HTTP_HEADERS_SENT and this
|
|
231
|
+
// would fail to produce a handled response.
|
|
232
|
+
if (!response.headersSent) {
|
|
233
|
+
response.setHeader('cache-control', 'no-store')
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
console.error(
|
|
237
|
+
'Something unexpected occurred querying Graphql endpoint: \n',
|
|
238
|
+
err
|
|
239
|
+
)
|
|
240
|
+
OTELLogger(
|
|
241
|
+
'error',
|
|
242
|
+
'Something unexpected occurred querying Graphql endpoint: %o',
|
|
243
|
+
err
|
|
244
|
+
)
|
|
245
|
+
|
|
246
|
+
if (err instanceof BadRequestError) {
|
|
247
|
+
response.status(400).end()
|
|
248
|
+
return
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if (err instanceof UnauthorizedError) {
|
|
252
|
+
response.status(401).end()
|
|
253
|
+
return
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
response.status(500).end()
|
|
257
|
+
}
|
|
258
|
+
|
|
153
259
|
const handler: NextApiHandler = async (request, response) => {
|
|
154
260
|
if (request.method !== 'POST' && request.method !== 'GET') {
|
|
155
261
|
response.status(405).end()
|
|
@@ -222,53 +328,7 @@ const handler: NextApiHandler = async (request, response) => {
|
|
|
222
328
|
const hasErrors = Array.isArray(errors) && errors.length > 0
|
|
223
329
|
|
|
224
330
|
if (hasErrors) {
|
|
225
|
-
|
|
226
|
-
// `name` is "GraphQLError" — the original FastStoreError (carrying the
|
|
227
|
-
// upstream status) is nested in `originalError`. Recover it so the BFF
|
|
228
|
-
// propagates the real status instead of collapsing everything to 500.
|
|
229
|
-
const fastStoreError = errors.map(recoverFastStoreError).find(Boolean)
|
|
230
|
-
const reportedErrors = errors.map((graphqlError) => {
|
|
231
|
-
const fsError = recoverFastStoreError(graphqlError)
|
|
232
|
-
|
|
233
|
-
return {
|
|
234
|
-
message: (graphqlError as { message?: string })?.message,
|
|
235
|
-
status: fsError?.extensions.status,
|
|
236
|
-
type: fsError?.extensions.type,
|
|
237
|
-
}
|
|
238
|
-
})
|
|
239
|
-
|
|
240
|
-
console.error('Graphql execution returned with error: ', reportedErrors)
|
|
241
|
-
OTELLogger(
|
|
242
|
-
'error',
|
|
243
|
-
'Graphql execution returned with error: %o',
|
|
244
|
-
reportedErrors
|
|
245
|
-
)
|
|
246
|
-
|
|
247
|
-
const status = fastStoreError?.extensions.status ?? 500
|
|
248
|
-
|
|
249
|
-
// No recoverable FastStoreError: keep the masked, body-less 500.
|
|
250
|
-
if (!fastStoreError) {
|
|
251
|
-
response.status(status).end()
|
|
252
|
-
return
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
// Only FastStoreError-derived details are exposed. `type`/`status` are a
|
|
256
|
-
// closed enum (safe everywhere); the free-text `message` may echo raw
|
|
257
|
-
// upstream text, so it is restricted to non-production responses. The
|
|
258
|
-
// full message is still available server-side via the log above.
|
|
259
|
-
const responseError = {
|
|
260
|
-
extensions: {
|
|
261
|
-
type: fastStoreError.extensions.type,
|
|
262
|
-
status: fastStoreError.extensions.status,
|
|
263
|
-
},
|
|
264
|
-
...(process.env.NODE_ENV !== 'production'
|
|
265
|
-
? { message: fastStoreError.message }
|
|
266
|
-
: {}),
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
response.status(status)
|
|
270
|
-
response.setHeader('content-type', 'application/json')
|
|
271
|
-
response.send(JSON.stringify({ errors: [responseError] }))
|
|
331
|
+
respondWithGraphqlErrors(errors, response)
|
|
272
332
|
return
|
|
273
333
|
}
|
|
274
334
|
|
|
@@ -321,28 +381,7 @@ const handler: NextApiHandler = async (request, response) => {
|
|
|
321
381
|
response.setHeader('content-type', 'application/json')
|
|
322
382
|
response.send(JSON.stringify({ data, errors }))
|
|
323
383
|
} catch (err) {
|
|
324
|
-
|
|
325
|
-
'Something unexpected occurred querying Graphql endpoint: \n',
|
|
326
|
-
err
|
|
327
|
-
)
|
|
328
|
-
OTELLogger(
|
|
329
|
-
'error',
|
|
330
|
-
'Something unexpected occurred querying Graphql endpoint: %o',
|
|
331
|
-
err
|
|
332
|
-
)
|
|
333
|
-
|
|
334
|
-
if (err instanceof BadRequestError) {
|
|
335
|
-
response.status(400).end()
|
|
336
|
-
return
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
if (err instanceof UnauthorizedError) {
|
|
340
|
-
response.status(401).end()
|
|
341
|
-
return
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
response.status(500).end()
|
|
345
|
-
return
|
|
384
|
+
respondToUnexpectedError(err, response)
|
|
346
385
|
}
|
|
347
386
|
}
|
|
348
387
|
|
|
@@ -4,8 +4,9 @@ import type {
|
|
|
4
4
|
ServerOrderDetailsQueryQuery,
|
|
5
5
|
ServerProfileQueryQuery,
|
|
6
6
|
} from '@generated/graphql'
|
|
7
|
+
import { useContext } from 'react'
|
|
7
8
|
import type { PageGlobalContext } from 'src/sdk/overrides/PageProvider'
|
|
8
|
-
import { usePage } from 'src/sdk/overrides/PageProvider'
|
|
9
|
+
import { PageContext, usePage } from 'src/sdk/overrides/PageProvider'
|
|
9
10
|
import type { OrderStatusCmsLabels } from 'src/utils/userOrderStatus'
|
|
10
11
|
import type { AccountNavigationLabels } from './getMyAccountRoutes'
|
|
11
12
|
|
|
@@ -76,9 +77,19 @@ export interface AccountPageContext extends PageGlobalContext {
|
|
|
76
77
|
navigationLabels?: AccountNavigationLabels
|
|
77
78
|
}
|
|
78
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Same data as `usePage<AccountPageContext>().navigationLabels`, but safe to
|
|
82
|
+
* call from components (e.g. the B2B organization drawer) that render both
|
|
83
|
+
* inside and outside a My Account `PageProvider` tree — returns `undefined`
|
|
84
|
+
* instead of throwing when there is no provider, so callers fall back to
|
|
85
|
+
* their hardcoded default label.
|
|
86
|
+
*/
|
|
79
87
|
export function useAccountNavigationLabels() {
|
|
80
|
-
const
|
|
81
|
-
|
|
88
|
+
const context = useContext(PageContext)?.context
|
|
89
|
+
|
|
90
|
+
return context && 'navigationLabels' in context
|
|
91
|
+
? context.navigationLabels
|
|
92
|
+
: undefined
|
|
82
93
|
}
|
|
83
94
|
|
|
84
95
|
export function useAccountPageData<
|
|
@@ -22,6 +22,7 @@ export type AccountNavigationLabels = Partial<{
|
|
|
22
22
|
companyLabel: string
|
|
23
23
|
contractLabel: string
|
|
24
24
|
cardsLabel: string
|
|
25
|
+
quotesLabel: string
|
|
25
26
|
}>
|
|
26
27
|
|
|
27
28
|
interface GetMyAccountRouteParams {
|
|
@@ -45,6 +46,7 @@ const ROUTE_LABEL_KEYS: Record<string, keyof AccountNavigationLabels> = {
|
|
|
45
46
|
[USER_DETAILS_ROUTE]: 'userDetailsLabel',
|
|
46
47
|
[SECURITY_ROUTE]: 'securityLabel',
|
|
47
48
|
[CARDS_ROUTE]: 'cardsLabel',
|
|
49
|
+
[QUOTES_ROUTE]: 'quotesLabel',
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
// This is the default route list for My Account, we should add then as the feature is implemented
|
|
@@ -62,7 +62,7 @@ export const isSearchPage = (x: any): x is SearchPageContext =>
|
|
|
62
62
|
x?.data?.title != undefined ||
|
|
63
63
|
x?.data?.searchTerm != undefined
|
|
64
64
|
|
|
65
|
-
const PageContext = createContext<PageProviderContextValue | null>(null)
|
|
65
|
+
export const PageContext = createContext<PageProviderContextValue | null>(null)
|
|
66
66
|
|
|
67
67
|
function PageProvider({
|
|
68
68
|
context,
|
|
@@ -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: /
|
|
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
|
})
|