import { describe, expect, it } from 'vitest'; import { weatherFor, type AirportWeather } from './weather'; const CONDITIONS = ['Clear', 'Cloudy', 'Rain', 'Fog']; describe('weatherFor', () => { it('is deterministic: same ICAO → identical weather on every call', () => { const a = weatherFor('EDDF'); for (let i = 0; i < 5; i++) expect(weatherFor('EDDF')).toEqual(a); }); it('different ICACOs mostly produce different weather', () => { const icaos = ['EDDF', 'EHAM', 'LFPG', 'LEMD', 'LIRF', 'EKCH', 'LSGG', 'BIAR', 'LFRS', 'EDDV']; const seen = new Set(icaos.map((i) => JSON.stringify(weatherFor(i)))); // 10 airports, 4 conditions × many wind/visibility values — collisions are vanishingly unlikely. expect(seen.size).toBeGreaterThanOrEqual(8); }); it('keeps every value in a sane range', () => { for (const icao of ['EDDF', 'EHAM', 'LFPG', 'LEMD', 'LIRF', 'EKCH', 'LSGG', 'BIAR']) { const w = weatherFor(icao); expect(CONDITIONS).toContain(w.condition); expect(w.windDirDeg).toBeGreaterThanOrEqual(0); expect(w.windDirDeg).toBeLessThan(360); expect(Number.isInteger(w.windDirDeg)).toBe(true); expect(w.windKt).toBeGreaterThanOrEqual(2); expect(w.windKt).toBeLessThanOrEqual(30); expect(w.visibilityM).toBeGreaterThan(0); } }); it('fog and rain reduce visibility relative to clear skies', () => { // Find one airport per condition by scanning a fixed set (deterministic data). const byCondition = new Map(); for (let i = 0; i < 200 && byCondition.size < CONDITIONS.length; i++) { const w = weatherFor(`TEST${i}`); if (!byCondition.has(w.condition)) byCondition.set(w.condition, w); } expect(byCondition.size).toBe(CONDITIONS.length); const fog = byCondition.get('Fog')!; const rain = byCondition.get('Rain')!; const clear = byCondition.get('Clear')!; expect(fog.visibilityM).toBeLessThan(2500); // 0.5–2 km band expect(rain.visibilityM).toBeGreaterThanOrEqual(4000); expect(rain.visibilityM).toBeLessThanOrEqual(10_000); expect(clear.visibilityM).toBeGreaterThanOrEqual(8000); }); it('dayKey: same day is deterministic, and some airports do change across days', () => { const icaos = ['EDDF', 'EHAM', 'LFPG', 'LEMD', 'LIRF']; for (const icao of icaos) { expect(weatherFor(icao, 3)).toEqual(weatherFor(icao, 3)); } let changed = 0; for (let i = 0; i < 50; i++) { const a = weatherFor(`TEST${i}`, 1); const b = weatherFor(`TEST${i}`, 2); if (JSON.stringify(a) !== JSON.stringify(b)) changed++; } expect(changed).toBeGreaterThan(0); // the dayKey actually feeds the seed }); it('no dayKey is stable and independent of any later dayKey argument', () => { const w = weatherFor('EDDF'); expect(weatherFor('EDDF')).toEqual(w); // A defined dayKey may differ from the default — that is allowed, not asserted. expect(CONDITIONS).toContain(weatherFor('EDDF', 0).condition); }); });