github.com/ungtb10d/cli/v2@v2.0.0-20221110210412-98537dd9d6a1/pkg/cmd/pr/view/view_test.go (about) 1 package view 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "io" 8 "net/http" 9 "os" 10 "regexp" 11 "testing" 12 13 "github.com/ungtb10d/cli/v2/api" 14 "github.com/ungtb10d/cli/v2/internal/browser" 15 "github.com/ungtb10d/cli/v2/internal/ghrepo" 16 "github.com/ungtb10d/cli/v2/internal/run" 17 "github.com/ungtb10d/cli/v2/pkg/cmd/pr/shared" 18 "github.com/ungtb10d/cli/v2/pkg/cmdutil" 19 "github.com/ungtb10d/cli/v2/pkg/httpmock" 20 "github.com/ungtb10d/cli/v2/pkg/iostreams" 21 "github.com/ungtb10d/cli/v2/test" 22 "github.com/google/shlex" 23 "github.com/stretchr/testify/assert" 24 "github.com/stretchr/testify/require" 25 ) 26 27 func Test_NewCmdView(t *testing.T) { 28 tests := []struct { 29 name string 30 args string 31 isTTY bool 32 want ViewOptions 33 wantErr string 34 }{ 35 { 36 name: "number argument", 37 args: "123", 38 isTTY: true, 39 want: ViewOptions{ 40 SelectorArg: "123", 41 BrowserMode: false, 42 }, 43 }, 44 { 45 name: "no argument", 46 args: "", 47 isTTY: true, 48 want: ViewOptions{ 49 SelectorArg: "", 50 BrowserMode: false, 51 }, 52 }, 53 { 54 name: "web mode", 55 args: "123 -w", 56 isTTY: true, 57 want: ViewOptions{ 58 SelectorArg: "123", 59 BrowserMode: true, 60 }, 61 }, 62 { 63 name: "no argument with --repo override", 64 args: "-R owner/repo", 65 isTTY: true, 66 wantErr: "argument required when using the --repo flag", 67 }, 68 { 69 name: "comments", 70 args: "123 -c", 71 isTTY: true, 72 want: ViewOptions{ 73 SelectorArg: "123", 74 Comments: true, 75 }, 76 }, 77 } 78 for _, tt := range tests { 79 t.Run(tt.name, func(t *testing.T) { 80 ios, _, _, _ := iostreams.Test() 81 ios.SetStdoutTTY(tt.isTTY) 82 ios.SetStdinTTY(tt.isTTY) 83 ios.SetStderrTTY(tt.isTTY) 84 85 f := &cmdutil.Factory{ 86 IOStreams: ios, 87 } 88 89 var opts *ViewOptions 90 cmd := NewCmdView(f, func(o *ViewOptions) error { 91 opts = o 92 return nil 93 }) 94 cmd.PersistentFlags().StringP("repo", "R", "", "") 95 96 argv, err := shlex.Split(tt.args) 97 require.NoError(t, err) 98 cmd.SetArgs(argv) 99 100 cmd.SetIn(&bytes.Buffer{}) 101 cmd.SetOut(io.Discard) 102 cmd.SetErr(io.Discard) 103 104 _, err = cmd.ExecuteC() 105 if tt.wantErr != "" { 106 require.EqualError(t, err, tt.wantErr) 107 return 108 } else { 109 require.NoError(t, err) 110 } 111 112 assert.Equal(t, tt.want.SelectorArg, opts.SelectorArg) 113 }) 114 } 115 } 116 117 func runCommand(rt http.RoundTripper, branch string, isTTY bool, cli string) (*test.CmdOut, error) { 118 ios, _, stdout, stderr := iostreams.Test() 119 ios.SetStdoutTTY(isTTY) 120 ios.SetStdinTTY(isTTY) 121 ios.SetStderrTTY(isTTY) 122 123 browser := &browser.Stub{} 124 factory := &cmdutil.Factory{ 125 IOStreams: ios, 126 Browser: browser, 127 } 128 129 cmd := NewCmdView(factory, nil) 130 131 argv, err := shlex.Split(cli) 132 if err != nil { 133 return nil, err 134 } 135 cmd.SetArgs(argv) 136 137 cmd.SetIn(&bytes.Buffer{}) 138 cmd.SetOut(io.Discard) 139 cmd.SetErr(io.Discard) 140 141 _, err = cmd.ExecuteC() 142 return &test.CmdOut{ 143 OutBuf: stdout, 144 ErrBuf: stderr, 145 BrowsedURL: browser.BrowsedURL(), 146 }, err 147 } 148 149 // hack for compatibility with old JSON fixture files 150 func prFromFixtures(fixtures map[string]string) (*api.PullRequest, error) { 151 var response struct { 152 Data struct { 153 Repository struct { 154 PullRequest *api.PullRequest 155 } 156 } 157 } 158 159 ff, err := os.Open(fixtures["PullRequestByNumber"]) 160 if err != nil { 161 return nil, err 162 } 163 defer ff.Close() 164 165 dec := json.NewDecoder(ff) 166 err = dec.Decode(&response) 167 if err != nil { 168 return nil, err 169 } 170 171 for name := range fixtures { 172 switch name { 173 case "PullRequestByNumber": 174 case "ReviewsForPullRequest", "CommentsForPullRequest": 175 ff, err := os.Open(fixtures[name]) 176 if err != nil { 177 return nil, err 178 } 179 defer ff.Close() 180 dec := json.NewDecoder(ff) 181 err = dec.Decode(&response) 182 if err != nil { 183 return nil, err 184 } 185 default: 186 return nil, fmt.Errorf("unrecognized fixture type: %q", name) 187 } 188 } 189 190 return response.Data.Repository.PullRequest, nil 191 } 192 193 func TestPRView_Preview_nontty(t *testing.T) { 194 tests := map[string]struct { 195 branch string 196 args string 197 fixtures map[string]string 198 expectedOutputs []string 199 }{ 200 "Open PR without metadata": { 201 branch: "master", 202 args: "12", 203 fixtures: map[string]string{ 204 "PullRequestByNumber": "./fixtures/prViewPreview.json", 205 }, 206 expectedOutputs: []string{ 207 `title:\tBlueberries are from a fork\n`, 208 `state:\tOPEN\n`, 209 `author:\tnobody\n`, 210 `labels:\t\n`, 211 `assignees:\t\n`, 212 `reviewers:\t\n`, 213 `projects:\t\n`, 214 `milestone:\t\n`, 215 `url:\thttps://github.com/OWNER/REPO/pull/12\n`, 216 `additions:\t100\n`, 217 `deletions:\t10\n`, 218 `number:\t12\n`, 219 `blueberries taste good`, 220 }, 221 }, 222 "Open PR with metadata by number": { 223 branch: "master", 224 args: "12", 225 fixtures: map[string]string{ 226 "PullRequestByNumber": "./fixtures/prViewPreviewWithMetadataByNumber.json", 227 }, 228 expectedOutputs: []string{ 229 `title:\tBlueberries are from a fork\n`, 230 `reviewers:\t1 \(Requested\)\n`, 231 `assignees:\tmarseilles, monaco\n`, 232 `labels:\tone, two, three, four, five\n`, 233 `projects:\tProject 1 \(column A\), Project 2 \(column B\), Project 3 \(column C\), Project 4 \(Awaiting triage\)\n`, 234 `milestone:\tuluru\n`, 235 `\*\*blueberries taste good\*\*`, 236 }, 237 }, 238 "Open PR with reviewers by number": { 239 branch: "master", 240 args: "12", 241 fixtures: map[string]string{ 242 "PullRequestByNumber": "./fixtures/prViewPreviewWithReviewersByNumber.json", 243 "ReviewsForPullRequest": "./fixtures/prViewPreviewManyReviews.json", 244 }, 245 expectedOutputs: []string{ 246 `title:\tBlueberries are from a fork\n`, 247 `state:\tOPEN\n`, 248 `author:\tnobody\n`, 249 `labels:\t\n`, 250 `assignees:\t\n`, 251 `projects:\t\n`, 252 `milestone:\t\n`, 253 `additions:\t100\n`, 254 `deletions:\t10\n`, 255 `reviewers:\tDEF \(Commented\), def \(Changes requested\), ghost \(Approved\), hubot \(Commented\), xyz \(Approved\), 123 \(Requested\), abc \(Requested\), my-org\/team-1 \(Requested\)\n`, 256 `\*\*blueberries taste good\*\*`, 257 }, 258 }, 259 "Closed PR": { 260 branch: "master", 261 args: "12", 262 fixtures: map[string]string{ 263 "PullRequestByNumber": "./fixtures/prViewPreviewClosedState.json", 264 }, 265 expectedOutputs: []string{ 266 `state:\tCLOSED\n`, 267 `author:\tnobody\n`, 268 `labels:\t\n`, 269 `assignees:\t\n`, 270 `reviewers:\t\n`, 271 `projects:\t\n`, 272 `milestone:\t\n`, 273 `additions:\t100\n`, 274 `deletions:\t10\n`, 275 `\*\*blueberries taste good\*\*`, 276 }, 277 }, 278 "Merged PR": { 279 branch: "master", 280 args: "12", 281 fixtures: map[string]string{ 282 "PullRequestByNumber": "./fixtures/prViewPreviewMergedState.json", 283 }, 284 expectedOutputs: []string{ 285 `state:\tMERGED\n`, 286 `author:\tnobody\n`, 287 `labels:\t\n`, 288 `assignees:\t\n`, 289 `reviewers:\t\n`, 290 `projects:\t\n`, 291 `milestone:\t\n`, 292 `additions:\t100\n`, 293 `deletions:\t10\n`, 294 `\*\*blueberries taste good\*\*`, 295 }, 296 }, 297 "Draft PR": { 298 branch: "master", 299 args: "12", 300 fixtures: map[string]string{ 301 "PullRequestByNumber": "./fixtures/prViewPreviewDraftState.json", 302 }, 303 expectedOutputs: []string{ 304 `title:\tBlueberries are from a fork\n`, 305 `state:\tDRAFT\n`, 306 `author:\tnobody\n`, 307 `labels:`, 308 `assignees:`, 309 `reviewers:`, 310 `projects:`, 311 `milestone:`, 312 `additions:\t100\n`, 313 `deletions:\t10\n`, 314 `\*\*blueberries taste good\*\*`, 315 }, 316 }, 317 } 318 319 for name, tc := range tests { 320 t.Run(name, func(t *testing.T) { 321 http := &httpmock.Registry{} 322 defer http.Verify(t) 323 324 pr, err := prFromFixtures(tc.fixtures) 325 require.NoError(t, err) 326 shared.RunCommandFinder("12", pr, ghrepo.New("OWNER", "REPO")) 327 328 output, err := runCommand(http, tc.branch, false, tc.args) 329 if err != nil { 330 t.Errorf("error running command `%v`: %v", tc.args, err) 331 } 332 333 assert.Equal(t, "", output.Stderr()) 334 335 //nolint:staticcheck // prefer exact matchers over ExpectLines 336 test.ExpectLines(t, output.String(), tc.expectedOutputs...) 337 }) 338 } 339 } 340 341 func TestPRView_Preview(t *testing.T) { 342 tests := map[string]struct { 343 branch string 344 args string 345 fixtures map[string]string 346 expectedOutputs []string 347 }{ 348 "Open PR without metadata": { 349 branch: "master", 350 args: "12", 351 fixtures: map[string]string{ 352 "PullRequestByNumber": "./fixtures/prViewPreview.json", 353 }, 354 expectedOutputs: []string{ 355 `Blueberries are from a fork #12`, 356 `Open.*nobody wants to merge 12 commits into master from blueberries . about X years ago`, 357 `.+100.-10`, 358 `blueberries taste good`, 359 `View this pull request on GitHub: https://github.com/OWNER/REPO/pull/12`, 360 }, 361 }, 362 "Open PR with metadata by number": { 363 branch: "master", 364 args: "12", 365 fixtures: map[string]string{ 366 "PullRequestByNumber": "./fixtures/prViewPreviewWithMetadataByNumber.json", 367 }, 368 expectedOutputs: []string{ 369 `Blueberries are from a fork #12`, 370 `Open.*nobody wants to merge 12 commits into master from blueberries . about X years ago`, 371 `.+100.-10`, 372 `Reviewers:.*1 \(.*Requested.*\)\n`, 373 `Assignees:.*marseilles, monaco\n`, 374 `Labels:.*one, two, three, four, five\n`, 375 `Projects:.*Project 1 \(column A\), Project 2 \(column B\), Project 3 \(column C\), Project 4 \(Awaiting triage\)\n`, 376 `Milestone:.*uluru\n`, 377 `blueberries taste good`, 378 `View this pull request on GitHub: https://github.com/OWNER/REPO/pull/12`, 379 }, 380 }, 381 "Open PR with reviewers by number": { 382 branch: "master", 383 args: "12", 384 fixtures: map[string]string{ 385 "PullRequestByNumber": "./fixtures/prViewPreviewWithReviewersByNumber.json", 386 "ReviewsForPullRequest": "./fixtures/prViewPreviewManyReviews.json", 387 }, 388 expectedOutputs: []string{ 389 `Blueberries are from a fork #12`, 390 `Reviewers: DEF \(Commented\), def \(Changes requested\), ghost \(Approved\), hubot \(Commented\), xyz \(Approved\), 123 \(Requested\), abc \(Requested\), my-org\/team-1 \(Requested\)`, 391 `blueberries taste good`, 392 `View this pull request on GitHub: https://github.com/OWNER/REPO/pull/12`, 393 }, 394 }, 395 "Closed PR": { 396 branch: "master", 397 args: "12", 398 fixtures: map[string]string{ 399 "PullRequestByNumber": "./fixtures/prViewPreviewClosedState.json", 400 }, 401 expectedOutputs: []string{ 402 `Blueberries are from a fork #12`, 403 `Closed.*nobody wants to merge 12 commits into master from blueberries . about X years ago`, 404 `.+100.-10`, 405 `blueberries taste good`, 406 `View this pull request on GitHub: https://github.com/OWNER/REPO/pull/12`, 407 }, 408 }, 409 "Merged PR": { 410 branch: "master", 411 args: "12", 412 fixtures: map[string]string{ 413 "PullRequestByNumber": "./fixtures/prViewPreviewMergedState.json", 414 }, 415 expectedOutputs: []string{ 416 `Blueberries are from a fork #12`, 417 `Merged.*nobody wants to merge 12 commits into master from blueberries . about X years ago`, 418 `.+100.-10`, 419 `blueberries taste good`, 420 `View this pull request on GitHub: https://github.com/OWNER/REPO/pull/12`, 421 }, 422 }, 423 "Draft PR": { 424 branch: "master", 425 args: "12", 426 fixtures: map[string]string{ 427 "PullRequestByNumber": "./fixtures/prViewPreviewDraftState.json", 428 }, 429 expectedOutputs: []string{ 430 `Blueberries are from a fork #12`, 431 `Draft.*nobody wants to merge 12 commits into master from blueberries . about X years ago`, 432 `.+100.-10`, 433 `blueberries taste good`, 434 `View this pull request on GitHub: https://github.com/OWNER/REPO/pull/12`, 435 }, 436 }, 437 "Open PR with all checks passing": { 438 branch: "master", 439 args: "12", 440 fixtures: map[string]string{ 441 "PullRequestByNumber": "./fixtures/prViewPreviewWithAllChecksPassing.json", 442 }, 443 expectedOutputs: []string{ 444 `Blueberries are from a fork #12`, 445 `Open.*nobody wants to merge 12 commits into master from blueberries . about X years ago`, 446 `.+100.-10 • ✓ Checks passing`, 447 `blueberries taste good`, 448 `View this pull request on GitHub: https://github.com/OWNER/REPO/pull/12`, 449 }, 450 }, 451 "Open PR with all checks failing": { 452 branch: "master", 453 args: "12", 454 fixtures: map[string]string{ 455 "PullRequestByNumber": "./fixtures/prViewPreviewWithAllChecksFailing.json", 456 }, 457 expectedOutputs: []string{ 458 `Blueberries are from a fork #12`, 459 `Open.*nobody wants to merge 12 commits into master from blueberries . about X years ago`, 460 `.+100.-10 • × All checks failing`, 461 `blueberries taste good`, 462 `View this pull request on GitHub: https://github.com/OWNER/REPO/pull/12`, 463 }, 464 }, 465 "Open PR with some checks failing": { 466 branch: "master", 467 args: "12", 468 fixtures: map[string]string{ 469 "PullRequestByNumber": "./fixtures/prViewPreviewWithSomeChecksFailing.json", 470 }, 471 expectedOutputs: []string{ 472 `Blueberries are from a fork #12`, 473 `Open.*nobody wants to merge 12 commits into master from blueberries . about X years ago`, 474 `.+100.-10 • × 1/2 checks failing`, 475 `blueberries taste good`, 476 `View this pull request on GitHub: https://github.com/OWNER/REPO/pull/12`, 477 }, 478 }, 479 "Open PR with some checks pending": { 480 branch: "master", 481 args: "12", 482 fixtures: map[string]string{ 483 "PullRequestByNumber": "./fixtures/prViewPreviewWithSomeChecksPending.json", 484 }, 485 expectedOutputs: []string{ 486 `Blueberries are from a fork #12`, 487 `Open.*nobody wants to merge 12 commits into master from blueberries . about X years ago`, 488 `.+100.-10 • - Checks pending`, 489 `blueberries taste good`, 490 `View this pull request on GitHub: https://github.com/OWNER/REPO/pull/12`, 491 }, 492 }, 493 "Open PR with no checks": { 494 branch: "master", 495 args: "12", 496 fixtures: map[string]string{ 497 "PullRequestByNumber": "./fixtures/prViewPreviewWithNoChecks.json", 498 }, 499 expectedOutputs: []string{ 500 `Blueberries are from a fork #12`, 501 `Open.*nobody wants to merge 12 commits into master from blueberries . about X years ago`, 502 `.+100.-10 • No checks`, 503 `blueberries taste good`, 504 `View this pull request on GitHub: https://github.com/OWNER/REPO/pull/12`, 505 }, 506 }, 507 } 508 509 for name, tc := range tests { 510 t.Run(name, func(t *testing.T) { 511 http := &httpmock.Registry{} 512 defer http.Verify(t) 513 514 pr, err := prFromFixtures(tc.fixtures) 515 require.NoError(t, err) 516 shared.RunCommandFinder("12", pr, ghrepo.New("OWNER", "REPO")) 517 518 output, err := runCommand(http, tc.branch, true, tc.args) 519 if err != nil { 520 t.Errorf("error running command `%v`: %v", tc.args, err) 521 } 522 523 assert.Equal(t, "", output.Stderr()) 524 525 out := output.String() 526 timeRE := regexp.MustCompile(`\d+ years`) 527 out = timeRE.ReplaceAllString(out, "X years") 528 529 //nolint:staticcheck // prefer exact matchers over ExpectLines 530 test.ExpectLines(t, out, tc.expectedOutputs...) 531 }) 532 } 533 } 534 535 func TestPRView_web_currentBranch(t *testing.T) { 536 http := &httpmock.Registry{} 537 defer http.Verify(t) 538 539 shared.RunCommandFinder("", &api.PullRequest{URL: "https://github.com/OWNER/REPO/pull/10"}, ghrepo.New("OWNER", "REPO")) 540 541 _, cmdTeardown := run.Stub() 542 defer cmdTeardown(t) 543 544 output, err := runCommand(http, "blueberries", true, "-w") 545 if err != nil { 546 t.Errorf("error running command `pr view`: %v", err) 547 } 548 549 assert.Equal(t, "", output.String()) 550 assert.Equal(t, "Opening github.com/OWNER/REPO/pull/10 in your browser.\n", output.Stderr()) 551 assert.Equal(t, "https://github.com/OWNER/REPO/pull/10", output.BrowsedURL) 552 } 553 554 func TestPRView_web_noResultsForBranch(t *testing.T) { 555 http := &httpmock.Registry{} 556 defer http.Verify(t) 557 558 shared.RunCommandFinder("", nil, nil) 559 560 _, cmdTeardown := run.Stub() 561 defer cmdTeardown(t) 562 563 _, err := runCommand(http, "blueberries", true, "-w") 564 if err == nil || err.Error() != `no pull requests found` { 565 t.Errorf("error running command `pr view`: %v", err) 566 } 567 } 568 569 func TestPRView_tty_Comments(t *testing.T) { 570 tests := map[string]struct { 571 branch string 572 cli string 573 fixtures map[string]string 574 expectedOutputs []string 575 wantsErr bool 576 }{ 577 "without comments flag": { 578 branch: "master", 579 cli: "123", 580 fixtures: map[string]string{ 581 "PullRequestByNumber": "./fixtures/prViewPreviewSingleComment.json", 582 "ReviewsForPullRequest": "./fixtures/prViewPreviewReviews.json", 583 }, 584 expectedOutputs: []string{ 585 `some title #12`, 586 `1 \x{1f615} • 2 \x{1f440} • 3 \x{2764}\x{fe0f}`, 587 `some body`, 588 `———————— Not showing 9 comments ————————`, 589 `marseilles \(Collaborator\) • Jan 9, 2020 • Newest comment`, 590 `4 \x{1f389} • 5 \x{1f604} • 6 \x{1f680}`, 591 `Comment 5`, 592 `Use --comments to view the full conversation`, 593 `View this pull request on GitHub: https://github.com/OWNER/REPO/pull/12`, 594 }, 595 }, 596 "with comments flag": { 597 branch: "master", 598 cli: "123 --comments", 599 fixtures: map[string]string{ 600 "PullRequestByNumber": "./fixtures/prViewPreviewSingleComment.json", 601 "ReviewsForPullRequest": "./fixtures/prViewPreviewReviews.json", 602 "CommentsForPullRequest": "./fixtures/prViewPreviewFullComments.json", 603 }, 604 expectedOutputs: []string{ 605 `some title #12`, 606 `some body`, 607 `monalisa • Jan 1, 2020 • Edited`, 608 `1 \x{1f615} • 2 \x{1f440} • 3 \x{2764}\x{fe0f} • 4 \x{1f389} • 5 \x{1f604} • 6 \x{1f680} • 7 \x{1f44e} • 8 \x{1f44d}`, 609 `Comment 1`, 610 `sam commented • Jan 2, 2020`, 611 `1 \x{1f44e} • 1 \x{1f44d}`, 612 `Review 1`, 613 `View the full review: https://github.com/OWNER/REPO/pull/12#pullrequestreview-1`, 614 `johnnytest \(Contributor\) • Jan 3, 2020`, 615 `Comment 2`, 616 `matt requested changes \(Owner\) • Jan 4, 2020`, 617 `1 \x{1f615} • 1 \x{1f440}`, 618 `Review 2`, 619 `View the full review: https://github.com/OWNER/REPO/pull/12#pullrequestreview-2`, 620 `elvisp \(Member\) • Jan 5, 2020`, 621 `Comment 3`, 622 `leah approved \(Member\) • Jan 6, 2020 • Edited`, 623 `Review 3`, 624 `View the full review: https://github.com/OWNER/REPO/pull/12#pullrequestreview-3`, 625 `loislane \(Owner\) • Jan 7, 2020`, 626 `Comment 4`, 627 `louise dismissed • Jan 8, 2020`, 628 `Review 4`, 629 `View the full review: https://github.com/OWNER/REPO/pull/12#pullrequestreview-4`, 630 `sam-spam • This comment has been marked as spam`, 631 `marseilles \(Collaborator\) • Jan 9, 2020 • Newest comment`, 632 `Comment 5`, 633 `View this pull request on GitHub: https://github.com/OWNER/REPO/pull/12`, 634 }, 635 }, 636 "with invalid comments flag": { 637 branch: "master", 638 cli: "123 --comments 3", 639 wantsErr: true, 640 }, 641 } 642 for name, tt := range tests { 643 t.Run(name, func(t *testing.T) { 644 http := &httpmock.Registry{} 645 defer http.Verify(t) 646 647 if len(tt.fixtures) > 0 { 648 pr, err := prFromFixtures(tt.fixtures) 649 require.NoError(t, err) 650 shared.RunCommandFinder("123", pr, ghrepo.New("OWNER", "REPO")) 651 } else { 652 shared.RunCommandFinder("123", nil, nil) 653 } 654 655 output, err := runCommand(http, tt.branch, true, tt.cli) 656 if tt.wantsErr { 657 assert.Error(t, err) 658 return 659 } 660 assert.NoError(t, err) 661 assert.Equal(t, "", output.Stderr()) 662 //nolint:staticcheck // prefer exact matchers over ExpectLines 663 test.ExpectLines(t, output.String(), tt.expectedOutputs...) 664 }) 665 } 666 } 667 668 func TestPRView_nontty_Comments(t *testing.T) { 669 tests := map[string]struct { 670 branch string 671 cli string 672 fixtures map[string]string 673 expectedOutputs []string 674 wantsErr bool 675 }{ 676 "without comments flag": { 677 branch: "master", 678 cli: "123", 679 fixtures: map[string]string{ 680 "PullRequestByNumber": "./fixtures/prViewPreviewSingleComment.json", 681 "ReviewsForPullRequest": "./fixtures/prViewPreviewReviews.json", 682 }, 683 expectedOutputs: []string{ 684 `title:\tsome title`, 685 `state:\tOPEN`, 686 `author:\tnobody`, 687 `url:\thttps://github.com/OWNER/REPO/pull/12`, 688 `some body`, 689 }, 690 }, 691 "with comments flag": { 692 branch: "master", 693 cli: "123 --comments", 694 fixtures: map[string]string{ 695 "PullRequestByNumber": "./fixtures/prViewPreviewSingleComment.json", 696 "ReviewsForPullRequest": "./fixtures/prViewPreviewReviews.json", 697 "CommentsForPullRequest": "./fixtures/prViewPreviewFullComments.json", 698 }, 699 expectedOutputs: []string{ 700 `author:\tmonalisa`, 701 `association:\tnone`, 702 `edited:\ttrue`, 703 `status:\tnone`, 704 `Comment 1`, 705 `author:\tsam`, 706 `association:\tnone`, 707 `edited:\tfalse`, 708 `status:\tcommented`, 709 `Review 1`, 710 `author:\tjohnnytest`, 711 `association:\tcontributor`, 712 `edited:\tfalse`, 713 `status:\tnone`, 714 `Comment 2`, 715 `author:\tmatt`, 716 `association:\towner`, 717 `edited:\tfalse`, 718 `status:\tchanges requested`, 719 `Review 2`, 720 `author:\telvisp`, 721 `association:\tmember`, 722 `edited:\tfalse`, 723 `status:\tnone`, 724 `Comment 3`, 725 `author:\tleah`, 726 `association:\tmember`, 727 `edited:\ttrue`, 728 `status:\tapproved`, 729 `Review 3`, 730 `author:\tloislane`, 731 `association:\towner`, 732 `edited:\tfalse`, 733 `status:\tnone`, 734 `Comment 4`, 735 `author:\tlouise`, 736 `association:\tnone`, 737 `edited:\tfalse`, 738 `status:\tdismissed`, 739 `Review 4`, 740 `author:\tmarseilles`, 741 `association:\tcollaborator`, 742 `edited:\tfalse`, 743 `status:\tnone`, 744 `Comment 5`, 745 }, 746 }, 747 "with invalid comments flag": { 748 branch: "master", 749 cli: "123 --comments 3", 750 wantsErr: true, 751 }, 752 } 753 for name, tt := range tests { 754 t.Run(name, func(t *testing.T) { 755 http := &httpmock.Registry{} 756 defer http.Verify(t) 757 758 if len(tt.fixtures) > 0 { 759 pr, err := prFromFixtures(tt.fixtures) 760 require.NoError(t, err) 761 shared.RunCommandFinder("123", pr, ghrepo.New("OWNER", "REPO")) 762 } else { 763 shared.RunCommandFinder("123", nil, nil) 764 } 765 766 output, err := runCommand(http, tt.branch, false, tt.cli) 767 if tt.wantsErr { 768 assert.Error(t, err) 769 return 770 } 771 assert.NoError(t, err) 772 assert.Equal(t, "", output.Stderr()) 773 //nolint:staticcheck // prefer exact matchers over ExpectLines 774 test.ExpectLines(t, output.String(), tt.expectedOutputs...) 775 }) 776 } 777 }