UNPKG

flight-planner

Version:

Plan and route VFR flights

321 lines (320 loc) 13.1 kB
import { metarFlightRule, metarFlightRuleColor, metarColorCode, metarCeiling, } from './metar.js'; import { formatClouds, formatTemperature, formatVisibility, formatWind } from './format.js'; import { FlightRules } from './index.js'; describe('Metar functions', () => { describe('metarFlightRule', () => { it('should return VFR for good weather conditions', () => { const metarData = { station: 'TEST', observationTime: new Date(), raw: 'RAW DATA', wind: { direction: 180, speed: 10 }, visibility: { value: 10000, unit: 'm' }, clouds: [{ quantity: 'FEW', height: 5000 }] }; expect(metarFlightRule(metarData)).toBe(FlightRules.VFR); }); it('should return LIFR for very poor visibility', () => { const metarData = { station: 'TEST', observationTime: new Date(), raw: 'RAW DATA', wind: { direction: 180, speed: 10 }, visibility: { value: 800, unit: 'm' } }; expect(metarFlightRule(metarData)).toBe(FlightRules.LIFR); }); it('should return LIFR for very low ceiling', () => { const metarData = { station: 'TEST', observationTime: new Date(), raw: 'RAW DATA', wind: { direction: 180, speed: 10 }, clouds: [{ quantity: 'OVC', height: 300 }] }; expect(metarFlightRule(metarData)).toBe(FlightRules.LIFR); }); }); describe('metarFlightRuleColor', () => { it('should return "green" for VFR', () => { const metarData = { station: 'TEST', observationTime: new Date(), raw: 'RAW DATA', wind: { direction: 180, speed: 10 }, visibility: { value: 10000, unit: 'm' }, clouds: [{ quantity: 'FEW', height: 5000 }] }; expect(metarFlightRuleColor(metarData)).toBe('green'); }); it('should return "purple" for LIFR', () => { const metarData = { station: 'TEST', observationTime: new Date(), raw: 'RAW DATA', wind: { direction: 180, speed: 10 }, visibility: { value: 800, unit: 'm' } }; expect(metarFlightRuleColor(metarData)).toBe('purple'); }); it('should return "red" for IFR', () => { const metarData = { station: 'TEST', observationTime: new Date(), raw: 'RAW DATA', wind: { direction: 180, speed: 10 }, visibility: { value: 4000, unit: 'm' }, clouds: [{ quantity: 'OVC', height: 700 }] }; expect(metarFlightRuleColor(metarData)).toBe('red'); }); it('should return "blue" for MVFR', () => { const metarData = { station: 'TEST', observationTime: new Date(), raw: 'RAW DATA', wind: { direction: 180, speed: 10 }, clouds: [{ quantity: 'OVC', height: 2500 }] }; expect(metarFlightRuleColor(metarData)).toBe('blue'); }); }); describe('metarColorCode', () => { it('should return "red" for very hazardous conditions', () => { const metarData = { station: 'TEST', observationTime: new Date(), raw: 'RAW DATA', wind: { direction: 180, speed: 45 }, visibility: { value: 1000, unit: 'm' } }; expect(metarColorCode(metarData)).toBe('red'); }); it('should return "amber" for hazardous conditions', () => { const metarData = { station: 'TEST', observationTime: new Date(), raw: 'RAW DATA', wind: { direction: 180, speed: 32 }, visibility: { value: 1500, unit: 'm' } }; expect(metarColorCode(metarData)).toBe('amber'); }); it('should return "yellow" for significant deterioration', () => { const metarData = { station: 'TEST', observationTime: new Date(), raw: 'RAW DATA', wind: { direction: 180, speed: 22 }, clouds: [{ quantity: 'BKN', height: 650 }] }; expect(metarColorCode(metarData)).toBe('yellow'); }); it('should return "blue" for minor deterioration', () => { const metarData = { station: 'TEST', observationTime: new Date(), raw: 'RAW DATA', wind: { direction: 180, speed: 16 }, clouds: [{ quantity: 'BKN', height: 1400 }] }; expect(metarColorCode(metarData)).toBe('blue'); }); it('should return "green" for normal operations', () => { const metarData = { station: 'TEST', observationTime: new Date(), raw: 'RAW DATA', wind: { direction: 180, speed: 10 }, visibility: { value: 8000, unit: 'm' }, clouds: [{ quantity: 'FEW', height: 3500 }] }; expect(metarColorCode(metarData)).toBe('green'); }); it('should handle wind gusts correctly', () => { const metarData = { station: 'TEST', observationTime: new Date(), raw: 'RAW DATA', wind: { direction: 180, speed: 15, gust: 35 }, visibility: { value: 8000, unit: 'm' } }; expect(metarColorCode(metarData)).toBe('yellow'); }); it('should handle visibility in statute miles', () => { const metarData = { station: 'TEST', observationTime: new Date(), raw: 'RAW DATA', wind: { direction: 180, speed: 10 }, visibility: { value: 0.75, unit: 'sm' } // Roughly 1200m }; expect(metarColorCode(metarData)).toBe('amber'); }); }); // describe('formatMetarQNH', () => { // it('should return formatted QNH when present', () => { // const metarData: Metar = { // station: 'TEST', // observationTime: new Date(), // raw: 'RAW DATA', // wind: { direction: 180, speed: 10 }, // qnh: { value: 1013, unit: 'hPa' } // }; // expect(formatPressure(metarData.qnh?.value!)).toBe('1013 hPa'); // }); // it('should return formatted QNH in inches when present', () => { // const metarData: Metar = { // station: 'TEST', // observationTime: new Date(), // raw: 'RAW DATA', // wind: { direction: 180, speed: 10 }, // qnh: { value: 29.92, unit: 'inHg' } // }; // expect(formatMetarQNH(metarData)).toBe('29.92 inHg'); // }); // }); describe('metarCeiling', () => { // it('should return "No ceiling" when no clouds are present', () => { // const metarData: Metar = { // station: 'TEST', // observationTime: new Date(), // raw: 'RAW DATA', // wind: { direction: 180, speed: 10 }, // }; // expect(formatMetarCeiling(metarData)).toBe('-'); // }); it('should return formatted ceiling when clouds are present', () => { const metarData = { station: 'TEST', observationTime: new Date(), raw: 'RAW DATA', wind: { direction: 180, speed: 10 }, clouds: [{ quantity: 'BKN', height: 3000 }] }; expect(metarCeiling(metarData)).toBe(3000); }); }); describe('formatMetarWind', () => { it('should return "Calm" when windDirection is not defined', () => { const metarData = { station: 'TEST', observationTime: new Date(), raw: 'RAW DATA', wind: { direction: 0, speed: 0 }, }; expect(formatWind(metarData.wind)).toBe('Calm'); }); it('should return wind direction and speed when windDirection and windSpeed are defined', () => { const metarData = { station: 'TEST', observationTime: new Date(), raw: 'RAW DATA', wind: { direction: 180, speed: 10 }, }; expect(formatWind(metarData.wind)).toBe('180° with 10kt'); }); it('should include gusting wind speed when windGust is defined', () => { const metarData = { station: 'TEST', observationTime: new Date(), raw: 'RAW DATA', wind: { direction: 180, speed: 10, gust: 20 }, }; expect(formatWind(metarData.wind)).toBe('180° with 10kt gusting 20kt'); }); it('should include variable wind direction when windDirection is an array', () => { const metarData = { station: 'TEST', observationTime: new Date(), raw: 'RAW DATA', wind: { direction: 350, speed: 12, directionMin: 340, directionMax: 360 }, }; expect(formatWind(metarData.wind)).toBe('350° with 12kt variable between 340° and 360°'); }); }); describe('formatMetarVisibility', () => { it('should return formatted visibility when present', () => { const metarData = { station: 'TEST', observationTime: new Date(), raw: 'RAW DATA', wind: { direction: 180, speed: 10 }, visibility: { value: 9999, unit: 'm' } }; expect(formatVisibility(metarData.visibility)).toBe('10 km+'); }); // it('should handle CAVOK condition correctly', () => { // const metarData: Metar = { // station: 'TEST', // observationTime: new Date(), // raw: 'EGLL 291020Z 24015KT CAVOK 18/09 Q1022', // wind: { direction: 240, speed: 15 }, // }; // expect(formatVisibility(metarData.visibility!)).toBe('10 km+'); // }); }); describe('formatMetarTemperature', () => { it('should return formatted temperature when present', () => { const metarData = { station: 'TEST', observationTime: new Date(), raw: 'RAW DATA', wind: { direction: 180, speed: 10 }, temperature: 23 }; expect(formatTemperature(metarData.temperature)).toBe('23°C'); }); }); describe('formatMetarDewpoint', () => { it('should return formatted dew point when present', () => { const metarData = { station: 'TEST', observationTime: new Date(), raw: 'RAW DATA', wind: { direction: 180, speed: 10 }, dewpoint: 15 }; expect(formatTemperature(metarData.dewpoint)).toBe('15°C'); }); }); describe('formatMetarClouds', () => { it('should return formatted clouds when present', () => { const metarData = { station: 'TEST', observationTime: new Date(), raw: 'RAW DATA', wind: { direction: 180, speed: 10 }, clouds: [{ quantity: 'BKN', height: 3000 }] }; expect(formatClouds(metarData.clouds)).toBe('Broken at 3000 ft'); }); it('should return formatted clouds with multiple layers', () => { const metarData = { station: 'TEST', observationTime: new Date(), raw: 'RAW DATA', wind: { direction: 180, speed: 10 }, clouds: [ { quantity: 'BKN', height: 3000 }, { quantity: 'OVC', height: 5000 } ] }; expect(formatClouds(metarData.clouds)).toBe('Broken at 3000 ft, Overcast at 5000 ft'); }); it('should return formatted clouds with different quantities', () => { const metarData = { station: 'TEST', observationTime: new Date(), raw: 'RAW DATA', wind: { direction: 180, speed: 10 }, clouds: [ { quantity: 'FEW', height: 1000 }, { quantity: 'SCT', height: 2000 }, { quantity: 'BKN', height: 3000 } ] }; expect(formatClouds(metarData.clouds)).toBe('Few at 1000 ft, Scattered at 2000 ft, Broken at 3000 ft'); }); }); });