import { describe, expect, it, vi } from 'vitest'; import { BROADCAST_ADDR } from '../mesh/codec.js'; import type { MeshService } from '../mesh/mesh.service.js'; import { WeatherService } from './weather.service.js'; const CURRENT = { temperature_2m: 18.4, apparent_temperature: 16.9, relative_humidity_2m: 65.2, wind_speed_10m: 12.3, weather_code: 2, }; const EXPECTED_REPORT = 'Lublin weather: 18°C (feels 17), partly cloudy, humidity 65%, wind 12 km/h'; describe('WeatherService formatReport', () => { it('formats a one-line report from the current-weather payload', () => { const svc = new WeatherService({} as MeshService); expect(svc.formatReport(CURRENT)).toBe(EXPECTED_REPORT); }); it('falls back to `code ` for unknown WMO codes', () => { const svc = new WeatherService({} as MeshService); expect(svc.formatReport({ ...CURRENT, weather_code: 99 })).toBe( EXPECTED_REPORT.replace('partly cloudy', 'code 99'), ); }); }); describe('WeatherService cron report', () => { it('fetches and broadcasts the formatted report on success', async () => { const sendText = vi.fn(async (..._args: unknown[]) => 1); const fetchMock = vi.fn(async (..._args: unknown[]) => ({ ok: true, json: async () => ({ current: CURRENT }), })); vi.stubGlobal('fetch', fetchMock); try { const svc = new WeatherService({ sendText } as unknown as MeshService); await svc.report(); expect(fetchMock).toHaveBeenCalledTimes(1); const url = String(fetchMock.mock.calls[0][0]); expect(url.startsWith('https://api.open-meteo.com/v1/forecast?')).toBe( true, ); expect(url).toContain('latitude=51.2465'); expect(url).toContain('longitude=22.5684'); expect(sendText).toHaveBeenCalledTimes(1); expect(sendText).toHaveBeenCalledWith(BROADCAST_ADDR, EXPECTED_REPORT); } finally { vi.unstubAllGlobals(); } }); it('does not send and does not throw when the fetch fails', async () => { const sendText = vi.fn(async (..._args: unknown[]) => 1); vi.stubGlobal( 'fetch', vi.fn(async () => { throw new Error('network down'); }), ); try { const svc = new WeatherService({ sendText } as unknown as MeshService); await expect(svc.report()).resolves.toBeUndefined(); expect(sendText).not.toHaveBeenCalled(); } finally { vi.unstubAllGlobals(); } }); });