veza/apps/web/src/features/support/pages/SupportPage.test.tsx
senke 2281c91e8b feat(v0.13.5): polish marketplace & compliance — KYC, support, payout E2E
- Seller KYC via Stripe Identity (start verification, status check, webhook)
- Support ticket system (backend handler + frontend form page)
- E2E payout flow integration test (sale → payment → balance → payout)
- Migrations: seller_kyc columns, support_tickets table
- Frontend: SupportPage with SUMI design, lazy loading, routing

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 14:57:19 +01:00

116 lines
4.1 KiB
TypeScript

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { SupportPage } from './SupportPage';
// Mock dependencies
vi.mock('react-i18next', () => ({
useTranslation: () => ({
t: (key: string, fallback?: string) => fallback || key,
}),
}));
vi.mock('@/features/auth/hooks/useUser', () => ({
useUser: () => ({ data: { email: 'test@example.com', username: 'testuser' } }),
}));
vi.mock('@/features/auth/store/authStore', () => ({
useAuthStore: () => ({ isAuthenticated: true }),
}));
vi.mock('@/components/layout/DashboardLayout', () => ({
DashboardLayout: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
}));
const mockPost = vi.fn().mockResolvedValue({ data: { ticket_id: 'ticket-123' } });
vi.mock('@/services/api/client', () => ({
apiClient: { post: (...args: unknown[]) => mockPost(...args) },
}));
function renderWithProviders(ui: React.ReactElement) {
const queryClient = new QueryClient({
defaultOptions: { queries: { retry: false } },
});
return render(
<QueryClientProvider client={queryClient}>{ui}</QueryClientProvider>,
);
}
describe('SupportPage', () => {
beforeEach(() => {
vi.clearAllMocks();
mockPost.mockResolvedValue({ data: { ticket_id: 'ticket-123' } });
});
it('should render the support form', () => {
renderWithProviders(<SupportPage />);
expect(screen.getByText('Support')).toBeDefined();
expect(screen.getByLabelText('Email address')).toBeDefined();
expect(screen.getByLabelText('Subject')).toBeDefined();
expect(screen.getByLabelText('Message')).toBeDefined();
});
it('should pre-fill email from authenticated user', () => {
renderWithProviders(<SupportPage />);
const emailInput = screen.getByLabelText('Email address') as HTMLInputElement;
expect(emailInput.value).toBe('test@example.com');
});
it('should disable submit when form is incomplete', () => {
renderWithProviders(<SupportPage />);
const submitBtn = screen.getByRole('button', { name: /send message/i });
expect(submitBtn).toBeDisabled();
});
it('should enable submit when form is complete', async () => {
const user = userEvent.setup();
renderWithProviders(<SupportPage />);
await user.type(screen.getByLabelText('Subject'), 'Payment issue');
await user.type(screen.getByLabelText('Message'), 'I have a problem with my recent purchase.');
const submitBtn = screen.getByRole('button', { name: /send message/i });
expect(submitBtn).not.toBeDisabled();
});
it('should submit the form and show success message', async () => {
const user = userEvent.setup();
renderWithProviders(<SupportPage />);
await user.type(screen.getByLabelText('Subject'), 'Payment issue');
await user.type(screen.getByLabelText('Message'), 'I have a problem with my recent purchase.');
await user.click(screen.getByRole('button', { name: /send message/i }));
await waitFor(() => {
expect(screen.getByText('Message sent!')).toBeDefined();
});
expect(mockPost).toHaveBeenCalledWith('/support/tickets', expect.objectContaining({
email: 'test@example.com',
subject: 'Payment issue',
category: 'general',
}));
});
it('should show error on submission failure', async () => {
mockPost.mockRejectedValueOnce(new Error('Network error'));
const user = userEvent.setup();
renderWithProviders(<SupportPage />);
await user.type(screen.getByLabelText('Subject'), 'Payment issue');
await user.type(screen.getByLabelText('Message'), 'I have a problem with my recent purchase.');
await user.click(screen.getByRole('button', { name: /send message/i }));
await waitFor(() => {
expect(screen.getByRole('alert')).toBeDefined();
});
});
it('should render quick help links', () => {
renderWithProviders(<SupportPage />);
expect(screen.getByText('Quick help')).toBeDefined();
expect(screen.getByText('Payment issues')).toBeDefined();
expect(screen.getByText('Account settings')).toBeDefined();
});
});