import { describe, expect, it } from 'vitest'; import { EventBus } from '../src/core/EventBus'; import { GameClock, ageOn, type ClockConfig } from '../src/core/GameClock'; const FAST: ClockConfig = { nightClockMinutes: 360, nightRealMinutes: 13, nightDate: '2026-07-18' }; describe('GameClock', () => { it('emits one tick per in-game minute, in order', () => { const bus = new EventBus(); const ticks: number[] = []; bus.on('clock:tick', ({ clockMin }) => ticks.push(clockMin)); const clock = new GameClock(bus, FAST); clock.start(); const msPerClockMin = (FAST.nightRealMinutes * 60_000) / FAST.nightClockMinutes; for (let i = 0; i < 50; i++) clock.update(msPerClockMin / 5); // uneven small steps expect(ticks).toEqual(Array.from({ length: ticks.length }, (_, i) => i)); expect(clock.clockMin).toBe(ticks[ticks.length - 1]); }); it('does not advance while paused or before start', () => { const bus = new EventBus(); const clock = new GameClock(bus, FAST); clock.update(10_000); expect(clock.clockMin).toBe(0); clock.start(); clock.update(5_000); const at = clock.clockMin; clock.pause(); clock.update(60_000); expect(clock.clockMin).toBe(at); }); it('caps at night end', () => { const bus = new EventBus(); const clock = new GameClock(bus, FAST); clock.start(); clock.update(FAST.nightRealMinutes * 60_000 * 3); expect(clock.clockMin).toBe(360); expect(clock.isOver).toBe(true); }); it('formats the label from a 9 PM start', () => { const bus = new EventBus(); const clock = new GameClock(bus, FAST); expect(clock.label).toBe('9:00 PM'); }); }); describe('ageOn (the ID birthday math)', () => { const night = new Date('2026-07-18T00:00:00'); it('18th birthday IS tonight → 18 (they get in)', () => { expect(ageOn('2008-07-18', night)).toBe(18); }); it('18th birthday is tomorrow → 17 (denied, so close)', () => { expect(ageOn('2008-07-19', night)).toBe(17); }); it('birthday was yesterday → 18', () => { expect(ageOn('2008-07-17', night)).toBe(18); }); it('leap-day DOB counts the year correctly', () => { expect(ageOn('2008-02-29', night)).toBe(18); expect(ageOn('2008-02-29', new Date('2026-02-28T00:00:00'))).toBe(17); expect(ageOn('2008-02-29', new Date('2026-03-01T00:00:00'))).toBe(18); }); });