Implement alert instruction whitespace normalization
This commit is contained in:
@@ -492,7 +492,7 @@ func parseAlert(raw json.RawMessage) (parsedAlert, bool) {
|
||||
Headline: firstStringField(fields, "headline", "title"),
|
||||
Severity: stringField(fields, "severity"),
|
||||
Description: stringField(fields, "description"),
|
||||
Instruction: stringField(fields, "instruction"),
|
||||
Instruction: collapseWhitespace(stringField(fields, "instruction")),
|
||||
}
|
||||
start, startOK := firstTimeField(fields, "onset", "startsAt", "startTime", "effective", "sent")
|
||||
end, endOK := firstTimeField(fields, "ends", "endsAt", "endTime", "expires")
|
||||
@@ -542,6 +542,10 @@ func firstTimeField(fields map[string]json.RawMessage, names ...string) (time.Ti
|
||||
return time.Time{}, false
|
||||
}
|
||||
|
||||
func collapseWhitespace(value string) string {
|
||||
return strings.Join(strings.Fields(value), " ")
|
||||
}
|
||||
|
||||
func intersect(left timeutil.Period, right timeutil.Period) timeutil.Period {
|
||||
start := left.Start
|
||||
if right.Start.After(start) {
|
||||
|
||||
@@ -211,7 +211,7 @@ func TestAlertOverlap(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAlertOverlapUsesOnsetAndEnds(t *testing.T) {
|
||||
raw := json.RawMessage(`{"event":"Wind Advisory","headline":"Wind Advisory issued June 16 at 12:39PM CDT until June 17 at 8:00PM CDT by NWS St Louis MO","severity":"Moderate","description":"Southwest winds 20 to 30 mph with gusts up to 45 mph expected.","instruction":"Secure outdoor objects.","effective":"2026-06-16T17:39:00Z","onset":"2026-06-17T18:00:00Z","ends":"2026-06-18T01:00:00Z","expires":"2026-06-17T08:45:00Z"}`)
|
||||
raw := json.RawMessage(`{"event":"Wind Advisory","headline":"Wind Advisory issued June 16 at 12:39PM CDT until June 17 at 8:00PM CDT by NWS St Louis MO","severity":"Moderate","description":"Southwest winds 20 to 30 mph with gusts up to 45 mph expected.","instruction":"Secure outdoor objects.\n\nUse extra\tcaution.","effective":"2026-06-16T17:39:00Z","onset":"2026-06-17T18:00:00Z","ends":"2026-06-18T01:00:00Z","expires":"2026-06-17T08:45:00Z"}`)
|
||||
alertRun := &weatherdata.AlertRun{Alerts: []json.RawMessage{raw}}
|
||||
period := timeutil.Period{
|
||||
Start: mustParse("2026-06-17T12:00:00-05:00"),
|
||||
@@ -237,11 +237,34 @@ func TestAlertOverlapUsesOnsetAndEnds(t *testing.T) {
|
||||
if overlaps[0].Description != "Southwest winds 20 to 30 mph with gusts up to 45 mph expected." {
|
||||
t.Fatalf("Description = %q, want preserved description", overlaps[0].Description)
|
||||
}
|
||||
if overlaps[0].Instruction != "Secure outdoor objects." {
|
||||
if overlaps[0].Instruction != "Secure outdoor objects. Use extra caution." {
|
||||
t.Fatalf("Instruction = %q, want preserved instruction", overlaps[0].Instruction)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCollapseWhitespace(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
value string
|
||||
want string
|
||||
}{
|
||||
{name: "newlines", value: "Secure outdoor objects.\nUse extra caution.", want: "Secure outdoor objects. Use extra caution."},
|
||||
{name: "crlf", value: "Secure outdoor objects.\r\nUse extra caution.", want: "Secure outdoor objects. Use extra caution."},
|
||||
{name: "tabs and repeated spaces", value: "Secure\toutdoor objects.", want: "Secure outdoor objects."},
|
||||
{name: "leading trailing", value: " Secure outdoor objects. ", want: "Secure outdoor objects."},
|
||||
{name: "empty", value: "", want: ""},
|
||||
{name: "all whitespace", value: " \n\t\r\n ", want: ""},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := collapseWhitespace(tt.value); got != tt.want {
|
||||
t.Fatalf("collapseWhitespace(%q) = %q, want %q", tt.value, got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAlertOverlapUsesOnsetAndEndsForLocalDateRelevance(t *testing.T) {
|
||||
location, err := time.LoadLocation("America/Chicago")
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user