TestStatsE2E exercises `flow stats` against a real (but temp) flow root: empty stats succeed, --card writes a file, and a garbage --since value returns exit code 2.
(t *testing.T)
| 14 | // empty stats succeed, --card writes a file, and a garbage --since value |
| 15 | // returns exit code 2. |
| 16 | func TestStatsE2E(t *testing.T) { |
| 17 | tmp := t.TempDir() |
| 18 | flowRoot := filepath.Join(tmp, "flow") |
| 19 | t.Setenv("FLOW_ROOT", flowRoot) |
| 20 | t.Setenv("HOME", tmp) |
| 21 | |
| 22 | // Mirror the same stubs as TestE2EFullRoundtrip so cmdInit doesn't try |
| 23 | // to touch real ~/.claude or run osascript. |
| 24 | oldOverride := spawner.Override |
| 25 | spawner.Override = spawner.BackendITerm |
| 26 | t.Cleanup(func() { spawner.Override = oldOverride }) |
| 27 | |
| 28 | oldOsa := iterm.Runner |
| 29 | iterm.Runner = func(args []string) error { return nil } |
| 30 | t.Cleanup(func() { iterm.Runner = oldOsa }) |
| 31 | |
| 32 | oldClaude := claude.SkipPermissionsRunner |
| 33 | claude.SkipPermissionsRunner = func(prompt string) error { return nil } |
| 34 | t.Cleanup(func() { claude.SkipPermissionsRunner = oldClaude }) |
| 35 | |
| 36 | oldNewUUID := claude.NewUUID |
| 37 | claude.NewUUID = func() (string, error) { return "stats-e2e-uuid", nil } |
| 38 | t.Cleanup(func() { claude.NewUUID = oldNewUUID }) |
| 39 | |
| 40 | // init — creates the tree, db, and skill files. |
| 41 | if rc := cmdInit(nil); rc != 0 { |
| 42 | t.Fatalf("init rc=%d", rc) |
| 43 | } |
| 44 | |
| 45 | // stats on an empty-but-initialized root must succeed (all zeros, no panic). |
| 46 | if rc := cmdStats(nil); rc != 0 { |
| 47 | t.Fatalf("stats rc=%d, want 0", rc) |
| 48 | } |
| 49 | |
| 50 | // --card writes a file and exits 0. |
| 51 | card := filepath.Join(flowRoot, "card.html") |
| 52 | if rc := cmdStats([]string{"--card", "--out", card}); rc != 0 { |
| 53 | t.Fatalf("stats --card rc=%d, want 0", rc) |
| 54 | } |
| 55 | if _, err := os.Stat(card); err != nil { |
| 56 | t.Fatalf("card not written: %v", err) |
| 57 | } |
| 58 | |
| 59 | // A garbage --since value is a usage error (rc=2). |
| 60 | if rc := cmdStats([]string{"--since", "garbage"}); rc != 2 { |
| 61 | t.Fatalf("bad --since rc=%d, want 2", rc) |
| 62 | } |
| 63 | } |
| 64 | |
| 65 | // TestE2EFullRoundtrip exercises the full command surface in the order a |
| 66 | // user would hit it for a realistic session: init, add project, add task |