import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest' import { useEventGrouping } from '../../composables/useEventGrouping' import type { StoredEvent } from '../../composables/useEventStorage' function makeEvent(overrides: Partial & { dateTime: string }): StoredEvent { return { eventToken: `evt-${Math.random().toString(36).slice(2, 8)}`, title: 'Test Event', ...overrides, } } describe('useEventGrouping', () => { // Fixed "now": Wednesday, 2026-03-11 12:00 local const NOW = new Date(2026, 2, 11, 12, 0, 0) beforeEach(() => { vi.useFakeTimers() vi.setSystemTime(NOW) }) afterEach(() => { vi.useRealTimers() }) it('returns empty array when no events', () => { const sections = useEventGrouping([], NOW) expect(sections).toEqual([]) }) it('classifies a today event into "today" section', () => { const event = makeEvent({ dateTime: '2026-03-11T18:30:00' }) const sections = useEventGrouping([event], NOW) expect(sections).toHaveLength(1) expect(sections[0]!.key).toBe('today') expect(sections[0]!.label).toBe('Today') expect(sections[0]!.dateGroups[0]!.events).toHaveLength(1) }) it('classifies events into all five sections', () => { const events = [ makeEvent({ title: 'Today', dateTime: '2026-03-11T10:00:00' }), makeEvent({ title: 'This Week', dateTime: '2026-03-13T10:00:00' }), // Friday (same week) makeEvent({ title: 'Next Week', dateTime: '2026-03-16T10:00:00' }), // Monday next week makeEvent({ title: 'Later', dateTime: '2026-03-30T10:00:00' }), // far future makeEvent({ title: 'Past', dateTime: '2026-03-09T10:00:00' }), // Monday (past) ] const sections = useEventGrouping(events, NOW) expect(sections).toHaveLength(5) expect(sections[0]!.key).toBe('today') expect(sections[1]!.key).toBe('thisWeek') expect(sections[2]!.key).toBe('nextWeek') expect(sections[3]!.key).toBe('later') expect(sections[4]!.key).toBe('past') }) it('omits empty sections', () => { const events = [ makeEvent({ title: 'Today', dateTime: '2026-03-11T10:00:00' }), makeEvent({ title: 'Past', dateTime: '2026-03-01T10:00:00' }), ] const sections = useEventGrouping(events, NOW) expect(sections).toHaveLength(2) expect(sections[0]!.key).toBe('today') expect(sections[1]!.key).toBe('past') }) it('sorts upcoming events ascending by time', () => { const events = [ makeEvent({ title: 'Later', dateTime: '2026-03-11T20:00:00' }), makeEvent({ title: 'Earlier', dateTime: '2026-03-11T08:00:00' }), ] const sections = useEventGrouping(events, NOW) const todayEvents = sections[0]!.dateGroups[0]!.events expect(todayEvents[0]!.title).toBe('Earlier') expect(todayEvents[1]!.title).toBe('Later') }) it('sorts past events descending by time (most recent first)', () => { const events = [ makeEvent({ title: 'Older', dateTime: '2026-03-01T10:00:00' }), makeEvent({ title: 'Newer', dateTime: '2026-03-09T10:00:00' }), ] const sections = useEventGrouping(events, NOW) const pastEvents = sections[0]!.dateGroups expect(pastEvents[0]!.events[0]!.title).toBe('Newer') expect(pastEvents[1]!.events[0]!.title).toBe('Older') }) it('groups events by date within a section', () => { const events = [ makeEvent({ title: 'Fri AM', dateTime: '2026-03-13T09:00:00' }), makeEvent({ title: 'Fri PM', dateTime: '2026-03-13T18:00:00' }), makeEvent({ title: 'Sat', dateTime: '2026-03-14T12:00:00' }), ] const sections = useEventGrouping(events, NOW) expect(sections[0]!.key).toBe('thisWeek') const dateGroups = sections[0]!.dateGroups expect(dateGroups).toHaveLength(2) // Friday and Saturday expect(dateGroups[0]!.events).toHaveLength(2) // Two Friday events expect(dateGroups[1]!.events).toHaveLength(1) // One Saturday event }) it('sets showSubheader=false for "today" section', () => { const event = makeEvent({ dateTime: '2026-03-11T18:00:00' }) const sections = useEventGrouping([event], NOW) expect(sections[0]!.dateGroups[0]!.showSubheader).toBe(false) }) it('sets showSubheader=true for non-today sections', () => { const events = [ makeEvent({ dateTime: '2026-03-13T10:00:00' }), // thisWeek makeEvent({ dateTime: '2026-03-30T10:00:00' }), // later (beyond next week) makeEvent({ dateTime: '2026-03-01T10:00:00' }), // past ] const sections = useEventGrouping(events, NOW) for (const section of sections) { for (const group of section.dateGroups) { expect(group.showSubheader).toBe(true) } } }) it('sets emphasized=true only for "today" section', () => { const events = [ makeEvent({ dateTime: '2026-03-11T18:00:00' }), makeEvent({ dateTime: '2026-03-30T10:00:00' }), ] const sections = useEventGrouping(events, NOW) expect(sections[0]!.emphasized).toBe(true) // today expect(sections[1]!.emphasized).toBe(false) // later }) it('on Sunday, tomorrow (Monday) goes to "nextWeek" not "thisWeek"', () => { // Sunday 2026-03-15 const sunday = new Date(2026, 2, 15, 12, 0, 0) const mondayEvent = makeEvent({ title: 'Monday', dateTime: '2026-03-16T10:00:00' }) const sections = useEventGrouping([mondayEvent], sunday) expect(sections).toHaveLength(1) expect(sections[0]!.key).toBe('nextWeek') }) it('on Sunday, today events still appear under "today"', () => { const sunday = new Date(2026, 2, 15, 12, 0, 0) const todayEvent = makeEvent({ dateTime: '2026-03-15T18:00:00' }) const sections = useEventGrouping([todayEvent], sunday) expect(sections[0]!.key).toBe('today') }) it('dateGroup labels are formatted via Intl', () => { const event = makeEvent({ dateTime: '2026-03-13T10:00:00' }) // Friday const sections = useEventGrouping([event], NOW) const label = sections[0]!.dateGroups[0]!.label // The exact format depends on locale, but should contain the day number expect(label).toContain('13') }) })