teqo-backup/tests/unit/activityAllDay.unit.spec.ts

92 lines
3.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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',
)
})
})