github.com/ungtb10d/cli/v2@v2.0.0-20221110210412-98537dd9d6a1/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/ungtb10d/cli/v2/internal/config" 12 "github.com/ungtb10d/cli/v2/pkg/cmdutil" 13 "github.com/ungtb10d/cli/v2/pkg/httpmock" 14 "github.com/ungtb10d/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 wantErr bool 110 wantOut string 111 stubs func(*httpmock.Registry) 112 nontty bool 113 }{ 114 { 115 name: "no gists", 116 opts: &ListOptions{}, 117 stubs: func(reg *httpmock.Registry) { 118 reg.Register( 119 httpmock.GraphQL(query), 120 httpmock.StringResponse(`{ "data": { "viewer": { 121 "gists": { "nodes": [] } 122 } } }`)) 123 }, 124 wantErr: true, 125 }, 126 { 127 name: "default behavior", 128 opts: &ListOptions{}, 129 stubs: func(reg *httpmock.Registry) { 130 reg.Register( 131 httpmock.GraphQL(query), 132 httpmock.StringResponse(fmt.Sprintf( 133 `{ "data": { "viewer": { "gists": { "nodes": [ 134 { 135 "name": "1234567890", 136 "files": [{ "name": "cool.txt" }], 137 "description": "", 138 "updatedAt": "%[1]v", 139 "isPublic": true 140 }, 141 { 142 "name": "4567890123", 143 "files": [{ "name": "gistfile0.txt" }], 144 "description": "", 145 "updatedAt": "%[1]v", 146 "isPublic": true 147 }, 148 { 149 "name": "2345678901", 150 "files": [ 151 { "name": "gistfile0.txt" }, 152 { "name": "gistfile1.txt" } 153 ], 154 "description": "tea leaves thwart those who court catastrophe", 155 "updatedAt": "%[1]v", 156 "isPublic": false 157 }, 158 { 159 "name": "3456789012", 160 "files": [ 161 { "name": "gistfile0.txt" }, 162 { "name": "gistfile1.txt" }, 163 { "name": "gistfile2.txt" }, 164 { "name": "gistfile3.txt" }, 165 { "name": "gistfile4.txt" }, 166 { "name": "gistfile5.txt" }, 167 { "name": "gistfile6.txt" }, 168 { "name": "gistfile7.txt" }, 169 { "name": "gistfile9.txt" }, 170 { "name": "gistfile10.txt" }, 171 { "name": "gistfile11.txt" } 172 ], 173 "description": "short desc", 174 "updatedAt": "%[1]v", 175 "isPublic": false 176 } 177 ] } } } }`, 178 sixHoursAgo.Format(time.RFC3339), 179 )), 180 ) 181 }, 182 wantOut: heredoc.Doc(` 183 1234567890 cool.txt 1 file public about 6 hours ago 184 4567890123 1 file public about 6 hours ago 185 2345678901 tea leaves thwart those who ... 2 files secret about 6 hours ago 186 3456789012 short desc 11 files secret about 6 hours ago 187 `), 188 }, 189 { 190 name: "with public filter", 191 opts: &ListOptions{Visibility: "public"}, 192 stubs: func(reg *httpmock.Registry) { 193 reg.Register( 194 httpmock.GraphQL(query), 195 httpmock.StringResponse(fmt.Sprintf( 196 `{ "data": { "viewer": { "gists": { "nodes": [ 197 { 198 "name": "1234567890", 199 "files": [{ "name": "cool.txt" }], 200 "description": "", 201 "updatedAt": "%[1]v", 202 "isPublic": true 203 }, 204 { 205 "name": "4567890123", 206 "files": [{ "name": "gistfile0.txt" }], 207 "description": "", 208 "updatedAt": "%[1]v", 209 "isPublic": true 210 } 211 ] } } } }`, 212 sixHoursAgo.Format(time.RFC3339), 213 )), 214 ) 215 }, 216 wantOut: heredoc.Doc(` 217 1234567890 cool.txt 1 file public about 6 hours ago 218 4567890123 1 file public about 6 hours ago 219 `), 220 }, 221 { 222 name: "with secret filter", 223 opts: &ListOptions{Visibility: "secret"}, 224 stubs: func(reg *httpmock.Registry) { 225 reg.Register( 226 httpmock.GraphQL(query), 227 httpmock.StringResponse(fmt.Sprintf( 228 `{ "data": { "viewer": { "gists": { "nodes": [ 229 { 230 "name": "2345678901", 231 "files": [ 232 { "name": "gistfile0.txt" }, 233 { "name": "gistfile1.txt" } 234 ], 235 "description": "tea leaves thwart those who court catastrophe", 236 "updatedAt": "%[1]v", 237 "isPublic": false 238 }, 239 { 240 "name": "3456789012", 241 "files": [ 242 { "name": "gistfile0.txt" }, 243 { "name": "gistfile1.txt" }, 244 { "name": "gistfile2.txt" }, 245 { "name": "gistfile3.txt" }, 246 { "name": "gistfile4.txt" }, 247 { "name": "gistfile5.txt" }, 248 { "name": "gistfile6.txt" }, 249 { "name": "gistfile7.txt" }, 250 { "name": "gistfile9.txt" }, 251 { "name": "gistfile10.txt" }, 252 { "name": "gistfile11.txt" } 253 ], 254 "description": "short desc", 255 "updatedAt": "%[1]v", 256 "isPublic": false 257 } 258 ] } } } }`, 259 sixHoursAgo.Format(time.RFC3339), 260 )), 261 ) 262 }, 263 wantOut: heredoc.Doc(` 264 2345678901 tea leaves thwart those who ... 2 files secret about 6 hours ago 265 3456789012 short desc 11 files secret about 6 hours ago 266 `), 267 }, 268 { 269 name: "with limit", 270 opts: &ListOptions{Limit: 1}, 271 stubs: func(reg *httpmock.Registry) { 272 reg.Register( 273 httpmock.GraphQL(query), 274 httpmock.StringResponse(fmt.Sprintf( 275 `{ "data": { "viewer": { "gists": { "nodes": [ 276 { 277 "name": "1234567890", 278 "files": [{ "name": "cool.txt" }], 279 "description": "", 280 "updatedAt": "%v", 281 "isPublic": true 282 } 283 ] } } } }`, 284 sixHoursAgo.Format(time.RFC3339), 285 )), 286 ) 287 }, 288 wantOut: "1234567890 cool.txt 1 file public about 6 hours ago\n", 289 }, 290 { 291 name: "nontty output", 292 opts: &ListOptions{}, 293 stubs: func(reg *httpmock.Registry) { 294 reg.Register( 295 httpmock.GraphQL(query), 296 httpmock.StringResponse(fmt.Sprintf( 297 `{ "data": { "viewer": { "gists": { "nodes": [ 298 { 299 "name": "1234567890", 300 "files": [{ "name": "cool.txt" }], 301 "description": "", 302 "updatedAt": "%[1]v", 303 "isPublic": true 304 }, 305 { 306 "name": "4567890123", 307 "files": [{ "name": "gistfile0.txt" }], 308 "description": "", 309 "updatedAt": "%[1]v", 310 "isPublic": true 311 }, 312 { 313 "name": "2345678901", 314 "files": [ 315 { "name": "gistfile0.txt" }, 316 { "name": "gistfile1.txt" } 317 ], 318 "description": "tea leaves thwart those who court catastrophe", 319 "updatedAt": "%[1]v", 320 "isPublic": false 321 }, 322 { 323 "name": "3456789012", 324 "files": [ 325 { "name": "gistfile0.txt" }, 326 { "name": "gistfile1.txt" }, 327 { "name": "gistfile2.txt" }, 328 { "name": "gistfile3.txt" }, 329 { "name": "gistfile4.txt" }, 330 { "name": "gistfile5.txt" }, 331 { "name": "gistfile6.txt" }, 332 { "name": "gistfile7.txt" }, 333 { "name": "gistfile9.txt" }, 334 { "name": "gistfile10.txt" }, 335 { "name": "gistfile11.txt" } 336 ], 337 "description": "short desc", 338 "updatedAt": "%[1]v", 339 "isPublic": false 340 } 341 ] } } } }`, 342 absTime.Format(time.RFC3339), 343 )), 344 ) 345 }, 346 wantOut: heredoc.Doc(` 347 1234567890 cool.txt 1 file public 2020-07-30T15:24:28Z 348 4567890123 1 file public 2020-07-30T15:24:28Z 349 2345678901 tea leaves thwart those who court catastrophe 2 files secret 2020-07-30T15:24:28Z 350 3456789012 short desc 11 files secret 2020-07-30T15:24:28Z 351 `), 352 nontty: true, 353 }, 354 } 355 356 for _, tt := range tests { 357 reg := &httpmock.Registry{} 358 tt.stubs(reg) 359 360 tt.opts.HttpClient = func() (*http.Client, error) { 361 return &http.Client{Transport: reg}, nil 362 } 363 364 tt.opts.Config = func() (config.Config, error) { 365 return config.NewBlankConfig(), nil 366 } 367 368 ios, _, stdout, _ := iostreams.Test() 369 ios.SetStdoutTTY(!tt.nontty) 370 tt.opts.IO = ios 371 372 if tt.opts.Limit == 0 { 373 tt.opts.Limit = 10 374 } 375 376 if tt.opts.Visibility == "" { 377 tt.opts.Visibility = "all" 378 } 379 t.Run(tt.name, func(t *testing.T) { 380 err := listRun(tt.opts) 381 if tt.wantErr { 382 assert.Error(t, err) 383 } else { 384 assert.NoError(t, err) 385 } 386 387 assert.Equal(t, tt.wantOut, stdout.String()) 388 reg.Verify(t) 389 }) 390 } 391 }