11package cmd
22
33import (
4+ "encoding/json"
5+ "io"
46 "testing"
57 "time"
68
9+ "github.com/github/gh-stack/internal/config"
10+ "github.com/github/gh-stack/internal/git"
11+ "github.com/github/gh-stack/internal/stack"
712 "github.com/stretchr/testify/assert"
13+ "github.com/stretchr/testify/require"
814)
915
1016func TestTimeAgo (t * testing.T ) {
@@ -30,3 +36,171 @@ func TestTimeAgo(t *testing.T) {
3036 })
3137 }
3238}
39+
40+ func TestViewJSON (t * testing.T ) {
41+ git .SetOps (& git.MockOps {
42+ IsAncestorFn : func (ancestor , descendant string ) (bool , error ) {
43+ return true , nil // all branches are linear
44+ },
45+ })
46+
47+ tests := []struct {
48+ name string
49+ stack * stack.Stack
50+ currentBranch string
51+ wantTrunk string
52+ wantBranches int
53+ wantCurrent string
54+ }{
55+ {
56+ name : "basic stack with PRs" ,
57+ stack : & stack.Stack {
58+ Prefix : "feat" ,
59+ Trunk : stack.BranchRef {Branch : "main" , Head : "aaa" },
60+ Branches : []stack.BranchRef {
61+ {
62+ Branch : "feat/01" ,
63+ Head : "bbb" ,
64+ Base : "aaa" ,
65+ PullRequest : & stack.PullRequestRef {Number : 42 , URL : "https://github.com/o/r/pull/42" },
66+ },
67+ {
68+ Branch : "feat/02" ,
69+ Head : "ccc" ,
70+ Base : "bbb" ,
71+ PullRequest : & stack.PullRequestRef {Number : 43 , URL : "https://github.com/o/r/pull/43" },
72+ },
73+ },
74+ },
75+ currentBranch : "feat/02" ,
76+ wantTrunk : "main" ,
77+ wantBranches : 2 ,
78+ wantCurrent : "feat/02" ,
79+ },
80+ {
81+ name : "stack with merged branch" ,
82+ stack : & stack.Stack {
83+ Trunk : stack.BranchRef {Branch : "main" , Head : "aaa" },
84+ Branches : []stack.BranchRef {
85+ {
86+ Branch : "layer-1" ,
87+ Head : "bbb" ,
88+ Base : "aaa" ,
89+ PullRequest : & stack.PullRequestRef {Number : 10 , Merged : true },
90+ },
91+ {
92+ Branch : "layer-2" ,
93+ Head : "ccc" ,
94+ Base : "bbb" ,
95+ },
96+ },
97+ },
98+ currentBranch : "layer-2" ,
99+ wantTrunk : "main" ,
100+ wantBranches : 2 ,
101+ wantCurrent : "layer-2" ,
102+ },
103+ {
104+ name : "empty stack" ,
105+ stack : & stack.Stack {
106+ Trunk : stack.BranchRef {Branch : "main" },
107+ Branches : []stack.BranchRef {},
108+ },
109+ currentBranch : "main" ,
110+ wantTrunk : "main" ,
111+ wantBranches : 0 ,
112+ wantCurrent : "main" ,
113+ },
114+ }
115+
116+ for _ , tt := range tests {
117+ t .Run (tt .name , func (t * testing.T ) {
118+ cfg , outR , _ := config .NewTestConfig ()
119+ defer outR .Close ()
120+
121+ err := viewJSON (cfg , tt .stack , tt .currentBranch )
122+ require .NoError (t , err )
123+ cfg .Out .Close ()
124+
125+ raw , err := io .ReadAll (outR )
126+ require .NoError (t , err )
127+
128+ var got viewJSONOutput
129+ err = json .Unmarshal (raw , & got )
130+ require .NoError (t , err , "output should be valid JSON: %s" , string (raw ))
131+
132+ assert .Equal (t , tt .wantTrunk , got .Trunk )
133+ assert .Equal (t , tt .wantCurrent , got .CurrentBranch )
134+ assert .Len (t , got .Branches , tt .wantBranches )
135+ })
136+ }
137+ }
138+
139+ func TestViewJSON_BranchFields (t * testing.T ) {
140+ git .SetOps (& git.MockOps {
141+ IsAncestorFn : func (ancestor , descendant string ) (bool , error ) {
142+ // feat/02 needs rebase
143+ if descendant == "feat/02" {
144+ return false , nil
145+ }
146+ return true , nil
147+ },
148+ })
149+
150+ s := & stack.Stack {
151+ Prefix : "feat" ,
152+ Trunk : stack.BranchRef {Branch : "main" , Head : "aaa111" },
153+ Branches : []stack.BranchRef {
154+ {
155+ Branch : "feat/01" ,
156+ Head : "bbb222" ,
157+ Base : "aaa111" ,
158+ PullRequest : & stack.PullRequestRef {Number : 42 , URL : "https://github.com/o/r/pull/42" , Merged : true },
159+ },
160+ {
161+ Branch : "feat/02" ,
162+ Head : "ccc333" ,
163+ Base : "bbb222" ,
164+ PullRequest : & stack.PullRequestRef {Number : 43 , URL : "https://github.com/o/r/pull/43" },
165+ },
166+ },
167+ }
168+
169+ cfg , outR , _ := config .NewTestConfig ()
170+ defer outR .Close ()
171+
172+ err := viewJSON (cfg , s , "feat/02" )
173+ require .NoError (t , err )
174+ cfg .Out .Close ()
175+
176+ raw , err := io .ReadAll (outR )
177+ require .NoError (t , err )
178+
179+ var got viewJSONOutput
180+ require .NoError (t , json .Unmarshal (raw , & got ))
181+
182+ assert .Equal (t , "feat" , got .Prefix )
183+
184+ // First branch: merged
185+ b0 := got .Branches [0 ]
186+ assert .Equal (t , "feat/01" , b0 .Name )
187+ assert .Equal (t , "bbb222" , b0 .Head )
188+ assert .Equal (t , "aaa111" , b0 .Base )
189+ assert .False (t , b0 .IsCurrent )
190+ assert .True (t , b0 .IsMerged )
191+ assert .False (t , b0 .NeedsRebase , "merged branches should not need rebase" )
192+ require .NotNil (t , b0 .PR )
193+ assert .Equal (t , 42 , b0 .PR .Number )
194+ assert .Equal (t , "MERGED" , b0 .PR .State )
195+ assert .Equal (t , "https://github.com/o/r/pull/42" , b0 .PR .URL )
196+
197+ // Second branch: current, needs rebase
198+ b1 := got .Branches [1 ]
199+ assert .Equal (t , "feat/02" , b1 .Name )
200+ assert .True (t , b1 .IsCurrent )
201+ assert .False (t , b1 .IsMerged )
202+ assert .True (t , b1 .NeedsRebase )
203+ require .NotNil (t , b1 .PR )
204+ assert .Equal (t , 43 , b1 .PR .Number )
205+ assert .Equal (t , "OPEN" , b1 .PR .State )
206+ }
0 commit comments