diff --git a/internal/adapters/inbound/httpapi/endpoints_test.go b/internal/adapters/inbound/httpapi/endpoints_test.go index 4d34559..d354e1f 100644 --- a/internal/adapters/inbound/httpapi/endpoints_test.go +++ b/internal/adapters/inbound/httpapi/endpoints_test.go @@ -1361,6 +1361,9 @@ func TestCurrentConditionsMetricDefaultJSON(t *testing.T) { if payload.Data["conditionText"] != "Rain" { t.Fatalf("expected conditionText Rain, got %#v", payload.Data["conditionText"]) } + if payload.Data["conditionCode"] != float64(63) { + t.Fatalf("expected conditionCode 63, got %#v", payload.Data["conditionCode"]) + } } func TestCurrentConditionsUSJSON(t *testing.T) { @@ -1426,6 +1429,9 @@ func TestCurrentConditionsXMLAndTextFormats(t *testing.T) { if !strings.Contains(w.Body.String(), "temperatureF") { t.Fatalf("expected US field temperatureF in XML payload: %s", w.Body.String()) } + if !strings.Contains(w.Body.String(), "2") { + t.Fatalf("expected conditionCode in XML payload: %s", w.Body.String()) + } w = httptest.NewRecorder() req = httptest.NewRequest(http.MethodGet, "/conditions/current?format=TEXT", nil) @@ -1437,7 +1443,7 @@ func TestCurrentConditionsXMLAndTextFormats(t *testing.T) { if !strings.Contains(w.Header().Get("Content-Type"), "text/plain") { t.Fatalf("expected text/plain content type, got %q", w.Header().Get("Content-Type")) } - if !strings.Contains(w.Body.String(), "Conditions text") { + if !strings.Contains(w.Body.String(), "Condition Code: 2") { t.Fatalf("expected rendered text template body, got %q", w.Body.String()) } } @@ -2458,7 +2464,7 @@ func testRenderers(t *testing.T) *render.Registry { "weatherstories.txt.tmpl": "Weather Stories", "weatherstories_latest.txt.tmpl": "Latest Weather Story", "alerts_active.txt.tmpl": "{{if .Data}}Active Alerts\nAlerts: {{len .Data.Alerts}}{{range .Data.Alerts}}\n{{.ID}}{{if .Headline}}\nHeadline: {{.Headline}}{{end}}{{if .Ends}}\nEnds: {{.Ends}}{{end}}{{end}}{{else}}No active alerts data available.{{end}}", - "conditions_current.txt.tmpl": "Conditions text", + "conditions_current.txt.tmpl": "Condition Code: {{.Data.ConditionCode}}", } { tmpl, err := template.New(name).Parse(body) if err != nil { diff --git a/internal/adapters/inbound/httpapi/presenter/conditions.go b/internal/adapters/inbound/httpapi/presenter/conditions.go index 6421b94..1bb1520 100644 --- a/internal/adapters/inbound/httpapi/presenter/conditions.go +++ b/internal/adapters/inbound/httpapi/presenter/conditions.go @@ -4,25 +4,27 @@ package presenter import ( "gitea.maximumdirect.net/ejr/weatherapi/internal/app" + "gitea.maximumdirect.net/ejr/weatherfeeder/model" "gitea.maximumdirect.net/ejr/weatherfeeder/standards" ) // CurrentConditionsResponse is the response shape for /conditions/current. // Unit-bearing fields are populated according to the requested unit mode. type CurrentConditionsResponse struct { - TemperatureC *float64 `json:"temperatureC,omitempty" xml:"temperatureC,omitempty"` - ApparentTemperatureC *float64 `json:"apparentTemperatureC,omitempty" xml:"apparentTemperatureC,omitempty"` - DewpointC *float64 `json:"dewpointC,omitempty" xml:"dewpointC,omitempty"` - WindSpeedKmh *float64 `json:"windSpeedKmh,omitempty" xml:"windSpeedKmh,omitempty"` - TemperatureF *float64 `json:"temperatureF,omitempty" xml:"temperatureF,omitempty"` - ApparentTemperatureF *float64 `json:"apparentTemperatureF,omitempty" xml:"apparentTemperatureF,omitempty"` - DewpointF *float64 `json:"dewpointF,omitempty" xml:"dewpointF,omitempty"` - WindSpeedMph *float64 `json:"windSpeedMph,omitempty" xml:"windSpeedMph,omitempty"` - RelativeHumidityPercent *float64 `json:"relativeHumidityPercent,omitempty" xml:"relativeHumidityPercent,omitempty"` - WindDirectionDegrees *float64 `json:"windDirectionDegrees,omitempty" xml:"windDirectionDegrees,omitempty"` - ConditionText string `json:"conditionText,omitempty" xml:"conditionText,omitempty"` - IsDay *bool `json:"isDay,omitempty" xml:"isDay,omitempty"` - IsDayText string `json:"-" xml:"-"` + TemperatureC *float64 `json:"temperatureC,omitempty" xml:"temperatureC,omitempty"` + ApparentTemperatureC *float64 `json:"apparentTemperatureC,omitempty" xml:"apparentTemperatureC,omitempty"` + DewpointC *float64 `json:"dewpointC,omitempty" xml:"dewpointC,omitempty"` + WindSpeedKmh *float64 `json:"windSpeedKmh,omitempty" xml:"windSpeedKmh,omitempty"` + TemperatureF *float64 `json:"temperatureF,omitempty" xml:"temperatureF,omitempty"` + ApparentTemperatureF *float64 `json:"apparentTemperatureF,omitempty" xml:"apparentTemperatureF,omitempty"` + DewpointF *float64 `json:"dewpointF,omitempty" xml:"dewpointF,omitempty"` + WindSpeedMph *float64 `json:"windSpeedMph,omitempty" xml:"windSpeedMph,omitempty"` + RelativeHumidityPercent *float64 `json:"relativeHumidityPercent,omitempty" xml:"relativeHumidityPercent,omitempty"` + WindDirectionDegrees *float64 `json:"windDirectionDegrees,omitempty" xml:"windDirectionDegrees,omitempty"` + ConditionCode model.WMOCode `json:"conditionCode" xml:"conditionCode"` + ConditionText string `json:"conditionText,omitempty" xml:"conditionText,omitempty"` + IsDay *bool `json:"isDay,omitempty" xml:"isDay,omitempty"` + IsDayText string `json:"-" xml:"-"` } func CurrentConditionsPayload(conditions *app.CurrentConditions, units Units, precision int) any { @@ -33,6 +35,7 @@ func CurrentConditionsPayload(conditions *app.CurrentConditions, units Units, pr out := CurrentConditionsResponse{ RelativeHumidityPercent: roundedPtr(copyFloat64Ptr(conditions.RelativeHumidityPercent), precision), WindDirectionDegrees: roundedPtr(copyFloat64Ptr(conditions.WindDirectionDegrees), precision), + ConditionCode: conditions.ConditionCode, ConditionText: standards.WMOText(conditions.ConditionCode, conditions.IsDay), IsDay: copyBoolPtr(conditions.IsDay), IsDayText: boolText(conditions.IsDay), diff --git a/internal/adapters/inbound/httpapi/presenter/payload_test.go b/internal/adapters/inbound/httpapi/presenter/payload_test.go index 6e01597..f41e722 100644 --- a/internal/adapters/inbound/httpapi/presenter/payload_test.go +++ b/internal/adapters/inbound/httpapi/presenter/payload_test.go @@ -378,6 +378,9 @@ func TestCurrentConditionsPayloadMetricAndUS(t *testing.T) { if metric.ConditionText != "Sunny" { t.Fatalf("expected condition text Sunny, got %q", metric.ConditionText) } + if metric.ConditionCode != 0 { + t.Fatalf("expected condition code 0, got %d", metric.ConditionCode) + } usPayload := CurrentConditionsPayload(conditions, UnitsUS, 2) us, ok := usPayload.(CurrentConditionsResponse) @@ -389,6 +392,9 @@ func TestCurrentConditionsPayloadMetricAndUS(t *testing.T) { if us.TemperatureC != nil || us.WindSpeedKmh != nil { t.Fatalf("expected metric fields omitted for US payload") } + if us.ConditionCode != 0 { + t.Fatalf("expected condition code 0, got %d", us.ConditionCode) + } } func TestCurrentConditionsPayloadUsesNightConditionText(t *testing.T) { diff --git a/templates/conditions_current.txt.tmpl b/templates/conditions_current.txt.tmpl index eaaa5b2..a9c6566 100644 --- a/templates/conditions_current.txt.tmpl +++ b/templates/conditions_current.txt.tmpl @@ -1,5 +1,6 @@ {{- if .Data -}} Current Conditions +Condition Code: {{.Data.ConditionCode}} {{- if .Data.ConditionText}} Condition: {{.Data.ConditionText}} {{- end}}