1// Copyright 2016 The go-github AUTHORS. All rights reserved. 2// 3// Use of this source code is governed by a BSD-style 4// license that can be found in the LICENSE file. 5 6package github 7 8import ( 9 "context" 10 "encoding/json" 11 "fmt" 12 "net/http" 13 "reflect" 14 "testing" 15) 16 17func TestPullRequestsService_ListReviews(t *testing.T) { 18 client, mux, _, teardown := setup() 19 defer teardown() 20 21 mux.HandleFunc("/repos/o/r/pulls/1/reviews", func(w http.ResponseWriter, r *http.Request) { 22 testMethod(t, r, "GET") 23 testFormValues(t, r, values{ 24 "page": "2", 25 }) 26 fmt.Fprint(w, `[{"id":1},{"id":2}]`) 27 }) 28 29 opt := &ListOptions{Page: 2} 30 ctx := context.Background() 31 reviews, _, err := client.PullRequests.ListReviews(ctx, "o", "r", 1, opt) 32 if err != nil { 33 t.Errorf("PullRequests.ListReviews returned error: %v", err) 34 } 35 36 want := []*PullRequestReview{ 37 {ID: Int64(1)}, 38 {ID: Int64(2)}, 39 } 40 if !reflect.DeepEqual(reviews, want) { 41 t.Errorf("PullRequests.ListReviews returned %+v, want %+v", reviews, want) 42 } 43 44 const methodName = "ListReviews" 45 testBadOptions(t, methodName, func() (err error) { 46 _, _, err = client.PullRequests.ListReviews(ctx, "\n", "\n", -1, opt) 47 return err 48 }) 49 50 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 51 got, resp, err := client.PullRequests.ListReviews(ctx, "o", "r", 1, opt) 52 if got != nil { 53 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 54 } 55 return resp, err 56 }) 57} 58 59func TestPullRequestsService_ListReviews_invalidOwner(t *testing.T) { 60 client, _, _, teardown := setup() 61 defer teardown() 62 63 ctx := context.Background() 64 _, _, err := client.PullRequests.ListReviews(ctx, "%", "r", 1, nil) 65 testURLParseError(t, err) 66} 67 68func TestPullRequestsService_GetReview(t *testing.T) { 69 client, mux, _, teardown := setup() 70 defer teardown() 71 72 mux.HandleFunc("/repos/o/r/pulls/1/reviews/1", func(w http.ResponseWriter, r *http.Request) { 73 testMethod(t, r, "GET") 74 fmt.Fprint(w, `{"id":1}`) 75 }) 76 77 ctx := context.Background() 78 review, _, err := client.PullRequests.GetReview(ctx, "o", "r", 1, 1) 79 if err != nil { 80 t.Errorf("PullRequests.GetReview returned error: %v", err) 81 } 82 83 want := &PullRequestReview{ID: Int64(1)} 84 if !reflect.DeepEqual(review, want) { 85 t.Errorf("PullRequests.GetReview returned %+v, want %+v", review, want) 86 } 87 88 const methodName = "GetReview" 89 testBadOptions(t, methodName, func() (err error) { 90 _, _, err = client.PullRequests.GetReview(ctx, "\n", "\n", -1, -1) 91 return err 92 }) 93 94 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 95 got, resp, err := client.PullRequests.GetReview(ctx, "o", "r", 1, 1) 96 if got != nil { 97 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 98 } 99 return resp, err 100 }) 101} 102 103func TestPullRequestsService_GetReview_invalidOwner(t *testing.T) { 104 client, _, _, teardown := setup() 105 defer teardown() 106 107 ctx := context.Background() 108 _, _, err := client.PullRequests.GetReview(ctx, "%", "r", 1, 1) 109 testURLParseError(t, err) 110} 111 112func TestPullRequestsService_DeletePendingReview(t *testing.T) { 113 client, mux, _, teardown := setup() 114 defer teardown() 115 116 mux.HandleFunc("/repos/o/r/pulls/1/reviews/1", func(w http.ResponseWriter, r *http.Request) { 117 testMethod(t, r, "DELETE") 118 fmt.Fprint(w, `{"id":1}`) 119 }) 120 121 ctx := context.Background() 122 review, _, err := client.PullRequests.DeletePendingReview(ctx, "o", "r", 1, 1) 123 if err != nil { 124 t.Errorf("PullRequests.DeletePendingReview returned error: %v", err) 125 } 126 127 want := &PullRequestReview{ID: Int64(1)} 128 if !reflect.DeepEqual(review, want) { 129 t.Errorf("PullRequests.DeletePendingReview returned %+v, want %+v", review, want) 130 } 131 132 const methodName = "DeletePendingReview" 133 testBadOptions(t, methodName, func() (err error) { 134 _, _, err = client.PullRequests.DeletePendingReview(ctx, "\n", "\n", -1, -1) 135 return err 136 }) 137 138 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 139 got, resp, err := client.PullRequests.DeletePendingReview(ctx, "o", "r", 1, 1) 140 if got != nil { 141 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 142 } 143 return resp, err 144 }) 145} 146 147func TestPullRequestsService_DeletePendingReview_invalidOwner(t *testing.T) { 148 client, _, _, teardown := setup() 149 defer teardown() 150 151 ctx := context.Background() 152 _, _, err := client.PullRequests.DeletePendingReview(ctx, "%", "r", 1, 1) 153 testURLParseError(t, err) 154} 155 156func TestPullRequestsService_ListReviewComments(t *testing.T) { 157 client, mux, _, teardown := setup() 158 defer teardown() 159 160 mux.HandleFunc("/repos/o/r/pulls/1/reviews/1/comments", func(w http.ResponseWriter, r *http.Request) { 161 testMethod(t, r, "GET") 162 fmt.Fprint(w, `[{"id":1},{"id":2}]`) 163 }) 164 165 ctx := context.Background() 166 comments, _, err := client.PullRequests.ListReviewComments(ctx, "o", "r", 1, 1, nil) 167 if err != nil { 168 t.Errorf("PullRequests.ListReviewComments returned error: %v", err) 169 } 170 171 want := []*PullRequestComment{ 172 {ID: Int64(1)}, 173 {ID: Int64(2)}, 174 } 175 if !reflect.DeepEqual(comments, want) { 176 t.Errorf("PullRequests.ListReviewComments returned %+v, want %+v", comments, want) 177 } 178 179 const methodName = "ListReviewComments" 180 testBadOptions(t, methodName, func() (err error) { 181 _, _, err = client.PullRequests.ListReviewComments(ctx, "\n", "\n", -1, -1, nil) 182 return err 183 }) 184 185 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 186 got, resp, err := client.PullRequests.ListReviewComments(ctx, "o", "r", 1, 1, nil) 187 if got != nil { 188 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 189 } 190 return resp, err 191 }) 192} 193 194func TestPullRequestsService_ListReviewComments_withOptions(t *testing.T) { 195 client, mux, _, teardown := setup() 196 defer teardown() 197 198 mux.HandleFunc("/repos/o/r/pulls/1/reviews/1/comments", func(w http.ResponseWriter, r *http.Request) { 199 testMethod(t, r, "GET") 200 testFormValues(t, r, values{ 201 "page": "2", 202 }) 203 fmt.Fprint(w, `[]`) 204 }) 205 206 ctx := context.Background() 207 _, _, err := client.PullRequests.ListReviewComments(ctx, "o", "r", 1, 1, &ListOptions{Page: 2}) 208 if err != nil { 209 t.Errorf("PullRequests.ListReviewComments returned error: %v", err) 210 } 211 212 const methodName = "ListReviewComments" 213 testBadOptions(t, methodName, func() (err error) { 214 _, _, err = client.PullRequests.ListReviewComments(ctx, "\n", "\n", -1, -1, &ListOptions{Page: 2}) 215 return err 216 }) 217 218 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 219 got, resp, err := client.PullRequests.ListReviewComments(ctx, "o", "r", 1, 1, &ListOptions{Page: 2}) 220 if got != nil { 221 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 222 } 223 return resp, err 224 }) 225} 226 227func TestPullRequestReviewRequest_isComfortFadePreview(t *testing.T) { 228 path := "path/to/file.go" 229 body := "this is a comment body" 230 left, right := "LEFT", "RIGHT" 231 pos1, pos2, pos3 := 1, 2, 3 232 line1, line2, line3 := 11, 22, 33 233 234 tests := []struct { 235 name string 236 review *PullRequestReviewRequest 237 wantErr error 238 wantBool bool 239 }{{ 240 name: "empty review", 241 review: &PullRequestReviewRequest{}, 242 wantBool: false, 243 }, { 244 name: "nil comment", 245 review: &PullRequestReviewRequest{Comments: []*DraftReviewComment{nil}}, 246 wantBool: false, 247 }, { 248 name: "old-style review", 249 review: &PullRequestReviewRequest{ 250 Comments: []*DraftReviewComment{{ 251 Path: &path, 252 Body: &body, 253 Position: &pos1, 254 }, { 255 Path: &path, 256 Body: &body, 257 Position: &pos2, 258 }, { 259 Path: &path, 260 Body: &body, 261 Position: &pos3, 262 }}, 263 }, 264 wantBool: false, 265 }, { 266 name: "new-style review", 267 review: &PullRequestReviewRequest{ 268 Comments: []*DraftReviewComment{{ 269 Path: &path, 270 Body: &body, 271 Side: &right, 272 Line: &line1, 273 }, { 274 Path: &path, 275 Body: &body, 276 Side: &left, 277 Line: &line2, 278 }, { 279 Path: &path, 280 Body: &body, 281 Side: &right, 282 Line: &line3, 283 }}, 284 }, 285 wantBool: true, 286 }, { 287 name: "blended comment", 288 review: &PullRequestReviewRequest{ 289 Comments: []*DraftReviewComment{{ 290 Path: &path, 291 Body: &body, 292 Position: &pos1, // can't have both styles. 293 Side: &right, 294 Line: &line1, 295 }}, 296 }, 297 wantErr: ErrMixedCommentStyles, 298 }, { 299 name: "position then line", 300 review: &PullRequestReviewRequest{ 301 Comments: []*DraftReviewComment{{ 302 Path: &path, 303 Body: &body, 304 Position: &pos1, 305 }, { 306 Path: &path, 307 Body: &body, 308 Side: &right, 309 Line: &line1, 310 }}, 311 }, 312 wantErr: ErrMixedCommentStyles, 313 }, { 314 name: "line then position", 315 review: &PullRequestReviewRequest{ 316 Comments: []*DraftReviewComment{{ 317 Path: &path, 318 Body: &body, 319 Side: &right, 320 Line: &line1, 321 }, { 322 Path: &path, 323 Body: &body, 324 Position: &pos1, 325 }}, 326 }, 327 wantErr: ErrMixedCommentStyles, 328 }} 329 330 for _, tc := range tests { 331 t.Run(tc.name, func(t *testing.T) { 332 gotBool, gotErr := tc.review.isComfortFadePreview() 333 if tc.wantErr != nil { 334 if gotErr != tc.wantErr { 335 t.Errorf("isComfortFadePreview() = %v, wanted %v", gotErr, tc.wantErr) 336 } 337 } else { 338 if gotBool != tc.wantBool { 339 t.Errorf("isComfortFadePreview() = %v, wanted %v", gotBool, tc.wantBool) 340 } 341 } 342 }) 343 } 344} 345 346func TestPullRequestsService_ListReviewComments_invalidOwner(t *testing.T) { 347 client, _, _, teardown := setup() 348 defer teardown() 349 350 ctx := context.Background() 351 _, _, err := client.PullRequests.ListReviewComments(ctx, "%", "r", 1, 1, nil) 352 testURLParseError(t, err) 353} 354 355func TestPullRequestsService_CreateReview(t *testing.T) { 356 client, mux, _, teardown := setup() 357 defer teardown() 358 359 input := &PullRequestReviewRequest{ 360 CommitID: String("commit_id"), 361 Body: String("b"), 362 Event: String("APPROVE"), 363 } 364 365 mux.HandleFunc("/repos/o/r/pulls/1/reviews", func(w http.ResponseWriter, r *http.Request) { 366 v := new(PullRequestReviewRequest) 367 json.NewDecoder(r.Body).Decode(v) 368 369 testMethod(t, r, "POST") 370 if !reflect.DeepEqual(v, input) { 371 t.Errorf("Request body = %+v, want %+v", v, input) 372 } 373 374 fmt.Fprint(w, `{"id":1}`) 375 }) 376 377 ctx := context.Background() 378 review, _, err := client.PullRequests.CreateReview(ctx, "o", "r", 1, input) 379 if err != nil { 380 t.Errorf("PullRequests.CreateReview returned error: %v", err) 381 } 382 383 want := &PullRequestReview{ID: Int64(1)} 384 if !reflect.DeepEqual(review, want) { 385 t.Errorf("PullRequests.CreateReview returned %+v, want %+v", review, want) 386 } 387 388 const methodName = "CreateReview" 389 testBadOptions(t, methodName, func() (err error) { 390 _, _, err = client.PullRequests.CreateReview(ctx, "\n", "\n", -1, input) 391 return err 392 }) 393 394 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 395 got, resp, err := client.PullRequests.CreateReview(ctx, "o", "r", 1, input) 396 if got != nil { 397 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 398 } 399 return resp, err 400 }) 401} 402 403func TestPullRequestsService_CreateReview_invalidOwner(t *testing.T) { 404 client, _, _, teardown := setup() 405 defer teardown() 406 407 ctx := context.Background() 408 _, _, err := client.PullRequests.CreateReview(ctx, "%", "r", 1, &PullRequestReviewRequest{}) 409 testURLParseError(t, err) 410} 411 412func TestPullRequestsService_CreateReview_badReview(t *testing.T) { 413 client, _, _, teardown := setup() 414 defer teardown() 415 416 ctx := context.Background() 417 418 path := "path/to/file.go" 419 body := "this is a comment body" 420 right := "RIGHT" 421 pos1 := 1 422 line1 := 11 423 badReview := &PullRequestReviewRequest{ 424 Comments: []*DraftReviewComment{{ 425 Path: &path, 426 Body: &body, 427 Side: &right, 428 Line: &line1, 429 }, { 430 Path: &path, 431 Body: &body, 432 Position: &pos1, 433 }}} 434 435 _, _, err := client.PullRequests.CreateReview(ctx, "o", "r", 1, badReview) 436 if err == nil { 437 t.Errorf("CreateReview badReview err = nil, want err") 438 } 439} 440 441func TestPullRequestsService_CreateReview_addHeader(t *testing.T) { 442 client, mux, _, teardown := setup() 443 defer teardown() 444 445 path := "path/to/file.go" 446 body := "this is a comment body" 447 left, right := "LEFT", "RIGHT" 448 line1, line2, line3 := 11, 22, 33 449 input := &PullRequestReviewRequest{ 450 Comments: []*DraftReviewComment{{ 451 Path: &path, 452 Body: &body, 453 Side: &right, 454 Line: &line1, 455 }, { 456 Path: &path, 457 Body: &body, 458 Side: &left, 459 Line: &line2, 460 }, { 461 Path: &path, 462 Body: &body, 463 Side: &right, 464 Line: &line3, 465 }}, 466 } 467 468 mux.HandleFunc("/repos/o/r/pulls/1/reviews", func(w http.ResponseWriter, r *http.Request) { 469 v := new(PullRequestReviewRequest) 470 json.NewDecoder(r.Body).Decode(v) 471 472 testMethod(t, r, "POST") 473 if !reflect.DeepEqual(v, input) { 474 t.Errorf("Request body = %+v, want %+v", v, input) 475 } 476 477 fmt.Fprint(w, `{"id":1}`) 478 }) 479 480 ctx := context.Background() 481 482 _, _, err := client.PullRequests.CreateReview(ctx, "o", "r", 1, input) 483 if err != nil { 484 t.Errorf("CreateReview addHeader err = %v, want nil", err) 485 } 486} 487 488func TestPullRequestsService_UpdateReview(t *testing.T) { 489 client, mux, _, teardown := setup() 490 defer teardown() 491 492 mux.HandleFunc("/repos/o/r/pulls/1/reviews/1", func(w http.ResponseWriter, r *http.Request) { 493 testMethod(t, r, "PUT") 494 fmt.Fprintf(w, `{"id":1}`) 495 }) 496 497 ctx := context.Background() 498 got, _, err := client.PullRequests.UpdateReview(ctx, "o", "r", 1, 1, "updated_body") 499 if err != nil { 500 t.Errorf("PullRequests.UpdateReview returned error: %v", err) 501 } 502 503 want := &PullRequestReview{ID: Int64(1)} 504 if !reflect.DeepEqual(got, want) { 505 t.Errorf("PullRequests.UpdateReview = %+v, want %+v", got, want) 506 } 507 508 const methodName = "UpdateReview" 509 testBadOptions(t, methodName, func() (err error) { 510 _, _, err = client.PullRequests.UpdateReview(ctx, "\n", "\n", -1, -1, "updated_body") 511 return err 512 }) 513 514 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 515 got, resp, err := client.PullRequests.UpdateReview(ctx, "o", "r", 1, 1, "updated_body") 516 if got != nil { 517 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 518 } 519 return resp, err 520 }) 521} 522 523func TestPullRequestsService_SubmitReview(t *testing.T) { 524 client, mux, _, teardown := setup() 525 defer teardown() 526 527 input := &PullRequestReviewRequest{ 528 Body: String("b"), 529 Event: String("APPROVE"), 530 } 531 532 mux.HandleFunc("/repos/o/r/pulls/1/reviews/1/events", func(w http.ResponseWriter, r *http.Request) { 533 v := new(PullRequestReviewRequest) 534 json.NewDecoder(r.Body).Decode(v) 535 536 testMethod(t, r, "POST") 537 if !reflect.DeepEqual(v, input) { 538 t.Errorf("Request body = %+v, want %+v", v, input) 539 } 540 541 fmt.Fprint(w, `{"id":1}`) 542 }) 543 544 ctx := context.Background() 545 review, _, err := client.PullRequests.SubmitReview(ctx, "o", "r", 1, 1, input) 546 if err != nil { 547 t.Errorf("PullRequests.SubmitReview returned error: %v", err) 548 } 549 550 want := &PullRequestReview{ID: Int64(1)} 551 if !reflect.DeepEqual(review, want) { 552 t.Errorf("PullRequests.SubmitReview returned %+v, want %+v", review, want) 553 } 554 555 const methodName = "SubmitReview" 556 testBadOptions(t, methodName, func() (err error) { 557 _, _, err = client.PullRequests.SubmitReview(ctx, "\n", "\n", -1, -1, input) 558 return err 559 }) 560 561 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 562 got, resp, err := client.PullRequests.SubmitReview(ctx, "o", "r", 1, 1, input) 563 if got != nil { 564 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 565 } 566 return resp, err 567 }) 568} 569 570func TestPullRequestsService_SubmitReview_invalidOwner(t *testing.T) { 571 client, _, _, teardown := setup() 572 defer teardown() 573 574 ctx := context.Background() 575 _, _, err := client.PullRequests.SubmitReview(ctx, "%", "r", 1, 1, &PullRequestReviewRequest{}) 576 testURLParseError(t, err) 577} 578 579func TestPullRequestsService_DismissReview(t *testing.T) { 580 client, mux, _, teardown := setup() 581 defer teardown() 582 583 input := &PullRequestReviewDismissalRequest{Message: String("m")} 584 585 mux.HandleFunc("/repos/o/r/pulls/1/reviews/1/dismissals", func(w http.ResponseWriter, r *http.Request) { 586 v := new(PullRequestReviewDismissalRequest) 587 json.NewDecoder(r.Body).Decode(v) 588 589 testMethod(t, r, "PUT") 590 if !reflect.DeepEqual(v, input) { 591 t.Errorf("Request body = %+v, want %+v", v, input) 592 } 593 594 fmt.Fprint(w, `{"id":1}`) 595 }) 596 597 ctx := context.Background() 598 review, _, err := client.PullRequests.DismissReview(ctx, "o", "r", 1, 1, input) 599 if err != nil { 600 t.Errorf("PullRequests.DismissReview returned error: %v", err) 601 } 602 603 want := &PullRequestReview{ID: Int64(1)} 604 if !reflect.DeepEqual(review, want) { 605 t.Errorf("PullRequests.DismissReview returned %+v, want %+v", review, want) 606 } 607 608 const methodName = "ListReviews" 609 testBadOptions(t, methodName, func() (err error) { 610 _, _, err = client.PullRequests.DismissReview(ctx, "\n", "\n", -1, -1, input) 611 return err 612 }) 613 614 testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { 615 got, resp, err := client.PullRequests.DismissReview(ctx, "o", "r", 1, 1, input) 616 if got != nil { 617 t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) 618 } 619 return resp, err 620 }) 621} 622 623func TestPullRequestsService_DismissReview_invalidOwner(t *testing.T) { 624 client, _, _, teardown := setup() 625 defer teardown() 626 627 ctx := context.Background() 628 _, _, err := client.PullRequests.DismissReview(ctx, "%", "r", 1, 1, &PullRequestReviewDismissalRequest{}) 629 testURLParseError(t, err) 630} 631