70 lines
3.0 KiB
TypeScript
70 lines
3.0 KiB
TypeScript
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<string, AirportWeather>();
|
||
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);
|
||
});
|
||
});
|