Implemented weather stories support
All checks were successful
ci/woodpecker/push/build-image Pipeline was successful

This commit is contained in:
2026-05-30 07:06:29 -05:00
parent bde515d146
commit ecea856e8e
18 changed files with 760 additions and 4 deletions

View File

@@ -14,6 +14,8 @@ type Repository interface {
LatestHourlyForecast(ctx context.Context) (*model.WeatherForecastRun, error)
LatestNarrativeForecast(ctx context.Context) (*model.WeatherForecastRun, error)
LatestForecastDiscussion(ctx context.Context) (*model.WeatherForecastDiscussion, error)
LatestWeatherStoryRun(ctx context.Context) (*model.WeatherStoryRun, error)
LatestWeatherStory(ctx context.Context) (*model.WeatherStory, error)
LatestAlertRun(ctx context.Context) (*model.WeatherAlertRun, error)
CurrentConditions(ctx context.Context, observationWindowMinutes int) (*CurrentConditions, error)
}
@@ -43,6 +45,14 @@ func (s *Service) LatestForecastDiscussion(ctx context.Context) (*model.WeatherF
return s.repo.LatestForecastDiscussion(ctx)
}
func (s *Service) LatestWeatherStoryRun(ctx context.Context) (*model.WeatherStoryRun, error) {
return s.repo.LatestWeatherStoryRun(ctx)
}
func (s *Service) LatestWeatherStory(ctx context.Context) (*model.WeatherStory, error) {
return s.repo.LatestWeatherStory(ctx)
}
func (s *Service) LatestAlertRun(ctx context.Context) (*model.WeatherAlertRun, error) {
return s.repo.LatestAlertRun(ctx)
}

View File

@@ -15,6 +15,8 @@ type fakeRepository struct {
forecast *model.WeatherForecastRun
narrative *model.WeatherForecastRun
discussion *model.WeatherForecastDiscussion
storyRun *model.WeatherStoryRun
story *model.WeatherStory
alerts *model.WeatherAlertRun
conditions *CurrentConditions
err error
@@ -38,6 +40,14 @@ func (r *fakeRepository) LatestForecastDiscussion(context.Context) (*model.Weath
return r.discussion, r.err
}
func (r *fakeRepository) LatestWeatherStoryRun(context.Context) (*model.WeatherStoryRun, error) {
return r.storyRun, r.err
}
func (r *fakeRepository) LatestWeatherStory(context.Context) (*model.WeatherStory, error) {
return r.story, r.err
}
func (r *fakeRepository) LatestAlertRun(context.Context) (*model.WeatherAlertRun, error) {
return r.alerts, r.err
}
@@ -112,6 +122,32 @@ func TestServiceDelegatesForecastDiscussion(t *testing.T) {
}
}
func TestServiceDelegatesWeatherStoryRun(t *testing.T) {
repo := &fakeRepository{storyRun: &model.WeatherStoryRun{OfficeID: "LSX"}}
svc := NewService(repo)
run, err := svc.LatestWeatherStoryRun(context.Background())
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if run == nil || run.OfficeID != "LSX" {
t.Fatalf("unexpected weather story run: %+v", run)
}
}
func TestServiceDelegatesWeatherStory(t *testing.T) {
repo := &fakeRepository{story: &model.WeatherStory{OfficeID: "LSX", Title: "Rain chances"}}
svc := NewService(repo)
story, err := svc.LatestWeatherStory(context.Background())
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if story == nil || story.Title != "Rain chances" {
t.Fatalf("unexpected weather story: %+v", story)
}
}
func TestServiceUsesDefaultCurrentConditionsWindow(t *testing.T) {
repo := &fakeRepository{conditions: &CurrentConditions{ConditionCode: model.WMOUnknown}}
svc := NewService(repo)