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.Outlooks = outlooks
|
||||||
|
out.Discussions = filterOutlookDiscussions(out.Discussions, out.Outlooks)
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,6 +124,12 @@ func cloneOutlookRun(run *model.WeatherOutlookRun) *model.WeatherOutlookRun {
|
|||||||
out.Outlooks[i] = cloneOutlook(run.Outlooks[i])
|
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
|
return &out
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,6 +142,31 @@ func cloneOutlook(outlook model.WeatherOutlook) model.WeatherOutlook {
|
|||||||
return out
|
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 {
|
func copyFloat64(value *float64) *float64 {
|
||||||
if value == nil {
|
if value == nil {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package app
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -131,6 +132,7 @@ func TestServiceDelegatesLatestConvectiveOutlookRun(t *testing.T) {
|
|||||||
if run == nil || run.LocationID != "stl" {
|
if run == nil || run.LocationID != "stl" {
|
||||||
t.Fatalf("unexpected outlook run: %+v", run)
|
t.Fatalf("unexpected outlook run: %+v", run)
|
||||||
}
|
}
|
||||||
|
assertDiscussionDays(t, run, []int{1, 2})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestServiceLatestConvectiveOutlookNoData(t *testing.T) {
|
func TestServiceLatestConvectiveOutlookNoData(t *testing.T) {
|
||||||
@@ -208,6 +210,7 @@ func TestServiceLatestConvectiveOutlookFiltersByDay(t *testing.T) {
|
|||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
assertOutlookIDs(t, run, []string{"day-2"})
|
assertOutlookIDs(t, run, []string{"day-2"})
|
||||||
|
assertDiscussionDays(t, run, []int{2})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestServiceLatestConvectiveOutlookFiltersByOutlookType(t *testing.T) {
|
func TestServiceLatestConvectiveOutlookFiltersByOutlookType(t *testing.T) {
|
||||||
@@ -219,6 +222,7 @@ func TestServiceLatestConvectiveOutlookFiltersByOutlookType(t *testing.T) {
|
|||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
assertOutlookIDs(t, run, []string{"tor-1"})
|
assertOutlookIDs(t, run, []string{"tor-1"})
|
||||||
|
assertDiscussionDays(t, run, []int{1})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestServiceLatestConvectiveOutlookFiltersByContainsLocation(t *testing.T) {
|
func TestServiceLatestConvectiveOutlookFiltersByContainsLocation(t *testing.T) {
|
||||||
@@ -230,7 +234,21 @@ func TestServiceLatestConvectiveOutlookFiltersByContainsLocation(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error: %v", err)
|
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) {
|
func TestServiceLatestConvectiveOutlookFiltersByActiveAt(t *testing.T) {
|
||||||
@@ -243,6 +261,7 @@ func TestServiceLatestConvectiveOutlookFiltersByActiveAt(t *testing.T) {
|
|||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
assertOutlookIDs(t, run, []string{"cat-1", "tor-1"})
|
assertOutlookIDs(t, run, []string{"cat-1", "tor-1"})
|
||||||
|
assertDiscussionDays(t, run, []int{1})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestServiceLatestConvectiveOutlookCombinesFilters(t *testing.T) {
|
func TestServiceLatestConvectiveOutlookCombinesFilters(t *testing.T) {
|
||||||
@@ -262,6 +281,7 @@ func TestServiceLatestConvectiveOutlookCombinesFilters(t *testing.T) {
|
|||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
assertOutlookIDs(t, run, []string{"cat-1"})
|
assertOutlookIDs(t, run, []string{"cat-1"})
|
||||||
|
assertDiscussionDays(t, run, []int{1})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestServiceLatestConvectiveOutlookActiveAtBoundary(t *testing.T) {
|
func TestServiceLatestConvectiveOutlookActiveAtBoundary(t *testing.T) {
|
||||||
@@ -277,12 +297,14 @@ func TestServiceLatestConvectiveOutlookActiveAtBoundary(t *testing.T) {
|
|||||||
t.Fatalf("unexpected validFrom error: %v", err)
|
t.Fatalf("unexpected validFrom error: %v", err)
|
||||||
}
|
}
|
||||||
assertOutlookIDs(t, fromRun, []string{"cat-1"})
|
assertOutlookIDs(t, fromRun, []string{"cat-1"})
|
||||||
|
assertDiscussionDays(t, fromRun, []int{1})
|
||||||
|
|
||||||
toRun, err := svc.LatestConvectiveOutlook(context.Background(), OutlookFilter{ActiveAt: &validTo})
|
toRun, err := svc.LatestConvectiveOutlook(context.Background(), OutlookFilter{ActiveAt: &validTo})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected validTo error: %v", err)
|
t.Fatalf("unexpected validTo error: %v", err)
|
||||||
}
|
}
|
||||||
assertOutlookIDs(t, toRun, nil)
|
assertOutlookIDs(t, toRun, nil)
|
||||||
|
assertDiscussionDays(t, toRun, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestServiceLatestConvectiveOutlookKeepsRunMetadataWithEmptyOutlooks(t *testing.T) {
|
func TestServiceLatestConvectiveOutlookKeepsRunMetadataWithEmptyOutlooks(t *testing.T) {
|
||||||
@@ -306,6 +328,12 @@ func TestServiceLatestConvectiveOutlookKeepsRunMetadataWithEmptyOutlooks(t *test
|
|||||||
if len(run.Outlooks) != 0 {
|
if len(run.Outlooks) != 0 {
|
||||||
t.Fatalf("expected no outlooks, got %+v", run.Outlooks)
|
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) {
|
func TestServiceLatestConvectiveOutlookDoesNotMutateRepositoryRun(t *testing.T) {
|
||||||
@@ -325,9 +353,12 @@ func TestServiceLatestConvectiveOutlookDoesNotMutateRepositoryRun(t *testing.T)
|
|||||||
*run.Longitude = -99
|
*run.Longitude = -99
|
||||||
*run.IssuedAt = testTime(99)
|
*run.IssuedAt = testTime(99)
|
||||||
*run.Outlooks[0].SeverityRank = 99
|
*run.Outlooks[0].SeverityRank = 99
|
||||||
|
*run.Discussions[0].UpdatedAt = testTime(98)
|
||||||
run.Outlooks[0].Geometry[0] = '{'
|
run.Outlooks[0].Geometry[0] = '{'
|
||||||
run.Outlooks[0].ID = "changed"
|
run.Outlooks[0].ID = "changed"
|
||||||
|
run.Discussions[0].Headline = "changed"
|
||||||
run.Outlooks = run.Outlooks[:1]
|
run.Outlooks = run.Outlooks[:1]
|
||||||
|
run.Discussions = run.Discussions[:1]
|
||||||
|
|
||||||
if *original.Latitude != 38.62 {
|
if *original.Latitude != 38.62 {
|
||||||
t.Fatalf("expected original latitude unchanged, got %v", *original.Latitude)
|
t.Fatalf("expected original latitude unchanged, got %v", *original.Latitude)
|
||||||
@@ -350,6 +381,15 @@ func TestServiceLatestConvectiveOutlookDoesNotMutateRepositoryRun(t *testing.T)
|
|||||||
if len(original.Outlooks) != 3 {
|
if len(original.Outlooks) != 3 {
|
||||||
t.Fatalf("expected original outlook slice unchanged, got %d entries", len(original.Outlooks))
|
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) {
|
func TestServicePropagatesErrors(t *testing.T) {
|
||||||
@@ -376,8 +416,25 @@ func testOutlookRun() *model.WeatherOutlookRun {
|
|||||||
Outlooks: []model.WeatherOutlook{
|
Outlooks: []model.WeatherOutlook{
|
||||||
testOutlook("cat-1", 1, "categorical", true, testTime(12), testTime(18), 5, `["cat"]`),
|
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("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