Files
leocrm/frontend/src/__tests__/calendar/MonthView.test.tsx
T
A0-Orchestrator 7350739554 T08b: Frontend Calendar UI (month view, kanban, ICS, resources, sharing)
- 8 calendar components (MonthView, KanbanBoard, AppointmentModal, TaskDetailPanel, IcsControls, ResourceBooking, SharingSettings + API client)

- 2 pages (/calendar, /calendar/kanban) + zustand store

- 17 vitest tests (MonthView 5, KanbanBoard 6, AppointmentModal 6) all passing

- i18n: calendar namespace in en/de (104 lines each, +exportSuccess key)

- TS strict mode pass, npm run build pass
2026-06-30 11:35:08 +02:00

139 lines
4.3 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React from 'react';
import { describe, it, expect, vi } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/react';
import { MonthView } from '@/components/calendar/MonthView';
import type { CalendarEntry } from '@/api/calendar';
const sampleEntries: CalendarEntry[] = [
{
id: 'a-1',
calendar_id: 'cal-1',
entry_type: 'appointment',
subtype: 'normal',
title: 'Team-Meeting',
start_at: '2026-06-15T09:00:00.000Z',
end_at: '2026-06-15T10:00:00.000Z',
all_day: false,
priority: 'medium',
status: 'open',
created_by: 'u-1',
},
{
id: 'a-2',
calendar_id: 'cal-1',
entry_type: 'appointment',
subtype: 'normal',
title: 'Kundentermin',
start_at: '2026-06-22T14:00:00.000Z',
end_at: '2026-06-22T15:00:00.000Z',
all_day: false,
priority: 'high',
status: 'open',
created_by: 'u-1',
},
];
describe('MonthView', () => {
it('renders the month grid with header', () => {
render(
<MonthView
visibleMonth={new Date(2026, 5, 1)}
entries={[]}
onCreateAt={vi.fn()}
onEditEntry={vi.fn()}
onMoveEntry={vi.fn()}
/>
);
expect(screen.getByTestId('month-view')).toBeInTheDocument();
expect(screen.getByTestId('month-view-grid')).toBeInTheDocument();
// Header includes month name and year
expect(screen.getByTestId('month-view-header').textContent).toContain('2026');
});
it('renders all 42 day cells (6 weeks × 7 days)', () => {
render(
<MonthView
visibleMonth={new Date(2026, 5, 1)}
entries={[]}
onCreateAt={vi.fn()}
onEditEntry={vi.fn()}
onMoveEntry={vi.fn()}
/>
);
const cells = screen.getAllByRole('button', { hidden: false }).filter((el) =>
el.getAttribute('data-testid')?.startsWith('month-cell-')
);
expect(cells.length).toBe(42);
});
it('renders an entry chip for each appointment and clicking it fires onEditEntry', () => {
const onEdit = vi.fn();
render(
<MonthView
visibleMonth={new Date(2026, 5, 1)}
entries={sampleEntries}
onCreateAt={vi.fn()}
onEditEntry={onEdit}
onMoveEntry={vi.fn()}
/>
);
expect(screen.getByTestId('month-entry-a-1')).toBeInTheDocument();
expect(screen.getByTestId('month-entry-a-2')).toBeInTheDocument();
fireEvent.click(screen.getByTestId('month-entry-a-1'));
expect(onEdit).toHaveBeenCalledWith(
expect.objectContaining({ id: 'a-1', title: 'Team-Meeting' })
);
});
it('clicking an empty cell fires onCreateAt with the day Date', () => {
const onCreate = vi.fn();
render(
<MonthView
visibleMonth={new Date(2026, 5, 1)}
entries={[]}
onCreateAt={onCreate}
onEditEntry={vi.fn()}
onMoveEntry={vi.fn()}
/>
);
// Pick the first cell of the grid
const cells = screen.getAllByRole('button', { hidden: false }).filter((el) =>
el.getAttribute('data-testid')?.startsWith('month-cell-')
);
fireEvent.click(cells[0]);
expect(onCreate).toHaveBeenCalledTimes(1);
const arg = onCreate.mock.calls[0][0] as Date;
expect(arg).toBeInstanceOf(Date);
});
it('drag-and-drop fires onMoveEntry with the new start time-of-day preserved', () => {
const onMove = vi.fn();
const { container } = render(
<MonthView
visibleMonth={new Date(2026, 5, 1)}
entries={sampleEntries}
onCreateAt={vi.fn()}
onEditEntry={vi.fn()}
onMoveEntry={onMove}
/>
);
const entryEl = screen.getByTestId('month-entry-a-1');
const cells = container.querySelectorAll('[data-testid^="month-cell-"]');
// Pick a cell that's clearly different from June 15
const targetCell = cells[20] as HTMLElement;
const dataTransfer = {
setData: vi.fn(),
getData: (k: string) => (k === 'application/x-calendar-entry' ? 'a-1' : ''),
types: ['application/x-calendar-entry'],
effectAllowed: '',
dropEffect: '',
};
fireEvent.dragStart(entryEl, { dataTransfer });
fireEvent.dragOver(targetCell, { dataTransfer });
fireEvent.drop(targetCell, { dataTransfer });
expect(onMove).toHaveBeenCalledTimes(1);
const [, newStart] = onMove.mock.calls[0];
expect(newStart).toBeInstanceOf(Date);
});
});