import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { PreferenceSettings } from './PreferenceSettings';
import { PreferenceSettings as PreferenceSettingsType } from '../../types/settings';
// Mock ResizeObserver for tests
global.ResizeObserver = vi.fn().mockImplementation(() => ({
observe: vi.fn(),
unobserve: vi.fn(),
disconnect: vi.fn(),
}));
// Mock Select component
vi.mock('@/components/ui/select', () => ({
Select: ({ value, onChange, options, placeholder }: any) => (
),
}));
// Mock RadioGroup
vi.mock('@/components/ui/radio-group', () => ({
RadioGroup: ({ children, value, onValueChange }: any) => (
{children}
),
RadioGroupItem: ({ value, id }: any) => (
),
}));
// Mock Label
vi.mock('@/components/ui/label', () => ({
Label: ({ children, htmlFor }: any) => (
),
}));
// Mock useTranslation hook
vi.mock('@/hooks/useTranslation', () => ({
useTranslation: () => ({
t: (key: string) => {
const translations: Record = {
'settings.language.language': 'Language',
'settings.language.title': 'Language and Region',
'settings.preferences.timezone': 'Time Zone',
'settings.language.description': 'Choose your preferred language',
'settings.appearance.theme': 'Theme',
'settings.appearance.light': 'Light',
'settings.appearance.dark': 'Dark',
'settings.appearance.system': 'System',
'common.search': 'Search',
};
return translations[key] ?? key;
},
changeLanguage: vi.fn(),
language: 'en',
isReady: true,
}),
}));
describe('PreferenceSettings Component', () => {
const mockPreferences: PreferenceSettingsType = {
language: 'en',
timezone: 'UTC',
theme: 'auto',
};
const mockOnChange = vi.fn();
beforeEach(() => {
vi.clearAllMocks();
});
it('should render all preference fields', () => {
render(
,
);
expect(screen.getByText('Language')).toBeInTheDocument();
// Bug #18: label was "Language and Region", now correctly "Time Zone"
expect(screen.getByText('Time Zone')).toBeInTheDocument();
expect(screen.getByText('Theme')).toBeInTheDocument();
expect(screen.getByTestId('radio-group')).toBeInTheDocument();
});
it('should display current language value', () => {
render(
,
);
const selects = screen.getAllByTestId('select');
const languageSelect = selects[0].querySelector('select');
expect(languageSelect).toHaveValue('en');
});
it('should call onChange when language changes', () => {
render(
,
);
const selects = screen.getAllByTestId('select');
const languageSelect = selects[0].querySelector('select');
if (languageSelect) {
fireEvent.change(languageSelect, { target: { value: 'fr' } });
expect(mockOnChange).toHaveBeenCalledWith({
...mockPreferences,
language: 'fr',
});
}
});
it('should display current timezone value', () => {
render(
,
);
const selects = screen.getAllByTestId('select');
const timezoneSelect = selects[1].querySelector('select');
expect(timezoneSelect).toHaveValue('UTC');
});
it('should call onChange when timezone changes', () => {
render(
,
);
const selects = screen.getAllByTestId('select');
const timezoneSelect = selects[1].querySelector('select');
if (timezoneSelect) {
fireEvent.change(timezoneSelect, { target: { value: 'Europe/Paris' } });
expect(mockOnChange).toHaveBeenCalledWith({
...mockPreferences,
timezone: 'Europe/Paris',
});
}
});
it('should display current theme value', () => {
render(
,
);
const radioGroup = screen.getByTestId('radio-group');
expect(radioGroup).toHaveAttribute('data-value', 'auto');
});
it('should call onChange when theme changes to light', () => {
render(
,
);
const lightButton = screen.getByText('Select Light');
fireEvent.click(lightButton);
expect(mockOnChange).toHaveBeenCalledWith({
...mockPreferences,
theme: 'light',
});
});
it('should call onChange when theme changes to dark', () => {
render(
,
);
const darkButton = screen.getByText('Select Dark');
fireEvent.click(darkButton);
expect(mockOnChange).toHaveBeenCalledWith({
...mockPreferences,
theme: 'dark',
});
});
it('should call onChange when theme changes to auto', () => {
render(
,
);
const autoButton = screen.getByText('Select Auto');
fireEvent.click(autoButton);
expect(mockOnChange).toHaveBeenCalledWith({
...mockPreferences,
theme: 'auto',
});
});
it('should render all theme options', () => {
render(
,
);
expect(screen.getByTestId('radio-light')).toBeInTheDocument();
expect(screen.getByTestId('radio-dark')).toBeInTheDocument();
expect(screen.getByTestId('radio-auto')).toBeInTheDocument();
});
});