import { render, screen } from '@testing-library/react' import userEvent from '@testing-library/user-event' import { describe, it, expect, vi } from 'vitest' import { axe } from 'vitest-axe' import { Calendar } from './calendar' const MAY_15_2026 = new Date(2026, 4, 15) describe('Calendar', () => { it('renders a grid with day buttons for the given month', () => { render() expect(screen.getByRole('grid')).toBeInTheDocument() expect(screen.getByRole('button', { name: /May 15th, 2026/ })).toBeInTheDocument() }) it('selects a date when a day is clicked', async () => { const user = userEvent.setup() const onSelect = vi.fn() render() await user.click(screen.getByRole('button', { name: /May 20th, 2026/ })) expect(onSelect).toHaveBeenCalled() const [selected] = onSelect.mock.calls[0]! expect(selected).toBeInstanceOf(Date) expect((selected as Date).getDate()).toBe(20) }) it('reflects the controlled selected date with aria-selected', () => { render() const cell = screen.getByRole('gridcell', { selected: true }) expect(cell).toHaveAttribute('data-day', '2026-05-15') }) it('keeps focus on the focused day across a controlled selected update', () => { const { rerender } = render() const day15 = screen.getByRole('button', { name: /May 15th, 2026/ }) day15.focus() expect(document.activeElement).toBe(day15) rerender() const day15After = screen.getByRole('button', { name: /May 15th, 2026/ }) expect(day15After).toBe(day15) expect(document.activeElement).toBe(day15) }) it('applies size variant via --cell-size CSS variable on the root', () => { const { container, rerender } = render() expect(container.querySelector('[data-slot="calendar"]')?.className).toContain('--cell-size:--spacing(6)') rerender() expect(container.querySelector('[data-slot="calendar"]')?.className).toContain('--cell-size:--spacing(10)') }) it('renders prev/next navigation buttons that change months', async () => { const user = userEvent.setup() const onMonthChange = vi.fn() render() await user.click(screen.getByRole('button', { name: /next month/i })) expect(onMonthChange).toHaveBeenCalled() const [nextMonth] = onMonthChange.mock.calls[0]! expect((nextMonth as Date).getMonth()).toBe(5) }) it('has no accessibility violations', async () => { const { container } = render() expect(await axe(container)).toHaveNoViolations() }) })