Files
MealQuest/web/src/plan/week.test.ts
T
2026-10-09 07:42:48 -04:00

76 lines
3.7 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 { addDays, dayAndDate, dayOfMonth, defaultWeek, localNow, weekdayKicker, weekdayName, weekLabel, weekStart } from './week.ts'
// SCHEDULE drafts the plan on Fridays (Sunday = 0) at 09:00 in New York.
const SCHEDULE = { timezone: 'America/New_York', plan_draft_dow: 5, plan_draft_time: '09:00' }
describe('week helpers', () => {
it('finds the Monday of a week and moves by days across months and years', () => {
expect(weekStart('2026-10-07')).toBe('2026-10-05')
expect(weekStart('2026-10-05')).toBe('2026-10-05')
expect(weekStart('2026-10-11')).toBe('2026-10-05')
expect(addDays('2026-10-05', 7)).toBe('2026-10-12')
expect(addDays('2026-10-05', -7)).toBe('2026-09-28')
expect(addDays('2026-12-28', 7)).toBe('2027-01-04')
})
it('crosses a DST change without losing a day', () => {
expect(addDays('2026-10-26', 7)).toBe('2026-11-02')
expect(addDays('2027-03-08', 7)).toBe('2027-03-15')
})
it('labels weeks as the API does, by ISO week', () => {
expect(weekLabel('2026-10-05')).toEqual({ week: 'Week 41', dates: 'Oct 5 – 11' })
expect(weekLabel('2026-09-28')).toEqual({ week: 'Week 40', dates: 'Sep 28 – Oct 4' })
expect(weekLabel('2026-12-28')).toEqual({ week: 'Week 53', dates: 'Dec 28 – Jan 3' })
expect(weekLabel('2027-01-04')).toEqual({ week: 'Week 1', dates: 'Jan 4 – 10' })
})
it('names the day of a date as a tile kicker', () => {
expect(weekdayKicker('2026-10-05')).toBe('MON')
expect(weekdayKicker('2026-10-11')).toBe('SUN')
})
it('names the day of a date in full', () => {
expect(weekdayName('2026-10-09')).toBe('Friday')
expect(weekdayName('2026-10-11')).toBe('Sunday')
})
it('names the day of a date in full with its month and day', () => {
expect(dayAndDate('2026-10-10')).toBe('Saturday, Oct 10')
expect(dayAndDate('2026-11-01')).toBe('Sunday, Nov 1')
})
it('reads the day of the month of a date', () => {
expect(dayOfMonth('2026-10-05')).toBe(5)
expect(dayOfMonth('2026-10-31')).toBe(31)
expect(() => dayOfMonth('2026-10-32')).toThrow('not a real date')
})
it('refuses a week start that is not a Monday, and a date that is not real', () => {
expect(() => weekLabel('2026-10-06')).toThrow('week start 2026-10-06 is not a Monday')
expect(() => addDays('2026-02-30', 1)).toThrow('not a real date')
expect(() => weekStart('Oct 5')).toThrow('not a YYYY-MM-DD date')
})
it('reads the household-local date and clock in its zone', () => {
// 03:30 UTC on Thursday is still Wednesday evening in New York.
expect(localNow('America/New_York', new Date('2026-10-08T03:30:00Z'))).toEqual({ date: '2026-10-07', time: '23:30' })
expect(localNow('Asia/Tokyo', new Date('2026-10-08T03:30:00Z'))).toEqual({ date: '2026-10-08', time: '12:30' })
})
it('opens on this week until the plan_draft time, then on next week', () => {
expect(defaultWeek(SCHEDULE, new Date('2026-10-07T16:00:00Z'))).toBe('2026-10-05') // Wed noon
expect(defaultWeek(SCHEDULE, new Date('2026-10-09T12:59:00Z'))).toBe('2026-10-05') // Fri 08:59
expect(defaultWeek(SCHEDULE, new Date('2026-10-09T13:00:00Z'))).toBe('2026-10-12') // Fri 09:00
expect(defaultWeek(SCHEDULE, new Date('2026-10-10T16:00:00Z'))).toBe('2026-10-12') // Sat
expect(defaultWeek(SCHEDULE, new Date('2026-10-12T04:30:00Z'))).toBe('2026-10-12') // the next Mon, 00:30
})
it('counts a Sunday plan_draft day as the end of the Monday-start week', () => {
const sunday = { ...SCHEDULE, plan_draft_dow: 0, plan_draft_time: '18:00' }
expect(defaultWeek(sunday, new Date('2026-10-10T16:00:00Z'))).toBe('2026-10-05') // Sat
expect(defaultWeek(sunday, new Date('2026-10-11T22:00:00Z'))).toBe('2026-10-12') // Sun 18:00
})
})