124 lines
3.9 KiB
Go
124 lines
3.9 KiB
Go
package changes
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"gitea.maximumdirect.net/eric/weatherreporter/internal/briefing"
|
|
"gitea.maximumdirect.net/eric/weatherreporter/internal/forecast"
|
|
)
|
|
|
|
func TestCompareDailyNoMeaningfulChanges(t *testing.T) {
|
|
previous := dailyBriefing(60, 70, 30, at("2026-05-29T08:00:00Z"), nil, forecast.Indicators{})
|
|
current := dailyBriefing(61, 71, 35, at("2026-05-29T08:30:00Z"), nil, forecast.Indicators{})
|
|
|
|
changes, err := CompareDaily(previous, current, testThresholds())
|
|
if err != nil {
|
|
t.Fatalf("CompareDaily() error = %v", err)
|
|
}
|
|
if len(changes) != 0 {
|
|
t.Fatalf("changes = %#v, want none", changes)
|
|
}
|
|
}
|
|
|
|
func TestCompareDailyTemperatureThreshold(t *testing.T) {
|
|
previous := dailyBriefing(50, 70, 10, at("2026-05-29T08:00:00Z"), nil, forecast.Indicators{})
|
|
current := dailyBriefing(58, 79, 10, at("2026-05-29T08:00:00Z"), nil, forecast.Indicators{})
|
|
|
|
changes, err := CompareDaily(previous, current, testThresholds())
|
|
if err != nil {
|
|
t.Fatalf("CompareDaily() error = %v", err)
|
|
}
|
|
if countType(changes, "temperature_shift") != 2 {
|
|
t.Fatalf("changes = %#v, want low and high temperature changes", changes)
|
|
}
|
|
}
|
|
|
|
func TestCompareDailyPrecipTimingShift(t *testing.T) {
|
|
previous := dailyBriefing(60, 70, 60, at("2026-05-29T08:00:00Z"), nil, forecast.Indicators{})
|
|
current := dailyBriefing(60, 70, 60, at("2026-05-29T11:00:00Z"), nil, forecast.Indicators{})
|
|
|
|
changes, err := CompareDaily(previous, current, testThresholds())
|
|
if err != nil {
|
|
t.Fatalf("CompareDaily() error = %v", err)
|
|
}
|
|
if countType(changes, "precip_timing_shift") != 1 {
|
|
t.Fatalf("changes = %#v, want timing shift", changes)
|
|
}
|
|
}
|
|
|
|
func TestCompareDailyAlertAddedAndRemoved(t *testing.T) {
|
|
previous := dailyBriefing(60, 70, 10, at("2026-05-29T08:00:00Z"), []string{"Wind Advisory"}, forecast.Indicators{})
|
|
current := dailyBriefing(60, 70, 10, at("2026-05-29T08:00:00Z"), []string{"Flood Watch"}, forecast.Indicators{})
|
|
|
|
changes, err := CompareDaily(previous, current, testThresholds())
|
|
if err != nil {
|
|
t.Fatalf("CompareDaily() error = %v", err)
|
|
}
|
|
if countType(changes, "alert_added") != 1 || countType(changes, "alert_removed") != 1 {
|
|
t.Fatalf("changes = %#v, want one alert added and one removed", changes)
|
|
}
|
|
}
|
|
|
|
func TestCompareDailyIndicatorChange(t *testing.T) {
|
|
previous := dailyBriefing(60, 70, 10, at("2026-05-29T08:00:00Z"), nil, forecast.Indicators{})
|
|
current := dailyBriefing(60, 70, 10, at("2026-05-29T08:00:00Z"), nil, forecast.Indicators{Snow: true})
|
|
|
|
changes, err := CompareDaily(previous, current, testThresholds())
|
|
if err != nil {
|
|
t.Fatalf("CompareDaily() error = %v", err)
|
|
}
|
|
if countType(changes, "snow_risk_change") != 1 {
|
|
t.Fatalf("changes = %#v, want snow risk change", changes)
|
|
}
|
|
}
|
|
|
|
func dailyBriefing(low float64, high float64, precip float64, precipTime time.Time, alerts []string, indicators forecast.Indicators) briefing.Package {
|
|
alertOverlaps := make([]forecast.AlertOverlap, 0, len(alerts))
|
|
for _, alert := range alerts {
|
|
alertOverlaps = append(alertOverlaps, forecast.AlertOverlap{Event: alert})
|
|
}
|
|
return briefing.Package{
|
|
Daily: &briefing.Daily{
|
|
BottomLine: briefing.BottomLine{
|
|
Temperature: forecast.Range{Min: &low, Max: &high},
|
|
MaxPrecipProbability: &forecast.TimedValue{
|
|
Value: precip,
|
|
Time: precipTime,
|
|
},
|
|
},
|
|
RelevantAlerts: alertOverlaps,
|
|
Dayparts: []forecast.DaypartSummary{
|
|
{Name: "morning", Indicators: indicators},
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func testThresholds() Thresholds {
|
|
return Thresholds{
|
|
TemperatureDegrees: 5,
|
|
PrecipProbabilityPoints: 20,
|
|
WindGustMilesPerHour: 10,
|
|
PrecipTimingShiftMinutes: 120,
|
|
}
|
|
}
|
|
|
|
func countType(changes []Change, changeType string) int {
|
|
var count int
|
|
for _, change := range changes {
|
|
if change.Type == changeType {
|
|
count++
|
|
}
|
|
}
|
|
return count
|
|
}
|
|
|
|
func at(value string) time.Time {
|
|
parsed, err := time.Parse(time.RFC3339, value)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return parsed
|
|
}
|