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 }) =>
{children}
, })); 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( {ui}, ); } describe('SupportPage', () => { beforeEach(() => { vi.clearAllMocks(); mockPost.mockResolvedValue({ data: { ticket_id: 'ticket-123' } }); }); it('should render the support form', () => { renderWithProviders(); 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(); const emailInput = screen.getByLabelText('Email address') as HTMLInputElement; expect(emailInput.value).toBe('test@example.com'); }); it('should disable submit when form is incomplete', () => { renderWithProviders(); 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(); 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(); 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(); 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(); expect(screen.getByText('Quick help')).toBeDefined(); expect(screen.getByText('Payment issues')).toBeDefined(); expect(screen.getByText('Account settings')).toBeDefined(); }); });