4
4
"bytes"
5
5
"errors"
6
6
"fmt"
7
+ "strings"
7
8
"testing"
8
9
9
10
"github.com/google/go-cmp/cmp"
@@ -39,6 +40,12 @@ type (
39
40
40
41
// TestCaseTemplates is a suit of testCaseTemplates.
41
42
TestCaseTemplates []TestCaseTemplate
43
+
44
+ // HelpInfo contains information obtained from help message.
45
+ HelpInfo struct {
46
+ CommandName string
47
+ Subcommands []string
48
+ }
42
49
)
43
50
44
51
// OutputShouldBe returns a check for output.
@@ -52,6 +59,34 @@ func OutputShouldBe(expected string) OutputCheck {
52
59
}
53
60
}
54
61
62
+ // HelpShouldShowCommandName returns a check for command name.
63
+ func HelpShouldShowCommandName (name string ) OutputCheck {
64
+ return func (t * testing.T , output string ) {
65
+ t .Helper ()
66
+
67
+ help := ParseHelp (t , output )
68
+
69
+ if help .CommandName != name {
70
+ t .Errorf ("expected %v, but actual %v" , name , help .CommandName )
71
+ }
72
+ }
73
+ }
74
+
75
+ // HelpShouldShowSubcommands returns a check for subcommands.
76
+ func HelpShouldShowSubcommands (subcommands []string ) OutputCheck {
77
+ return func (t * testing.T , output string ) {
78
+ t .Helper ()
79
+
80
+ help := ParseHelp (t , output )
81
+
82
+ for _ , subcommand := range subcommands {
83
+ if ! Contains (subcommand , help .Subcommands ) {
84
+ t .Errorf ("subcommand %v is not included in %v" , subcommand , help .Subcommands )
85
+ }
86
+ }
87
+ }
88
+ }
89
+
55
90
// ErrorShouldBe returns a check for error.
56
91
func ErrorShouldBe (expected error ) ErrorCheck {
57
92
return func (t * testing.T , err error ) {
@@ -158,17 +193,81 @@ func (cts TestCaseTemplates) Build(cmdBuilder func() *cobra.Command) TestCases {
158
193
return TestCases (testCases )
159
194
}
160
195
161
- // RootSucceeds returns a template which tests if the root succeeds.
162
- func RootSucceeds ( ) TestCaseTemplate {
196
+ // HasName returns a template which tests if the root -h succeeds and shows the name .
197
+ func HasName ( name string ) TestCaseTemplate {
163
198
return TestCaseTemplate {
164
- Name : "root succeeds" ,
199
+ Name : fmt .Sprintf ("root has Name %s" , name ),
200
+ Args : []string {"-h" },
201
+ OutputCheck : HelpShouldShowCommandName (name ),
165
202
}
166
203
}
167
204
168
- // HasSubcommand returns a template which tests if it has the subcommand and it succeeds.
169
- func HasSubcommand ( name string ) TestCaseTemplate {
205
+ // HasSubcommands returns a template which tests if it has the subcommand and it succeeds.
206
+ func HasSubcommands ( subcommands ... string ) TestCaseTemplate {
170
207
return TestCaseTemplate {
171
- Name : fmt .Sprintf ("has Subcommand %s and it succeeds" , name ),
172
- Args : []string {name },
208
+ Name : fmt .Sprintf ("has Subcommands %s and it succeeds" , subcommands ),
209
+ Args : []string {"-h" },
210
+ OutputCheck : HelpShouldShowSubcommands (subcommands ),
211
+ }
212
+ }
213
+
214
+ // ParseHelp parses a help message.
215
+ func ParseHelp (t * testing.T , helpMessage string ) HelpInfo {
216
+ t .Helper ()
217
+
218
+ lines := strings .Split (helpMessage , "\n " )
219
+
220
+ literal := map [string ][]string {}
221
+
222
+ i := 0
223
+ for i < len (lines ) {
224
+ if lines [i ] == "" {
225
+ i ++
226
+
227
+ continue
228
+ }
229
+
230
+ if ! strings .HasSuffix (lines [i ], ":" ) {
231
+ i ++
232
+
233
+ continue
234
+ }
235
+
236
+ key := strings .TrimSuffix (lines [i ], ":" )
237
+ i ++
238
+
239
+ for j := i ; j < len (lines ); j ++ {
240
+ if ! strings .HasPrefix (lines [j ], " " ) {
241
+ break
242
+ }
243
+
244
+ literal [key ] = append (literal [key ], strings .TrimSpace (lines [j ]))
245
+ }
173
246
}
247
+
248
+ if len (literal ["Usage" ]) == 0 {
249
+ t .Fatal ("help message has no Usage section" )
250
+ }
251
+
252
+ cmdName := strings .Fields (literal ["Usage" ][0 ])[0 ]
253
+
254
+ subcommands := []string {}
255
+ for _ , cmdDescriptions := range literal ["Available Commands" ] {
256
+ subcommands = append (subcommands , strings .Fields (cmdDescriptions )[0 ])
257
+ }
258
+
259
+ return HelpInfo {
260
+ CommandName : cmdName ,
261
+ Subcommands : subcommands ,
262
+ }
263
+ }
264
+
265
+ func Contains (str string , arr []string ) bool {
266
+ for _ , elem := range arr {
267
+ if str == elem {
268
+ return true
269
+ }
270
+ }
271
+
272
+ return false
174
273
}
0 commit comments