package openmeteo import ( "encoding/json" "testing" "time" "gitea.maximumdirect.net/ejr/weatherfeeder/model" "gitea.maximumdirect.net/ejr/weatherfeeder/standards" ) func TestBuildForecastUsesCanonicalTextDescription(t *testing.T) { weatherCode := 2 isDay := 1 parsed := omForecastResponse{ Timezone: "UTC", UTCOffsetSeconds: 0, Hourly: omForecastHourly{ Time: []string{"2026-03-16T19:00"}, WeatherCode: []*int{&weatherCode}, IsDay: []*int{&isDay}, }, } run, effectiveAt, err := buildForecast(parsed, time.Time{}) if err != nil { t.Fatalf("buildForecast() error = %v", err) } if len(run.Periods) != 1 { t.Fatalf("periods len = %d, want 1", len(run.Periods)) } expectedText := standards.WMOText(model.WMOCode(weatherCode), boolPtr(true)) if got := run.Periods[0].TextDescription; got != expectedText { t.Fatalf("TextDescription = %q, want %q", got, expectedText) } wantIssued := time.Date(2026, 3, 16, 19, 0, 0, 0, time.UTC) if !run.IssuedAt.Equal(wantIssued) { t.Fatalf("IssuedAt = %s, want %s", run.IssuedAt.Format(time.RFC3339), wantIssued.Format(time.RFC3339)) } if !effectiveAt.Equal(wantIssued) { t.Fatalf("effectiveAt = %s, want %s", effectiveAt.Format(time.RFC3339), wantIssued.Format(time.RFC3339)) } assertNoLegacyForecastDescriptionKeys(t, run.Periods[0]) } func boolPtr(v bool) *bool { return &v } func assertNoLegacyForecastDescriptionKeys(t *testing.T, period any) { t.Helper() b, err := json.Marshal(period) if err != nil { t.Fatalf("json.Marshal(period) error = %v", err) } var got map[string]any if err := json.Unmarshal(b, &got); err != nil { t.Fatalf("json.Unmarshal(period) error = %v", err) } for _, key := range []string{"conditionText", "providerRawDescription", "detailedText", "iconUrl"} { if _, ok := got[key]; ok { t.Fatalf("unexpected legacy key %q in marshaled period: %#v", key, got) } } }