Share day-style render context and template blocks

This commit is contained in:
2026-06-16 15:03:35 +00:00
parent e3bcecc5c1
commit 121f28fd29
10 changed files with 426 additions and 252 deletions

View File

@@ -272,6 +272,192 @@ func TestBuildTodayRenderContextAllowsOmittedOptionalModules(t *testing.T) {
}
}
func TestBuildDayStyleRenderContextsPopulateSharedFieldsAndPlanningModules(t *testing.T) {
type result struct {
title string
forecastDateLabel string
generatedAtLabel string
timezone string
validPeriod timeutil.Period
metadata bool
current bool
hourly bool
dailySummary bool
daypartSummaries bool
dayparts int
precip bool
alerts bool
outlooks bool
discussion bool
spcDiscussion bool
story bool
planning bool
collected bool
derived bool
}
tests := []struct {
name string
wantTitle string
wantGeneratedLabel string
wantDayparts int
build func(t *testing.T) result
}{
{
name: "daily",
wantTitle: "Monday's Weather",
wantGeneratedLabel: "Saturday, June 13, 2026 at 9:14 AM",
wantDayparts: 3,
build: func(t *testing.T) result {
t.Helper()
collected := testCollected()
derived := testDailyDerived()
ctx, err := BuildDailyRenderContext(testDailyMetadata(), testDailySnapshot(t), Daily{
Summary: "Daily summary.",
ForecastDiscussion: []string{"Daily discussion."},
}, collected, derived)
if err != nil {
t.Fatalf("BuildDailyRenderContext() error = %v", err)
}
return result{
title: ctx.Report.Title,
forecastDateLabel: ctx.Report.ForecastDateLabel,
generatedAtLabel: ctx.Report.GeneratedAtLabel,
timezone: ctx.Report.Timezone,
validPeriod: ctx.Report.ValidPeriod,
metadata: ctx.Modules.Metadata != nil && ctx.Modules.Metadata.ReportID == report.Daily,
current: ctx.Modules.CurrentConditions != nil,
hourly: ctx.Modules.HourlyForecast != nil,
dailySummary: ctx.Modules.DerivedDailySummary != nil,
daypartSummaries: ctx.Modules.DerivedDaypartSummaries != nil,
dayparts: len(ctx.Modules.Dayparts),
precip: ctx.Modules.PrecipTiming != nil,
alerts: ctx.Modules.AlertDigest != nil,
outlooks: ctx.Modules.SPCConvectiveOutlooks != nil,
discussion: ctx.Modules.AreaForecastDiscussion != nil,
spcDiscussion: ctx.Modules.SPCConvectiveDiscussion != nil,
story: ctx.Modules.WeatherStory != nil,
planning: ctx.Modules.DailyPlanning != nil,
collected: ctx.Collected.FetchedAt.Equal(collected.FetchedAt),
derived: len(ctx.Derived.DaypartSummaries) == len(derived.DaypartSummaries),
}
},
},
{
name: "today",
wantTitle: "Today's Weather",
wantGeneratedLabel: "Monday, June 15, 2026 at 7:14 AM",
wantDayparts: 2,
build: func(t *testing.T) result {
t.Helper()
collected := testCollected()
derived := testTodayDerived()
ctx, err := BuildTodayRenderContext(testTodayMetadata(), testTodaySnapshot(t), Today{
Summary: "Today summary.",
ForecastDiscussion: []string{"Today discussion."},
}, collected, derived)
if err != nil {
t.Fatalf("BuildTodayRenderContext() error = %v", err)
}
return result{
title: ctx.Report.Title,
forecastDateLabel: ctx.Report.ForecastDateLabel,
generatedAtLabel: ctx.Report.GeneratedAtLabel,
timezone: ctx.Report.Timezone,
validPeriod: ctx.Report.ValidPeriod,
metadata: ctx.Modules.Metadata != nil && ctx.Modules.Metadata.ReportID == report.Today,
current: ctx.Modules.CurrentConditions != nil,
hourly: ctx.Modules.HourlyForecast != nil,
dailySummary: ctx.Modules.DerivedDailySummary != nil,
daypartSummaries: ctx.Modules.DerivedDaypartSummaries != nil,
dayparts: len(ctx.Modules.Dayparts),
precip: ctx.Modules.PrecipTiming != nil,
alerts: ctx.Modules.AlertDigest != nil,
outlooks: ctx.Modules.SPCConvectiveOutlooks != nil,
discussion: ctx.Modules.AreaForecastDiscussion != nil,
spcDiscussion: ctx.Modules.SPCConvectiveDiscussion != nil,
story: ctx.Modules.WeatherStory != nil,
planning: ctx.Modules.TodayPlanning != nil,
collected: ctx.Collected.FetchedAt.Equal(collected.FetchedAt),
derived: len(ctx.Derived.DaypartSummaries) == len(derived.DaypartSummaries),
}
},
},
{
name: "tomorrow",
wantTitle: "Monday's Weather",
wantGeneratedLabel: "Sunday, June 14, 2026 at 9:14 AM",
wantDayparts: 2,
build: func(t *testing.T) result {
t.Helper()
collected := testCollected()
derived := testTomorrowDerived()
ctx, err := BuildTomorrowRenderContext(testTomorrowMetadata(), testTomorrowSnapshot(t), Tomorrow{
Summary: "Tomorrow summary.",
ForecastDiscussion: []string{"Tomorrow discussion."},
}, collected, derived)
if err != nil {
t.Fatalf("BuildTomorrowRenderContext() error = %v", err)
}
return result{
title: ctx.Report.Title,
forecastDateLabel: ctx.Report.ForecastDateLabel,
generatedAtLabel: ctx.Report.GeneratedAtLabel,
timezone: ctx.Report.Timezone,
validPeriod: ctx.Report.ValidPeriod,
metadata: ctx.Modules.Metadata != nil && ctx.Modules.Metadata.ReportID == report.Tomorrow,
current: ctx.Modules.CurrentConditions != nil,
hourly: ctx.Modules.HourlyForecast != nil,
dailySummary: ctx.Modules.DerivedDailySummary != nil,
daypartSummaries: ctx.Modules.DerivedDaypartSummaries != nil,
dayparts: len(ctx.Modules.Dayparts),
precip: ctx.Modules.PrecipTiming != nil,
alerts: ctx.Modules.AlertDigest != nil,
outlooks: ctx.Modules.SPCConvectiveOutlooks != nil,
discussion: ctx.Modules.AreaForecastDiscussion != nil,
spcDiscussion: ctx.Modules.SPCConvectiveDiscussion != nil,
story: ctx.Modules.WeatherStory != nil,
planning: ctx.Modules.TomorrowPlanning != nil,
collected: ctx.Collected.FetchedAt.Equal(collected.FetchedAt),
derived: len(ctx.Derived.DaypartSummaries) == len(derived.DaypartSummaries),
}
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
result := test.build(t)
if result.title != test.wantTitle {
t.Fatalf("title = %q, want %q", result.title, test.wantTitle)
}
if result.forecastDateLabel != "Monday, June 15, 2026" {
t.Fatalf("forecastDateLabel = %q, want Monday, June 15, 2026", result.forecastDateLabel)
}
if result.generatedAtLabel != test.wantGeneratedLabel {
t.Fatalf("generatedAtLabel = %q, want %q", result.generatedAtLabel, test.wantGeneratedLabel)
}
if result.timezone != "America/Chicago" {
t.Fatalf("timezone = %q, want America/Chicago", result.timezone)
}
if !result.validPeriod.IsValid() {
t.Fatalf("validPeriod = %#v, want valid period", result.validPeriod)
}
if !result.metadata || !result.current || !result.hourly || !result.dailySummary || !result.daypartSummaries || !result.precip || !result.alerts || !result.outlooks || !result.discussion || !result.spcDiscussion || !result.story {
t.Fatalf("common modules = %#v, want all shared modules populated", result)
}
if result.dayparts != test.wantDayparts {
t.Fatalf("dayparts = %d, want %d", result.dayparts, test.wantDayparts)
}
if !result.planning {
t.Fatalf("planning = false, want %s planning module populated", test.name)
}
if !result.collected || !result.derived {
t.Fatalf("facts passthrough = collected:%t derived:%t, want both true", result.collected, result.derived)
}
})
}
}
func TestBuildDailyRenderContext(t *testing.T) {
metadata := testDailyMetadata()
snapshot := testDailySnapshot(t)