github.com/cli/cli@v1.14.1-0.20210902173923-1af6a669e342/pkg/cmd/workflow/view/view_test.go (about) 1 package view 2 3 import ( 4 "bytes" 5 "io/ioutil" 6 "net/http" 7 "testing" 8 9 "github.com/MakeNowJust/heredoc" 10 "github.com/cli/cli/internal/ghrepo" 11 runShared "github.com/cli/cli/pkg/cmd/run/shared" 12 "github.com/cli/cli/pkg/cmd/workflow/shared" 13 "github.com/cli/cli/pkg/cmdutil" 14 "github.com/cli/cli/pkg/httpmock" 15 "github.com/cli/cli/pkg/iostreams" 16 "github.com/cli/cli/pkg/prompt" 17 "github.com/google/shlex" 18 "github.com/stretchr/testify/assert" 19 ) 20 21 func TestNewCmdView(t *testing.T) { 22 tests := []struct { 23 name string 24 cli string 25 tty bool 26 wants ViewOptions 27 wantsErr bool 28 }{ 29 { 30 name: "blank tty", 31 tty: true, 32 wants: ViewOptions{ 33 Prompt: true, 34 }, 35 }, 36 { 37 name: "blank nontty", 38 wantsErr: true, 39 }, 40 { 41 name: "arg tty", 42 cli: "123", 43 tty: true, 44 wants: ViewOptions{ 45 Selector: "123", 46 }, 47 }, 48 { 49 name: "arg nontty", 50 cli: "123", 51 wants: ViewOptions{ 52 Selector: "123", 53 Raw: true, 54 }, 55 }, 56 { 57 name: "web tty", 58 cli: "--web", 59 tty: true, 60 wants: ViewOptions{ 61 Prompt: true, 62 Web: true, 63 }, 64 }, 65 { 66 name: "web nontty", 67 cli: "-w 123", 68 wants: ViewOptions{ 69 Raw: true, 70 Web: true, 71 Selector: "123", 72 }, 73 }, 74 { 75 name: "yaml tty", 76 cli: "--yaml", 77 tty: true, 78 wants: ViewOptions{ 79 Prompt: true, 80 YAML: true, 81 }, 82 }, 83 { 84 name: "yaml nontty", 85 cli: "-y 123", 86 wants: ViewOptions{ 87 Raw: true, 88 YAML: true, 89 Selector: "123", 90 }, 91 }, 92 { 93 name: "ref tty", 94 cli: "--ref 456", 95 tty: true, 96 wantsErr: true, 97 }, 98 { 99 name: "ref nontty", 100 cli: "123 -r 456", 101 wantsErr: true, 102 }, 103 { 104 name: "yaml ref tty", 105 cli: "--yaml --ref 456", 106 tty: true, 107 wants: ViewOptions{ 108 Prompt: true, 109 YAML: true, 110 Ref: "456", 111 }, 112 }, 113 { 114 name: "yaml ref nontty", 115 cli: "123 -y -r 456", 116 wants: ViewOptions{ 117 Raw: true, 118 YAML: true, 119 Ref: "456", 120 Selector: "123", 121 }, 122 }, 123 } 124 125 for _, tt := range tests { 126 t.Run(tt.name, func(t *testing.T) { 127 io, _, _, _ := iostreams.Test() 128 io.SetStdinTTY(tt.tty) 129 io.SetStdoutTTY(tt.tty) 130 131 f := &cmdutil.Factory{ 132 IOStreams: io, 133 } 134 135 argv, err := shlex.Split(tt.cli) 136 assert.NoError(t, err) 137 138 var gotOpts *ViewOptions 139 cmd := NewCmdView(f, func(opts *ViewOptions) error { 140 gotOpts = opts 141 return nil 142 }) 143 cmd.SetArgs(argv) 144 cmd.SetIn(&bytes.Buffer{}) 145 cmd.SetOut(ioutil.Discard) 146 cmd.SetErr(ioutil.Discard) 147 148 _, err = cmd.ExecuteC() 149 if tt.wantsErr { 150 assert.Error(t, err) 151 return 152 } 153 154 assert.NoError(t, err) 155 assert.Equal(t, tt.wants.Selector, gotOpts.Selector) 156 assert.Equal(t, tt.wants.Ref, gotOpts.Ref) 157 assert.Equal(t, tt.wants.Web, gotOpts.Web) 158 assert.Equal(t, tt.wants.Prompt, gotOpts.Prompt) 159 assert.Equal(t, tt.wants.Raw, gotOpts.Raw) 160 assert.Equal(t, tt.wants.YAML, gotOpts.YAML) 161 }) 162 } 163 } 164 165 func TestViewRun(t *testing.T) { 166 aWorkflow := shared.Workflow{ 167 Name: "a workflow", 168 ID: 123, 169 Path: ".github/workflows/flow.yml", 170 State: shared.Active, 171 } 172 aWorkflowContent := `{"content":"bmFtZTogYSB3b3JrZmxvdwo="}` 173 aWorkflowInfo := heredoc.Doc(` 174 a workflow - flow.yml 175 ID: 123 176 177 Total runs 10 178 Recent runs 179 X cool commit timed out trunk push 1 180 - cool commit in progress trunk push 2 181 ✓ cool commit successful trunk push 3 182 ✓ cool commit cancelled trunk push 4 183 184 To see more runs for this workflow, try: gh run list --workflow flow.yml 185 To see the YAML for this workflow, try: gh workflow view flow.yml --yaml 186 `) 187 188 tests := []struct { 189 name string 190 opts *ViewOptions 191 httpStubs func(*httpmock.Registry) 192 askStubs func(*prompt.AskStubber) 193 tty bool 194 wantOut string 195 wantErrOut string 196 wantErr bool 197 }{ 198 { 199 name: "no enabled workflows", 200 tty: true, 201 opts: &ViewOptions{ 202 Prompt: true, 203 }, 204 httpStubs: func(reg *httpmock.Registry) { 205 reg.Register( 206 httpmock.REST("GET", "repos/OWNER/REPO/actions/workflows"), 207 httpmock.JSONResponse(shared.WorkflowsPayload{})) 208 }, 209 wantErrOut: "could not fetch workflows for OWNER/REPO: no workflows are enabled", 210 wantErr: true, 211 }, 212 { 213 name: "web", 214 tty: true, 215 opts: &ViewOptions{ 216 Selector: "123", 217 Web: true, 218 }, 219 httpStubs: func(reg *httpmock.Registry) { 220 reg.Register( 221 httpmock.REST("GET", "repos/OWNER/REPO/actions/workflows/123"), 222 httpmock.JSONResponse(aWorkflow), 223 ) 224 }, 225 wantOut: "Opening github.com/OWNER/REPO/actions/workflows/flow.yml in your browser.\n", 226 }, 227 { 228 name: "web notty", 229 tty: false, 230 opts: &ViewOptions{ 231 Selector: "123", 232 Web: true, 233 }, 234 httpStubs: func(reg *httpmock.Registry) { 235 reg.Register( 236 httpmock.REST("GET", "repos/OWNER/REPO/actions/workflows/123"), 237 httpmock.JSONResponse(aWorkflow), 238 ) 239 }, 240 wantOut: "", 241 }, 242 { 243 name: "web with yaml", 244 tty: true, 245 opts: &ViewOptions{ 246 Selector: "123", 247 YAML: true, 248 Web: true, 249 }, 250 httpStubs: func(reg *httpmock.Registry) { 251 reg.Register( 252 httpmock.REST("GET", "repos/OWNER/REPO/actions/workflows/123"), 253 httpmock.JSONResponse(aWorkflow), 254 ) 255 reg.Register( 256 httpmock.GraphQL(`query RepositoryInfo\b`), 257 httpmock.StringResponse(`{ "data": { "repository": { "defaultBranchRef": { "name": "trunk" } } } }`), 258 ) 259 }, 260 wantOut: "Opening github.com/OWNER/REPO/blob/trunk/.github/workflows/flow.yml in your browser.\n", 261 }, 262 { 263 name: "web with yaml and ref", 264 tty: true, 265 opts: &ViewOptions{ 266 Selector: "123", 267 Ref: "base", 268 YAML: true, 269 Web: true, 270 }, 271 httpStubs: func(reg *httpmock.Registry) { 272 reg.Register( 273 httpmock.REST("GET", "repos/OWNER/REPO/actions/workflows/123"), 274 httpmock.JSONResponse(aWorkflow), 275 ) 276 }, 277 wantOut: "Opening github.com/OWNER/REPO/blob/base/.github/workflows/flow.yml in your browser.\n", 278 }, 279 { 280 name: "workflow with yaml", 281 tty: true, 282 opts: &ViewOptions{ 283 Selector: "123", 284 YAML: true, 285 }, 286 httpStubs: func(reg *httpmock.Registry) { 287 reg.Register( 288 httpmock.REST("GET", "repos/OWNER/REPO/actions/workflows/123"), 289 httpmock.JSONResponse(aWorkflow), 290 ) 291 reg.Register( 292 httpmock.REST("GET", "repos/OWNER/REPO/contents/.github/workflows/flow.yml"), 293 httpmock.StringResponse(aWorkflowContent), 294 ) 295 }, 296 wantOut: "a workflow - flow.yml\nID: 123\n\nname: a workflow\n\n\n", 297 }, 298 { 299 name: "workflow with yaml notty", 300 tty: false, 301 opts: &ViewOptions{ 302 Selector: "123", 303 YAML: true, 304 }, 305 httpStubs: func(reg *httpmock.Registry) { 306 reg.Register( 307 httpmock.REST("GET", "repos/OWNER/REPO/actions/workflows/123"), 308 httpmock.JSONResponse(aWorkflow), 309 ) 310 reg.Register( 311 httpmock.REST("GET", "repos/OWNER/REPO/contents/.github/workflows/flow.yml"), 312 httpmock.StringResponse(aWorkflowContent), 313 ) 314 }, 315 wantOut: "a workflow - flow.yml\nID: 123\n\nname: a workflow\n\n\n", 316 }, 317 { 318 name: "workflow with yaml not found", 319 tty: true, 320 opts: &ViewOptions{ 321 Selector: "123", 322 YAML: true, 323 }, 324 httpStubs: func(reg *httpmock.Registry) { 325 reg.Register( 326 httpmock.REST("GET", "repos/OWNER/REPO/actions/workflows/123"), 327 httpmock.JSONResponse(aWorkflow), 328 ) 329 reg.Register( 330 httpmock.REST("GET", "repos/OWNER/REPO/contents/.github/workflows/flow.yml"), 331 httpmock.StatusStringResponse(404, "not Found"), 332 ) 333 }, 334 wantErr: true, 335 wantErrOut: "could not find workflow file flow.yml, try specifying a branch or tag using `--ref`", 336 }, 337 { 338 name: "workflow with yaml and ref", 339 tty: true, 340 opts: &ViewOptions{ 341 Selector: "123", 342 Ref: "456", 343 YAML: true, 344 }, 345 httpStubs: func(reg *httpmock.Registry) { 346 reg.Register( 347 httpmock.REST("GET", "repos/OWNER/REPO/actions/workflows/123"), 348 httpmock.JSONResponse(aWorkflow), 349 ) 350 reg.Register( 351 httpmock.REST("GET", "repos/OWNER/REPO/contents/.github/workflows/flow.yml"), 352 httpmock.StringResponse(aWorkflowContent), 353 ) 354 }, 355 wantOut: "a workflow - flow.yml\nID: 123\n\nname: a workflow\n\n\n", 356 }, 357 { 358 name: "workflow info", 359 tty: true, 360 opts: &ViewOptions{ 361 Selector: "123", 362 }, 363 httpStubs: func(reg *httpmock.Registry) { 364 reg.Register( 365 httpmock.REST("GET", "repos/OWNER/REPO/actions/workflows/123"), 366 httpmock.JSONResponse(aWorkflow), 367 ) 368 reg.Register( 369 httpmock.REST("GET", "repos/OWNER/REPO/actions/workflows/123/runs"), 370 httpmock.JSONResponse(runShared.RunsPayload{ 371 TotalCount: 10, 372 WorkflowRuns: runShared.TestRuns[0:4], 373 }), 374 ) 375 }, 376 wantOut: aWorkflowInfo, 377 }, 378 { 379 name: "workflow info notty", 380 tty: true, 381 opts: &ViewOptions{ 382 Selector: "123", 383 }, 384 httpStubs: func(reg *httpmock.Registry) { 385 reg.Register( 386 httpmock.REST("GET", "repos/OWNER/REPO/actions/workflows/123"), 387 httpmock.JSONResponse(aWorkflow), 388 ) 389 reg.Register( 390 httpmock.REST("GET", "repos/OWNER/REPO/actions/workflows/123/runs"), 391 httpmock.JSONResponse(runShared.RunsPayload{ 392 TotalCount: 10, 393 WorkflowRuns: runShared.TestRuns[0:4], 394 }), 395 ) 396 }, 397 wantOut: aWorkflowInfo, 398 }, 399 } 400 401 for _, tt := range tests { 402 reg := &httpmock.Registry{} 403 tt.httpStubs(reg) 404 tt.opts.HttpClient = func() (*http.Client, error) { 405 return &http.Client{Transport: reg}, nil 406 } 407 408 io, _, stdout, _ := iostreams.Test() 409 io.SetStdoutTTY(tt.tty) 410 io.SetStdinTTY(tt.tty) 411 tt.opts.IO = io 412 413 tt.opts.BaseRepo = func() (ghrepo.Interface, error) { 414 return ghrepo.FromFullName("OWNER/REPO") 415 } 416 417 browser := &cmdutil.TestBrowser{} 418 tt.opts.Browser = browser 419 420 as, teardown := prompt.InitAskStubber() 421 defer teardown() 422 if tt.askStubs != nil { 423 tt.askStubs(as) 424 } 425 426 t.Run(tt.name, func(t *testing.T) { 427 err := runView(tt.opts) 428 if tt.wantErr { 429 assert.Error(t, err) 430 assert.Equal(t, tt.wantErrOut, err.Error()) 431 return 432 } 433 assert.NoError(t, err) 434 assert.Equal(t, tt.wantOut, stdout.String()) 435 reg.Verify(t) 436 }) 437 } 438 }