Clean up app test setup
This commit is contained in:
@@ -83,16 +83,11 @@ func TestFetchAndSaveBundleRequiresOutputPath(t *testing.T) {
|
|||||||
|
|
||||||
func TestGenerateReportWritesReportAndPreflight(t *testing.T) {
|
func TestGenerateReportWritesReportAndPreflight(t *testing.T) {
|
||||||
server := dailyBundleServer(t)
|
server := dailyBundleServer(t)
|
||||||
cfg := dailyTestConfig(t, server)
|
cfg := dailyWorkspaceConfig(t, server)
|
||||||
cfg.Workspace.Root = t.TempDir()
|
resolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
resolved, err := ResolveGenerate(GenerateRequest{
|
|
||||||
Config: cfg,
|
|
||||||
Report: ReportDaily,
|
Report: ReportDaily,
|
||||||
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
||||||
}, mustParse("2026-05-29T05:00:00-05:00"))
|
}, "2026-05-29T05:00:00-05:00")
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ResolveGenerate() error = %v", err)
|
|
||||||
}
|
|
||||||
renderer := &recordingRenderer{
|
renderer := &recordingRenderer{
|
||||||
renderResult: &scriptorium.RenderResult{
|
renderResult: &scriptorium.RenderResult{
|
||||||
Command: []string{"scriptorium", "render"},
|
Command: []string{"scriptorium", "render"},
|
||||||
@@ -113,11 +108,7 @@ func TestGenerateReportWritesReportAndPreflight(t *testing.T) {
|
|||||||
runBody: "# Daily Report\n\nRain this morning.\n",
|
runBody: "# Daily Report\n\nRain this morning.\n",
|
||||||
}
|
}
|
||||||
outputPath := filepath.Join(t.TempDir(), "daily.md")
|
outputPath := filepath.Join(t.TempDir(), "daily.md")
|
||||||
filesystemStore, err := state.NewFilesystemStore(cfg.Workspace)
|
store := recordingFilesystemStore(t, cfg)
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("NewFilesystemStore() error = %v", err)
|
|
||||||
}
|
|
||||||
store := &recordingStore{Store: filesystemStore}
|
|
||||||
|
|
||||||
result, err := GenerateReport(context.Background(), ReportRequest{
|
result, err := GenerateReport(context.Background(), ReportRequest{
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
@@ -342,20 +333,12 @@ func TestGeneratedTemplateReportsUseRichArtifactsAndCuratedDataPackages(t *testi
|
|||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
cfg := dailyTestConfig(t, server)
|
cfg := dailyWorkspaceConfig(t, server)
|
||||||
cfg.Workspace.Root = t.TempDir()
|
resolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
resolved, err := ResolveGenerate(GenerateRequest{
|
|
||||||
Config: cfg,
|
|
||||||
Report: tt.kind,
|
Report: tt.kind,
|
||||||
Date: tt.date,
|
Date: tt.date,
|
||||||
}, tt.now)
|
}, tt.now.Format(time.RFC3339))
|
||||||
if err != nil {
|
renderer := successfulGeneratedTextRenderer("")
|
||||||
t.Fatalf("ResolveGenerate() error = %v", err)
|
|
||||||
}
|
|
||||||
renderer := &recordingRenderer{
|
|
||||||
renderResult: &scriptorium.RenderResult{ExitCode: 0},
|
|
||||||
structuredRunResult: &scriptorium.StructuredRunResult{ExitCode: 0},
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := GenerateReport(context.Background(), ReportRequest{
|
result, err := GenerateReport(context.Background(), ReportRequest{
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
@@ -477,28 +460,12 @@ func TestGenerateReportOmitsSPCConvectiveDiscussionBelowThreshold(t *testing.T)
|
|||||||
|
|
||||||
func TestGenerateHourlyReportUsesGeneratedTextTemplateWorkflow(t *testing.T) {
|
func TestGenerateHourlyReportUsesGeneratedTextTemplateWorkflow(t *testing.T) {
|
||||||
server := hourlyBundleServer(t)
|
server := hourlyBundleServer(t)
|
||||||
cfg := config.Defaults()
|
cfg := hourlyTestConfig(t, server)
|
||||||
cfg.WeatherAPI.BaseURL = server.URL + "/"
|
resolved := resolveGenerateForTest(t, cfg, GenerateRequest{Report: ReportHourly}, "2026-05-29T08:30:00-05:00")
|
||||||
cfg.WeatherAPI.Timezone = "America/Chicago"
|
|
||||||
cfg.Workspace.Root = t.TempDir()
|
|
||||||
cfg.Location.ID = "home"
|
|
||||||
cfg.Location.Name = "Brentwood"
|
|
||||||
cfg.Location.Region = "MO"
|
|
||||||
resolved, err := ResolveGenerate(GenerateRequest{
|
|
||||||
Config: cfg,
|
|
||||||
Report: ReportHourly,
|
|
||||||
}, mustParse("2026-05-29T08:30:00-05:00"))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ResolveGenerate() error = %v", err)
|
|
||||||
}
|
|
||||||
if resolved.Definition.GenerationMode != report.GenerationModeGeneratedTextTemplate {
|
if resolved.Definition.GenerationMode != report.GenerationModeGeneratedTextTemplate {
|
||||||
t.Fatalf("GenerationMode = %q, want generated text template", resolved.Definition.GenerationMode)
|
t.Fatalf("GenerationMode = %q, want generated text template", resolved.Definition.GenerationMode)
|
||||||
}
|
}
|
||||||
filesystemStore, err := state.NewFilesystemStore(cfg.Workspace)
|
store := recordingFilesystemStore(t, cfg)
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("NewFilesystemStore() error = %v", err)
|
|
||||||
}
|
|
||||||
store := &recordingStore{Store: filesystemStore}
|
|
||||||
renderer := &recordingRenderer{
|
renderer := &recordingRenderer{
|
||||||
renderResult: &scriptorium.RenderResult{
|
renderResult: &scriptorium.RenderResult{
|
||||||
Command: []string{"scriptorium", "render"},
|
Command: []string{"scriptorium", "render"},
|
||||||
@@ -642,18 +609,8 @@ func TestGenerateHourlyReportUsesGeneratedTextTemplateWorkflow(t *testing.T) {
|
|||||||
|
|
||||||
func TestGenerateHourlyReportCopiesOutputAndNotifiesManagedReport(t *testing.T) {
|
func TestGenerateHourlyReportCopiesOutputAndNotifiesManagedReport(t *testing.T) {
|
||||||
cfg, resolved, store, notifier, outputPath := hourlyGeneratedTextFixture(t)
|
cfg, resolved, store, notifier, outputPath := hourlyGeneratedTextFixture(t)
|
||||||
notifier.result = &NotificationResult{
|
notifier.result = successfulNotificationResult()
|
||||||
RunID: "distributor-run",
|
renderer := successfulGeneratedTextRenderer(validHourlyGeneratedTextJSON())
|
||||||
Status: "succeeded",
|
|
||||||
UploadStatus: "accepted",
|
|
||||||
PipelineID: "reports",
|
|
||||||
Report: []byte(`{"actions":[{"action":"replace_older"}]}`),
|
|
||||||
}
|
|
||||||
renderer := &recordingRenderer{
|
|
||||||
renderResult: &scriptorium.RenderResult{ExitCode: 0},
|
|
||||||
structuredRunResult: &scriptorium.StructuredRunResult{ExitCode: 0},
|
|
||||||
structuredRunBody: validHourlyGeneratedTextJSON(),
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := GenerateReport(context.Background(), ReportRequest{
|
result, err := GenerateReport(context.Background(), ReportRequest{
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
@@ -725,38 +682,21 @@ func TestGenerateHourlyReportCopiesOutputAndNotifiesManagedReport(t *testing.T)
|
|||||||
|
|
||||||
func TestGenerateTodayReportCopiesOutputAndNotifiesTodayTemplateValues(t *testing.T) {
|
func TestGenerateTodayReportCopiesOutputAndNotifiesTodayTemplateValues(t *testing.T) {
|
||||||
server := dailyBundleServer(t)
|
server := dailyBundleServer(t)
|
||||||
cfg := config.Defaults()
|
cfg := dailyWorkspaceConfig(t, server)
|
||||||
cfg.WeatherAPI.BaseURL = server.URL + "/"
|
|
||||||
cfg.WeatherAPI.Timezone = "America/Chicago"
|
|
||||||
cfg.Workspace.Root = t.TempDir()
|
|
||||||
cfg.Notify.Distributor.Enabled = true
|
cfg.Notify.Distributor.Enabled = true
|
||||||
cfg.Notify.Distributor.PipelineIDTemplate = "weatherreporter.{report_id}.{artifact_group}"
|
cfg.Notify.Distributor.PipelineIDTemplate = "weatherreporter.{report_id}.{artifact_group}"
|
||||||
cfg.Notify.Distributor.BundleIDTemplate = "{artifact_group}.{batch_output_name}.{report_id}"
|
cfg.Notify.Distributor.BundleIDTemplate = "{artifact_group}.{batch_output_name}.{report_id}"
|
||||||
cfg.Notify.Distributor.IdempotencyKeyTemplate = "{bundle_id}.{run_id}"
|
cfg.Notify.Distributor.IdempotencyKeyTemplate = "{bundle_id}.{run_id}"
|
||||||
cfg.Notify.Distributor.ReportPathTemplates = []string{"{valid_start_date}/{artifact_group}/{batch_output_name}"}
|
cfg.Notify.Distributor.ReportPathTemplates = []string{"{valid_start_date}/{artifact_group}/{batch_output_name}"}
|
||||||
resolved, err := ResolveGenerate(GenerateRequest{
|
resolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
Config: cfg,
|
|
||||||
Report: ReportToday,
|
Report: ReportToday,
|
||||||
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
||||||
}, mustParse("2026-05-29T05:00:00-05:00"))
|
}, "2026-05-29T05:00:00-05:00")
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ResolveGenerate() error = %v", err)
|
|
||||||
}
|
|
||||||
outputPath := filepath.Join(t.TempDir(), "today-copy.md")
|
outputPath := filepath.Join(t.TempDir(), "today-copy.md")
|
||||||
notifier := &recordingNotifier{
|
notifier := &recordingNotifier{
|
||||||
result: &NotificationResult{
|
result: successfulNotificationResult(),
|
||||||
RunID: "distributor-run",
|
|
||||||
Status: "succeeded",
|
|
||||||
UploadStatus: "accepted",
|
|
||||||
PipelineID: "reports",
|
|
||||||
Report: []byte(`{"actions":[{"action":"replace_older"}]}`),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
renderer := &recordingRenderer{
|
|
||||||
renderResult: &scriptorium.RenderResult{ExitCode: 0},
|
|
||||||
structuredRunResult: &scriptorium.StructuredRunResult{ExitCode: 0},
|
|
||||||
structuredRunBody: validTodayGeneratedTextJSON(),
|
|
||||||
}
|
}
|
||||||
|
renderer := successfulGeneratedTextRenderer(validTodayGeneratedTextJSON())
|
||||||
|
|
||||||
result, err := GenerateReport(context.Background(), ReportRequest{
|
result, err := GenerateReport(context.Background(), ReportRequest{
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
@@ -941,28 +881,17 @@ func TestGenerateReportSavesFinalMetadataForMarkdownAndGeneratedTextReports(t *t
|
|||||||
|
|
||||||
func TestGenerateTomorrowReportNotificationUsesTomorrowTemplateValues(t *testing.T) {
|
func TestGenerateTomorrowReportNotificationUsesTomorrowTemplateValues(t *testing.T) {
|
||||||
server := dailyBundleServer(t)
|
server := dailyBundleServer(t)
|
||||||
cfg := config.Defaults()
|
cfg := dailyWorkspaceConfig(t, server)
|
||||||
cfg.WeatherAPI.BaseURL = server.URL + "/"
|
|
||||||
cfg.WeatherAPI.Timezone = "America/Chicago"
|
|
||||||
cfg.Workspace.Root = t.TempDir()
|
|
||||||
cfg.Notify.Distributor.Enabled = true
|
cfg.Notify.Distributor.Enabled = true
|
||||||
cfg.Notify.Distributor.PipelineIDTemplate = "weatherreporter.{report_id}.{artifact_group}"
|
cfg.Notify.Distributor.PipelineIDTemplate = "weatherreporter.{report_id}.{artifact_group}"
|
||||||
cfg.Notify.Distributor.BundleIDTemplate = "{artifact_group}.{batch_output_name}.{report_id}"
|
cfg.Notify.Distributor.BundleIDTemplate = "{artifact_group}.{batch_output_name}.{report_id}"
|
||||||
cfg.Notify.Distributor.IdempotencyKeyTemplate = "{bundle_id}.{run_id}"
|
cfg.Notify.Distributor.IdempotencyKeyTemplate = "{bundle_id}.{run_id}"
|
||||||
cfg.Notify.Distributor.ReportPathTemplates = []string{"{valid_start_date}/{artifact_group}/{batch_output_name}"}
|
cfg.Notify.Distributor.ReportPathTemplates = []string{"{valid_start_date}/{artifact_group}/{batch_output_name}"}
|
||||||
resolved, err := ResolveGenerate(GenerateRequest{
|
resolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
Config: cfg,
|
|
||||||
Report: ReportTomorrow,
|
Report: ReportTomorrow,
|
||||||
}, mustParse("2026-05-29T18:00:00-05:00"))
|
}, "2026-05-29T18:00:00-05:00")
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ResolveGenerate() error = %v", err)
|
|
||||||
}
|
|
||||||
notifier := &recordingNotifier{}
|
notifier := &recordingNotifier{}
|
||||||
renderer := &recordingRenderer{
|
renderer := successfulGeneratedTextRenderer(validTomorrowGeneratedTextJSON())
|
||||||
renderResult: &scriptorium.RenderResult{ExitCode: 0},
|
|
||||||
structuredRunResult: &scriptorium.StructuredRunResult{ExitCode: 0},
|
|
||||||
structuredRunBody: validTomorrowGeneratedTextJSON(),
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := GenerateReport(context.Background(), ReportRequest{
|
result, err := GenerateReport(context.Background(), ReportRequest{
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
@@ -1080,15 +1009,11 @@ func TestGenerateHourlyReportPersistsStructuredRunFailure(t *testing.T) {
|
|||||||
|
|
||||||
func TestGenerateHourlyReportPreservesRawTextOnValidationFailure(t *testing.T) {
|
func TestGenerateHourlyReportPreservesRawTextOnValidationFailure(t *testing.T) {
|
||||||
cfg, resolved, store, notifier, outputPath := hourlyGeneratedTextFixture(t)
|
cfg, resolved, store, notifier, outputPath := hourlyGeneratedTextFixture(t)
|
||||||
renderer := &recordingRenderer{
|
renderer := successfulGeneratedTextRenderer(`{
|
||||||
renderResult: &scriptorium.RenderResult{ExitCode: 0},
|
|
||||||
structuredRunResult: &scriptorium.StructuredRunResult{ExitCode: 0},
|
|
||||||
structuredRunBody: `{
|
|
||||||
"summary": "Storm chances increase through late morning.",
|
"summary": "Storm chances increase through late morning.",
|
||||||
"forecast_discussion": "A front will keep the region unsettled.",
|
"forecast_discussion": "A front will keep the region unsettled.",
|
||||||
"details": "not allowed"
|
"details": "not allowed"
|
||||||
}`,
|
}`)
|
||||||
}
|
|
||||||
|
|
||||||
_, err := GenerateReport(context.Background(), ReportRequest{
|
_, err := GenerateReport(context.Background(), ReportRequest{
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
@@ -1116,11 +1041,7 @@ func TestGenerateHourlyReportPreservesRawTextOnValidationFailure(t *testing.T) {
|
|||||||
func TestGenerateHourlyReportRejectsUnsupportedTemplateBeforeStructuredRun(t *testing.T) {
|
func TestGenerateHourlyReportRejectsUnsupportedTemplateBeforeStructuredRun(t *testing.T) {
|
||||||
cfg, resolved, store, notifier, outputPath := hourlyGeneratedTextFixture(t)
|
cfg, resolved, store, notifier, outputPath := hourlyGeneratedTextFixture(t)
|
||||||
resolved.Definition.TemplateID = "missing-template"
|
resolved.Definition.TemplateID = "missing-template"
|
||||||
renderer := &recordingRenderer{
|
renderer := successfulGeneratedTextRenderer(validHourlyGeneratedTextJSON())
|
||||||
renderResult: &scriptorium.RenderResult{ExitCode: 0},
|
|
||||||
structuredRunResult: &scriptorium.StructuredRunResult{ExitCode: 0},
|
|
||||||
structuredRunBody: validHourlyGeneratedTextJSON(),
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := GenerateReport(context.Background(), ReportRequest{
|
_, err := GenerateReport(context.Background(), ReportRequest{
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
@@ -1150,19 +1071,14 @@ func TestGenerateHourlyReportRejectsUnsupportedTemplateBeforeStructuredRun(t *te
|
|||||||
|
|
||||||
func TestGenerateReportDisabledNotificationDoesNotCallNotifier(t *testing.T) {
|
func TestGenerateReportDisabledNotificationDoesNotCallNotifier(t *testing.T) {
|
||||||
server := dailyBundleServer(t)
|
server := dailyBundleServer(t)
|
||||||
cfg := dailyTestConfig(t, server)
|
cfg := dailyWorkspaceConfig(t, server)
|
||||||
cfg.Workspace.Root = t.TempDir()
|
resolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
resolved, err := ResolveGenerate(GenerateRequest{
|
|
||||||
Config: cfg,
|
|
||||||
Report: ReportDaily,
|
Report: ReportDaily,
|
||||||
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
||||||
}, mustParse("2026-05-29T05:00:00-05:00"))
|
}, "2026-05-29T05:00:00-05:00")
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ResolveGenerate() error = %v", err)
|
|
||||||
}
|
|
||||||
notifier := &recordingNotifier{}
|
notifier := &recordingNotifier{}
|
||||||
|
|
||||||
_, err = GenerateReport(context.Background(), ReportRequest{
|
_, err := GenerateReport(context.Background(), ReportRequest{
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
Resolved: resolved,
|
Resolved: resolved,
|
||||||
Renderer: successfulRenderer("# Daily Report\n"),
|
Renderer: successfulRenderer("# Daily Report\n"),
|
||||||
@@ -1178,26 +1094,13 @@ func TestGenerateReportDisabledNotificationDoesNotCallNotifier(t *testing.T) {
|
|||||||
|
|
||||||
func TestGenerateReportNotifiesManagedReportPath(t *testing.T) {
|
func TestGenerateReportNotifiesManagedReportPath(t *testing.T) {
|
||||||
server := dailyBundleServer(t)
|
server := dailyBundleServer(t)
|
||||||
cfg := dailyTestConfig(t, server)
|
cfg := dailyNotificationConfig(t, server)
|
||||||
cfg.Workspace.Root = t.TempDir()
|
resolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
cfg.Notify.Distributor.Enabled = true
|
|
||||||
cfg.Notify.Distributor.PipelineIDTemplate = "weatherreporter.{artifact_group}"
|
|
||||||
resolved, err := ResolveGenerate(GenerateRequest{
|
|
||||||
Config: cfg,
|
|
||||||
Report: ReportDaily,
|
Report: ReportDaily,
|
||||||
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
||||||
}, mustParse("2026-05-29T05:00:00-05:00"))
|
}, "2026-05-29T05:00:00-05:00")
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ResolveGenerate() error = %v", err)
|
|
||||||
}
|
|
||||||
notifier := &recordingNotifier{
|
notifier := &recordingNotifier{
|
||||||
result: &NotificationResult{
|
result: successfulNotificationResult(),
|
||||||
RunID: "distributor-run",
|
|
||||||
Status: "succeeded",
|
|
||||||
UploadStatus: "accepted",
|
|
||||||
PipelineID: "reports",
|
|
||||||
Report: []byte(`{"actions":[{"action":"replace_older"}]}`),
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
outputPath := filepath.Join(t.TempDir(), "daily-copy.md")
|
outputPath := filepath.Join(t.TempDir(), "daily-copy.md")
|
||||||
|
|
||||||
@@ -1266,25 +1169,15 @@ func TestGenerateReportNotifiesManagedReportPath(t *testing.T) {
|
|||||||
|
|
||||||
func TestGenerateReportNotificationFailureFailsReport(t *testing.T) {
|
func TestGenerateReportNotificationFailureFailsReport(t *testing.T) {
|
||||||
server := dailyBundleServer(t)
|
server := dailyBundleServer(t)
|
||||||
cfg := dailyTestConfig(t, server)
|
cfg := dailyNotificationConfig(t, server)
|
||||||
cfg.Workspace.Root = t.TempDir()
|
resolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
cfg.Notify.Distributor.Enabled = true
|
|
||||||
cfg.Notify.Distributor.PipelineIDTemplate = "weatherreporter.{artifact_group}"
|
|
||||||
resolved, err := ResolveGenerate(GenerateRequest{
|
|
||||||
Config: cfg,
|
|
||||||
Report: ReportDaily,
|
Report: ReportDaily,
|
||||||
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
||||||
}, mustParse("2026-05-29T05:00:00-05:00"))
|
}, "2026-05-29T05:00:00-05:00")
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ResolveGenerate() error = %v", err)
|
|
||||||
}
|
|
||||||
notifier := &recordingNotifier{err: errors.New("upload rejected")}
|
notifier := &recordingNotifier{err: errors.New("upload rejected")}
|
||||||
|
|
||||||
store, err := state.NewFilesystemStore(cfg.Workspace)
|
store := recordingFilesystemStore(t, cfg)
|
||||||
if err != nil {
|
_, err := GenerateReport(context.Background(), ReportRequest{
|
||||||
t.Fatalf("NewFilesystemStore() error = %v", err)
|
|
||||||
}
|
|
||||||
_, err = GenerateReport(context.Background(), ReportRequest{
|
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
Resolved: resolved,
|
Resolved: resolved,
|
||||||
Renderer: successfulRenderer("# Daily Report\n"),
|
Renderer: successfulRenderer("# Daily Report\n"),
|
||||||
@@ -1342,21 +1235,14 @@ func TestGenerateReportDoesNotNotifyAfterRenderOrRunFailure(t *testing.T) {
|
|||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
cfg := dailyTestConfig(t, server)
|
cfg := dailyNotificationConfig(t, server)
|
||||||
cfg.Workspace.Root = t.TempDir()
|
resolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
cfg.Notify.Distributor.Enabled = true
|
|
||||||
cfg.Notify.Distributor.PipelineIDTemplate = "weatherreporter.{artifact_group}"
|
|
||||||
resolved, err := ResolveGenerate(GenerateRequest{
|
|
||||||
Config: cfg,
|
|
||||||
Report: ReportDaily,
|
Report: ReportDaily,
|
||||||
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
||||||
}, mustParse("2026-05-29T05:00:00-05:00"))
|
}, "2026-05-29T05:00:00-05:00")
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ResolveGenerate() error = %v", err)
|
|
||||||
}
|
|
||||||
notifier := &recordingNotifier{}
|
notifier := &recordingNotifier{}
|
||||||
|
|
||||||
_, err = GenerateReport(context.Background(), ReportRequest{
|
_, err := GenerateReport(context.Background(), ReportRequest{
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
Resolved: resolved,
|
Resolved: resolved,
|
||||||
Renderer: tt.renderer,
|
Renderer: tt.renderer,
|
||||||
@@ -1379,17 +1265,13 @@ func TestGenerateReportDoesNotNotifyAfterFetchFailure(t *testing.T) {
|
|||||||
cfg.Workspace.Root = t.TempDir()
|
cfg.Workspace.Root = t.TempDir()
|
||||||
cfg.Notify.Distributor.Enabled = true
|
cfg.Notify.Distributor.Enabled = true
|
||||||
cfg.Notify.Distributor.PipelineIDTemplate = "weatherreporter.{artifact_group}"
|
cfg.Notify.Distributor.PipelineIDTemplate = "weatherreporter.{artifact_group}"
|
||||||
resolved, err := ResolveGenerate(GenerateRequest{
|
resolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
Config: cfg,
|
|
||||||
Report: ReportDaily,
|
Report: ReportDaily,
|
||||||
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
||||||
}, mustParse("2026-05-29T05:00:00-05:00"))
|
}, "2026-05-29T05:00:00-05:00")
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ResolveGenerate() error = %v", err)
|
|
||||||
}
|
|
||||||
notifier := &recordingNotifier{}
|
notifier := &recordingNotifier{}
|
||||||
|
|
||||||
_, err = GenerateReport(context.Background(), ReportRequest{
|
_, err := GenerateReport(context.Background(), ReportRequest{
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
Resolved: resolved,
|
Resolved: resolved,
|
||||||
Renderer: successfulRenderer("# Daily Report\n"),
|
Renderer: successfulRenderer("# Daily Report\n"),
|
||||||
@@ -1405,18 +1287,11 @@ func TestGenerateReportDoesNotNotifyAfterFetchFailure(t *testing.T) {
|
|||||||
|
|
||||||
func TestGenerateReportPersistsFailedPreflight(t *testing.T) {
|
func TestGenerateReportPersistsFailedPreflight(t *testing.T) {
|
||||||
server := dailyBundleServer(t)
|
server := dailyBundleServer(t)
|
||||||
cfg := config.Defaults()
|
cfg := dailyWorkspaceConfig(t, server)
|
||||||
cfg.WeatherAPI.BaseURL = server.URL + "/"
|
resolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
cfg.WeatherAPI.Timezone = "America/Chicago"
|
|
||||||
cfg.Workspace.Root = t.TempDir()
|
|
||||||
resolved, err := ResolveGenerate(GenerateRequest{
|
|
||||||
Config: cfg,
|
|
||||||
Report: ReportDaily,
|
Report: ReportDaily,
|
||||||
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
||||||
}, mustParse("2026-05-29T05:00:00-05:00"))
|
}, "2026-05-29T05:00:00-05:00")
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ResolveGenerate() error = %v", err)
|
|
||||||
}
|
|
||||||
renderer := &recordingRenderer{
|
renderer := &recordingRenderer{
|
||||||
renderResult: &scriptorium.RenderResult{
|
renderResult: &scriptorium.RenderResult{
|
||||||
Command: []string{"scriptorium", "render"},
|
Command: []string{"scriptorium", "render"},
|
||||||
@@ -1426,7 +1301,7 @@ func TestGenerateReportPersistsFailedPreflight(t *testing.T) {
|
|||||||
err: errors.New("scriptorium render exited with code 1: render failed"),
|
err: errors.New("scriptorium render exited with code 1: render failed"),
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = GenerateReport(context.Background(), ReportRequest{
|
_, err := GenerateReport(context.Background(), ReportRequest{
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
Resolved: resolved,
|
Resolved: resolved,
|
||||||
Renderer: renderer,
|
Renderer: renderer,
|
||||||
@@ -1434,10 +1309,7 @@ func TestGenerateReportPersistsFailedPreflight(t *testing.T) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("GenerateReport() error = nil, want render error")
|
t.Fatal("GenerateReport() error = nil, want render error")
|
||||||
}
|
}
|
||||||
store, err := state.NewFilesystemStore(cfg.Workspace)
|
store := recordingFilesystemStore(t, cfg)
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("NewFilesystemStore() error = %v", err)
|
|
||||||
}
|
|
||||||
paths, err := store.Paths(resolved)
|
paths, err := store.Paths(resolved)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Paths() error = %v", err)
|
t.Fatalf("Paths() error = %v", err)
|
||||||
@@ -1460,18 +1332,11 @@ func TestGenerateReportPersistsFailedPreflight(t *testing.T) {
|
|||||||
|
|
||||||
func TestGenerateReportReturnsRunErrorAfterPreflight(t *testing.T) {
|
func TestGenerateReportReturnsRunErrorAfterPreflight(t *testing.T) {
|
||||||
server := dailyBundleServer(t)
|
server := dailyBundleServer(t)
|
||||||
cfg := config.Defaults()
|
cfg := dailyWorkspaceConfig(t, server)
|
||||||
cfg.WeatherAPI.BaseURL = server.URL + "/"
|
resolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
cfg.WeatherAPI.Timezone = "America/Chicago"
|
|
||||||
cfg.Workspace.Root = t.TempDir()
|
|
||||||
resolved, err := ResolveGenerate(GenerateRequest{
|
|
||||||
Config: cfg,
|
|
||||||
Report: ReportDaily,
|
Report: ReportDaily,
|
||||||
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
||||||
}, mustParse("2026-05-29T05:00:00-05:00"))
|
}, "2026-05-29T05:00:00-05:00")
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ResolveGenerate() error = %v", err)
|
|
||||||
}
|
|
||||||
renderer := &recordingRenderer{
|
renderer := &recordingRenderer{
|
||||||
renderResult: &scriptorium.RenderResult{ExitCode: 0},
|
renderResult: &scriptorium.RenderResult{ExitCode: 0},
|
||||||
structuredRunResult: &scriptorium.StructuredRunResult{
|
structuredRunResult: &scriptorium.StructuredRunResult{
|
||||||
@@ -1481,7 +1346,7 @@ func TestGenerateReportReturnsRunErrorAfterPreflight(t *testing.T) {
|
|||||||
structuredRunErr: errors.New("scriptorium run exited with code 2: validation failed"),
|
structuredRunErr: errors.New("scriptorium run exited with code 2: validation failed"),
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = GenerateReport(context.Background(), ReportRequest{
|
_, err := GenerateReport(context.Background(), ReportRequest{
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
Resolved: resolved,
|
Resolved: resolved,
|
||||||
Renderer: renderer,
|
Renderer: renderer,
|
||||||
@@ -1492,10 +1357,7 @@ func TestGenerateReportReturnsRunErrorAfterPreflight(t *testing.T) {
|
|||||||
if renderer.renderCalls != 1 || renderer.structuredRunCalls != 1 || renderer.runCalls != 0 {
|
if renderer.renderCalls != 1 || renderer.structuredRunCalls != 1 || renderer.runCalls != 0 {
|
||||||
t.Fatalf("calls render=%d structured=%d run=%d, want render and structured run only", renderer.renderCalls, renderer.structuredRunCalls, renderer.runCalls)
|
t.Fatalf("calls render=%d structured=%d run=%d, want render and structured run only", renderer.renderCalls, renderer.structuredRunCalls, renderer.runCalls)
|
||||||
}
|
}
|
||||||
store, err := state.NewFilesystemStore(cfg.Workspace)
|
store := recordingFilesystemStore(t, cfg)
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("NewFilesystemStore() error = %v", err)
|
|
||||||
}
|
|
||||||
paths, err := store.Paths(resolved)
|
paths, err := store.Paths(resolved)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Paths() error = %v", err)
|
t.Fatalf("Paths() error = %v", err)
|
||||||
@@ -1513,32 +1375,18 @@ func TestGenerateReportReturnsRunErrorAfterPreflight(t *testing.T) {
|
|||||||
|
|
||||||
func TestGenerateReportIncludesRecentChangesFromPriorSnapshot(t *testing.T) {
|
func TestGenerateReportIncludesRecentChangesFromPriorSnapshot(t *testing.T) {
|
||||||
server := dailyBundleServer(t)
|
server := dailyBundleServer(t)
|
||||||
cfg := config.Defaults()
|
cfg := dailyWorkspaceConfig(t, server)
|
||||||
cfg.WeatherAPI.BaseURL = server.URL + "/"
|
store := recordingFilesystemStore(t, cfg)
|
||||||
cfg.WeatherAPI.Timezone = "America/Chicago"
|
priorResolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
cfg.Workspace.Root = t.TempDir()
|
|
||||||
store, err := state.NewFilesystemStore(cfg.Workspace)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("NewFilesystemStore() error = %v", err)
|
|
||||||
}
|
|
||||||
priorResolved, err := ResolveGenerate(GenerateRequest{
|
|
||||||
Config: cfg,
|
|
||||||
Report: ReportDaily,
|
Report: ReportDaily,
|
||||||
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
||||||
}, mustParse("2026-05-29T04:00:00-05:00"))
|
}, "2026-05-29T04:00:00-05:00")
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ResolveGenerate(prior) error = %v", err)
|
|
||||||
}
|
|
||||||
savePriorRun(t, store, priorResolved, priorDailyModuleSnapshot(t, priorResolved))
|
savePriorRun(t, store, priorResolved, priorDailyModuleSnapshot(t, priorResolved))
|
||||||
|
|
||||||
currentResolved, err := ResolveGenerate(GenerateRequest{
|
currentResolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
Config: cfg,
|
|
||||||
Report: ReportDaily,
|
Report: ReportDaily,
|
||||||
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
||||||
}, mustParse("2026-05-29T05:00:00-05:00"))
|
}, "2026-05-29T05:00:00-05:00")
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ResolveGenerate(current) error = %v", err)
|
|
||||||
}
|
|
||||||
renderer := &recordingRenderer{
|
renderer := &recordingRenderer{
|
||||||
renderResult: &scriptorium.RenderResult{ExitCode: 0},
|
renderResult: &scriptorium.RenderResult{ExitCode: 0},
|
||||||
runResult: &scriptorium.RunResult{ExitCode: 0},
|
runResult: &scriptorium.RunResult{ExitCode: 0},
|
||||||
@@ -1568,37 +1416,19 @@ func TestGenerateReportIncludesRecentChangesFromPriorSnapshot(t *testing.T) {
|
|||||||
|
|
||||||
func TestGenerateTodayReportUsesTodayIdentityAndRecentChanges(t *testing.T) {
|
func TestGenerateTodayReportUsesTodayIdentityAndRecentChanges(t *testing.T) {
|
||||||
server := dailyBundleServer(t)
|
server := dailyBundleServer(t)
|
||||||
cfg := config.Defaults()
|
cfg := dailyWorkspaceConfig(t, server)
|
||||||
cfg.WeatherAPI.BaseURL = server.URL + "/"
|
store := recordingFilesystemStore(t, cfg)
|
||||||
cfg.WeatherAPI.Timezone = "America/Chicago"
|
priorResolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
cfg.Workspace.Root = t.TempDir()
|
|
||||||
store, err := state.NewFilesystemStore(cfg.Workspace)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("NewFilesystemStore() error = %v", err)
|
|
||||||
}
|
|
||||||
priorResolved, err := ResolveGenerate(GenerateRequest{
|
|
||||||
Config: cfg,
|
|
||||||
Report: ReportToday,
|
Report: ReportToday,
|
||||||
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
||||||
}, mustParse("2026-05-29T04:00:00-05:00"))
|
}, "2026-05-29T04:00:00-05:00")
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ResolveGenerate(prior) error = %v", err)
|
|
||||||
}
|
|
||||||
savePriorRun(t, store, priorResolved, priorDailyModuleSnapshot(t, priorResolved))
|
savePriorRun(t, store, priorResolved, priorDailyModuleSnapshot(t, priorResolved))
|
||||||
|
|
||||||
currentResolved, err := ResolveGenerate(GenerateRequest{
|
currentResolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
Config: cfg,
|
|
||||||
Report: ReportToday,
|
Report: ReportToday,
|
||||||
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
||||||
}, mustParse("2026-05-29T05:00:00-05:00"))
|
}, "2026-05-29T05:00:00-05:00")
|
||||||
if err != nil {
|
renderer := successfulGeneratedTextRenderer(validTodayGeneratedTextJSON())
|
||||||
t.Fatalf("ResolveGenerate(current) error = %v", err)
|
|
||||||
}
|
|
||||||
renderer := &recordingRenderer{
|
|
||||||
renderResult: &scriptorium.RenderResult{ExitCode: 0},
|
|
||||||
structuredRunResult: &scriptorium.StructuredRunResult{ExitCode: 0},
|
|
||||||
structuredRunBody: validTodayGeneratedTextJSON(),
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := GenerateReport(context.Background(), ReportRequest{
|
result, err := GenerateReport(context.Background(), ReportRequest{
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
@@ -1655,22 +1485,11 @@ func TestGenerateTodayReportUsesTodayIdentityAndRecentChanges(t *testing.T) {
|
|||||||
|
|
||||||
func TestGenerateTomorrowReportUsesTomorrowBriefingDate(t *testing.T) {
|
func TestGenerateTomorrowReportUsesTomorrowBriefingDate(t *testing.T) {
|
||||||
server := dailyBundleServer(t)
|
server := dailyBundleServer(t)
|
||||||
cfg := config.Defaults()
|
cfg := dailyWorkspaceConfig(t, server)
|
||||||
cfg.WeatherAPI.BaseURL = server.URL + "/"
|
resolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
cfg.WeatherAPI.Timezone = "America/Chicago"
|
|
||||||
cfg.Workspace.Root = t.TempDir()
|
|
||||||
resolved, err := ResolveGenerate(GenerateRequest{
|
|
||||||
Config: cfg,
|
|
||||||
Report: ReportTomorrow,
|
Report: ReportTomorrow,
|
||||||
}, mustParse("2026-05-29T18:00:00-05:00"))
|
}, "2026-05-29T18:00:00-05:00")
|
||||||
if err != nil {
|
renderer := successfulGeneratedTextRenderer(validTomorrowGeneratedTextJSON())
|
||||||
t.Fatalf("ResolveGenerate() error = %v", err)
|
|
||||||
}
|
|
||||||
renderer := &recordingRenderer{
|
|
||||||
renderResult: &scriptorium.RenderResult{ExitCode: 0},
|
|
||||||
structuredRunResult: &scriptorium.StructuredRunResult{ExitCode: 0},
|
|
||||||
structuredRunBody: validTomorrowGeneratedTextJSON(),
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := GenerateReport(context.Background(), ReportRequest{
|
result, err := GenerateReport(context.Background(), ReportRequest{
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
@@ -1732,35 +1551,17 @@ func TestGenerateTomorrowReportUsesTomorrowBriefingDate(t *testing.T) {
|
|||||||
|
|
||||||
func TestTomorrowReportCanCompareAgainstPriorTomorrowSnapshot(t *testing.T) {
|
func TestTomorrowReportCanCompareAgainstPriorTomorrowSnapshot(t *testing.T) {
|
||||||
server := dailyBundleServer(t)
|
server := dailyBundleServer(t)
|
||||||
cfg := config.Defaults()
|
cfg := dailyWorkspaceConfig(t, server)
|
||||||
cfg.WeatherAPI.BaseURL = server.URL + "/"
|
store := recordingFilesystemStore(t, cfg)
|
||||||
cfg.WeatherAPI.Timezone = "America/Chicago"
|
priorResolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
cfg.Workspace.Root = t.TempDir()
|
|
||||||
store, err := state.NewFilesystemStore(cfg.Workspace)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("NewFilesystemStore() error = %v", err)
|
|
||||||
}
|
|
||||||
priorResolved, err := ResolveGenerate(GenerateRequest{
|
|
||||||
Config: cfg,
|
|
||||||
Report: ReportTomorrow,
|
Report: ReportTomorrow,
|
||||||
}, mustParse("2026-05-29T17:00:00-05:00"))
|
}, "2026-05-29T17:00:00-05:00")
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ResolveGenerate(prior) error = %v", err)
|
|
||||||
}
|
|
||||||
savePriorRun(t, store, priorResolved, priorDailyModuleSnapshot(t, priorResolved))
|
savePriorRun(t, store, priorResolved, priorDailyModuleSnapshot(t, priorResolved))
|
||||||
|
|
||||||
currentResolved, err := ResolveGenerate(GenerateRequest{
|
currentResolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
Config: cfg,
|
|
||||||
Report: ReportTomorrow,
|
Report: ReportTomorrow,
|
||||||
}, mustParse("2026-05-29T18:00:00-05:00"))
|
}, "2026-05-29T18:00:00-05:00")
|
||||||
if err != nil {
|
renderer := successfulGeneratedTextRenderer(validTomorrowGeneratedTextJSON())
|
||||||
t.Fatalf("ResolveGenerate(current) error = %v", err)
|
|
||||||
}
|
|
||||||
renderer := &recordingRenderer{
|
|
||||||
renderResult: &scriptorium.RenderResult{ExitCode: 0},
|
|
||||||
structuredRunResult: &scriptorium.StructuredRunResult{ExitCode: 0},
|
|
||||||
structuredRunBody: validTomorrowGeneratedTextJSON(),
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := GenerateReport(context.Background(), ReportRequest{
|
result, err := GenerateReport(context.Background(), ReportRequest{
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
@@ -1781,31 +1582,17 @@ func TestTomorrowReportCanCompareAgainstPriorTomorrowSnapshot(t *testing.T) {
|
|||||||
|
|
||||||
func TestDailyReportIgnoresPriorTomorrowSnapshot(t *testing.T) {
|
func TestDailyReportIgnoresPriorTomorrowSnapshot(t *testing.T) {
|
||||||
server := dailyBundleServer(t)
|
server := dailyBundleServer(t)
|
||||||
cfg := config.Defaults()
|
cfg := dailyWorkspaceConfig(t, server)
|
||||||
cfg.WeatherAPI.BaseURL = server.URL + "/"
|
store := recordingFilesystemStore(t, cfg)
|
||||||
cfg.WeatherAPI.Timezone = "America/Chicago"
|
priorResolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
cfg.Workspace.Root = t.TempDir()
|
|
||||||
store, err := state.NewFilesystemStore(cfg.Workspace)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("NewFilesystemStore() error = %v", err)
|
|
||||||
}
|
|
||||||
priorResolved, err := ResolveGenerate(GenerateRequest{
|
|
||||||
Config: cfg,
|
|
||||||
Report: ReportTomorrow,
|
Report: ReportTomorrow,
|
||||||
}, mustParse("2026-05-28T18:00:00-05:00"))
|
}, "2026-05-28T18:00:00-05:00")
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ResolveGenerate(prior) error = %v", err)
|
|
||||||
}
|
|
||||||
savePriorRun(t, store, priorResolved, priorDailyModuleSnapshot(t, priorResolved))
|
savePriorRun(t, store, priorResolved, priorDailyModuleSnapshot(t, priorResolved))
|
||||||
|
|
||||||
currentResolved, err := ResolveGenerate(GenerateRequest{
|
currentResolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
Config: cfg,
|
|
||||||
Report: ReportDaily,
|
Report: ReportDaily,
|
||||||
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
||||||
}, mustParse("2026-05-29T05:00:00-05:00"))
|
}, "2026-05-29T05:00:00-05:00")
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ResolveGenerate(current) error = %v", err)
|
|
||||||
}
|
|
||||||
result, err := GenerateReport(context.Background(), ReportRequest{
|
result, err := GenerateReport(context.Background(), ReportRequest{
|
||||||
Config: cfg,
|
Config: cfg,
|
||||||
Resolved: currentResolved,
|
Resolved: currentResolved,
|
||||||
@@ -1825,29 +1612,15 @@ func TestDailyReportIgnoresPriorTomorrowSnapshot(t *testing.T) {
|
|||||||
|
|
||||||
func TestGenerateThreeDayReportWritesReportAndRecentChanges(t *testing.T) {
|
func TestGenerateThreeDayReportWritesReportAndRecentChanges(t *testing.T) {
|
||||||
server := dailyBundleServer(t)
|
server := dailyBundleServer(t)
|
||||||
cfg := config.Defaults()
|
cfg := dailyWorkspaceConfig(t, server)
|
||||||
cfg.WeatherAPI.BaseURL = server.URL + "/"
|
store := recordingFilesystemStore(t, cfg)
|
||||||
cfg.WeatherAPI.Timezone = "America/Chicago"
|
priorResolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
cfg.Workspace.Root = t.TempDir()
|
|
||||||
store, err := state.NewFilesystemStore(cfg.Workspace)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("NewFilesystemStore() error = %v", err)
|
|
||||||
}
|
|
||||||
priorResolved, err := ResolveGenerate(GenerateRequest{
|
|
||||||
Config: cfg,
|
|
||||||
Report: ReportThreeDay,
|
Report: ReportThreeDay,
|
||||||
}, mustParse("2026-05-29T04:00:00-05:00"))
|
}, "2026-05-29T04:00:00-05:00")
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ResolveGenerate(prior) error = %v", err)
|
|
||||||
}
|
|
||||||
savePriorRun(t, store, priorResolved, priorOutlookModuleSnapshot(t, "2026-05-30"))
|
savePriorRun(t, store, priorResolved, priorOutlookModuleSnapshot(t, "2026-05-30"))
|
||||||
currentResolved, err := ResolveGenerate(GenerateRequest{
|
currentResolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
Config: cfg,
|
|
||||||
Report: ReportThreeDay,
|
Report: ReportThreeDay,
|
||||||
}, mustParse("2026-05-29T05:00:00-05:00"))
|
}, "2026-05-29T05:00:00-05:00")
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ResolveGenerate(current) error = %v", err)
|
|
||||||
}
|
|
||||||
renderer := &recordingRenderer{
|
renderer := &recordingRenderer{
|
||||||
renderResult: &scriptorium.RenderResult{ExitCode: 0},
|
renderResult: &scriptorium.RenderResult{ExitCode: 0},
|
||||||
runResult: &scriptorium.RunResult{ExitCode: 0},
|
runResult: &scriptorium.RunResult{ExitCode: 0},
|
||||||
@@ -1884,29 +1657,15 @@ func TestGenerateThreeDayReportWritesReportAndRecentChanges(t *testing.T) {
|
|||||||
|
|
||||||
func TestGenerateWeekendReportWritesReportAndRecentChanges(t *testing.T) {
|
func TestGenerateWeekendReportWritesReportAndRecentChanges(t *testing.T) {
|
||||||
server := dailyBundleServer(t)
|
server := dailyBundleServer(t)
|
||||||
cfg := config.Defaults()
|
cfg := dailyWorkspaceConfig(t, server)
|
||||||
cfg.WeatherAPI.BaseURL = server.URL + "/"
|
store := recordingFilesystemStore(t, cfg)
|
||||||
cfg.WeatherAPI.Timezone = "America/Chicago"
|
priorResolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
cfg.Workspace.Root = t.TempDir()
|
|
||||||
store, err := state.NewFilesystemStore(cfg.Workspace)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("NewFilesystemStore() error = %v", err)
|
|
||||||
}
|
|
||||||
priorResolved, err := ResolveGenerate(GenerateRequest{
|
|
||||||
Config: cfg,
|
|
||||||
Report: ReportWeekend,
|
Report: ReportWeekend,
|
||||||
}, mustParse("2026-05-29T04:00:00-05:00"))
|
}, "2026-05-29T04:00:00-05:00")
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ResolveGenerate(prior) error = %v", err)
|
|
||||||
}
|
|
||||||
savePriorRun(t, store, priorResolved, priorOutlookModuleSnapshot(t, "2026-05-30"))
|
savePriorRun(t, store, priorResolved, priorOutlookModuleSnapshot(t, "2026-05-30"))
|
||||||
currentResolved, err := ResolveGenerate(GenerateRequest{
|
currentResolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
Config: cfg,
|
|
||||||
Report: ReportWeekend,
|
Report: ReportWeekend,
|
||||||
}, mustParse("2026-05-29T05:00:00-05:00"))
|
}, "2026-05-29T05:00:00-05:00")
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ResolveGenerate(current) error = %v", err)
|
|
||||||
}
|
|
||||||
renderer := &recordingRenderer{
|
renderer := &recordingRenderer{
|
||||||
renderResult: &scriptorium.RenderResult{ExitCode: 0},
|
renderResult: &scriptorium.RenderResult{ExitCode: 0},
|
||||||
runResult: &scriptorium.RunResult{ExitCode: 0},
|
runResult: &scriptorium.RunResult{ExitCode: 0},
|
||||||
@@ -1943,19 +1702,12 @@ func TestGenerateWeekendReportWritesReportAndRecentChanges(t *testing.T) {
|
|||||||
|
|
||||||
func TestGenerateStormReportWritesReport(t *testing.T) {
|
func TestGenerateStormReportWritesReport(t *testing.T) {
|
||||||
server := dailyBundleServer(t)
|
server := dailyBundleServer(t)
|
||||||
cfg := config.Defaults()
|
cfg := dailyWorkspaceConfig(t, server)
|
||||||
cfg.WeatherAPI.BaseURL = server.URL + "/"
|
resolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
cfg.WeatherAPI.Timezone = "America/Chicago"
|
|
||||||
cfg.Workspace.Root = t.TempDir()
|
|
||||||
resolved, err := ResolveGenerate(GenerateRequest{
|
|
||||||
Config: cfg,
|
|
||||||
Report: ReportStorm,
|
Report: ReportStorm,
|
||||||
StormStart: mustParse("2026-05-29T06:00:00-05:00"),
|
StormStart: mustParse("2026-05-29T06:00:00-05:00"),
|
||||||
StormEnd: mustParse("2026-05-29T10:00:00-05:00"),
|
StormEnd: mustParse("2026-05-29T10:00:00-05:00"),
|
||||||
}, mustParse("2026-05-29T05:00:00-05:00"))
|
}, "2026-05-29T05:00:00-05:00")
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ResolveGenerate() error = %v", err)
|
|
||||||
}
|
|
||||||
renderer := &recordingRenderer{
|
renderer := &recordingRenderer{
|
||||||
renderResult: &scriptorium.RenderResult{ExitCode: 0},
|
renderResult: &scriptorium.RenderResult{ExitCode: 0},
|
||||||
runResult: &scriptorium.RunResult{ExitCode: 0},
|
runResult: &scriptorium.RunResult{ExitCode: 0},
|
||||||
@@ -1993,18 +1745,11 @@ func TestGenerateStormReportWritesReport(t *testing.T) {
|
|||||||
|
|
||||||
func TestInspectGeneratedReportArtifacts(t *testing.T) {
|
func TestInspectGeneratedReportArtifacts(t *testing.T) {
|
||||||
server := dailyBundleServer(t)
|
server := dailyBundleServer(t)
|
||||||
cfg := config.Defaults()
|
cfg := dailyWorkspaceConfig(t, server)
|
||||||
cfg.WeatherAPI.BaseURL = server.URL + "/"
|
resolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
cfg.WeatherAPI.Timezone = "America/Chicago"
|
|
||||||
cfg.Workspace.Root = t.TempDir()
|
|
||||||
resolved, err := ResolveGenerate(GenerateRequest{
|
|
||||||
Config: cfg,
|
|
||||||
Report: ReportDaily,
|
Report: ReportDaily,
|
||||||
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
||||||
}, mustParse("2026-05-29T05:00:00-05:00"))
|
}, "2026-05-29T05:00:00-05:00")
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ResolveGenerate() error = %v", err)
|
|
||||||
}
|
|
||||||
renderer := &recordingRenderer{
|
renderer := &recordingRenderer{
|
||||||
renderResult: &scriptorium.RenderResult{ExitCode: 0},
|
renderResult: &scriptorium.RenderResult{ExitCode: 0},
|
||||||
runResult: &scriptorium.RunResult{ExitCode: 0},
|
runResult: &scriptorium.RunResult{ExitCode: 0},
|
||||||
@@ -2061,30 +1806,16 @@ func TestInspectGeneratedReportArtifacts(t *testing.T) {
|
|||||||
|
|
||||||
func TestInspectPriorSnapshot(t *testing.T) {
|
func TestInspectPriorSnapshot(t *testing.T) {
|
||||||
server := dailyBundleServer(t)
|
server := dailyBundleServer(t)
|
||||||
cfg := config.Defaults()
|
cfg := dailyWorkspaceConfig(t, server)
|
||||||
cfg.WeatherAPI.BaseURL = server.URL + "/"
|
store := recordingFilesystemStore(t, cfg)
|
||||||
cfg.WeatherAPI.Timezone = "America/Chicago"
|
priorResolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
cfg.Workspace.Root = t.TempDir()
|
|
||||||
store, err := state.NewFilesystemStore(cfg.Workspace)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("NewFilesystemStore() error = %v", err)
|
|
||||||
}
|
|
||||||
priorResolved, err := ResolveGenerate(GenerateRequest{
|
|
||||||
Config: cfg,
|
|
||||||
Report: ReportDaily,
|
Report: ReportDaily,
|
||||||
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
||||||
}, mustParse("2026-05-29T04:00:00-05:00"))
|
}, "2026-05-29T04:00:00-05:00")
|
||||||
if err != nil {
|
currentResolved := resolveGenerateForTest(t, cfg, GenerateRequest{
|
||||||
t.Fatalf("ResolveGenerate(prior) error = %v", err)
|
|
||||||
}
|
|
||||||
currentResolved, err := ResolveGenerate(GenerateRequest{
|
|
||||||
Config: cfg,
|
|
||||||
Report: ReportDaily,
|
Report: ReportDaily,
|
||||||
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
Date: mustParse("2026-05-29T12:00:00-05:00"),
|
||||||
}, mustParse("2026-05-29T05:00:00-05:00"))
|
}, "2026-05-29T05:00:00-05:00")
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ResolveGenerate(current) error = %v", err)
|
|
||||||
}
|
|
||||||
renderer := &recordingRenderer{
|
renderer := &recordingRenderer{
|
||||||
renderResult: &scriptorium.RenderResult{ExitCode: 0},
|
renderResult: &scriptorium.RenderResult{ExitCode: 0},
|
||||||
runResult: &scriptorium.RunResult{ExitCode: 0},
|
runResult: &scriptorium.RunResult{ExitCode: 0},
|
||||||
@@ -2381,10 +2112,7 @@ func TestResolveBatchMorningSkipsWeekendOnSunday(t *testing.T) {
|
|||||||
|
|
||||||
func TestRunBatchContinuesAfterReportFailure(t *testing.T) {
|
func TestRunBatchContinuesAfterReportFailure(t *testing.T) {
|
||||||
server := dailyBundleServer(t)
|
server := dailyBundleServer(t)
|
||||||
cfg := config.Defaults()
|
cfg := dailyWorkspaceConfig(t, server)
|
||||||
cfg.WeatherAPI.BaseURL = server.URL + "/"
|
|
||||||
cfg.WeatherAPI.Timezone = "America/Chicago"
|
|
||||||
cfg.Workspace.Root = t.TempDir()
|
|
||||||
renderer := &selectiveRenderer{
|
renderer := &selectiveRenderer{
|
||||||
failRenderPrompt: "weather.three_day_outlook",
|
failRenderPrompt: "weather.three_day_outlook",
|
||||||
runBody: "# Batch Report\n",
|
runBody: "# Batch Report\n",
|
||||||
@@ -2422,12 +2150,7 @@ func TestRunBatchContinuesAfterReportFailure(t *testing.T) {
|
|||||||
|
|
||||||
func TestRunBatchContinuesAfterNotificationFailure(t *testing.T) {
|
func TestRunBatchContinuesAfterNotificationFailure(t *testing.T) {
|
||||||
server := dailyBundleServer(t)
|
server := dailyBundleServer(t)
|
||||||
cfg := config.Defaults()
|
cfg := dailyNotificationConfig(t, server)
|
||||||
cfg.WeatherAPI.BaseURL = server.URL + "/"
|
|
||||||
cfg.WeatherAPI.Timezone = "America/Chicago"
|
|
||||||
cfg.Workspace.Root = t.TempDir()
|
|
||||||
cfg.Notify.Distributor.Enabled = true
|
|
||||||
cfg.Notify.Distributor.PipelineIDTemplate = "weatherreporter.{artifact_group}"
|
|
||||||
notifier := &recordingNotifier{
|
notifier := &recordingNotifier{
|
||||||
errByReport: map[report.ID]error{
|
errByReport: map[report.ID]error{
|
||||||
report.ThreeDay: errors.New("distributor unavailable"),
|
report.ThreeDay: errors.New("distributor unavailable"),
|
||||||
@@ -2507,10 +2230,7 @@ func TestRunBatchContinuesAfterNotificationFailure(t *testing.T) {
|
|||||||
|
|
||||||
func TestRunBatchUsesOutputDirectory(t *testing.T) {
|
func TestRunBatchUsesOutputDirectory(t *testing.T) {
|
||||||
server := dailyBundleServer(t)
|
server := dailyBundleServer(t)
|
||||||
cfg := config.Defaults()
|
cfg := dailyWorkspaceConfig(t, server)
|
||||||
cfg.WeatherAPI.BaseURL = server.URL + "/"
|
|
||||||
cfg.WeatherAPI.Timezone = "America/Chicago"
|
|
||||||
cfg.Workspace.Root = t.TempDir()
|
|
||||||
outputDir := filepath.Join(t.TempDir(), "reports")
|
outputDir := filepath.Join(t.TempDir(), "reports")
|
||||||
|
|
||||||
result, err := RunBatchDetailed(context.Background(), BatchRequest{
|
result, err := RunBatchDetailed(context.Background(), BatchRequest{
|
||||||
@@ -2548,10 +2268,7 @@ func TestRunBatchUsesOutputDirectory(t *testing.T) {
|
|||||||
|
|
||||||
func TestRunBatchMorningUsesTodayOutputName(t *testing.T) {
|
func TestRunBatchMorningUsesTodayOutputName(t *testing.T) {
|
||||||
server := dailyBundleServer(t)
|
server := dailyBundleServer(t)
|
||||||
cfg := config.Defaults()
|
cfg := dailyWorkspaceConfig(t, server)
|
||||||
cfg.WeatherAPI.BaseURL = server.URL + "/"
|
|
||||||
cfg.WeatherAPI.Timezone = "America/Chicago"
|
|
||||||
cfg.Workspace.Root = t.TempDir()
|
|
||||||
outputDir := filepath.Join(t.TempDir(), "reports")
|
outputDir := filepath.Join(t.TempDir(), "reports")
|
||||||
|
|
||||||
result, err := RunBatchDetailed(context.Background(), BatchRequest{
|
result, err := RunBatchDetailed(context.Background(), BatchRequest{
|
||||||
@@ -2617,6 +2334,70 @@ func dailyTestConfig(t *testing.T, server *httptest.Server) config.Config {
|
|||||||
return cfg
|
return cfg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func dailyWorkspaceConfig(t *testing.T, server *httptest.Server) config.Config {
|
||||||
|
t.Helper()
|
||||||
|
cfg := dailyTestConfig(t, server)
|
||||||
|
cfg.Workspace.Root = t.TempDir()
|
||||||
|
return cfg
|
||||||
|
}
|
||||||
|
|
||||||
|
func dailyNotificationConfig(t *testing.T, server *httptest.Server) config.Config {
|
||||||
|
t.Helper()
|
||||||
|
cfg := dailyWorkspaceConfig(t, server)
|
||||||
|
cfg.Notify.Distributor.Enabled = true
|
||||||
|
cfg.Notify.Distributor.PipelineIDTemplate = "weatherreporter.{artifact_group}"
|
||||||
|
return cfg
|
||||||
|
}
|
||||||
|
|
||||||
|
func resolveGenerateForTest(t *testing.T, cfg config.Config, req GenerateRequest, now string) report.Resolved {
|
||||||
|
t.Helper()
|
||||||
|
req.Config = cfg
|
||||||
|
resolved, err := ResolveGenerate(req, mustParse(now))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("ResolveGenerate() error = %v", err)
|
||||||
|
}
|
||||||
|
return resolved
|
||||||
|
}
|
||||||
|
|
||||||
|
func recordingFilesystemStore(t *testing.T, cfg config.Config) *recordingStore {
|
||||||
|
t.Helper()
|
||||||
|
filesystemStore, err := state.NewFilesystemStore(cfg.Workspace)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("NewFilesystemStore() error = %v", err)
|
||||||
|
}
|
||||||
|
return &recordingStore{Store: filesystemStore}
|
||||||
|
}
|
||||||
|
|
||||||
|
func successfulNotificationResult() *NotificationResult {
|
||||||
|
return &NotificationResult{
|
||||||
|
RunID: "distributor-run",
|
||||||
|
Status: "succeeded",
|
||||||
|
UploadStatus: "accepted",
|
||||||
|
PipelineID: "reports",
|
||||||
|
Report: []byte(`{"actions":[{"action":"replace_older"}]}`),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func successfulGeneratedTextRenderer(body string) *recordingRenderer {
|
||||||
|
return &recordingRenderer{
|
||||||
|
renderResult: &scriptorium.RenderResult{ExitCode: 0},
|
||||||
|
structuredRunResult: &scriptorium.StructuredRunResult{ExitCode: 0},
|
||||||
|
structuredRunBody: body,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func hourlyTestConfig(t *testing.T, server *httptest.Server) config.Config {
|
||||||
|
t.Helper()
|
||||||
|
cfg := config.Defaults()
|
||||||
|
cfg.WeatherAPI.BaseURL = server.URL + "/"
|
||||||
|
cfg.WeatherAPI.Timezone = "America/Chicago"
|
||||||
|
cfg.Workspace.Root = t.TempDir()
|
||||||
|
cfg.Location.ID = "home"
|
||||||
|
cfg.Location.Name = "Brentwood"
|
||||||
|
cfg.Location.Region = "MO"
|
||||||
|
return cfg
|
||||||
|
}
|
||||||
|
|
||||||
func hourlyGeneratedTextFixture(t *testing.T) (config.Config, report.Resolved, *recordingStore, *recordingNotifier, string) {
|
func hourlyGeneratedTextFixture(t *testing.T) (config.Config, report.Resolved, *recordingStore, *recordingNotifier, string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
server := hourlyBundleServer(t)
|
server := hourlyBundleServer(t)
|
||||||
@@ -2653,12 +2434,10 @@ func hourlyGeneratedTextConfigWithModules(t *testing.T, server *httptest.Server,
|
|||||||
|
|
||||||
func applyHourlyGeneratedTextSettings(cfg *config.Config, t *testing.T, server *httptest.Server) {
|
func applyHourlyGeneratedTextSettings(cfg *config.Config, t *testing.T, server *httptest.Server) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
cfg.WeatherAPI.BaseURL = server.URL + "/"
|
base := hourlyTestConfig(t, server)
|
||||||
cfg.WeatherAPI.Timezone = "America/Chicago"
|
cfg.WeatherAPI = base.WeatherAPI
|
||||||
cfg.Workspace.Root = t.TempDir()
|
cfg.Workspace = base.Workspace
|
||||||
cfg.Location.ID = "home"
|
cfg.Location = base.Location
|
||||||
cfg.Location.Name = "Brentwood"
|
|
||||||
cfg.Location.Region = "MO"
|
|
||||||
cfg.Notify.Distributor.Enabled = true
|
cfg.Notify.Distributor.Enabled = true
|
||||||
cfg.Notify.Distributor.PipelineIDTemplate = "weatherreporter.{artifact_group}"
|
cfg.Notify.Distributor.PipelineIDTemplate = "weatherreporter.{artifact_group}"
|
||||||
cfg.Notify.Distributor.BundleIDTemplate = "weatherreporter.{location_id}.{report_id}"
|
cfg.Notify.Distributor.BundleIDTemplate = "weatherreporter.{location_id}.{report_id}"
|
||||||
@@ -2668,18 +2447,8 @@ func applyHourlyGeneratedTextSettings(cfg *config.Config, t *testing.T, server *
|
|||||||
|
|
||||||
func resolveHourlyGeneratedTextFixture(t *testing.T, cfg config.Config) (report.Resolved, *recordingStore, *recordingNotifier, string) {
|
func resolveHourlyGeneratedTextFixture(t *testing.T, cfg config.Config) (report.Resolved, *recordingStore, *recordingNotifier, string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
resolved, err := ResolveGenerate(GenerateRequest{
|
resolved := resolveGenerateForTest(t, cfg, GenerateRequest{Report: ReportHourly}, "2026-05-29T08:30:00-05:00")
|
||||||
Config: cfg,
|
return resolved, recordingFilesystemStore(t, cfg), &recordingNotifier{}, filepath.Join(t.TempDir(), "hourly-copy.md")
|
||||||
Report: ReportHourly,
|
|
||||||
}, mustParse("2026-05-29T08:30:00-05:00"))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("ResolveGenerate() error = %v", err)
|
|
||||||
}
|
|
||||||
filesystemStore, err := state.NewFilesystemStore(cfg.Workspace)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("NewFilesystemStore() error = %v", err)
|
|
||||||
}
|
|
||||||
return resolved, &recordingStore{Store: filesystemStore}, &recordingNotifier{}, filepath.Join(t.TempDir(), "hourly-copy.md")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func validHourlyGeneratedTextJSON() string {
|
func validHourlyGeneratedTextJSON() string {
|
||||||
|
|||||||
Reference in New Issue
Block a user