Clean up CLI test setup
This commit is contained in:
@@ -65,17 +65,13 @@ func TestRunUnknownCommand(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRunGenerateStormWritesMarkdownReport(t *testing.T) {
|
||||
server := dailyServer(t)
|
||||
tempDir := t.TempDir()
|
||||
scriptoriumPath := writeFakeScriptorium(t, tempDir)
|
||||
workspaceRoot := filepath.Join(tempDir, "workspace")
|
||||
configPath := writeTestConfig(t, server, scriptoriumPath, workspaceRoot)
|
||||
outPath := filepath.Join(tempDir, "storm.md")
|
||||
fixture := newCLIFixture(t, writeFakeScriptorium)
|
||||
outPath := fixture.path("storm.md")
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
|
||||
_, err := runTestCommand(t, runner,
|
||||
"generate", "storm",
|
||||
"--config", configPath,
|
||||
"--config", fixture.configPath,
|
||||
"--start", "2026-05-29T06:00",
|
||||
"--end", "2026-05-29T10:00",
|
||||
"--out", outPath,
|
||||
@@ -84,143 +80,113 @@ func TestRunGenerateStormWritesMarkdownReport(t *testing.T) {
|
||||
t.Fatalf("Run() error = %v", err)
|
||||
}
|
||||
assertFileContains(t, outPath, "# Daily Report")
|
||||
dataPackagePath := oneArtifact(t, workspaceRoot, "data-packages", "storm", "2026-05-29", "*.data_package.yaml")
|
||||
dataPackagePath := oneArtifact(t, fixture.workspaceRoot, "data-packages", "storm", "2026-05-29", "*.data_package.yaml")
|
||||
assertFileContains(t, dataPackagePath, "id: storm")
|
||||
assertFileContains(t, dataPackagePath, "prompt_id: weather.storm_report")
|
||||
}
|
||||
|
||||
func TestRunGenerateTomorrowWritesMarkdownReport(t *testing.T) {
|
||||
server := dailyServer(t)
|
||||
tempDir := t.TempDir()
|
||||
scriptoriumPath := writeFakeScriptorium(t, tempDir)
|
||||
workspaceRoot := filepath.Join(tempDir, "workspace")
|
||||
configPath := writeTestConfig(t, server, scriptoriumPath, workspaceRoot)
|
||||
outPath := filepath.Join(tempDir, "tomorrow.md")
|
||||
fixture := newCLIFixture(t, writeFakeScriptorium)
|
||||
outPath := fixture.path("tomorrow.md")
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
|
||||
_, err := runTestCommand(t, runner,
|
||||
"generate", "tomorrow",
|
||||
"--config", configPath,
|
||||
"--config", fixture.configPath,
|
||||
"--out", outPath,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("Run() error = %v", err)
|
||||
}
|
||||
assertFileContains(t, outPath, "# Saturday's Weather")
|
||||
dataPackagePath := oneArtifact(t, workspaceRoot, "data-packages", "tomorrow", "2026-05-30", "*.data_package.yaml")
|
||||
dataPackagePath := oneArtifact(t, fixture.workspaceRoot, "data-packages", "tomorrow", "2026-05-30", "*.data_package.yaml")
|
||||
assertFileContains(t, dataPackagePath, "id: tomorrow")
|
||||
assertFileContains(t, dataPackagePath, "tomorrow_planning:")
|
||||
reportPath := oneArtifact(t, workspaceRoot, "reports", "tomorrow", "*.md")
|
||||
reportPath := oneArtifact(t, fixture.workspaceRoot, "reports", "tomorrow", "*.md")
|
||||
if !strings.Contains(filepath.Base(reportPath), "tomorrow") {
|
||||
t.Fatalf("managed report = %q, want tomorrow report", reportPath)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunEveningGeneratesTomorrowReport(t *testing.T) {
|
||||
server := dailyServer(t)
|
||||
tempDir := t.TempDir()
|
||||
scriptoriumPath := writeFakeScriptorium(t, tempDir)
|
||||
workspaceRoot := filepath.Join(tempDir, "workspace")
|
||||
configPath := writeTestConfig(t, server, scriptoriumPath, workspaceRoot)
|
||||
fixture := newCLIFixture(t, writeFakeScriptorium)
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
|
||||
_, err := runTestCommand(t, runner,
|
||||
"run", "evening",
|
||||
"--config", configPath,
|
||||
"--config", fixture.configPath,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("Run() error = %v", err)
|
||||
}
|
||||
_ = oneArtifact(t, workspaceRoot, "data-packages", "tomorrow", "2026-05-30", "*.data_package.yaml")
|
||||
reportPath := oneArtifact(t, workspaceRoot, "reports", "tomorrow", "*.md")
|
||||
_ = oneArtifact(t, fixture.workspaceRoot, "data-packages", "tomorrow", "2026-05-30", "*.data_package.yaml")
|
||||
reportPath := oneArtifact(t, fixture.workspaceRoot, "reports", "tomorrow", "*.md")
|
||||
if !strings.Contains(filepath.Base(reportPath), "tomorrow") {
|
||||
t.Fatalf("managed report = %q, want only tomorrow report", reportPath)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRunGenerateThreeDayWritesMarkdownReport(t *testing.T) {
|
||||
server := dailyServer(t)
|
||||
tempDir := t.TempDir()
|
||||
scriptoriumPath := writeFakeScriptorium(t, tempDir)
|
||||
workspaceRoot := filepath.Join(tempDir, "workspace")
|
||||
configPath := writeTestConfig(t, server, scriptoriumPath, workspaceRoot)
|
||||
outPath := filepath.Join(tempDir, "three-day.md")
|
||||
fixture := newCLIFixture(t, writeFakeScriptorium)
|
||||
outPath := fixture.path("three-day.md")
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
|
||||
_, err := runTestCommand(t, runner,
|
||||
"generate", "three-day",
|
||||
"--config", configPath,
|
||||
"--config", fixture.configPath,
|
||||
"--out", outPath,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("Run() error = %v", err)
|
||||
}
|
||||
assertFileContains(t, outPath, "# Daily Report")
|
||||
dataPackagePath := oneArtifact(t, workspaceRoot, "data-packages", "three-day", "2026-05-29", "*.data_package.yaml")
|
||||
dataPackagePath := oneArtifact(t, fixture.workspaceRoot, "data-packages", "three-day", "2026-05-29", "*.data_package.yaml")
|
||||
assertFileContains(t, dataPackagePath, "id: three_day")
|
||||
assertFileContains(t, dataPackagePath, "derived_daypart_summaries:")
|
||||
}
|
||||
|
||||
func TestRunGenerateWeekendWritesMarkdownReport(t *testing.T) {
|
||||
server := dailyServer(t)
|
||||
tempDir := t.TempDir()
|
||||
scriptoriumPath := writeFakeScriptorium(t, tempDir)
|
||||
workspaceRoot := filepath.Join(tempDir, "workspace")
|
||||
configPath := writeTestConfig(t, server, scriptoriumPath, workspaceRoot)
|
||||
outPath := filepath.Join(tempDir, "weekend.md")
|
||||
fixture := newCLIFixture(t, writeFakeScriptorium)
|
||||
outPath := fixture.path("weekend.md")
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
|
||||
_, err := runTestCommand(t, runner,
|
||||
"generate", "weekend",
|
||||
"--config", configPath,
|
||||
"--config", fixture.configPath,
|
||||
"--out", outPath,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("Run() error = %v", err)
|
||||
}
|
||||
assertFileContains(t, outPath, "# Daily Report")
|
||||
dataPackagePath := oneArtifact(t, workspaceRoot, "data-packages", "weekend", "2026-05-29", "*.data_package.yaml")
|
||||
dataPackagePath := oneArtifact(t, fixture.workspaceRoot, "data-packages", "weekend", "2026-05-29", "*.data_package.yaml")
|
||||
assertFileContains(t, dataPackagePath, "id: weekend")
|
||||
assertFileContains(t, dataPackagePath, "derived_daypart_summaries:")
|
||||
}
|
||||
|
||||
func TestRunMorningIncludesWeekendExceptSunday(t *testing.T) {
|
||||
server := dailyServer(t)
|
||||
tempDir := t.TempDir()
|
||||
scriptoriumPath := writeFakeScriptorium(t, tempDir)
|
||||
workspaceRoot := filepath.Join(tempDir, "workspace")
|
||||
configPath := writeTestConfig(t, server, scriptoriumPath, workspaceRoot)
|
||||
fixture := newCLIFixture(t, writeFakeScriptorium)
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
|
||||
_, err := runTestCommand(t, runner,
|
||||
"run", "morning",
|
||||
"--config", configPath,
|
||||
"--config", fixture.configPath,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("Run() error = %v", err)
|
||||
}
|
||||
_ = oneArtifact(t, workspaceRoot, "data-packages", "today", "2026-05-29", "*.data_package.yaml")
|
||||
_ = oneArtifact(t, workspaceRoot, "data-packages", "weekend", "2026-05-29", "*.data_package.yaml")
|
||||
dailyPackages, err := filepath.Glob(filepath.Join(workspaceRoot, "data-packages", "daily", "2026-05-29", "*.data_package.yaml"))
|
||||
if err != nil {
|
||||
t.Fatalf("glob daily packages: %v", err)
|
||||
}
|
||||
if len(dailyPackages) != 0 {
|
||||
t.Fatalf("daily packages = %#v, want morning batch to use Today only", dailyPackages)
|
||||
}
|
||||
_ = oneArtifact(t, fixture.workspaceRoot, "data-packages", "today", "2026-05-29", "*.data_package.yaml")
|
||||
_ = oneArtifact(t, fixture.workspaceRoot, "data-packages", "weekend", "2026-05-29", "*.data_package.yaml")
|
||||
noArtifacts(t, fixture.workspaceRoot, "data-packages", "daily", "2026-05-29", "*.data_package.yaml")
|
||||
}
|
||||
|
||||
func TestRunMorningReportsPartialFailureAndContinues(t *testing.T) {
|
||||
server := dailyServer(t)
|
||||
tempDir := t.TempDir()
|
||||
scriptoriumPath := writeFailingScriptorium(t, tempDir)
|
||||
workspaceRoot := filepath.Join(tempDir, "workspace")
|
||||
configPath := writeTestConfig(t, server, scriptoriumPath, workspaceRoot)
|
||||
fixture := newCLIFixture(t, writeFailingScriptorium)
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
|
||||
output, err := runTestCommand(t, runner,
|
||||
"run", "morning",
|
||||
"--config", configPath,
|
||||
"--config", fixture.configPath,
|
||||
)
|
||||
if err == nil {
|
||||
t.Fatal("Run() error = nil, want aggregate failure")
|
||||
@@ -239,8 +205,8 @@ func TestRunMorningReportsPartialFailureAndContinues(t *testing.T) {
|
||||
if !strings.Contains(output.stderr, "status=failed") || !strings.Contains(output.stderr, "status=succeeded") {
|
||||
t.Fatalf("stderr missing structured report logs:\n%s", output.stderr)
|
||||
}
|
||||
_ = oneArtifact(t, workspaceRoot, "data-packages", "today", "2026-05-29", "*.data_package.yaml")
|
||||
_ = oneArtifact(t, workspaceRoot, "data-packages", "weekend", "2026-05-29", "*.data_package.yaml")
|
||||
_ = oneArtifact(t, fixture.workspaceRoot, "data-packages", "today", "2026-05-29", "*.data_package.yaml")
|
||||
_ = oneArtifact(t, fixture.workspaceRoot, "data-packages", "weekend", "2026-05-29", "*.data_package.yaml")
|
||||
}
|
||||
|
||||
func TestBatchOutputIncludesNotificationDetails(t *testing.T) {
|
||||
@@ -326,17 +292,13 @@ func TestBatchOutputDoesNotExposeSecretLikeNotificationErrors(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRunEveningUsesOutputDirectoryAndSummary(t *testing.T) {
|
||||
server := dailyServer(t)
|
||||
tempDir := t.TempDir()
|
||||
scriptoriumPath := writeFakeScriptorium(t, tempDir)
|
||||
workspaceRoot := filepath.Join(tempDir, "workspace")
|
||||
outputDir := filepath.Join(tempDir, "copies")
|
||||
configPath := writeTestConfig(t, server, scriptoriumPath, workspaceRoot)
|
||||
fixture := newCLIFixture(t, writeFakeScriptorium)
|
||||
outputDir := fixture.path("copies")
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
|
||||
output, err := runTestCommand(t, runner,
|
||||
"run", "evening",
|
||||
"--config", configPath,
|
||||
"--config", fixture.configPath,
|
||||
"--out-dir", outputDir,
|
||||
)
|
||||
if err != nil {
|
||||
@@ -375,12 +337,8 @@ func TestRunEveningReportsNotificationSuccess(t *testing.T) {
|
||||
t.Cleanup(distributorServer.Close)
|
||||
tempDir := t.TempDir()
|
||||
scriptoriumPath := writeFakeScriptorium(t, tempDir)
|
||||
configPath := filepath.Join(tempDir, "config.yml")
|
||||
workspaceRoot := filepath.Join(tempDir, "workspace")
|
||||
configBody := "weather_api:\n base_url: " + server.URL + "/\n timezone: America/Chicago\nscriptorium:\n binary: " + scriptoriumPath + "\nworkspace:\n root: " + workspaceRoot + "\nnotify:\n distributor:\n enabled: true\n endpoint: " + distributorServer.URL + "\n token_env: CLI_DISTRIBUTOR_TOKEN\n pipeline_id_template: weatherreporter.{artifact_group}\n"
|
||||
if err := os.WriteFile(configPath, []byte(configBody), 0o600); err != nil {
|
||||
t.Fatalf("write config: %v", err)
|
||||
}
|
||||
configPath := writeTestConfigWithDistributor(t, server, scriptoriumPath, workspaceRoot, distributorServer.URL)
|
||||
t.Setenv("CLI_DISTRIBUTOR_TOKEN", "cli-secret-token")
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
@@ -421,12 +379,8 @@ func TestRunEveningReportsNotificationFailureWithoutToken(t *testing.T) {
|
||||
t.Cleanup(distributorServer.Close)
|
||||
tempDir := t.TempDir()
|
||||
scriptoriumPath := writeFakeScriptorium(t, tempDir)
|
||||
configPath := filepath.Join(tempDir, "config.yml")
|
||||
workspaceRoot := filepath.Join(tempDir, "workspace")
|
||||
configBody := "weather_api:\n base_url: " + server.URL + "/\n timezone: America/Chicago\nscriptorium:\n binary: " + scriptoriumPath + "\nworkspace:\n root: " + workspaceRoot + "\nnotify:\n distributor:\n enabled: true\n endpoint: " + distributorServer.URL + "\n token_env: CLI_DISTRIBUTOR_TOKEN\n pipeline_id_template: weatherreporter.{artifact_group}\n"
|
||||
if err := os.WriteFile(configPath, []byte(configBody), 0o600); err != nil {
|
||||
t.Fatalf("write config: %v", err)
|
||||
}
|
||||
configPath := writeTestConfigWithDistributor(t, server, scriptoriumPath, workspaceRoot, distributorServer.URL)
|
||||
t.Setenv("CLI_DISTRIBUTOR_TOKEN", "cli-secret-token")
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
@@ -460,61 +414,33 @@ func TestRunEveningReportsNotificationFailureWithoutToken(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRunMorningGeneratesTodayAndThreeDayOnSunday(t *testing.T) {
|
||||
server := dailyServer(t)
|
||||
tempDir := t.TempDir()
|
||||
scriptoriumPath := writeFakeScriptorium(t, tempDir)
|
||||
configPath := filepath.Join(tempDir, "config.yml")
|
||||
workspaceRoot := filepath.Join(tempDir, "workspace")
|
||||
configBody := "weather_api:\n base_url: " + server.URL + "/\n timezone: America/Chicago\nscriptorium:\n binary: " + scriptoriumPath + "\nworkspace:\n root: " + workspaceRoot + "\n"
|
||||
if err := os.WriteFile(configPath, []byte(configBody), 0o600); err != nil {
|
||||
t.Fatalf("write config: %v", err)
|
||||
}
|
||||
fixture := newCLIFixture(t, writeFakeScriptorium)
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
runner := Runner{Clock: timeutil.FixedClock{Time: time.Date(2026, 5, 31, 12, 0, 0, 0, time.UTC)}}
|
||||
|
||||
err := runner.Run(context.Background(), []string{
|
||||
"run", "morning",
|
||||
"--config", configPath,
|
||||
"--config", fixture.configPath,
|
||||
}, &stdout, &stderr)
|
||||
if err != nil {
|
||||
t.Fatalf("Run() error = %v", err)
|
||||
}
|
||||
todayPackages, err := filepath.Glob(filepath.Join(workspaceRoot, "data-packages", "today", "2026-05-31", "*.data_package.yaml"))
|
||||
if err != nil {
|
||||
t.Fatalf("glob today packages: %v", err)
|
||||
}
|
||||
threeDayPackages, err := filepath.Glob(filepath.Join(workspaceRoot, "data-packages", "three-day", "2026-05-31", "*.data_package.yaml"))
|
||||
if err != nil {
|
||||
t.Fatalf("glob 3-day packages: %v", err)
|
||||
}
|
||||
dailyPackages, err := filepath.Glob(filepath.Join(workspaceRoot, "data-packages", "daily", "2026-05-31", "*.data_package.yaml"))
|
||||
if err != nil {
|
||||
t.Fatalf("glob daily packages: %v", err)
|
||||
}
|
||||
if len(todayPackages) != 1 || len(threeDayPackages) != 1 || len(dailyPackages) != 0 {
|
||||
t.Fatalf("today packages = %#v, 3-day packages = %#v, daily packages = %#v; want Today and 3-day only", todayPackages, threeDayPackages, dailyPackages)
|
||||
}
|
||||
_ = oneArtifact(t, fixture.workspaceRoot, "data-packages", "today", "2026-05-31", "*.data_package.yaml")
|
||||
_ = oneArtifact(t, fixture.workspaceRoot, "data-packages", "three-day", "2026-05-31", "*.data_package.yaml")
|
||||
noArtifacts(t, fixture.workspaceRoot, "data-packages", "daily", "2026-05-31", "*.data_package.yaml")
|
||||
}
|
||||
|
||||
func TestRunGenerateDailyWritesMarkdownReport(t *testing.T) {
|
||||
server := dailyServer(t)
|
||||
tempDir := t.TempDir()
|
||||
scriptoriumPath := writeFakeScriptorium(t, tempDir)
|
||||
configPath := filepath.Join(tempDir, "config.yml")
|
||||
workspaceRoot := filepath.Join(tempDir, "workspace")
|
||||
configBody := "weather_api:\n base_url: " + server.URL + "/\n timezone: America/Chicago\nscriptorium:\n binary: " + scriptoriumPath + "\nworkspace:\n root: " + workspaceRoot + "\n"
|
||||
if err := os.WriteFile(configPath, []byte(configBody), 0o600); err != nil {
|
||||
t.Fatalf("write config: %v", err)
|
||||
}
|
||||
outPath := filepath.Join(tempDir, "daily.md")
|
||||
fixture := newCLIFixture(t, writeFakeScriptorium)
|
||||
outPath := fixture.path("daily.md")
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
|
||||
err := runner.Run(context.Background(), []string{
|
||||
"generate", "daily",
|
||||
"--config", configPath,
|
||||
"--config", fixture.configPath,
|
||||
"--date", "2026-05-29",
|
||||
"--tz", "UTC",
|
||||
"--out", outPath,
|
||||
@@ -529,14 +455,8 @@ func TestRunGenerateDailyWritesMarkdownReport(t *testing.T) {
|
||||
if !strings.Contains(string(report), "# Friday's Weather") {
|
||||
t.Fatalf("report output missing markdown:\n%s", string(report))
|
||||
}
|
||||
dataPackageMatches, err := filepath.Glob(filepath.Join(workspaceRoot, "data-packages", "daily", "2026-05-29", "*.data_package.yaml"))
|
||||
if err != nil {
|
||||
t.Fatalf("glob data package: %v", err)
|
||||
}
|
||||
if len(dataPackageMatches) != 1 {
|
||||
t.Fatalf("data package files = %#v, want one", dataPackageMatches)
|
||||
}
|
||||
data, err := os.ReadFile(dataPackageMatches[0])
|
||||
dataPackagePath := oneArtifact(t, fixture.workspaceRoot, "data-packages", "daily", "2026-05-29", "*.data_package.yaml")
|
||||
data, err := os.ReadFile(dataPackagePath)
|
||||
if err != nil {
|
||||
t.Fatalf("read managed data package: %v", err)
|
||||
}
|
||||
@@ -550,31 +470,19 @@ func TestRunGenerateDailyWritesMarkdownReport(t *testing.T) {
|
||||
!strings.Contains(string(data), "timezone: UTC") {
|
||||
t.Fatalf("data package missing configured location with overridden timezone:\n%s", string(data))
|
||||
}
|
||||
preflightMatches, err := filepath.Glob(filepath.Join(workspaceRoot, "preflight", "daily", "2026-05-29", "*.render.json"))
|
||||
if err != nil {
|
||||
t.Fatalf("glob preflight: %v", err)
|
||||
}
|
||||
if len(preflightMatches) != 1 {
|
||||
t.Fatalf("preflight files = %#v, want one render output", preflightMatches)
|
||||
}
|
||||
preflight, err := os.ReadFile(preflightMatches[0])
|
||||
preflightPath := oneArtifact(t, fixture.workspaceRoot, "preflight", "daily", "2026-05-29", "*.render.json")
|
||||
preflight, err := os.ReadFile(preflightPath)
|
||||
if err != nil {
|
||||
t.Fatalf("read preflight: %v", err)
|
||||
}
|
||||
if !strings.Contains(string(preflight), `ok`) {
|
||||
t.Fatalf("preflight missing fake render output:\n%s", string(preflight))
|
||||
}
|
||||
reportMatches, err := filepath.Glob(filepath.Join(workspaceRoot, "reports", "daily", "*.md"))
|
||||
if err != nil {
|
||||
t.Fatalf("glob managed report: %v", err)
|
||||
}
|
||||
if len(reportMatches) != 1 {
|
||||
t.Fatalf("managed reports = %#v, want one", reportMatches)
|
||||
}
|
||||
rawGeneratedTextPath := oneArtifact(t, workspaceRoot, "snapshots", "daily", "2026-05-29", "*.generated_text.raw.json")
|
||||
validatedGeneratedTextPath := oneArtifact(t, workspaceRoot, "snapshots", "daily", "2026-05-29", "*.generated_text.json")
|
||||
renderContextPath := oneArtifact(t, workspaceRoot, "snapshots", "daily", "2026-05-29", "*.render_context.json")
|
||||
metadataPath := oneArtifact(t, workspaceRoot, "snapshots", "daily", "2026-05-29", "*.metadata.json")
|
||||
_ = oneArtifact(t, fixture.workspaceRoot, "reports", "daily", "*.md")
|
||||
rawGeneratedTextPath := oneArtifact(t, fixture.workspaceRoot, "snapshots", "daily", "2026-05-29", "*.generated_text.raw.json")
|
||||
validatedGeneratedTextPath := oneArtifact(t, fixture.workspaceRoot, "snapshots", "daily", "2026-05-29", "*.generated_text.json")
|
||||
renderContextPath := oneArtifact(t, fixture.workspaceRoot, "snapshots", "daily", "2026-05-29", "*.render_context.json")
|
||||
metadataPath := oneArtifact(t, fixture.workspaceRoot, "snapshots", "daily", "2026-05-29", "*.metadata.json")
|
||||
assertFileContains(t, rawGeneratedTextPath, `"summary": "Showers are possible during the selected day."`)
|
||||
assertFileContains(t, validatedGeneratedTextPath, `"summary":"Showers are possible during the selected day."`)
|
||||
assertFileContains(t, renderContextPath, `"Title": "Friday's Weather"`)
|
||||
@@ -582,19 +490,15 @@ func TestRunGenerateDailyWritesMarkdownReport(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRunGenerateTodayWritesGeneratedTextReport(t *testing.T) {
|
||||
server := dailyServer(t)
|
||||
tempDir := t.TempDir()
|
||||
scriptoriumPath := writeStructuredOutputScriptorium(t, tempDir)
|
||||
workspaceRoot := filepath.Join(tempDir, "workspace")
|
||||
configPath := writeTestConfig(t, server, scriptoriumPath, workspaceRoot)
|
||||
outPath := filepath.Join(tempDir, "today.md")
|
||||
fixture := newCLIFixture(t, writeStructuredOutputScriptorium)
|
||||
outPath := fixture.path("today.md")
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
|
||||
err := runner.Run(context.Background(), []string{
|
||||
"generate", "today",
|
||||
"--config", configPath,
|
||||
"--config", fixture.configPath,
|
||||
"--date", "2026-05-29",
|
||||
"--out", outPath,
|
||||
}, &stdout, &stderr)
|
||||
@@ -614,7 +518,7 @@ func TestRunGenerateTodayWritesGeneratedTextReport(t *testing.T) {
|
||||
t.Fatalf("today report output missing %q:\n%s", want, string(report))
|
||||
}
|
||||
}
|
||||
dataPackagePath := oneArtifact(t, workspaceRoot, "data-packages", "today", "2026-05-29", "*.data_package.yaml")
|
||||
dataPackagePath := oneArtifact(t, fixture.workspaceRoot, "data-packages", "today", "2026-05-29", "*.data_package.yaml")
|
||||
dataPackage, err := os.ReadFile(dataPackagePath)
|
||||
if err != nil {
|
||||
t.Fatalf("read managed data package: %v", err)
|
||||
@@ -624,17 +528,11 @@ func TestRunGenerateTodayWritesGeneratedTextReport(t *testing.T) {
|
||||
!strings.Contains(string(dataPackage), "today_planning:") {
|
||||
t.Fatalf("data package output missing Today content:\n%s", string(dataPackage))
|
||||
}
|
||||
dailyPackages, err := filepath.Glob(filepath.Join(workspaceRoot, "data-packages", "daily", "2026-05-29", "*.data_package.yaml"))
|
||||
if err != nil {
|
||||
t.Fatalf("glob daily packages: %v", err)
|
||||
}
|
||||
if len(dailyPackages) != 0 {
|
||||
t.Fatalf("daily packages = %#v, want generate today to stay separate", dailyPackages)
|
||||
}
|
||||
rawGeneratedTextPath := oneArtifact(t, workspaceRoot, "snapshots", "today", "2026-05-29", "*.generated_text.raw.json")
|
||||
validatedGeneratedTextPath := oneArtifact(t, workspaceRoot, "snapshots", "today", "2026-05-29", "*.generated_text.json")
|
||||
renderContextPath := oneArtifact(t, workspaceRoot, "snapshots", "today", "2026-05-29", "*.render_context.json")
|
||||
managedReportPath := oneArtifact(t, workspaceRoot, "reports", "today", "*.md")
|
||||
noArtifacts(t, fixture.workspaceRoot, "data-packages", "daily", "2026-05-29", "*.data_package.yaml")
|
||||
rawGeneratedTextPath := oneArtifact(t, fixture.workspaceRoot, "snapshots", "today", "2026-05-29", "*.generated_text.raw.json")
|
||||
validatedGeneratedTextPath := oneArtifact(t, fixture.workspaceRoot, "snapshots", "today", "2026-05-29", "*.generated_text.json")
|
||||
renderContextPath := oneArtifact(t, fixture.workspaceRoot, "snapshots", "today", "2026-05-29", "*.render_context.json")
|
||||
managedReportPath := oneArtifact(t, fixture.workspaceRoot, "reports", "today", "*.md")
|
||||
assertFileContains(t, rawGeneratedTextPath, `"summary": "Today starts with showers before improving."`)
|
||||
assertFileContains(t, validatedGeneratedTextPath, `"summary":"Today starts with showers before improving."`)
|
||||
assertFileContains(t, renderContextPath, `"Title": "Today's Weather"`)
|
||||
@@ -642,19 +540,15 @@ func TestRunGenerateTodayWritesGeneratedTextReport(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRunGenerateHourlyWritesGeneratedTextReport(t *testing.T) {
|
||||
server := dailyServer(t)
|
||||
tempDir := t.TempDir()
|
||||
scriptoriumPath := writeStructuredOutputScriptorium(t, tempDir)
|
||||
workspaceRoot := filepath.Join(tempDir, "workspace")
|
||||
configPath := writeTestConfig(t, server, scriptoriumPath, workspaceRoot)
|
||||
outPath := filepath.Join(tempDir, "hourly.md")
|
||||
fixture := newCLIFixture(t, writeStructuredOutputScriptorium)
|
||||
outPath := fixture.path("hourly.md")
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
runner := Runner{Clock: timeutil.FixedClock{Time: time.Date(2026, 5, 29, 11, 0, 0, 0, time.UTC)}}
|
||||
|
||||
err := runner.Run(context.Background(), []string{
|
||||
"generate", "hourly",
|
||||
"--config", configPath,
|
||||
"--config", fixture.configPath,
|
||||
"--out", outPath,
|
||||
}, &stdout, &stderr)
|
||||
if err != nil {
|
||||
@@ -674,7 +568,7 @@ func TestRunGenerateHourlyWritesGeneratedTextReport(t *testing.T) {
|
||||
t.Fatalf("report output missing %q:\n%s", want, string(report))
|
||||
}
|
||||
}
|
||||
dataPackagePath := oneArtifact(t, workspaceRoot, "data-packages", "hourly", "2026-05-29", "*.data_package.yaml")
|
||||
dataPackagePath := oneArtifact(t, fixture.workspaceRoot, "data-packages", "hourly", "2026-05-29", "*.data_package.yaml")
|
||||
dataPackage, err := os.ReadFile(dataPackagePath)
|
||||
if err != nil {
|
||||
t.Fatalf("read managed data package: %v", err)
|
||||
@@ -684,10 +578,10 @@ func TestRunGenerateHourlyWritesGeneratedTextReport(t *testing.T) {
|
||||
!strings.Contains(string(dataPackage), "hourly_forecast:") {
|
||||
t.Fatalf("data package output missing hourly content:\n%s", string(dataPackage))
|
||||
}
|
||||
rawGeneratedTextPath := oneArtifact(t, workspaceRoot, "snapshots", "hourly", "2026-05-29", "*.generated_text.raw.json")
|
||||
validatedGeneratedTextPath := oneArtifact(t, workspaceRoot, "snapshots", "hourly", "2026-05-29", "*.generated_text.json")
|
||||
renderContextPath := oneArtifact(t, workspaceRoot, "snapshots", "hourly", "2026-05-29", "*.render_context.json")
|
||||
managedReportPath := oneArtifact(t, workspaceRoot, "reports", "hourly", "*.md")
|
||||
rawGeneratedTextPath := oneArtifact(t, fixture.workspaceRoot, "snapshots", "hourly", "2026-05-29", "*.generated_text.raw.json")
|
||||
validatedGeneratedTextPath := oneArtifact(t, fixture.workspaceRoot, "snapshots", "hourly", "2026-05-29", "*.generated_text.json")
|
||||
renderContextPath := oneArtifact(t, fixture.workspaceRoot, "snapshots", "hourly", "2026-05-29", "*.render_context.json")
|
||||
managedReportPath := oneArtifact(t, fixture.workspaceRoot, "reports", "hourly", "*.md")
|
||||
assertFileContains(t, rawGeneratedTextPath, `"summary": " Storm chances increase through late morning. "`)
|
||||
assertFileContains(t, validatedGeneratedTextPath, `"summary":"Storm chances increase through late morning."`)
|
||||
assertFileContains(t, renderContextPath, `"Report": {`)
|
||||
@@ -699,38 +593,24 @@ func TestRunGenerateHourlyWritesGeneratedTextReport(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRunInspectTodayArtifacts(t *testing.T) {
|
||||
server := dailyServer(t)
|
||||
tempDir := t.TempDir()
|
||||
scriptoriumPath := writeFakeScriptorium(t, tempDir)
|
||||
configPath := filepath.Join(tempDir, "config.yml")
|
||||
workspaceRoot := filepath.Join(tempDir, "workspace")
|
||||
configBody := "weather_api:\n base_url: " + server.URL + "/\n timezone: America/Chicago\nscriptorium:\n binary: " + scriptoriumPath + "\nworkspace:\n root: " + workspaceRoot + "\n"
|
||||
if err := os.WriteFile(configPath, []byte(configBody), 0o600); err != nil {
|
||||
t.Fatalf("write config: %v", err)
|
||||
}
|
||||
fixture := newCLIFixture(t, writeFakeScriptorium)
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
|
||||
err := runner.Run(context.Background(), []string{
|
||||
"generate", "today",
|
||||
"--config", configPath,
|
||||
"--config", fixture.configPath,
|
||||
"--date", "2026-05-29",
|
||||
}, &stdout, &stderr)
|
||||
if err != nil {
|
||||
t.Fatalf("Run(generate) error = %v", err)
|
||||
}
|
||||
dataPackageMatches, err := filepath.Glob(filepath.Join(workspaceRoot, "data-packages", "today", "2026-05-29", "*.data_package.yaml"))
|
||||
if err != nil {
|
||||
t.Fatalf("glob data package: %v", err)
|
||||
}
|
||||
if len(dataPackageMatches) != 1 {
|
||||
t.Fatalf("data package files = %#v, want one", dataPackageMatches)
|
||||
}
|
||||
runID := strings.TrimSuffix(filepath.Base(dataPackageMatches[0]), ".data_package.yaml")
|
||||
dataPackagePath := oneArtifact(t, fixture.workspaceRoot, "data-packages", "today", "2026-05-29", "*.data_package.yaml")
|
||||
runID := strings.TrimSuffix(filepath.Base(dataPackagePath), ".data_package.yaml")
|
||||
|
||||
stdout.Reset()
|
||||
err = runner.Run(context.Background(), []string{"inspect", "reports", "--config", configPath, "--limit", "1"}, &stdout, &stderr)
|
||||
err = runner.Run(context.Background(), []string{"inspect", "reports", "--config", fixture.configPath, "--limit", "1"}, &stdout, &stderr)
|
||||
if err != nil {
|
||||
t.Fatalf("Run(inspect reports) error = %v", err)
|
||||
}
|
||||
@@ -741,7 +621,7 @@ func TestRunInspectTodayArtifacts(t *testing.T) {
|
||||
var sourcesOutput string
|
||||
for _, command := range []string{"metadata", "modules", "data-package", "sources"} {
|
||||
stdout.Reset()
|
||||
err = runner.Run(context.Background(), []string{"inspect", command, "--config", configPath, runID}, &stdout, &stderr)
|
||||
err = runner.Run(context.Background(), []string{"inspect", command, "--config", fixture.configPath, runID}, &stdout, &stderr)
|
||||
if err != nil {
|
||||
t.Fatalf("Run(inspect %s) error = %v", command, err)
|
||||
}
|
||||
@@ -758,38 +638,24 @@ func TestRunInspectTodayArtifacts(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRunInspectGeneratedArtifacts(t *testing.T) {
|
||||
server := dailyServer(t)
|
||||
tempDir := t.TempDir()
|
||||
scriptoriumPath := writeFakeScriptorium(t, tempDir)
|
||||
configPath := filepath.Join(tempDir, "config.yml")
|
||||
workspaceRoot := filepath.Join(tempDir, "workspace")
|
||||
configBody := "weather_api:\n base_url: " + server.URL + "/\n timezone: America/Chicago\nscriptorium:\n binary: " + scriptoriumPath + "\nworkspace:\n root: " + workspaceRoot + "\n"
|
||||
if err := os.WriteFile(configPath, []byte(configBody), 0o600); err != nil {
|
||||
t.Fatalf("write config: %v", err)
|
||||
}
|
||||
fixture := newCLIFixture(t, writeFakeScriptorium)
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
|
||||
err := runner.Run(context.Background(), []string{
|
||||
"generate", "daily",
|
||||
"--config", configPath,
|
||||
"--config", fixture.configPath,
|
||||
"--date", "2026-05-29",
|
||||
}, &stdout, &stderr)
|
||||
if err != nil {
|
||||
t.Fatalf("Run(generate) error = %v", err)
|
||||
}
|
||||
dataPackageMatches, err := filepath.Glob(filepath.Join(workspaceRoot, "data-packages", "daily", "2026-05-29", "*.data_package.yaml"))
|
||||
if err != nil {
|
||||
t.Fatalf("glob data package: %v", err)
|
||||
}
|
||||
if len(dataPackageMatches) != 1 {
|
||||
t.Fatalf("data package files = %#v, want one", dataPackageMatches)
|
||||
}
|
||||
runID := strings.TrimSuffix(filepath.Base(dataPackageMatches[0]), ".data_package.yaml")
|
||||
dataPackagePath := oneArtifact(t, fixture.workspaceRoot, "data-packages", "daily", "2026-05-29", "*.data_package.yaml")
|
||||
runID := strings.TrimSuffix(filepath.Base(dataPackagePath), ".data_package.yaml")
|
||||
|
||||
stdout.Reset()
|
||||
err = runner.Run(context.Background(), []string{"inspect", "reports", "--config", configPath, "--limit", "1"}, &stdout, &stderr)
|
||||
err = runner.Run(context.Background(), []string{"inspect", "reports", "--config", fixture.configPath, "--limit", "1"}, &stdout, &stderr)
|
||||
if err != nil {
|
||||
t.Fatalf("Run(inspect reports) error = %v", err)
|
||||
}
|
||||
@@ -800,7 +666,7 @@ func TestRunInspectGeneratedArtifacts(t *testing.T) {
|
||||
var sourcesOutput string
|
||||
for _, command := range []string{"metadata", "modules", "data-package", "sources"} {
|
||||
stdout.Reset()
|
||||
err = runner.Run(context.Background(), []string{"inspect", command, "--config", configPath, runID}, &stdout, &stderr)
|
||||
err = runner.Run(context.Background(), []string{"inspect", command, "--config", fixture.configPath, runID}, &stdout, &stderr)
|
||||
if err != nil {
|
||||
t.Fatalf("Run(inspect %s) error = %v", command, err)
|
||||
}
|
||||
@@ -818,11 +684,7 @@ func TestRunInspectGeneratedArtifacts(t *testing.T) {
|
||||
|
||||
func TestRunInspectMissingMetadata(t *testing.T) {
|
||||
tempDir := t.TempDir()
|
||||
configPath := filepath.Join(tempDir, "config.yml")
|
||||
configBody := "workspace:\n root: " + filepath.Join(tempDir, "workspace") + "\n"
|
||||
if err := os.WriteFile(configPath, []byte(configBody), 0o600); err != nil {
|
||||
t.Fatalf("write config: %v", err)
|
||||
}
|
||||
configPath := writeWorkspaceConfig(t, filepath.Join(tempDir, "workspace"))
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
@@ -838,11 +700,7 @@ func TestRunInspectMissingMetadata(t *testing.T) {
|
||||
|
||||
func TestRunInspectRunCommandsParseRunIDAndConfig(t *testing.T) {
|
||||
tempDir := t.TempDir()
|
||||
configPath := filepath.Join(tempDir, "config.yml")
|
||||
configBody := "workspace:\n root: " + filepath.Join(tempDir, "workspace") + "\n"
|
||||
if err := os.WriteFile(configPath, []byte(configBody), 0o600); err != nil {
|
||||
t.Fatalf("write config: %v", err)
|
||||
}
|
||||
configPath := writeWorkspaceConfig(t, filepath.Join(tempDir, "workspace"))
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
commands := []string{"metadata", "modules", "data-package", "prior", "sources"}
|
||||
|
||||
@@ -936,10 +794,7 @@ func TestResolveGenerateSupportsEveryReportCommandName(t *testing.T) {
|
||||
|
||||
func TestResolveGenerateHourlyAppliesSharedFlags(t *testing.T) {
|
||||
runner := Runner{Clock: fixedClock()}
|
||||
configPath := filepath.Join(t.TempDir(), "config.yml")
|
||||
if err := os.WriteFile(configPath, []byte("weather_api:\n units: metric\n timezone: UTC\n"), 0o600); err != nil {
|
||||
t.Fatalf("write config: %v", err)
|
||||
}
|
||||
configPath := writeConfigFile(t, "weather_api:\n units: metric\n timezone: UTC\n")
|
||||
|
||||
req, err := runner.resolveGenerate([]string{"hourly", "--config", configPath, "--units", "us", "--tz", "America/Chicago", "--out", "./hourly.md"})
|
||||
if err != nil {
|
||||
@@ -1259,16 +1114,56 @@ func dailyServer(t *testing.T) *httptest.Server {
|
||||
return server
|
||||
}
|
||||
|
||||
func writeTestConfig(t *testing.T, server *httptest.Server, scriptoriumPath string, workspaceRoot string) string {
|
||||
type cliFixture struct {
|
||||
tempDir string
|
||||
workspaceRoot string
|
||||
configPath string
|
||||
}
|
||||
|
||||
func newCLIFixture(t *testing.T, writeScriptorium func(*testing.T, string) string) cliFixture {
|
||||
t.Helper()
|
||||
server := dailyServer(t)
|
||||
tempDir := t.TempDir()
|
||||
scriptoriumPath := writeScriptorium(t, tempDir)
|
||||
workspaceRoot := filepath.Join(tempDir, "workspace")
|
||||
|
||||
return cliFixture{
|
||||
tempDir: tempDir,
|
||||
workspaceRoot: workspaceRoot,
|
||||
configPath: writeTestConfig(t, server, scriptoriumPath, workspaceRoot),
|
||||
}
|
||||
}
|
||||
|
||||
func (f cliFixture) path(name string) string {
|
||||
return filepath.Join(f.tempDir, name)
|
||||
}
|
||||
|
||||
func writeConfigFile(t *testing.T, body string) string {
|
||||
t.Helper()
|
||||
configPath := filepath.Join(t.TempDir(), "config.yml")
|
||||
configBody := "weather_api:\n base_url: " + server.URL + "/\n timezone: America/Chicago\nscriptorium:\n binary: " + scriptoriumPath + "\nworkspace:\n root: " + workspaceRoot + "\n"
|
||||
if err := os.WriteFile(configPath, []byte(configBody), 0o600); err != nil {
|
||||
if err := os.WriteFile(configPath, []byte(body), 0o600); err != nil {
|
||||
t.Fatalf("write config: %v", err)
|
||||
}
|
||||
return configPath
|
||||
}
|
||||
|
||||
func writeTestConfig(t *testing.T, server *httptest.Server, scriptoriumPath string, workspaceRoot string) string {
|
||||
t.Helper()
|
||||
configBody := "weather_api:\n base_url: " + server.URL + "/\n timezone: America/Chicago\nscriptorium:\n binary: " + scriptoriumPath + "\nworkspace:\n root: " + workspaceRoot + "\n"
|
||||
return writeConfigFile(t, configBody)
|
||||
}
|
||||
|
||||
func writeTestConfigWithDistributor(t *testing.T, server *httptest.Server, scriptoriumPath string, workspaceRoot string, distributorEndpoint string) string {
|
||||
t.Helper()
|
||||
configBody := "weather_api:\n base_url: " + server.URL + "/\n timezone: America/Chicago\nscriptorium:\n binary: " + scriptoriumPath + "\nworkspace:\n root: " + workspaceRoot + "\nnotify:\n distributor:\n enabled: true\n endpoint: " + distributorEndpoint + "\n token_env: CLI_DISTRIBUTOR_TOKEN\n pipeline_id_template: weatherreporter.{artifact_group}\n"
|
||||
return writeConfigFile(t, configBody)
|
||||
}
|
||||
|
||||
func writeWorkspaceConfig(t *testing.T, workspaceRoot string) string {
|
||||
t.Helper()
|
||||
return writeConfigFile(t, "workspace:\n root: "+workspaceRoot+"\n")
|
||||
}
|
||||
|
||||
func oneArtifact(t *testing.T, root string, parts ...string) string {
|
||||
t.Helper()
|
||||
matches, err := filepath.Glob(filepath.Join(append([]string{root}, parts...)...))
|
||||
@@ -1281,6 +1176,17 @@ func oneArtifact(t *testing.T, root string, parts ...string) string {
|
||||
return matches[0]
|
||||
}
|
||||
|
||||
func noArtifacts(t *testing.T, root string, parts ...string) {
|
||||
t.Helper()
|
||||
matches, err := filepath.Glob(filepath.Join(append([]string{root}, parts...)...))
|
||||
if err != nil {
|
||||
t.Fatalf("glob artifact: %v", err)
|
||||
}
|
||||
if len(matches) != 0 {
|
||||
t.Fatalf("artifact matches = %#v, want none", matches)
|
||||
}
|
||||
}
|
||||
|
||||
func assertFileContains(t *testing.T, path string, want string) {
|
||||
t.Helper()
|
||||
data, err := os.ReadFile(path)
|
||||
|
||||
Reference in New Issue
Block a user