Add daily planning module
This commit is contained in:
@@ -337,6 +337,77 @@ func TestOutdoorWindowsAndTomorrowPlanningModulesPreserveDailyContent(t *testing
|
||||
}
|
||||
}
|
||||
|
||||
func TestDailyPlanningModulePackagesPlanningFields(t *testing.T) {
|
||||
registry := MustDefaultModuleRegistry()
|
||||
ctx := dailyModuleContext()
|
||||
|
||||
output, err := registry.BuildModule(ctx, module.ConfigItem{ID: module.DailyPlanning})
|
||||
if err != nil {
|
||||
t.Fatalf("BuildModule(daily planning) error = %v", err)
|
||||
}
|
||||
if output.ID != module.DailyPlanning || output.StanzaName != "daily_planning" {
|
||||
t.Fatalf("output = %#v, want daily planning stanza", output)
|
||||
}
|
||||
planning := moduleValue[DailyPlanningModule](t, output)
|
||||
if len(planning.MorningReadiness) == 0 ||
|
||||
len(planning.CommuteSchoolWorkdayConcerns) == 0 ||
|
||||
len(planning.OvernightChangeWatch) == 0 {
|
||||
t.Fatalf("daily planning = %#v, want populated planning fields", planning)
|
||||
}
|
||||
if !containsString(planning.MorningReadiness, "Morning precipitation chance peaks near 60%.") {
|
||||
t.Fatalf("MorningReadiness = %#v, want precipitation readiness note", planning.MorningReadiness)
|
||||
}
|
||||
if !containsString(planning.CommuteSchoolWorkdayConcerns, "Afternoon alert overlap needs attention.") {
|
||||
t.Fatalf("CommuteSchoolWorkdayConcerns = %#v, want alert-overlap concern", planning.CommuteSchoolWorkdayConcerns)
|
||||
}
|
||||
if !containsString(planning.OvernightChangeWatch, "Watch for forecast timing or intensity adjustments overnight.") {
|
||||
t.Fatalf("OvernightChangeWatch = %#v, want overnight fallback note", planning.OvernightChangeWatch)
|
||||
}
|
||||
data, err := json.Marshal(output.Value)
|
||||
if err != nil {
|
||||
t.Fatalf("marshal daily planning: %v", err)
|
||||
}
|
||||
jsonText := string(data)
|
||||
for _, field := range []string{"morning_readiness", "commute_school_workday_concerns", "overnight_change_watch"} {
|
||||
if !strings.Contains(jsonText, field) {
|
||||
t.Fatalf("daily planning json = %s, want field %s", jsonText, field)
|
||||
}
|
||||
}
|
||||
if strings.Contains(jsonText, "tomorrow_planning") || strings.Contains(jsonText, "morningReadiness") {
|
||||
t.Fatalf("daily planning json = %s, want daily snake_case fields only", jsonText)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDailyPlanningModuleRejectsUnsupportedReports(t *testing.T) {
|
||||
registry := MustDefaultModuleRegistry()
|
||||
for _, id := range []report.ID{report.DailyToday, report.Today, report.Tomorrow, report.Hourly, report.ThreeDay, report.Weekend, report.Storm} {
|
||||
t.Run(string(id), func(t *testing.T) {
|
||||
ctx := derivedModuleContext(id)
|
||||
_, err := registry.BuildModule(ctx, module.ConfigItem{ID: module.DailyPlanning})
|
||||
if err == nil || !strings.Contains(err.Error(), `module "daily_planning" is not compatible with report`) {
|
||||
t.Fatalf("BuildModule(%s) error = %v, want incompatible report", id, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDailyPlanningModuleHandlesMissingDailySummary(t *testing.T) {
|
||||
registry := MustDefaultModuleRegistry()
|
||||
ctx := dailyModuleContext()
|
||||
ctx.Derived.DailySummaries = nil
|
||||
|
||||
output, err := registry.BuildModule(ctx, module.ConfigItem{ID: module.DailyPlanning})
|
||||
if err != nil {
|
||||
t.Fatalf("BuildModule(daily planning) error = %v", err)
|
||||
}
|
||||
planning := moduleValue[DailyPlanningModule](t, output)
|
||||
if len(planning.MorningReadiness) != 0 ||
|
||||
len(planning.CommuteSchoolWorkdayConcerns) != 0 ||
|
||||
len(planning.OvernightChangeWatch) != 0 {
|
||||
t.Fatalf("daily planning = %#v, want empty output without daily summary", planning)
|
||||
}
|
||||
}
|
||||
|
||||
func TestTodayPlanningModulePackagesPlanningFields(t *testing.T) {
|
||||
registry := MustDefaultModuleRegistry()
|
||||
ctx := todayModuleContext()
|
||||
@@ -514,6 +585,16 @@ func todayModuleContext() ModuleContext {
|
||||
return ctx
|
||||
}
|
||||
|
||||
func dailyModuleContext() ModuleContext {
|
||||
ctx := derivedModuleContext(report.Tomorrow)
|
||||
ctx.Resolved.Definition = report.Definition{
|
||||
ID: report.ID("daily"),
|
||||
Name: "Daily Report",
|
||||
PromptID: "weather.daily_generated_text",
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
func derivedDaypart(name string, start string, end string, text string, temperature float64, apparent *float64, precip float64, gust float64) forecast.DaypartSummary {
|
||||
hour := derivedHour(start, text, precip, temperature, apparent, gust)
|
||||
return forecast.SummarizeDaypart(name, timeutil.Period{
|
||||
|
||||
Reference in New Issue
Block a user