The expiry date is no longer user-facing: it is removed from the API (request and response) and the frontend. The backend now automatically calculates it as the event date plus 7 days. The expired banner and RSVP-bar filtering by expired status are also removed from the UI, since expiry is purely an internal data-retention mechanism. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
158 lines
6.0 KiB
TypeScript
158 lines
6.0 KiB
TypeScript
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'
|
|
import { useEventGrouping } from '../../composables/useEventGrouping'
|
|
import type { StoredEvent } from '../../composables/useEventStorage'
|
|
|
|
function makeEvent(overrides: Partial<StoredEvent> & { 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')
|
|
})
|
|
})
|