94 lines
3.7 KiB
TypeScript
94 lines
3.7 KiB
TypeScript
import { describe, it, expect } from 'vitest'
|
||
import { describeRecurrence } from './recurrenceDescription'
|
||
|
||
// All test dates fall inside EU DST (Mar 29 – Oct 25, 2026), so Berlin is UTC+2.
|
||
// We spell the UTC instant explicitly so tests are timezone-independent.
|
||
const tuesdayFirstOfMonth = '2026-04-07T16:30:00.000Z' // Tue 2026-04-07 18:30 Berlin
|
||
const monday2ndOfMonth = '2026-04-13T16:30:00.000Z' // Mon 2026-04-13 18:30 Berlin
|
||
const sunday13thOfMonth = '2026-09-13T08:00:00.000Z' // Sun 2026-09-13 10:00 Berlin
|
||
const monday5thOfMonth = '2026-03-30T18:00:00.000Z' // Mon 2026-03-30 20:00 Berlin
|
||
|
||
describe('describeRecurrence', () => {
|
||
it('returns undefined for none / missing recurrenceType', () => {
|
||
expect(describeRecurrence({ recurrenceType: 'none', date: monday2ndOfMonth })).toBeUndefined()
|
||
expect(describeRecurrence({ recurrenceType: null, date: monday2ndOfMonth } as never)).toBeUndefined()
|
||
})
|
||
|
||
it('describes daily with time from event.date', () => {
|
||
const dateAt10 = '2026-04-13T08:00:00.000Z' // 10:00 Berlin
|
||
expect(describeRecurrence({ recurrenceType: 'daily', date: dateAt10 })).toBe(
|
||
'Täglich um 10:00 Uhr',
|
||
)
|
||
})
|
||
|
||
it('describes weekly using the weekday and time of event.date', () => {
|
||
expect(describeRecurrence({ recurrenceType: 'weekly', date: tuesdayFirstOfMonth })).toBe(
|
||
'Jeden Dienstag um 18:30 Uhr',
|
||
)
|
||
})
|
||
|
||
it('describes biweekly', () => {
|
||
expect(describeRecurrence({ recurrenceType: 'biweekly', date: monday2ndOfMonth })).toBe(
|
||
'Alle 2 Wochen, Montag um 18:30 Uhr',
|
||
)
|
||
})
|
||
|
||
it('describes monthlyByDate using the day-of-month from event.date', () => {
|
||
expect(describeRecurrence({ recurrenceType: 'monthlyByDate', date: sunday13thOfMonth })).toBe(
|
||
'Monatlich am 13. um 10:00 Uhr',
|
||
)
|
||
})
|
||
|
||
it('describes monthlyByWeekday using the Nth weekday from event.date', () => {
|
||
expect(describeRecurrence({ recurrenceType: 'monthlyByWeekday', date: monday2ndOfMonth })).toBe(
|
||
'Monatlich am 2. Montag um 18:30 Uhr',
|
||
)
|
||
expect(describeRecurrence({ recurrenceType: 'monthlyByWeekday', date: tuesdayFirstOfMonth })).toBe(
|
||
'Monatlich am 1. Dienstag um 18:30 Uhr',
|
||
)
|
||
})
|
||
|
||
it('clamps a 5th-occurrence weekday to the 4th (matches generator)', () => {
|
||
expect(describeRecurrence({ recurrenceType: 'monthlyByWeekday', date: monday5thOfMonth })).toBe(
|
||
'Monatlich am 4. Montag um 20:00 Uhr',
|
||
)
|
||
})
|
||
|
||
it('joins multiple custom rules and appends time once', () => {
|
||
const desc = describeRecurrence({
|
||
recurrenceType: 'custom',
|
||
date: monday2ndOfMonth,
|
||
recurrenceRules: [
|
||
{ frequency: 'monthlyByWeekday', weekday: 'tuesday', weekOfMonth: 'third' },
|
||
{ frequency: 'monthlyByWeekday', weekday: 'thursday', weekOfMonth: 'fourth' },
|
||
],
|
||
})
|
||
expect(desc).toBe(
|
||
'Am 3. Dienstag jedes Monats · Am 4. Donnerstag jedes Monats um 18:30 Uhr',
|
||
)
|
||
})
|
||
|
||
it('skips incomplete custom rules and returns Benutzerdefiniert if none are valid', () => {
|
||
expect(
|
||
describeRecurrence({
|
||
recurrenceType: 'custom',
|
||
date: monday2ndOfMonth,
|
||
recurrenceRules: [
|
||
// missing weekOfMonth
|
||
{ frequency: 'monthlyByWeekday', weekday: 'tuesday' },
|
||
],
|
||
}),
|
||
).toBe('Benutzerdefiniert um 18:30 Uhr')
|
||
})
|
||
|
||
it('omits the time clause when event.date is missing', () => {
|
||
expect(describeRecurrence({ recurrenceType: 'daily', date: null } as never)).toBe('Täglich')
|
||
})
|
||
|
||
it('pads minutes correctly (08:05, not 8:5)', () => {
|
||
const dateEarly = '2026-04-13T06:05:00.000Z' // 08:05 Berlin
|
||
expect(describeRecurrence({ recurrenceType: 'daily', date: dateEarly })).toBe(
|
||
'Täglich um 08:05 Uhr',
|
||
)
|
||
})
|
||
})
|