veza/apps/web/src/features/settings/pages/SettingsPage.test.tsx
2025-12-03 22:56:50 +01:00

205 lines
5.3 KiB
TypeScript

import { render, screen, waitFor, fireEvent } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { BrowserRouter } from 'react-router-dom';
import { SettingsPage } from './SettingsPage';
import * as settingsService from '../services/settingsService';
import { UserSettings } from '../types/settings';
import { ToastProvider } from '@/components/feedback/ToastProvider';
// Mock ResizeObserver for tests
global.ResizeObserver = vi.fn().mockImplementation(() => ({
observe: vi.fn(),
unobserve: vi.fn(),
disconnect: vi.fn(),
}));
// Mock settingsService
vi.mock('../services/settingsService', () => ({
getSettings: vi.fn(),
updateSettings: vi.fn(),
}));
// Mock useAuthStore
vi.mock('@/stores/auth', () => ({
useAuthStore: () => ({
user: {
id: 1,
username: 'testuser',
email: 'test@example.com',
},
}),
}));
// Mock SettingsTabs
vi.mock('../components/SettingsTabs', () => ({
SettingsTabs: ({ settings, onChange }: { settings: UserSettings; onChange: (s: UserSettings) => void }) => (
<div data-testid="settings-tabs">
<button onClick={() => onChange({ ...settings, preferences: { ...settings.preferences, language: 'fr' } })}>
Change Language
</button>
</div>
),
}));
const TestWrapper = ({ children }: { children: React.ReactNode }) => (
<BrowserRouter>
<ToastProvider>
{children}
</ToastProvider>
</BrowserRouter>
);
describe('SettingsPage', () => {
const mockSettings: UserSettings = {
notifications: {
email_notifications: true,
push_notifications: true,
browser_notifications: true,
email_on_follow: true,
email_on_like: true,
email_on_comment: true,
email_on_message: true,
email_on_mention: true,
email_marketing: false,
},
privacy: {
allow_search_indexing: true,
show_activity: true,
},
content: {
explicit_content: false,
autoplay: true,
},
preferences: {
language: 'en',
timezone: 'UTC',
theme: 'auto',
},
};
beforeEach(() => {
vi.clearAllMocks();
});
it('should load and display settings', async () => {
vi.mocked(settingsService.getSettings).mockResolvedValue(mockSettings);
render(
<TestWrapper>
<SettingsPage />
</TestWrapper>
);
await waitFor(() => {
expect(screen.getByText('Paramètres')).toBeInTheDocument();
});
expect(screen.getByText('Gérez vos paramètres de compte et préférences')).toBeInTheDocument();
expect(screen.getByTestId('settings-tabs')).toBeInTheDocument();
expect(screen.getByText('Sauvegarder')).toBeInTheDocument();
});
it('should display loading state', () => {
vi.mocked(settingsService.getSettings).mockImplementation(
() => new Promise(() => {}) // Never resolves
);
render(
<TestWrapper>
<SettingsPage />
</TestWrapper>
);
// Should show loading spinner
expect(screen.queryByText('Paramètres')).not.toBeInTheDocument();
});
it('should save settings on button click', async () => {
vi.mocked(settingsService.getSettings).mockResolvedValue(mockSettings);
vi.mocked(settingsService.updateSettings).mockResolvedValue();
render(
<TestWrapper>
<SettingsPage />
</TestWrapper>
);
await waitFor(() => {
expect(screen.getByText('Sauvegarder')).toBeInTheDocument();
});
const saveButton = screen.getByText('Sauvegarder');
fireEvent.click(saveButton);
await waitFor(() => {
expect(settingsService.updateSettings).toHaveBeenCalledWith(1, mockSettings);
});
});
it('should display validation errors', async () => {
const invalidSettings: UserSettings = {
...mockSettings,
preferences: {
...mockSettings.preferences,
language: 'invalid-lang' as any, // Invalid language
},
};
vi.mocked(settingsService.getSettings).mockResolvedValue(invalidSettings);
render(
<TestWrapper>
<SettingsPage />
</TestWrapper>
);
await waitFor(() => {
expect(screen.getByText('Sauvegarder')).toBeInTheDocument();
});
const saveButton = screen.getByText('Sauvegarder');
fireEvent.click(saveButton);
// Validation should prevent save
await waitFor(() => {
expect(settingsService.updateSettings).not.toHaveBeenCalled();
});
});
it('should handle load error', async () => {
vi.mocked(settingsService.getSettings).mockRejectedValue(new Error('Failed to load settings'));
render(
<TestWrapper>
<SettingsPage />
</TestWrapper>
);
await waitFor(() => {
expect(screen.getByText('Erreur de chargement des paramètres')).toBeInTheDocument();
});
});
it('should handle save error', async () => {
vi.mocked(settingsService.getSettings).mockResolvedValue(mockSettings);
vi.mocked(settingsService.updateSettings).mockRejectedValue(new Error('Failed to save'));
render(
<TestWrapper>
<SettingsPage />
</TestWrapper>
);
await waitFor(() => {
expect(screen.getByText('Sauvegarder')).toBeInTheDocument();
});
const saveButton = screen.getByText('Sauvegarder');
fireEvent.click(saveButton);
await waitFor(() => {
expect(settingsService.updateSettings).toHaveBeenCalled();
});
});
});