134 lines
4.0 KiB
TypeScript
134 lines
4.0 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import { buildTomorrowWeatherBrief, buildWeatherBrief } from "@/lib/weather-brief";
|
|
import type { WeatherForecast, HourlyForecast } from "@/types/forecast";
|
|
import type { WeatherWarning } from "@/types/imgw";
|
|
import { getWeatherCapabilities } from "@/types/weather-region";
|
|
|
|
function hour(overrides: Partial<HourlyForecast> = {}): HourlyForecast {
|
|
return {
|
|
time: "2026-06-14T08:00",
|
|
temperature: 10,
|
|
feelsLike: 9,
|
|
precipitationProbability: 20,
|
|
precipitation: 0,
|
|
weatherCode: 3,
|
|
windSpeed: 4,
|
|
source: "open-meteo",
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
function forecast(hours: HourlyForecast[]): WeatherForecast {
|
|
return {
|
|
latitude: 52.23,
|
|
longitude: 21.01,
|
|
region: "PL",
|
|
timezone: "Europe/Warsaw",
|
|
hourly: hours,
|
|
daily: [],
|
|
sources: ["open-meteo"],
|
|
capabilities: getWeatherCapabilities("PL"),
|
|
unavailableReasons: [],
|
|
};
|
|
}
|
|
|
|
function warning(overrides: Partial<WeatherWarning> = {}): WeatherWarning {
|
|
return {
|
|
id: "meteo-1",
|
|
kind: "meteo",
|
|
level: 2,
|
|
title: "Thunderstorms",
|
|
description: null,
|
|
comment: null,
|
|
validFrom: "2026-06-15T06:00:00.000Z",
|
|
validTo: "2026-06-15T18:00:00.000Z",
|
|
publishedAt: null,
|
|
probability: 80,
|
|
areas: [],
|
|
terytCodes: ["146501"],
|
|
provinces: ["mazowieckie"],
|
|
office: null,
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
describe("weather briefs", () => {
|
|
it("uses selected temperature, wind and precipitation units in the morning brief", () => {
|
|
const brief = buildWeatherBrief({
|
|
forecast: forecast([
|
|
hour({
|
|
time: "2026-06-14T08:00",
|
|
temperature: 10,
|
|
windSpeed: 4,
|
|
precipitationProbability: 80,
|
|
precipitation: 25.4,
|
|
}),
|
|
hour({ time: "2026-06-14T09:00", temperature: 12, windSpeed: 5, precipitationProbability: 30 }),
|
|
]),
|
|
warnings: [],
|
|
province: "mazowieckie",
|
|
countyTeryt: "1465",
|
|
locationName: "Warsaw",
|
|
language: "en",
|
|
temperatureUnit: "f",
|
|
windSpeedUnit: "mph",
|
|
precipitationUnit: "in",
|
|
now: new Date("2026-06-14T06:00:00.000Z"),
|
|
});
|
|
|
|
expect(brief).not.toBeNull();
|
|
expect(brief?.pushBody).toContain("50°F-54°F");
|
|
expect(brief?.pushBody).toContain("wind 11 mph");
|
|
expect(brief?.pushBody).not.toContain("km/h");
|
|
expect(brief?.body.join(" ")).toContain("1.00 in");
|
|
});
|
|
|
|
it("warns about tomorrow storms from model weather codes without IMGW warning", () => {
|
|
const brief = buildTomorrowWeatherBrief({
|
|
forecast: forecast([
|
|
hour({ time: "2026-06-15T08:00", temperature: 14, weatherCode: 3, precipitationProbability: 20 }),
|
|
hour({
|
|
time: "2026-06-15T15:00",
|
|
temperature: 21,
|
|
weatherCode: 95,
|
|
precipitationProbability: 30,
|
|
precipitation: 25.4,
|
|
}),
|
|
]),
|
|
warnings: [],
|
|
province: "mazowieckie",
|
|
countyTeryt: "1465",
|
|
locationName: "Warsaw",
|
|
language: "en",
|
|
precipitationUnit: "in",
|
|
now: new Date("2026-06-14T16:00:00.000Z"),
|
|
});
|
|
|
|
expect(brief?.severity).toBe("warning");
|
|
expect(brief?.headline).toBe("Thunderstorms are possible tomorrow");
|
|
expect(brief?.pushBody).toContain("thunderstorms");
|
|
expect(brief?.pushBody).toContain("1.00 in");
|
|
expect(brief?.pushBody).not.toContain("IMGW");
|
|
});
|
|
|
|
it("prefers relevant IMGW county warning over province-wide context", () => {
|
|
const brief = buildTomorrowWeatherBrief({
|
|
forecast: forecast([hour({ time: "2026-06-15T12:00", weatherCode: 3 })]),
|
|
warnings: [
|
|
warning({ title: "Radom storm", terytCodes: ["142501"] }),
|
|
warning({ title: "Warsaw storm", terytCodes: ["146501"] }),
|
|
],
|
|
province: "mazowieckie",
|
|
countyTeryt: "1465",
|
|
locationName: "Warsaw",
|
|
language: "en",
|
|
now: new Date("2026-06-14T16:00:00.000Z"),
|
|
});
|
|
|
|
expect(brief?.headline).toBe("Tomorrow: IMGW Warsaw storm");
|
|
expect(brief?.pushBody).toContain("IMGW: Warsaw storm");
|
|
expect(brief?.pushBody).not.toContain("Radom storm");
|
|
});
|
|
});
|