Filter outlook discussions with retained outlooks
This commit is contained in:
@@ -85,6 +85,7 @@ func (s *Service) LatestConvectiveOutlook(ctx context.Context, filter OutlookFil
|
||||
}
|
||||
}
|
||||
out.Outlooks = outlooks
|
||||
out.Discussions = filterOutlookDiscussions(out.Discussions, out.Outlooks)
|
||||
return out, nil
|
||||
}
|
||||
|
||||
@@ -123,6 +124,12 @@ func cloneOutlookRun(run *model.WeatherOutlookRun) *model.WeatherOutlookRun {
|
||||
out.Outlooks[i] = cloneOutlook(run.Outlooks[i])
|
||||
}
|
||||
}
|
||||
if run.Discussions != nil {
|
||||
out.Discussions = make([]model.WeatherOutlookDiscussion, len(run.Discussions))
|
||||
for i := range run.Discussions {
|
||||
out.Discussions[i] = cloneOutlookDiscussion(run.Discussions[i])
|
||||
}
|
||||
}
|
||||
return &out
|
||||
}
|
||||
|
||||
@@ -135,6 +142,31 @@ func cloneOutlook(outlook model.WeatherOutlook) model.WeatherOutlook {
|
||||
return out
|
||||
}
|
||||
|
||||
func cloneOutlookDiscussion(discussion model.WeatherOutlookDiscussion) model.WeatherOutlookDiscussion {
|
||||
out := discussion
|
||||
out.UpdatedAt = copyTime(discussion.UpdatedAt)
|
||||
return out
|
||||
}
|
||||
|
||||
func filterOutlookDiscussions(discussions []model.WeatherOutlookDiscussion, outlooks []model.WeatherOutlook) []model.WeatherOutlookDiscussion {
|
||||
if len(outlooks) == 0 {
|
||||
return []model.WeatherOutlookDiscussion{}
|
||||
}
|
||||
|
||||
retainedDays := make(map[int]struct{}, len(outlooks))
|
||||
for _, outlook := range outlooks {
|
||||
retainedDays[outlook.Day] = struct{}{}
|
||||
}
|
||||
|
||||
out := discussions[:0]
|
||||
for _, discussion := range discussions {
|
||||
if _, ok := retainedDays[discussion.Day]; ok {
|
||||
out = append(out, discussion)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func copyFloat64(value *float64) *float64 {
|
||||
if value == nil {
|
||||
return nil
|
||||
|
||||
@@ -5,6 +5,7 @@ package app
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -131,6 +132,7 @@ func TestServiceDelegatesLatestConvectiveOutlookRun(t *testing.T) {
|
||||
if run == nil || run.LocationID != "stl" {
|
||||
t.Fatalf("unexpected outlook run: %+v", run)
|
||||
}
|
||||
assertDiscussionDays(t, run, []int{1, 2})
|
||||
}
|
||||
|
||||
func TestServiceLatestConvectiveOutlookNoData(t *testing.T) {
|
||||
@@ -208,6 +210,7 @@ func TestServiceLatestConvectiveOutlookFiltersByDay(t *testing.T) {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
assertOutlookIDs(t, run, []string{"day-2"})
|
||||
assertDiscussionDays(t, run, []int{2})
|
||||
}
|
||||
|
||||
func TestServiceLatestConvectiveOutlookFiltersByOutlookType(t *testing.T) {
|
||||
@@ -219,6 +222,7 @@ func TestServiceLatestConvectiveOutlookFiltersByOutlookType(t *testing.T) {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
assertOutlookIDs(t, run, []string{"tor-1"})
|
||||
assertDiscussionDays(t, run, []int{1})
|
||||
}
|
||||
|
||||
func TestServiceLatestConvectiveOutlookFiltersByContainsLocation(t *testing.T) {
|
||||
@@ -230,7 +234,21 @@ func TestServiceLatestConvectiveOutlookFiltersByContainsLocation(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
assertOutlookIDs(t, run, []string{"cat-1", "tor-1"})
|
||||
assertOutlookIDs(t, run, []string{"cat-1", "tor-1", "day-2"})
|
||||
assertDiscussionDays(t, run, []int{1, 2})
|
||||
}
|
||||
|
||||
func TestServiceLatestConvectiveOutlookContainsLocationFalseReturnsEmptyRun(t *testing.T) {
|
||||
containsLocation := false
|
||||
repo := &fakeRepository{outlookRun: testOutlookRun()}
|
||||
svc := NewService(repo)
|
||||
|
||||
run, err := svc.LatestConvectiveOutlook(context.Background(), OutlookFilter{ContainsLocation: &containsLocation})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
assertOutlookIDs(t, run, nil)
|
||||
assertDiscussionDays(t, run, nil)
|
||||
}
|
||||
|
||||
func TestServiceLatestConvectiveOutlookFiltersByActiveAt(t *testing.T) {
|
||||
@@ -243,6 +261,7 @@ func TestServiceLatestConvectiveOutlookFiltersByActiveAt(t *testing.T) {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
assertOutlookIDs(t, run, []string{"cat-1", "tor-1"})
|
||||
assertDiscussionDays(t, run, []int{1})
|
||||
}
|
||||
|
||||
func TestServiceLatestConvectiveOutlookCombinesFilters(t *testing.T) {
|
||||
@@ -262,6 +281,7 @@ func TestServiceLatestConvectiveOutlookCombinesFilters(t *testing.T) {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
assertOutlookIDs(t, run, []string{"cat-1"})
|
||||
assertDiscussionDays(t, run, []int{1})
|
||||
}
|
||||
|
||||
func TestServiceLatestConvectiveOutlookActiveAtBoundary(t *testing.T) {
|
||||
@@ -277,12 +297,14 @@ func TestServiceLatestConvectiveOutlookActiveAtBoundary(t *testing.T) {
|
||||
t.Fatalf("unexpected validFrom error: %v", err)
|
||||
}
|
||||
assertOutlookIDs(t, fromRun, []string{"cat-1"})
|
||||
assertDiscussionDays(t, fromRun, []int{1})
|
||||
|
||||
toRun, err := svc.LatestConvectiveOutlook(context.Background(), OutlookFilter{ActiveAt: &validTo})
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected validTo error: %v", err)
|
||||
}
|
||||
assertOutlookIDs(t, toRun, nil)
|
||||
assertDiscussionDays(t, toRun, nil)
|
||||
}
|
||||
|
||||
func TestServiceLatestConvectiveOutlookKeepsRunMetadataWithEmptyOutlooks(t *testing.T) {
|
||||
@@ -306,6 +328,12 @@ func TestServiceLatestConvectiveOutlookKeepsRunMetadataWithEmptyOutlooks(t *test
|
||||
if len(run.Outlooks) != 0 {
|
||||
t.Fatalf("expected no outlooks, got %+v", run.Outlooks)
|
||||
}
|
||||
if run.Discussions == nil {
|
||||
t.Fatal("expected empty discussions slice, got nil")
|
||||
}
|
||||
if len(run.Discussions) != 0 {
|
||||
t.Fatalf("expected no discussions, got %+v", run.Discussions)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServiceLatestConvectiveOutlookDoesNotMutateRepositoryRun(t *testing.T) {
|
||||
@@ -325,9 +353,12 @@ func TestServiceLatestConvectiveOutlookDoesNotMutateRepositoryRun(t *testing.T)
|
||||
*run.Longitude = -99
|
||||
*run.IssuedAt = testTime(99)
|
||||
*run.Outlooks[0].SeverityRank = 99
|
||||
*run.Discussions[0].UpdatedAt = testTime(98)
|
||||
run.Outlooks[0].Geometry[0] = '{'
|
||||
run.Outlooks[0].ID = "changed"
|
||||
run.Discussions[0].Headline = "changed"
|
||||
run.Outlooks = run.Outlooks[:1]
|
||||
run.Discussions = run.Discussions[:1]
|
||||
|
||||
if *original.Latitude != 38.62 {
|
||||
t.Fatalf("expected original latitude unchanged, got %v", *original.Latitude)
|
||||
@@ -350,6 +381,15 @@ func TestServiceLatestConvectiveOutlookDoesNotMutateRepositoryRun(t *testing.T)
|
||||
if len(original.Outlooks) != 3 {
|
||||
t.Fatalf("expected original outlook slice unchanged, got %d entries", len(original.Outlooks))
|
||||
}
|
||||
if original.Discussions[0].UpdatedAt == nil || !original.Discussions[0].UpdatedAt.Equal(testTime(10)) {
|
||||
t.Fatalf("expected original discussion updatedAt unchanged, got %v", original.Discussions[0].UpdatedAt)
|
||||
}
|
||||
if original.Discussions[0].Headline != "Day 1 headline" {
|
||||
t.Fatalf("expected original discussion headline unchanged, got %q", original.Discussions[0].Headline)
|
||||
}
|
||||
if len(original.Discussions) != 3 {
|
||||
t.Fatalf("expected original discussion slice unchanged, got %d entries", len(original.Discussions))
|
||||
}
|
||||
}
|
||||
|
||||
func TestServicePropagatesErrors(t *testing.T) {
|
||||
@@ -376,8 +416,25 @@ func testOutlookRun() *model.WeatherOutlookRun {
|
||||
Outlooks: []model.WeatherOutlook{
|
||||
testOutlook("cat-1", 1, "categorical", true, testTime(12), testTime(18), 5, `["cat"]`),
|
||||
testOutlook("tor-1", 1, "tornado", true, testTime(13), testTime(19), 7, `["tor"]`),
|
||||
testOutlook("day-2", 2, "wind", false, testTime(18), testTime(24), 2, `["wind"]`),
|
||||
testOutlook("day-2", 2, "wind", true, testTime(18), testTime(24), 2, `["wind"]`),
|
||||
},
|
||||
Discussions: []model.WeatherOutlookDiscussion{
|
||||
testOutlookDiscussion(1),
|
||||
testOutlookDiscussion(2),
|
||||
testOutlookDiscussion(3),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func testOutlookDiscussion(day int) model.WeatherOutlookDiscussion {
|
||||
updatedAt := testTime(9 + day)
|
||||
dayText := strconv.Itoa(day)
|
||||
return model.WeatherOutlookDiscussion{
|
||||
Day: day,
|
||||
Headline: "Day " + dayText + " headline",
|
||||
Summary: "Day " + dayText + " summary",
|
||||
Discussion: "Day " + dayText + " discussion",
|
||||
UpdatedAt: &updatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -421,3 +478,18 @@ func assertOutlookIDs(t *testing.T, run *model.WeatherOutlookRun, want []string)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func assertDiscussionDays(t *testing.T, run *model.WeatherOutlookRun, want []int) {
|
||||
t.Helper()
|
||||
if run == nil {
|
||||
t.Fatal("expected outlook run")
|
||||
}
|
||||
if len(run.Discussions) != len(want) {
|
||||
t.Fatalf("expected discussion days %v, got %+v", want, run.Discussions)
|
||||
}
|
||||
for i := range want {
|
||||
if run.Discussions[i].Day != want[i] {
|
||||
t.Fatalf("expected discussion days %v, got %+v", want, run.Discussions)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user