diff --git a/packages/cli/src/commands/spend-request/__tests__/spend-request.test.tsx b/packages/cli/src/commands/spend-request/__tests__/spend-request.test.tsx index fffd85a..0c7831b 100644 --- a/packages/cli/src/commands/spend-request/__tests__/spend-request.test.tsx +++ b/packages/cli/src/commands/spend-request/__tests__/spend-request.test.tsx @@ -321,6 +321,86 @@ describe('spend-request', () => { }); }); + describe('card summary', () => { + it('RetrieveSpendRequest shows card_brand and card_last4 when full card is not expanded', async () => { + const request = makeSpendRequest({ + merchant_name: 'Acme', + card_brand: 'visa', + card_last4: '4242', + }); + const repo = makeMockRepo(request); + + const { lastFrame } = render( + {}} + />, + ); + + await vi.waitFor(() => { + const frame = lastFrame(); + expect(frame).toContain('Card:'); + expect(frame).toContain('visa'); + expect(frame).toContain('····4242'); + }); + }); + + it('RetrieveSpendRequest hides the card summary when the full card is expanded', async () => { + const request = makeSpendRequest({ + merchant_name: 'Acme', + card_brand: 'visa', + card_last4: '4242', + card: { + id: 'ic_1', + brand: 'visa', + exp_month: 12, + exp_year: 2030, + number: '4242424242424242', + }, + }); + const repo = makeMockRepo(request); + + const { lastFrame } = render( + {}} + />, + ); + + await vi.waitFor(() => { + const frame = lastFrame(); + expect(frame).toContain('Card Details:'); + expect(frame).not.toContain('····4242'); + }); + }); + + it('RetrieveSpendRequest omits the card summary for SPT (no brand/last4)', async () => { + const request = makeSpendRequest({ + merchant_name: 'Acme', + credential_type: 'shared_payment_token', + card_brand: undefined, + card_last4: undefined, + }); + const repo = makeMockRepo(request); + + const { lastFrame } = render( + {}} + />, + ); + + await vi.waitFor(() => { + const frame = lastFrame(); + expect(frame).toContain('Spend request approved'); + expect(frame).not.toContain('Card:'); + }); + }); + }); + describe('sanitization', () => { it('CreateSpendRequest sanitizes merchant_name and line_items', async () => { const request = makeSpendRequest(); diff --git a/packages/cli/src/commands/spend-request/retrieve.tsx b/packages/cli/src/commands/spend-request/retrieve.tsx index 32ad208..1ff41c5 100644 --- a/packages/cli/src/commands/spend-request/retrieve.tsx +++ b/packages/cli/src/commands/spend-request/retrieve.tsx @@ -484,6 +484,24 @@ export const RetrieveSpendRequest: React.FC = ({ )} )} + {!request?.card && (request?.card_brand || request?.card_last4) && ( + + Card: + + {' '} + {[ + request?.card_brand, + request?.card_last4 && `····${request.card_last4}`, + ] + .filter(Boolean) + .join(' ')} + + + {' '} + Use --include card to expand full card details + + + )} {request?.card && outputFile && ( {outputFilePath && ( diff --git a/packages/sdk/src/types/index.ts b/packages/sdk/src/types/index.ts index f2935d5..415a185 100644 --- a/packages/sdk/src/types/index.ts +++ b/packages/sdk/src/types/index.ts @@ -130,6 +130,8 @@ export interface SpendRequest { payment_details: string; credential_type?: CredentialType; network_id?: string; + card_brand?: string; + card_last4?: string; status: SpendRequestStatus; approval_url?: string; card?: Card;