test(05-04): add failing tests for calendar settings panel

- Three test cases: source list with name/type/visibility, visibility toggle calls updateSource, form validation
- Mocks calendar-api functions following existing test patterns

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-24 15:24:09 +02:00
parent c0f2f4ca51
commit f99ff9a498
@@ -0,0 +1,146 @@
import { cleanup, render, screen, waitFor, fireEvent } from '@testing-library/react';
import { afterEach, describe, expect, it, vi } from 'vitest';
// Mock next-intl
vi.mock('next-intl', () => ({
useTranslations: (ns: string) => (key: string) => {
const map: Record<string, Record<string, string>> = {
widgets: {
'calendar.addSource': 'Add source',
'calendar.sourceEmpty': 'No calendar sources configured. Add a source to display events.',
'calendar.connectionSuccess': 'Connection successful',
'calendar.connectionError': 'Connection failed. Please check the URL and credentials.',
},
settings: {
categoryCalendar: 'Calendar',
sourceDeleteConfirm: 'Are you sure you want to delete this calendar source?',
sourceDeleteCta: 'Delete source',
cancel: 'Cancel',
},
};
return map[ns]?.[key] ?? key;
},
}));
// Mock calendar-api
const mockFetchSources = vi.fn();
const mockUpdateSource = vi.fn();
const mockAddSource = vi.fn();
const mockDeleteSource = vi.fn();
const mockTestSource = vi.fn();
vi.mock('@/lib/calendar-api', () => ({
fetchSources: (...args: unknown[]) => mockFetchSources(...args),
updateSource: (...args: unknown[]) => mockUpdateSource(...args),
addSource: (...args: unknown[]) => mockAddSource(...args),
deleteSource: (...args: unknown[]) => mockDeleteSource(...args),
testSource: (...args: unknown[]) => mockTestSource(...args),
}));
afterEach(() => {
cleanup();
vi.restoreAllMocks();
});
describe('CalendarSettingsPanel', () => {
it('lists two sources with name, type badge, and visibility toggle', async () => {
mockFetchSources.mockResolvedValue([
{
id: 's1',
name: 'Work Calendar',
type: 'caldav',
isVisible: true,
color: '#ff0000',
lastSyncError: null,
},
{
id: 's2',
name: 'Holidays',
type: 'ics',
isVisible: false,
color: '#00ff00',
lastSyncError: null,
},
]);
const { CalendarSettingsPanel } = await import(
'@/components/settings/calendar-settings-panel'
);
render(<CalendarSettingsPanel />);
await waitFor(() => {
expect(screen.getByText('Work Calendar')).toBeInTheDocument();
});
expect(screen.getByText('Holidays')).toBeInTheDocument();
// Type badges
expect(screen.getByText('CalDAV')).toBeInTheDocument();
expect(screen.getByText('ICS')).toBeInTheDocument();
// Visibility toggles (checkboxes or switches)
const toggles = screen.getAllByRole('switch');
expect(toggles).toHaveLength(2);
});
it('calls updateSource with isVisible when toggling a source', async () => {
mockFetchSources.mockResolvedValue([
{
id: 's1',
name: 'Work Calendar',
type: 'caldav',
isVisible: true,
color: '#ff0000',
lastSyncError: null,
},
]);
mockUpdateSource.mockResolvedValue({
id: 's1',
name: 'Work Calendar',
type: 'caldav',
isVisible: false,
});
const { CalendarSettingsPanel } = await import(
'@/components/settings/calendar-settings-panel'
);
render(<CalendarSettingsPanel />);
await waitFor(() => {
expect(screen.getByText('Work Calendar')).toBeInTheDocument();
});
const toggle = screen.getByRole('switch');
fireEvent.click(toggle);
await waitFor(() => {
expect(mockUpdateSource).toHaveBeenCalledWith('s1', { isVisible: false });
});
});
it('requires name, type, and url before enabling add form submit', async () => {
mockFetchSources.mockResolvedValue([]);
const { CalendarSettingsPanel } = await import(
'@/components/settings/calendar-settings-panel'
);
render(<CalendarSettingsPanel />);
// Wait for empty state then click add button
await waitFor(() => {
expect(
screen.getByText('No calendar sources configured. Add a source to display events.'),
).toBeInTheDocument();
});
// Click the add source button
const addButton = screen.getByText('Add source');
fireEvent.click(addButton);
// Find the submit button in the form
await waitFor(() => {
const submitButton = screen.getByTestId('source-form-submit');
expect(submitButton).toBeDisabled();
});
});
});