11package main
22
33import (
4- "bytes"
54 "os"
6- "runtime"
5+ "os/exec"
6+ "path/filepath"
77 "strings"
88 "testing"
9-
10- "github.com/nilock/tuido/utils"
119)
1210
13- func TestShowVersionInfo (t * testing.T ) {
14- // Capture stdout
15- oldStdout := os .Stdout
16- r , w , _ := os .Pipe ()
17- os .Stdout = w
18-
19- showVersionInfo ()
20-
21- w .Close ()
22- os .Stdout = oldStdout
23-
24- var buf bytes.Buffer
25- buf .ReadFrom (r )
26- output := buf .String ()
27-
28- // Test that output contains expected components
29- expectedVersion := utils .Version ()
30- expectedPlatform := runtime .GOOS + "/" + runtime .GOARCH
31- expectedAsset := utils .BuildAssetName (expectedVersion , runtime .GOOS , runtime .GOARCH )
32-
33- if ! strings .Contains (output , expectedVersion ) {
34- t .Errorf ("Output should contain version %s, got: %s" , expectedVersion , output )
35- }
36-
37- if ! strings .Contains (output , expectedPlatform ) {
38- t .Errorf ("Output should contain platform %s, got: %s" , expectedPlatform , output )
39- }
40-
41- if ! strings .Contains (output , expectedAsset ) {
42- t .Errorf ("Output should contain asset name %s, got: %s" , expectedAsset , output )
11+ // buildBinary compiles tuido into a temp dir and returns the binary path.
12+ func buildBinary (t * testing.T ) string {
13+ t .Helper ()
14+ bin := filepath .Join (t .TempDir (), "tuido" )
15+ out , err := exec .Command ("go" , "build" , "-o" , bin , "." ).CombinedOutput ()
16+ if err != nil {
17+ t .Fatalf ("build failed: %v\n %s" , err , out )
4318 }
19+ return bin
20+ }
4421
45- // Test that output has the expected structure
46- lines := strings .Split (strings .TrimSpace (output ), "\n " )
47- if len (lines ) < 3 {
48- t .Errorf ("Expected at least 3 lines of output, got %d: %s" , len (lines ), output )
22+ // TestListCollapsesFileScopedItems asserts that `tuido list` collapses a file
23+ // containing a ##file control item down to that control item (plus a child
24+ // rollup), and does NOT emit the file-scoped siblings individually.
25+ func TestListCollapsesFileScopedItems (t * testing.T ) {
26+ bin := buildBinary (t )
27+
28+ work := t .TempDir ()
29+ content := strings .Join ([]string {
30+ "[@] Ship the parser rewrite ##file" ,
31+ "[x] sketch the grammar" ,
32+ "[ ] write the lexer" ,
33+ "[ ] write the parser" ,
34+ "[ ] wire up errors" ,
35+ }, "\n " ) + "\n "
36+ if err := os .WriteFile (filepath .Join (work , "TODO.md" ), []byte (content ), 0644 ); err != nil {
37+ t .Fatal (err )
4938 }
5039
51- // Test first line format
52- if ! strings . HasPrefix ( lines [ 0 ], "tuido " ) {
53- t .Errorf ( "First line should start with 'tuido ', got : %s" , lines [ 0 ] )
40+ out , err := exec . Command ( bin , "list" , work ). CombinedOutput ()
41+ if err != nil {
42+ t .Fatalf ( "list failed : %v \n % s" , err , out )
5443 }
44+ got := string (out )
5545
56- // Test second line format
57- if ! strings .HasPrefix ( lines [ 1 ] , "Platform: " ) {
58- t .Errorf ("Second line should start with 'Platform: ' , got: %s" , lines [ 1 ] )
46+ // the control item's text is shown...
47+ if ! strings .Contains ( got , "Ship the parser rewrite " ) {
48+ t .Errorf ("expected control item in output , got:\n %s" , got )
5949 }
60-
61- // Test third line format
62- if ! strings .HasPrefix (lines [2 ], "Asset: " ) {
63- t .Errorf ("Third line should start with 'Asset: ', got: %s" , lines [2 ])
50+ // ...with a child rollup (3 open/ongoing of 4 children)
51+ if ! strings .Contains (got , "3 of 4" ) {
52+ t .Errorf ("expected child rollup '3 of 4' in output, got:\n %s" , got )
6453 }
65-
66- // Test fourth line format (Available or error message)
67- if len (lines ) >= 4 {
68- if ! strings .HasPrefix (lines [3 ], "Available: " ) {
69- t .Errorf ("Fourth line should start with 'Available: ', got: %s" , lines [3 ])
54+ // but the file-scoped children must NOT be listed individually
55+ for _ , child := range []string {"write the lexer" , "write the parser" , "wire up errors" } {
56+ if strings .Contains (got , child ) {
57+ t .Errorf ("child %q should be collapsed behind the control item, got:\n %s" , child , got )
7058 }
7159 }
7260}
7361
74- func TestVersionInfoContainsExpectedAssetName (t * testing.T ) {
75- version := utils .Version ()
76- goos := runtime .GOOS
77- goarch := runtime .GOARCH
78-
79- expectedAsset := utils .BuildAssetName (version , goos , goarch )
80-
81- // Capture stdout
82- oldStdout := os .Stdout
83- r , w , _ := os .Pipe ()
84- os .Stdout = w
85-
86- showVersionInfo ()
87-
88- w .Close ()
89- os .Stdout = oldStdout
90-
91- var buf bytes.Buffer
92- buf .ReadFrom (r )
93- output := buf .String ()
94-
95- if ! strings .Contains (output , expectedAsset ) {
96- t .Errorf ("Version info should contain asset name %s, but output was: %s" , expectedAsset , output )
97- }
98- }
99-
100- func TestVersionInfoResilience (t * testing.T ) {
101- // This test ensures that even if network calls fail,
102- // the basic version info is still displayed
103-
104- // Capture stdout
105- oldStdout := os .Stdout
106- r , w , _ := os .Pipe ()
107- os .Stdout = w
108-
109- showVersionInfo ()
110-
111- w .Close ()
112- os .Stdout = oldStdout
113-
114- var buf bytes.Buffer
115- buf .ReadFrom (r )
116- output := buf .String ()
117-
118- // Even if network fails, we should still get basic info
119- if ! strings .Contains (output , "tuido" ) {
120- t .Error ("Output should always contain 'tuido' even on network failure" )
62+ // TestListUncontrolledFileUnchanged asserts that files WITHOUT a control item
63+ // still list every item, ie collapse is opt-in.
64+ func TestListUncontrolledFileUnchanged (t * testing.T ) {
65+ bin := buildBinary (t )
66+
67+ work := t .TempDir ()
68+ content := strings .Join ([]string {
69+ "[ ] buy milk" ,
70+ "[ ] call the dentist" ,
71+ }, "\n " ) + "\n "
72+ if err := os .WriteFile (filepath .Join (work , "list.md" ), []byte (content ), 0644 ); err != nil {
73+ t .Fatal (err )
12174 }
12275
123- if ! strings .Contains (output , "Platform:" ) {
124- t .Error ("Output should always contain 'Platform:' even on network failure" )
76+ out , err := exec .Command (bin , "list" , work ).CombinedOutput ()
77+ if err != nil {
78+ t .Fatalf ("list failed: %v\n %s" , err , out )
12579 }
80+ got := string (out )
12681
127- if ! strings .Contains (output , "Asset:" ) {
128- t .Error ("Output should always contain 'Asset:' even on network failure" )
129- }
130-
131- // Should either show "Available:" with asset info or error message
132- hasAvailable := strings .Contains (output , "Available:" )
133- if ! hasAvailable {
134- t .Error ("Output should contain 'Available:' line with either asset info or error message" )
82+ for _ , item := range []string {"buy milk" , "call the dentist" } {
83+ if ! strings .Contains (got , item ) {
84+ t .Errorf ("expected %q in output of uncontrolled file, got:\n %s" , item , got )
85+ }
13586 }
136- }
87+ }
0 commit comments