import React from 'react'; import { describe, expect, it, vi, beforeEach } from 'vitest'; import { act, fireEvent, render, screen, waitFor } from '@testing-library/react'; import { StripeCheckoutForm, PayPalCheckout, } from '../pages/WelcomeOrderSummaryPage'; const stripeRef: { current: any } = { current: null }; const elementsRef: { current: any } = { current: null }; const paypalPropsRef: { current: any } = { current: null }; const { confirmPaymentMock, completePurchaseMock, createPayPalOrderMock, capturePayPalOrderMock, } = vi.hoisted(() => ({ confirmPaymentMock: vi.fn(), completePurchaseMock: vi.fn(), createPayPalOrderMock: vi.fn(), capturePayPalOrderMock: vi.fn(), })); vi.mock('@stripe/react-stripe-js', () => ({ useStripe: () => stripeRef.current, useElements: () => elementsRef.current, PaymentElement: () =>
, Elements: ({ children }: { children: React.ReactNode }) => <>{children}, })); vi.mock('@paypal/react-paypal-js', () => ({ PayPalScriptProvider: ({ children }: { children: React.ReactNode }) => <>{children}, PayPalButtons: (props: any) => { paypalPropsRef.current = props; return ; }, })); vi.mock('../../api', () => ({ completeTenantPackagePurchase: completePurchaseMock, createTenantPackagePaymentIntent: vi.fn(), assignFreeTenantPackage: vi.fn(), createTenantPayPalOrder: createPayPalOrderMock, captureTenantPayPalOrder: capturePayPalOrderMock, })); describe('StripeCheckoutForm', () => { beforeEach(() => { confirmPaymentMock.mockReset(); completePurchaseMock.mockReset(); stripeRef.current = { confirmPayment: confirmPaymentMock }; elementsRef.current = {}; }); const renderStripeForm = (overrides?: Partial>) => render( key} {...overrides} /> ); it('completes the purchase when Stripe reports a successful payment', async () => { const onSuccess = vi.fn(); confirmPaymentMock.mockResolvedValue({ error: null, paymentIntent: { payment_method: 'pm_123' }, }); completePurchaseMock.mockResolvedValue(undefined); const { container } = renderStripeForm({ onSuccess }); const form = container.querySelector('form'); expect(form).toBeTruthy(); fireEvent.submit(form!); await waitFor(() => { expect(completePurchaseMock).toHaveBeenCalledWith({ packageId: 42, paymentMethodId: 'pm_123', }); }); expect(onSuccess).toHaveBeenCalled(); }); it('shows Stripe errors returned by confirmPayment', async () => { confirmPaymentMock.mockResolvedValue({ error: { message: 'Card declined' }, }); const { container } = renderStripeForm(); fireEvent.submit(container.querySelector('form')!); await waitFor(() => { expect(screen.getByText('Card declined')).toBeInTheDocument(); }); expect(completePurchaseMock).not.toHaveBeenCalled(); }); it('reports missing payment method id', async () => { confirmPaymentMock.mockResolvedValue({ error: null, paymentIntent: {}, }); const { container } = renderStripeForm(); fireEvent.submit(container.querySelector('form')!); await waitFor(() => { expect(screen.getByText('summary.stripe.missingPaymentId')).toBeInTheDocument(); }); expect(completePurchaseMock).not.toHaveBeenCalled(); }); }); describe('PayPalCheckout', () => { beforeEach(() => { paypalPropsRef.current = null; createPayPalOrderMock.mockReset(); capturePayPalOrderMock.mockReset(); }); it('creates and captures a PayPal order successfully', async () => { createPayPalOrderMock.mockResolvedValue('ORDER-123'); capturePayPalOrderMock.mockResolvedValue(undefined); const onSuccess = vi.fn(); render( key} /> ); expect(paypalPropsRef.current).toBeTruthy(); const { createOrder, onApprove } = paypalPropsRef.current; await act(async () => { const orderId = await createOrder(); expect(orderId).toBe('ORDER-123'); }); await act(async () => { await onApprove({ orderID: 'ORDER-123' }); }); await waitFor(() => { expect(createPayPalOrderMock).toHaveBeenCalledWith(99); expect(capturePayPalOrderMock).toHaveBeenCalledWith('ORDER-123'); expect(onSuccess).toHaveBeenCalled(); }); }); it('surfaces missing order id errors', async () => { createPayPalOrderMock.mockResolvedValue('ORDER-123'); render( key} /> ); const { onApprove } = paypalPropsRef.current; await act(async () => { await onApprove({ orderID: undefined }); }); await waitFor(() => { expect(screen.getByText('summary.paypal.missingOrderId')).toBeInTheDocument(); }); expect(capturePayPalOrderMock).not.toHaveBeenCalled(); }); });