mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 23:35:20 +00:00
92 lines
3.2 KiB
TypeScript
92 lines
3.2 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
||
|
||
import {
|
||
allDayCivilDateOf,
|
||
allDayEndInstant,
|
||
allDayEndInstantFromExclusive,
|
||
allDayExclusiveEndDate,
|
||
allDayRangeValid,
|
||
allDayStartInstant,
|
||
formatAllDayRangeLabel,
|
||
isCivilDate,
|
||
} from '@/lib/activityAllDay'
|
||
|
||
describe('activityAllDay civil date contract', () => {
|
||
it('recognizes only aaaa-mm-dd values', () => {
|
||
expect(isCivilDate('2026-08-10')).toBe(true)
|
||
expect(isCivilDate('2026-8-10')).toBe(false)
|
||
expect(isCivilDate('2026-08-10T09:00')).toBe(false)
|
||
expect(isCivilDate('')).toBe(false)
|
||
})
|
||
})
|
||
|
||
describe('activityAllDay storage instants', () => {
|
||
it('anchors the start on Bahia midnight (fixed −03, no DST)', () => {
|
||
expect(allDayStartInstant('2026-08-10')).toBe('2026-08-10T03:00:00.000Z')
|
||
})
|
||
|
||
it('anchors the inclusive end on the last day at Bahia midnight', () => {
|
||
expect(allDayEndInstant('2026-08-12')).toBe('2026-08-12T03:00:00.000Z')
|
||
})
|
||
|
||
it('round-trips a stored instant back to its civil date', () => {
|
||
expect(allDayCivilDateOf('2026-08-12T03:00:00.000Z')).toBe('2026-08-12')
|
||
})
|
||
|
||
it('rejects a malformed civil date defensively', () => {
|
||
expect(() => allDayStartInstant('10/08/2026')).toThrow()
|
||
})
|
||
})
|
||
|
||
describe('activityAllDay exclusive-end conversions (FullCalendar / iCal)', () => {
|
||
it('derives the exclusive end as the day after the last stored day', () => {
|
||
expect(allDayExclusiveEndDate('2026-08-12T03:00:00.000Z')).toBe('2026-08-13')
|
||
})
|
||
|
||
it('turns an exclusive end back into the stored inclusive instant', () => {
|
||
expect(allDayEndInstantFromExclusive('2026-08-13')).toBe('2026-08-12T03:00:00.000Z')
|
||
})
|
||
|
||
it('keeps single-day events stable across the round trip', () => {
|
||
const start = '2026-08-10T03:00:00.000Z'
|
||
expect(allDayEndInstantFromExclusive(allDayExclusiveEndDate(start))).toBe(start)
|
||
})
|
||
|
||
it('crosses month and year boundaries', () => {
|
||
expect(allDayExclusiveEndDate('2026-08-31T03:00:00.000Z')).toBe('2026-09-01')
|
||
expect(allDayExclusiveEndDate('2026-12-31T03:00:00.000Z')).toBe('2027-01-01')
|
||
expect(allDayEndInstantFromExclusive('2026-03-01')).toBe('2026-02-28T03:00:00.000Z')
|
||
})
|
||
})
|
||
|
||
describe('activityAllDay range rules', () => {
|
||
it('accepts a single-day range (end equals start)', () => {
|
||
const start = '2026-08-10T03:00:00.000Z'
|
||
expect(allDayRangeValid(start, start)).toBe(true)
|
||
})
|
||
|
||
it('accepts a multi-day range and rejects an inverted one', () => {
|
||
const start = '2026-08-10T03:00:00.000Z'
|
||
const end = '2026-08-12T03:00:00.000Z'
|
||
expect(allDayRangeValid(start, end)).toBe(true)
|
||
expect(allDayRangeValid(end, start)).toBe(false)
|
||
})
|
||
})
|
||
|
||
describe('formatAllDayRangeLabel', () => {
|
||
it('prints a single civil date for a one-day commitment', () => {
|
||
expect(formatAllDayRangeLabel('2026-08-10T03:00:00.000Z')).toBe('10/08/2026')
|
||
})
|
||
|
||
it('prints the full range for a multi-day commitment', () => {
|
||
expect(formatAllDayRangeLabel('2026-08-10T03:00:00.000Z', '2026-08-12T03:00:00.000Z')).toBe(
|
||
'10/08/2026 a 12/08/2026',
|
||
)
|
||
})
|
||
|
||
it('collapses a same-day range to the single date', () => {
|
||
expect(formatAllDayRangeLabel('2026-08-10T03:00:00.000Z', '2026-08-10T03:00:00.000Z')).toBe(
|
||
'10/08/2026',
|
||
)
|
||
})
|
||
})
|