package promptinput import ( "encoding/json" "strings" "testing" "time" "gitea.maximumdirect.net/eric/weatherreporter/internal/briefing" "gitea.maximumdirect.net/eric/weatherreporter/internal/report" "gitea.maximumdirect.net/eric/weatherreporter/internal/timeutil" ) func TestBuildDailyDataPackage(t *testing.T) { briefingPackage := validBriefingPackage() pkg, err := Build(briefingPackage) if err != nil { t.Fatalf("Build() error = %v", err) } if pkg.SchemaVersion != SchemaVersion { t.Fatalf("SchemaVersion = %q, want %q", pkg.SchemaVersion, SchemaVersion) } if pkg.RunID != "20260529T100000Z_daily_today" { t.Fatalf("RunID = %q, want briefing run id", pkg.RunID) } if pkg.Report.PromptID != "weather.daily_report" { t.Fatalf("PromptID = %q, want weather.daily_report", pkg.Report.PromptID) } if pkg.Briefing.Daily == nil { t.Fatal("Briefing.Daily = nil") } if pkg.RecentChanges.Items == nil || len(pkg.RecentChanges.Items) != 0 { t.Fatalf("RecentChanges.Items = %#v, want empty slice", pkg.RecentChanges.Items) } } func TestValidateRequiresFields(t *testing.T) { pkg, err := Build(validBriefingPackage()) if err != nil { t.Fatalf("Build() error = %v", err) } pkg.RunID = "" err = Validate(pkg) if err == nil { t.Fatal("Validate() error = nil, want required field error") } if !strings.Contains(err.Error(), "runId") { t.Fatalf("error = %q, want runId context", err.Error()) } } func TestBuildThreeDayDataPackage(t *testing.T) { briefingPackage := validBriefingPackage() briefingPackage.Metadata.RunID = "20260529T100000Z_three_day" briefingPackage.Metadata.ReportID = report.ThreeDay briefingPackage.Metadata.PromptID = "weather.three_day_outlook" briefingPackage.Daily = nil briefingPackage.ThreeDay = &briefing.ThreeDay{ Days: []briefing.OutlookDay{{Date: "2026-05-29"}}, } pkg, err := Build(briefingPackage) if err != nil { t.Fatalf("Build() error = %v", err) } if pkg.Report.ID != report.ThreeDay { t.Fatalf("Report.ID = %q, want three_day", pkg.Report.ID) } if pkg.Briefing.ThreeDay == nil { t.Fatal("Briefing.ThreeDay = nil") } } func TestBuildWeekendDataPackage(t *testing.T) { briefingPackage := validBriefingPackage() briefingPackage.Metadata.RunID = "20260529T100000Z_weekend" briefingPackage.Metadata.ReportID = report.Weekend briefingPackage.Metadata.PromptID = "weather.weekend_outlook" briefingPackage.Daily = nil briefingPackage.Weekend = &briefing.Weekend{ Days: []briefing.OutlookDay{{Date: "2026-05-30"}}, } pkg, err := Build(briefingPackage) if err != nil { t.Fatalf("Build() error = %v", err) } if pkg.Report.ID != report.Weekend { t.Fatalf("Report.ID = %q, want weekend", pkg.Report.ID) } if pkg.Briefing.Weekend == nil { t.Fatal("Briefing.Weekend = nil") } } func TestBuildStormDataPackage(t *testing.T) { briefingPackage := validBriefingPackage() briefingPackage.Metadata.RunID = "20260529T100000Z_storm" briefingPackage.Metadata.ReportID = report.Storm briefingPackage.Metadata.PromptID = "weather.storm_report" briefingPackage.Daily = nil briefingPackage.Storm = &briefing.Storm{ TimingWindow: briefingPackage.Metadata.ValidPeriod, Hazards: []string{"Thunderstorms"}, } pkg, err := Build(briefingPackage) if err != nil { t.Fatalf("Build() error = %v", err) } if pkg.Report.ID != report.Storm { t.Fatalf("Report.ID = %q, want storm", pkg.Report.ID) } if pkg.Report.PromptID != "weather.storm_report" { t.Fatalf("PromptID = %q, want weather.storm_report", pkg.Report.PromptID) } if pkg.Briefing.Storm == nil { t.Fatal("Briefing.Storm = nil") } } func TestMarshalDeterministic(t *testing.T) { pkg, err := Build(validBriefingPackage()) if err != nil { t.Fatalf("Build() error = %v", err) } first, err := json.MarshalIndent(pkg, "", " ") if err != nil { t.Fatalf("first marshal: %v", err) } second, err := json.MarshalIndent(pkg, "", " ") if err != nil { t.Fatalf("second marshal: %v", err) } if string(first) != string(second) { t.Fatalf("JSON output changed between marshals:\n%s\n---\n%s", string(first), string(second)) } } func validBriefingPackage() briefing.Package { generatedAt := time.Date(2026, 5, 29, 10, 0, 0, 0, time.UTC) return briefing.Package{ Metadata: briefing.Metadata{ SchemaVersion: briefing.SchemaVersion, RunID: "20260529T100000Z_daily_today", ReportID: report.DailyToday, PromptID: "weather.daily_report", GeneratedAt: generatedAt, Units: "us", Timezone: "America/Chicago", ValidPeriod: timeutil.Period{ Start: time.Date(2026, 5, 29, 5, 0, 0, 0, time.UTC), End: time.Date(2026, 5, 30, 5, 0, 0, 0, time.UTC), }, }, Daily: &briefing.Daily{ ForecastSummaryDate: "2026-05-29", }, } }