github.com/andrewhsu/cli/v2@v2.0.1-0.20210910131313-d4b4061f5b89/pkg/cmd/gist/list/list_test.go (about) 1 package list 2 3 import ( 4 "bytes" 5 "fmt" 6 "net/http" 7 "testing" 8 "time" 9 10 "github.com/MakeNowJust/heredoc" 11 "github.com/andrewhsu/cli/v2/internal/config" 12 "github.com/andrewhsu/cli/v2/pkg/cmdutil" 13 "github.com/andrewhsu/cli/v2/pkg/httpmock" 14 "github.com/andrewhsu/cli/v2/pkg/iostreams" 15 "github.com/google/shlex" 16 "github.com/stretchr/testify/assert" 17 ) 18 19 func TestNewCmdList(t *testing.T) { 20 tests := []struct { 21 name string 22 cli string 23 wants ListOptions 24 }{ 25 { 26 name: "no arguments", 27 wants: ListOptions{ 28 Limit: 10, 29 Visibility: "all", 30 }, 31 }, 32 { 33 name: "public", 34 cli: "--public", 35 wants: ListOptions{ 36 Limit: 10, 37 Visibility: "public", 38 }, 39 }, 40 { 41 name: "secret", 42 cli: "--secret", 43 wants: ListOptions{ 44 Limit: 10, 45 Visibility: "secret", 46 }, 47 }, 48 { 49 name: "secret with explicit false value", 50 cli: "--secret=false", 51 wants: ListOptions{ 52 Limit: 10, 53 Visibility: "all", 54 }, 55 }, 56 { 57 name: "public and secret", 58 cli: "--secret --public", 59 wants: ListOptions{ 60 Limit: 10, 61 Visibility: "secret", 62 }, 63 }, 64 { 65 name: "limit", 66 cli: "--limit 30", 67 wants: ListOptions{ 68 Limit: 30, 69 Visibility: "all", 70 }, 71 }, 72 } 73 74 for _, tt := range tests { 75 t.Run(tt.name, func(t *testing.T) { 76 f := &cmdutil.Factory{} 77 78 argv, err := shlex.Split(tt.cli) 79 assert.NoError(t, err) 80 81 var gotOpts *ListOptions 82 cmd := NewCmdList(f, func(opts *ListOptions) error { 83 gotOpts = opts 84 return nil 85 }) 86 cmd.SetArgs(argv) 87 cmd.SetIn(&bytes.Buffer{}) 88 cmd.SetOut(&bytes.Buffer{}) 89 cmd.SetErr(&bytes.Buffer{}) 90 91 _, err = cmd.ExecuteC() 92 assert.NoError(t, err) 93 94 assert.Equal(t, tt.wants.Visibility, gotOpts.Visibility) 95 assert.Equal(t, tt.wants.Limit, gotOpts.Limit) 96 }) 97 } 98 } 99 100 func Test_listRun(t *testing.T) { 101 const query = `query GistList\b` 102 sixHours, _ := time.ParseDuration("6h") 103 sixHoursAgo := time.Now().Add(-sixHours) 104 absTime, _ := time.Parse(time.RFC3339, "2020-07-30T15:24:28Z") 105 106 tests := []struct { 107 name string 108 opts *ListOptions 109 wantOut string 110 stubs func(*httpmock.Registry) 111 nontty bool 112 }{ 113 { 114 name: "no gists", 115 opts: &ListOptions{}, 116 stubs: func(reg *httpmock.Registry) { 117 reg.Register( 118 httpmock.GraphQL(query), 119 httpmock.StringResponse(`{ "data": { "viewer": { 120 "gists": { "nodes": [] } 121 } } }`)) 122 }, 123 wantOut: "", 124 }, 125 { 126 name: "default behavior", 127 opts: &ListOptions{}, 128 stubs: func(reg *httpmock.Registry) { 129 reg.Register( 130 httpmock.GraphQL(query), 131 httpmock.StringResponse(fmt.Sprintf( 132 `{ "data": { "viewer": { "gists": { "nodes": [ 133 { 134 "name": "1234567890", 135 "files": [{ "name": "cool.txt" }], 136 "description": "", 137 "updatedAt": "%[1]v", 138 "isPublic": true 139 }, 140 { 141 "name": "4567890123", 142 "files": [{ "name": "gistfile0.txt" }], 143 "description": "", 144 "updatedAt": "%[1]v", 145 "isPublic": true 146 }, 147 { 148 "name": "2345678901", 149 "files": [ 150 { "name": "gistfile0.txt" }, 151 { "name": "gistfile1.txt" } 152 ], 153 "description": "tea leaves thwart those who court catastrophe", 154 "updatedAt": "%[1]v", 155 "isPublic": false 156 }, 157 { 158 "name": "3456789012", 159 "files": [ 160 { "name": "gistfile0.txt" }, 161 { "name": "gistfile1.txt" }, 162 { "name": "gistfile2.txt" }, 163 { "name": "gistfile3.txt" }, 164 { "name": "gistfile4.txt" }, 165 { "name": "gistfile5.txt" }, 166 { "name": "gistfile6.txt" }, 167 { "name": "gistfile7.txt" }, 168 { "name": "gistfile9.txt" }, 169 { "name": "gistfile10.txt" }, 170 { "name": "gistfile11.txt" } 171 ], 172 "description": "short desc", 173 "updatedAt": "%[1]v", 174 "isPublic": false 175 } 176 ] } } } }`, 177 sixHoursAgo.Format(time.RFC3339), 178 )), 179 ) 180 }, 181 wantOut: heredoc.Doc(` 182 1234567890 cool.txt 1 file public about 6 hours ago 183 4567890123 1 file public about 6 hours ago 184 2345678901 tea leaves thwart those who ... 2 files secret about 6 hours ago 185 3456789012 short desc 11 files secret about 6 hours ago 186 `), 187 }, 188 { 189 name: "with public filter", 190 opts: &ListOptions{Visibility: "public"}, 191 stubs: func(reg *httpmock.Registry) { 192 reg.Register( 193 httpmock.GraphQL(query), 194 httpmock.StringResponse(fmt.Sprintf( 195 `{ "data": { "viewer": { "gists": { "nodes": [ 196 { 197 "name": "1234567890", 198 "files": [{ "name": "cool.txt" }], 199 "description": "", 200 "updatedAt": "%[1]v", 201 "isPublic": true 202 }, 203 { 204 "name": "4567890123", 205 "files": [{ "name": "gistfile0.txt" }], 206 "description": "", 207 "updatedAt": "%[1]v", 208 "isPublic": true 209 } 210 ] } } } }`, 211 sixHoursAgo.Format(time.RFC3339), 212 )), 213 ) 214 }, 215 wantOut: heredoc.Doc(` 216 1234567890 cool.txt 1 file public about 6 hours ago 217 4567890123 1 file public about 6 hours ago 218 `), 219 }, 220 { 221 name: "with secret filter", 222 opts: &ListOptions{Visibility: "secret"}, 223 stubs: func(reg *httpmock.Registry) { 224 reg.Register( 225 httpmock.GraphQL(query), 226 httpmock.StringResponse(fmt.Sprintf( 227 `{ "data": { "viewer": { "gists": { "nodes": [ 228 { 229 "name": "2345678901", 230 "files": [ 231 { "name": "gistfile0.txt" }, 232 { "name": "gistfile1.txt" } 233 ], 234 "description": "tea leaves thwart those who court catastrophe", 235 "updatedAt": "%[1]v", 236 "isPublic": false 237 }, 238 { 239 "name": "3456789012", 240 "files": [ 241 { "name": "gistfile0.txt" }, 242 { "name": "gistfile1.txt" }, 243 { "name": "gistfile2.txt" }, 244 { "name": "gistfile3.txt" }, 245 { "name": "gistfile4.txt" }, 246 { "name": "gistfile5.txt" }, 247 { "name": "gistfile6.txt" }, 248 { "name": "gistfile7.txt" }, 249 { "name": "gistfile9.txt" }, 250 { "name": "gistfile10.txt" }, 251 { "name": "gistfile11.txt" } 252 ], 253 "description": "short desc", 254 "updatedAt": "%[1]v", 255 "isPublic": false 256 } 257 ] } } } }`, 258 sixHoursAgo.Format(time.RFC3339), 259 )), 260 ) 261 }, 262 wantOut: heredoc.Doc(` 263 2345678901 tea leaves thwart those who ... 2 files secret about 6 hours ago 264 3456789012 short desc 11 files secret about 6 hours ago 265 `), 266 }, 267 { 268 name: "with limit", 269 opts: &ListOptions{Limit: 1}, 270 stubs: func(reg *httpmock.Registry) { 271 reg.Register( 272 httpmock.GraphQL(query), 273 httpmock.StringResponse(fmt.Sprintf( 274 `{ "data": { "viewer": { "gists": { "nodes": [ 275 { 276 "name": "1234567890", 277 "files": [{ "name": "cool.txt" }], 278 "description": "", 279 "updatedAt": "%v", 280 "isPublic": true 281 } 282 ] } } } }`, 283 sixHoursAgo.Format(time.RFC3339), 284 )), 285 ) 286 }, 287 wantOut: "1234567890 cool.txt 1 file public about 6 hours ago\n", 288 }, 289 { 290 name: "nontty output", 291 opts: &ListOptions{}, 292 stubs: func(reg *httpmock.Registry) { 293 reg.Register( 294 httpmock.GraphQL(query), 295 httpmock.StringResponse(fmt.Sprintf( 296 `{ "data": { "viewer": { "gists": { "nodes": [ 297 { 298 "name": "1234567890", 299 "files": [{ "name": "cool.txt" }], 300 "description": "", 301 "updatedAt": "%[1]v", 302 "isPublic": true 303 }, 304 { 305 "name": "4567890123", 306 "files": [{ "name": "gistfile0.txt" }], 307 "description": "", 308 "updatedAt": "%[1]v", 309 "isPublic": true 310 }, 311 { 312 "name": "2345678901", 313 "files": [ 314 { "name": "gistfile0.txt" }, 315 { "name": "gistfile1.txt" } 316 ], 317 "description": "tea leaves thwart those who court catastrophe", 318 "updatedAt": "%[1]v", 319 "isPublic": false 320 }, 321 { 322 "name": "3456789012", 323 "files": [ 324 { "name": "gistfile0.txt" }, 325 { "name": "gistfile1.txt" }, 326 { "name": "gistfile2.txt" }, 327 { "name": "gistfile3.txt" }, 328 { "name": "gistfile4.txt" }, 329 { "name": "gistfile5.txt" }, 330 { "name": "gistfile6.txt" }, 331 { "name": "gistfile7.txt" }, 332 { "name": "gistfile9.txt" }, 333 { "name": "gistfile10.txt" }, 334 { "name": "gistfile11.txt" } 335 ], 336 "description": "short desc", 337 "updatedAt": "%[1]v", 338 "isPublic": false 339 } 340 ] } } } }`, 341 absTime.Format(time.RFC3339), 342 )), 343 ) 344 }, 345 wantOut: heredoc.Doc(` 346 1234567890 cool.txt 1 file public 2020-07-30T15:24:28Z 347 4567890123 1 file public 2020-07-30T15:24:28Z 348 2345678901 tea leaves thwart those who court catastrophe 2 files secret 2020-07-30T15:24:28Z 349 3456789012 short desc 11 files secret 2020-07-30T15:24:28Z 350 `), 351 nontty: true, 352 }, 353 } 354 355 for _, tt := range tests { 356 reg := &httpmock.Registry{} 357 tt.stubs(reg) 358 359 tt.opts.HttpClient = func() (*http.Client, error) { 360 return &http.Client{Transport: reg}, nil 361 } 362 363 tt.opts.Config = func() (config.Config, error) { 364 return config.NewBlankConfig(), nil 365 } 366 367 io, _, stdout, _ := iostreams.Test() 368 io.SetStdoutTTY(!tt.nontty) 369 tt.opts.IO = io 370 371 if tt.opts.Limit == 0 { 372 tt.opts.Limit = 10 373 } 374 375 if tt.opts.Visibility == "" { 376 tt.opts.Visibility = "all" 377 } 378 t.Run(tt.name, func(t *testing.T) { 379 err := listRun(tt.opts) 380 assert.NoError(t, err) 381 382 assert.Equal(t, tt.wantOut, stdout.String()) 383 reg.Verify(t) 384 }) 385 } 386 }