not-tonight/tests/clock.test.ts
2026-07-19 16:20:53 +10:00

70 lines
2.3 KiB
TypeScript

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);
});
});