@@ -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\n printf '%s\\ n' \" $*\" >> \" $FDUTY_LOG\" \n printf '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