Skip to content

Commit 5954776

Browse files
committed
test(cli): cover the concurrent-incidents section of incident-summary.sh
The fake fduty now answers `--json` calls with a fixed start_time so the seventh section runs: assert the eight invocations, the exact ±15 min window passed to `incident list`, and that the other reads still use their compact defaults. A second case drops start_time and checks the section prints its SKIPPED marker with the manual command instead.
1 parent e1193be commit 5954776

1 file changed

Lines changed: 53 additions & 13 deletions

File tree

‎internal/cli/incident_summary_script_test.go‎

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ import (
99
"testing"
1010
)
1111

12-
func TestIncidentSummaryScriptCompactOutput(t *testing.T) {
12+
// runIncidentSummaryScript runs skills/flashduty/scripts/incident-summary.sh against a fake
13+
// fduty that logs every invocation. detailJSON is what the fake prints for `--json` calls; every
14+
// other call prints a one-line placeholder.
15+
func runIncidentSummaryScript(t *testing.T, detailJSON string) (output string, calls []string) {
16+
t.Helper()
1317
if runtime.GOOS == "windows" {
1418
t.Skip("Bash fixture is unavailable on Windows")
1519
}
@@ -19,31 +23,67 @@ func TestIncidentSummaryScriptCompactOutput(t *testing.T) {
1923
t.Fatalf("resolve repository root: %v", err)
2024
}
2125
script := filepath.Join(root, "skills", "flashduty", "scripts", "incident-summary.sh")
22-
log := filepath.Join(t.TempDir(), "fduty.log")
23-
bin := filepath.Join(t.TempDir(), "fduty")
24-
if err := os.WriteFile(bin, []byte("#!/usr/bin/env bash\nprintf '%s\\n' \"$*\" >> \"$FDUTY_LOG\"\nprintf 'compact result\\n'\n"), 0o755); err != nil {
26+
dir := t.TempDir()
27+
log := filepath.Join(dir, "fduty.log")
28+
bin := filepath.Join(dir, "fduty")
29+
fake := "#!/usr/bin/env bash\n" +
30+
"printf '%s\\n' \"$*\" >> \"$FDUTY_LOG\"\n" +
31+
"case \" $* \" in\n" +
32+
" *' --json '*) printf '%s\\n' \"$FDUTY_DETAIL_JSON\" ;;\n" +
33+
" *) printf 'compact result\\n' ;;\n" +
34+
"esac\n"
35+
if err := os.WriteFile(bin, []byte(fake), 0o755); err != nil {
2536
t.Fatalf("write fake fduty: %v", err)
2637
}
2738
t.Setenv("FDUTY_LOG", log)
39+
t.Setenv("FDUTY_DETAIL_JSON", detailJSON)
2840
t.Setenv("PATH", filepath.Dir(bin)+string(os.PathListSeparator)+os.Getenv("PATH"))
2941

30-
output, err := exec.Command("bash", script, "inc-1").CombinedOutput()
42+
out, err := exec.Command("bash", script, "inc-1").CombinedOutput()
3143
if err != nil {
32-
t.Fatalf("run incident summary: %v\n%s", err, output)
44+
t.Fatalf("run incident summary: %v\n%s", err, out)
3345
}
3446
invocations, err := os.ReadFile(log)
3547
if err != nil {
3648
t.Fatalf("read fake fduty log: %v", err)
3749
}
38-
lines := strings.FieldsFunc(strings.TrimSpace(string(invocations)), func(r rune) bool { return r == '\n' })
39-
if len(lines) != 6 {
40-
t.Fatalf("fduty calls = %d, want 6:\n%s", len(lines), invocations)
50+
calls = strings.FieldsFunc(strings.TrimSpace(string(invocations)), func(r rune) bool { return r == '\n' })
51+
return string(out), calls
52+
}
53+
54+
func TestIncidentSummaryScriptCompactOutput(t *testing.T) {
55+
// 2026-01-01T00:00:00Z = 1767225600; the concurrent-incidents window is ±15 min around it.
56+
_, calls := runIncidentSummaryScript(t, `{"incident_id":"inc-1","start_time":"2026-01-01T00:00:00Z"}`)
57+
if len(calls) != 8 {
58+
t.Fatalf("fduty calls = %d, want 8:\n%s", len(calls), strings.Join(calls, "\n"))
4159
}
4260
wantDetail := "incident detail inc-1 --fields incident_id,title,incident_severity,progress,ai_summary,root_cause,resolution,alert_cnt,start_time,channel_id --output-format toon"
43-
if lines[0] != wantDetail {
44-
t.Fatalf("detail call = %q, want compact projection %q", lines[0], wantDetail)
61+
if calls[0] != wantDetail {
62+
t.Fatalf("detail call = %q, want compact projection %q", calls[0], wantDetail)
63+
}
64+
if strings.Contains(strings.Join(calls[1:6], "\n"), "--output-format toon") {
65+
t.Fatalf("non-detail reads force raw toon instead of their compact defaults:\n%s", strings.Join(calls, "\n"))
66+
}
67+
if calls[6] != "incident detail inc-1 --json" {
68+
t.Fatalf("start_time probe = %q, want %q", calls[6], "incident detail inc-1 --json")
69+
}
70+
// ⑦ is a projected read like ①: explicit --fields keeps full titles and the num/channel_id
71+
// columns the card tells the agent to reason from, so toon is the compact form here.
72+
wantConcurrent := "incident list --since 1767224700 --until 1767226500 --limit 50 --fields incident_id,num,title,incident_severity,progress,start_time,channel_id --output-format toon"
73+
if calls[7] != wantConcurrent {
74+
t.Fatalf("concurrent-incidents call = %q, want %q", calls[7], wantConcurrent)
75+
}
76+
}
77+
78+
func TestIncidentSummaryScriptSkipsConcurrentWithoutStartTime(t *testing.T) {
79+
output, calls := runIncidentSummaryScript(t, `{"incident_id":"inc-1"}`)
80+
if len(calls) != 7 {
81+
t.Fatalf("fduty calls = %d, want 7 (six reads + the start_time probe, no list):\n%s", len(calls), strings.Join(calls, "\n"))
82+
}
83+
if !strings.Contains(output, "⑦ concurrent incidents: SKIPPED") {
84+
t.Fatalf("output lacks the SKIPPED marker for ⑦:\n%s", output)
4585
}
46-
if strings.Contains(strings.Join(lines[1:], "\n"), "--output-format toon") {
47-
t.Fatalf("non-detail reads force raw toon instead of their compact defaults:\n%s", invocations)
86+
if !strings.Contains(output, "fduty incident list --since <start-15m> --until <start+15m>") {
87+
t.Fatalf("SKIPPED marker lacks the manual command:\n%s", output)
4888
}
4989
}

0 commit comments

Comments
 (0)