import { describe, expect, it } from 'vitest'; import { formatDateEn, formatDateFr, formatHoursText, formatNextChangeEn, formatNextChangeFr, formatTimeEn, shortDayLabelEn, shortDayLabelFr, } from './format'; describe('formatDateFr / formatDateEn', () => { it('writes the day and month in full', () => { expect(formatDateFr('2026-09-20')).toBe('Dimanche 20 septembre'); expect(formatDateEn('2026-09-20')).toBe('Sunday 20 September'); }); it('does not pad the day number', () => { expect(formatDateFr('2026-09-01')).toBe('Mardi 1 septembre'); expect(formatDateEn('2026-09-01')).toBe('Tuesday 1 September'); }); it('handles every month', () => { expect(formatDateFr('2026-01-15')).toBe('Jeudi 15 janvier'); expect(formatDateFr('2026-08-15')).toBe('Samedi 15 août'); expect(formatDateFr('2026-12-25')).toBe('Vendredi 25 décembre'); expect(formatDateEn('2026-12-25')).toBe('Friday 25 December'); }); }); describe('short day labels', () => { it('uses three letters, Monday first on the screen', () => { expect([1, 2, 3, 4, 5, 6, 0].map(shortDayLabelFr)).toEqual([ 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam', 'Dim', ]); expect([1, 2, 3, 4, 5, 6, 0].map(shortDayLabelEn)).toEqual([ 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun', ]); }); }); describe('formatHoursText', () => { it('renders a single slot', () => { expect(formatHoursText([{ open: '10:00', close: '18:30' }])).toBe('10:00 – 18:30'); }); it('joins several slots with a middle dot', () => { expect( formatHoursText([ { open: '10:00', close: '13:00' }, { open: '14:00', close: '18:30' }, ]), ).toBe('10:00 – 13:00 · 14:00 – 18:30'); }); it('returns an empty string when the shop is closed', () => { expect(formatHoursText([])).toBe(''); }); }); describe('formatTimeEn', () => { it('uses the twelve-hour clock', () => { expect(formatTimeEn('18:30')).toBe('6:30 pm'); expect(formatTimeEn('10:00')).toBe('10:00 am'); }); it('names noon and midnight correctly', () => { expect(formatTimeEn('12:00')).toBe('12:00 pm'); expect(formatTimeEn('00:30')).toBe('12:30 am'); }); }); describe('formatNextChange', () => { it('announces today’s closing time', () => { expect(formatNextChangeFr({ kind: 'CLOSES', date: '2026-09-20', time: '18:30' }, '2026-09-20')).toBe( 'Ferme à 18:30', ); expect(formatNextChangeEn({ kind: 'CLOSES', date: '2026-09-20', time: '18:30' }, '2026-09-20')).toBe( 'Closes at 6:30 pm', ); }); it('announces a reopening later today', () => { expect(formatNextChangeFr({ kind: 'OPENS', date: '2026-09-20', time: '14:00' }, '2026-09-20')).toBe( 'Ouvre à 14:00', ); expect(formatNextChangeEn({ kind: 'OPENS', date: '2026-09-20', time: '14:00' }, '2026-09-20')).toBe( 'Opens at 2:00 pm', ); }); it('announces tomorrow by name', () => { expect(formatNextChangeFr({ kind: 'OPENS', date: '2026-09-21', time: '10:00' }, '2026-09-20')).toBe( 'Ouvre demain à 10:00', ); expect(formatNextChangeEn({ kind: 'OPENS', date: '2026-09-21', time: '10:00' }, '2026-09-20')).toBe( 'Opens tomorrow at 10:00 am', ); }); it('names the weekday when the reopening is further out', () => { expect(formatNextChangeFr({ kind: 'OPENS', date: '2026-09-22', time: '10:00' }, '2026-09-20')).toBe( 'Ouvre mardi à 10:00', ); expect(formatNextChangeEn({ kind: 'OPENS', date: '2026-09-22', time: '10:00' }, '2026-09-20')).toBe( 'Opens Tuesday at 10:00 am', ); }); it('says nothing when there is nothing to announce', () => { expect(formatNextChangeFr(null, '2026-09-20')).toBe(''); expect(formatNextChangeEn(null, '2026-09-20')).toBe(''); }); });