import { describe, it, expect, vi, afterEach } from 'vitest' import { relTime, formatWhen, fmtSchedule } from '../src/renderer/src/datetime' afterEach(() => { vi.useRealTimers() }) describe('relTime', () => { it('returns "never" for a missing timestamp', () => { expect(relTime(undefined)).toBe('never') expect(relTime(0)).toBe('never') }) it('buckets into just now / minutes / hours / days', () => { const now = new Date('2026-06-30T12:00:00Z').getTime() vi.useFakeTimers() vi.setSystemTime(now) expect(relTime(now - 20 * 1000)).toBe('just now') // < 1 min expect(relTime(now - 5 * 60_000)).toBe('5 min ago') expect(relTime(now - 3 * 3_600_000)).toBe('3 h ago') expect(relTime(now - 2 * 86_400_000)).toBe('2 d ago') }) }) describe('formatWhen', () => { it('labels today and yesterday with the time, older with a date', () => { const now = new Date('2026-06-30T12:00:00Z').getTime() vi.useFakeTimers() vi.setSystemTime(now) expect(formatWhen(now)).toMatch(/^Today, /) expect(formatWhen(now - 86_400_000)).toMatch(/^Yesterday, /) // A clearly-older timestamp falls through to an absolute date (with year). expect(formatWhen(new Date('2025-01-05T09:00:00Z').getTime())).toMatch(/2025/) }) }) describe('fmtSchedule', () => { it('formats a valid timestamp and never throws', () => { expect(fmtSchedule(new Date('2026-06-30T15:04:00Z').getTime())).toMatch(/2026/) // Defensive: NaN can't be formatted but must not throw. expect(typeof fmtSchedule(Number.NaN)).toBe('string') }) })