github.com/google/go-github/v71@v71.0.0/github/pulls_reviews_test.go (about)

     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  
     6  package github
     7  
     8  import (
     9  	"context"
    10  	"encoding/json"
    11  	"fmt"
    12  	"net/http"
    13  	"testing"
    14  
    15  	"github.com/google/go-cmp/cmp"
    16  )
    17  
    18  func TestPullRequestsService_ListReviews(t *testing.T) {
    19  	t.Parallel()
    20  	client, mux, _ := setup(t)
    21  
    22  	mux.HandleFunc("/repos/o/r/pulls/1/reviews", func(w http.ResponseWriter, r *http.Request) {
    23  		testMethod(t, r, "GET")
    24  		testFormValues(t, r, values{
    25  			"page": "2",
    26  		})
    27  		fmt.Fprint(w, `[{"id":1},{"id":2}]`)
    28  	})
    29  
    30  	opt := &ListOptions{Page: 2}
    31  	ctx := context.Background()
    32  	reviews, _, err := client.PullRequests.ListReviews(ctx, "o", "r", 1, opt)
    33  	if err != nil {
    34  		t.Errorf("PullRequests.ListReviews returned error: %v", err)
    35  	}
    36  
    37  	want := []*PullRequestReview{
    38  		{ID: Ptr(int64(1))},
    39  		{ID: Ptr(int64(2))},
    40  	}
    41  	if !cmp.Equal(reviews, want) {
    42  		t.Errorf("PullRequests.ListReviews returned %+v, want %+v", reviews, want)
    43  	}
    44  
    45  	const methodName = "ListReviews"
    46  	testBadOptions(t, methodName, func() (err error) {
    47  		_, _, err = client.PullRequests.ListReviews(ctx, "\n", "\n", -1, opt)
    48  		return err
    49  	})
    50  
    51  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
    52  		got, resp, err := client.PullRequests.ListReviews(ctx, "o", "r", 1, opt)
    53  		if got != nil {
    54  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
    55  		}
    56  		return resp, err
    57  	})
    58  }
    59  
    60  func TestPullRequestsService_ListReviews_invalidOwner(t *testing.T) {
    61  	t.Parallel()
    62  	client, _, _ := setup(t)
    63  
    64  	ctx := context.Background()
    65  	_, _, err := client.PullRequests.ListReviews(ctx, "%", "r", 1, nil)
    66  	testURLParseError(t, err)
    67  }
    68  
    69  func TestPullRequestsService_GetReview(t *testing.T) {
    70  	t.Parallel()
    71  	client, mux, _ := setup(t)
    72  
    73  	mux.HandleFunc("/repos/o/r/pulls/1/reviews/1", func(w http.ResponseWriter, r *http.Request) {
    74  		testMethod(t, r, "GET")
    75  		fmt.Fprint(w, `{"id":1}`)
    76  	})
    77  
    78  	ctx := context.Background()
    79  	review, _, err := client.PullRequests.GetReview(ctx, "o", "r", 1, 1)
    80  	if err != nil {
    81  		t.Errorf("PullRequests.GetReview returned error: %v", err)
    82  	}
    83  
    84  	want := &PullRequestReview{ID: Ptr(int64(1))}
    85  	if !cmp.Equal(review, want) {
    86  		t.Errorf("PullRequests.GetReview returned %+v, want %+v", review, want)
    87  	}
    88  
    89  	const methodName = "GetReview"
    90  	testBadOptions(t, methodName, func() (err error) {
    91  		_, _, err = client.PullRequests.GetReview(ctx, "\n", "\n", -1, -1)
    92  		return err
    93  	})
    94  
    95  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
    96  		got, resp, err := client.PullRequests.GetReview(ctx, "o", "r", 1, 1)
    97  		if got != nil {
    98  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
    99  		}
   100  		return resp, err
   101  	})
   102  }
   103  
   104  func TestPullRequestsService_GetReview_invalidOwner(t *testing.T) {
   105  	t.Parallel()
   106  	client, _, _ := setup(t)
   107  
   108  	ctx := context.Background()
   109  	_, _, err := client.PullRequests.GetReview(ctx, "%", "r", 1, 1)
   110  	testURLParseError(t, err)
   111  }
   112  
   113  func TestPullRequestsService_DeletePendingReview(t *testing.T) {
   114  	t.Parallel()
   115  	client, mux, _ := setup(t)
   116  
   117  	mux.HandleFunc("/repos/o/r/pulls/1/reviews/1", func(w http.ResponseWriter, r *http.Request) {
   118  		testMethod(t, r, "DELETE")
   119  		fmt.Fprint(w, `{"id":1}`)
   120  	})
   121  
   122  	ctx := context.Background()
   123  	review, _, err := client.PullRequests.DeletePendingReview(ctx, "o", "r", 1, 1)
   124  	if err != nil {
   125  		t.Errorf("PullRequests.DeletePendingReview returned error: %v", err)
   126  	}
   127  
   128  	want := &PullRequestReview{ID: Ptr(int64(1))}
   129  	if !cmp.Equal(review, want) {
   130  		t.Errorf("PullRequests.DeletePendingReview returned %+v, want %+v", review, want)
   131  	}
   132  
   133  	const methodName = "DeletePendingReview"
   134  	testBadOptions(t, methodName, func() (err error) {
   135  		_, _, err = client.PullRequests.DeletePendingReview(ctx, "\n", "\n", -1, -1)
   136  		return err
   137  	})
   138  
   139  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   140  		got, resp, err := client.PullRequests.DeletePendingReview(ctx, "o", "r", 1, 1)
   141  		if got != nil {
   142  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   143  		}
   144  		return resp, err
   145  	})
   146  }
   147  
   148  func TestPullRequestsService_DeletePendingReview_invalidOwner(t *testing.T) {
   149  	t.Parallel()
   150  	client, _, _ := setup(t)
   151  
   152  	ctx := context.Background()
   153  	_, _, err := client.PullRequests.DeletePendingReview(ctx, "%", "r", 1, 1)
   154  	testURLParseError(t, err)
   155  }
   156  
   157  func TestPullRequestsService_ListReviewComments(t *testing.T) {
   158  	t.Parallel()
   159  	client, mux, _ := setup(t)
   160  
   161  	mux.HandleFunc("/repos/o/r/pulls/1/reviews/1/comments", func(w http.ResponseWriter, r *http.Request) {
   162  		testMethod(t, r, "GET")
   163  		fmt.Fprint(w, `[{"id":1},{"id":2}]`)
   164  	})
   165  
   166  	ctx := context.Background()
   167  	comments, _, err := client.PullRequests.ListReviewComments(ctx, "o", "r", 1, 1, nil)
   168  	if err != nil {
   169  		t.Errorf("PullRequests.ListReviewComments returned error: %v", err)
   170  	}
   171  
   172  	want := []*PullRequestComment{
   173  		{ID: Ptr(int64(1))},
   174  		{ID: Ptr(int64(2))},
   175  	}
   176  	if !cmp.Equal(comments, want) {
   177  		t.Errorf("PullRequests.ListReviewComments returned %+v, want %+v", comments, want)
   178  	}
   179  
   180  	const methodName = "ListReviewComments"
   181  	testBadOptions(t, methodName, func() (err error) {
   182  		_, _, err = client.PullRequests.ListReviewComments(ctx, "\n", "\n", -1, -1, nil)
   183  		return err
   184  	})
   185  
   186  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   187  		got, resp, err := client.PullRequests.ListReviewComments(ctx, "o", "r", 1, 1, nil)
   188  		if got != nil {
   189  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   190  		}
   191  		return resp, err
   192  	})
   193  }
   194  
   195  func TestPullRequestsService_ListReviewComments_withOptions(t *testing.T) {
   196  	t.Parallel()
   197  	client, mux, _ := setup(t)
   198  
   199  	mux.HandleFunc("/repos/o/r/pulls/1/reviews/1/comments", func(w http.ResponseWriter, r *http.Request) {
   200  		testMethod(t, r, "GET")
   201  		testFormValues(t, r, values{
   202  			"page": "2",
   203  		})
   204  		fmt.Fprint(w, `[]`)
   205  	})
   206  
   207  	ctx := context.Background()
   208  	_, _, err := client.PullRequests.ListReviewComments(ctx, "o", "r", 1, 1, &ListOptions{Page: 2})
   209  	if err != nil {
   210  		t.Errorf("PullRequests.ListReviewComments returned error: %v", err)
   211  	}
   212  
   213  	const methodName = "ListReviewComments"
   214  	testBadOptions(t, methodName, func() (err error) {
   215  		_, _, err = client.PullRequests.ListReviewComments(ctx, "\n", "\n", -1, -1, &ListOptions{Page: 2})
   216  		return err
   217  	})
   218  
   219  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   220  		got, resp, err := client.PullRequests.ListReviewComments(ctx, "o", "r", 1, 1, &ListOptions{Page: 2})
   221  		if got != nil {
   222  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   223  		}
   224  		return resp, err
   225  	})
   226  }
   227  
   228  func TestPullRequestReviewRequest_isComfortFadePreview(t *testing.T) {
   229  	t.Parallel()
   230  	path := "path/to/file.go"
   231  	body := "this is a comment body"
   232  	left, right := "LEFT", "RIGHT"
   233  	pos1, pos2, pos3 := 1, 2, 3
   234  	line1, line2, line3 := 11, 22, 33
   235  
   236  	tests := []struct {
   237  		name     string
   238  		review   *PullRequestReviewRequest
   239  		wantErr  error
   240  		wantBool bool
   241  	}{{
   242  		name:     "empty review",
   243  		review:   &PullRequestReviewRequest{},
   244  		wantBool: false,
   245  	}, {
   246  		name:     "nil comment",
   247  		review:   &PullRequestReviewRequest{Comments: []*DraftReviewComment{nil}},
   248  		wantBool: false,
   249  	}, {
   250  		name: "old-style review",
   251  		review: &PullRequestReviewRequest{
   252  			Comments: []*DraftReviewComment{{
   253  				Path:     &path,
   254  				Body:     &body,
   255  				Position: &pos1,
   256  			}, {
   257  				Path:     &path,
   258  				Body:     &body,
   259  				Position: &pos2,
   260  			}, {
   261  				Path:     &path,
   262  				Body:     &body,
   263  				Position: &pos3,
   264  			}},
   265  		},
   266  		wantBool: false,
   267  	}, {
   268  		name: "new-style review",
   269  		review: &PullRequestReviewRequest{
   270  			Comments: []*DraftReviewComment{{
   271  				Path: &path,
   272  				Body: &body,
   273  				Side: &right,
   274  				Line: &line1,
   275  			}, {
   276  				Path: &path,
   277  				Body: &body,
   278  				Side: &left,
   279  				Line: &line2,
   280  			}, {
   281  				Path: &path,
   282  				Body: &body,
   283  				Side: &right,
   284  				Line: &line3,
   285  			}},
   286  		},
   287  		wantBool: true,
   288  	}, {
   289  		name: "blended comment",
   290  		review: &PullRequestReviewRequest{
   291  			Comments: []*DraftReviewComment{{
   292  				Path:     &path,
   293  				Body:     &body,
   294  				Position: &pos1, // can't have both styles.
   295  				Side:     &right,
   296  				Line:     &line1,
   297  			}},
   298  		},
   299  		wantErr: ErrMixedCommentStyles,
   300  	}, {
   301  		name: "position then line",
   302  		review: &PullRequestReviewRequest{
   303  			Comments: []*DraftReviewComment{{
   304  				Path:     &path,
   305  				Body:     &body,
   306  				Position: &pos1,
   307  			}, {
   308  				Path: &path,
   309  				Body: &body,
   310  				Side: &right,
   311  				Line: &line1,
   312  			}},
   313  		},
   314  		wantErr: ErrMixedCommentStyles,
   315  	}, {
   316  		name: "line then position",
   317  		review: &PullRequestReviewRequest{
   318  			Comments: []*DraftReviewComment{{
   319  				Path: &path,
   320  				Body: &body,
   321  				Side: &right,
   322  				Line: &line1,
   323  			}, {
   324  				Path:     &path,
   325  				Body:     &body,
   326  				Position: &pos1,
   327  			}},
   328  		},
   329  		wantErr: ErrMixedCommentStyles,
   330  	}}
   331  
   332  	for _, tc := range tests {
   333  		t.Run(tc.name, func(t *testing.T) {
   334  			t.Parallel()
   335  			gotBool, gotErr := tc.review.isComfortFadePreview()
   336  			if tc.wantErr != nil {
   337  				if gotErr != tc.wantErr {
   338  					t.Errorf("isComfortFadePreview() = %v, wanted %v", gotErr, tc.wantErr)
   339  				}
   340  			} else {
   341  				if gotBool != tc.wantBool {
   342  					t.Errorf("isComfortFadePreview() = %v, wanted %v", gotBool, tc.wantBool)
   343  				}
   344  			}
   345  		})
   346  	}
   347  }
   348  
   349  func TestPullRequestsService_ListReviewComments_invalidOwner(t *testing.T) {
   350  	t.Parallel()
   351  	client, _, _ := setup(t)
   352  
   353  	ctx := context.Background()
   354  	_, _, err := client.PullRequests.ListReviewComments(ctx, "%", "r", 1, 1, nil)
   355  	testURLParseError(t, err)
   356  }
   357  
   358  func TestPullRequestsService_CreateReview(t *testing.T) {
   359  	t.Parallel()
   360  	client, mux, _ := setup(t)
   361  
   362  	input := &PullRequestReviewRequest{
   363  		CommitID: Ptr("commit_id"),
   364  		Body:     Ptr("b"),
   365  		Event:    Ptr("APPROVE"),
   366  	}
   367  
   368  	mux.HandleFunc("/repos/o/r/pulls/1/reviews", func(w http.ResponseWriter, r *http.Request) {
   369  		v := new(PullRequestReviewRequest)
   370  		assertNilError(t, json.NewDecoder(r.Body).Decode(v))
   371  
   372  		testMethod(t, r, "POST")
   373  		if !cmp.Equal(v, input) {
   374  			t.Errorf("Request body = %+v, want %+v", v, input)
   375  		}
   376  
   377  		fmt.Fprint(w, `{"id":1}`)
   378  	})
   379  
   380  	ctx := context.Background()
   381  	review, _, err := client.PullRequests.CreateReview(ctx, "o", "r", 1, input)
   382  	if err != nil {
   383  		t.Errorf("PullRequests.CreateReview returned error: %v", err)
   384  	}
   385  
   386  	want := &PullRequestReview{ID: Ptr(int64(1))}
   387  	if !cmp.Equal(review, want) {
   388  		t.Errorf("PullRequests.CreateReview returned %+v, want %+v", review, want)
   389  	}
   390  
   391  	const methodName = "CreateReview"
   392  	testBadOptions(t, methodName, func() (err error) {
   393  		_, _, err = client.PullRequests.CreateReview(ctx, "\n", "\n", -1, input)
   394  		return err
   395  	})
   396  
   397  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   398  		got, resp, err := client.PullRequests.CreateReview(ctx, "o", "r", 1, input)
   399  		if got != nil {
   400  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   401  		}
   402  		return resp, err
   403  	})
   404  }
   405  
   406  func TestPullRequestsService_CreateReview_invalidOwner(t *testing.T) {
   407  	t.Parallel()
   408  	client, _, _ := setup(t)
   409  
   410  	ctx := context.Background()
   411  	_, _, err := client.PullRequests.CreateReview(ctx, "%", "r", 1, &PullRequestReviewRequest{})
   412  	testURLParseError(t, err)
   413  }
   414  
   415  func TestPullRequestsService_CreateReview_badReview(t *testing.T) {
   416  	t.Parallel()
   417  	client, _, _ := setup(t)
   418  
   419  	ctx := context.Background()
   420  
   421  	path := "path/to/file.go"
   422  	body := "this is a comment body"
   423  	right := "RIGHT"
   424  	pos1 := 1
   425  	line1 := 11
   426  	badReview := &PullRequestReviewRequest{
   427  		Comments: []*DraftReviewComment{{
   428  			Path: &path,
   429  			Body: &body,
   430  			Side: &right,
   431  			Line: &line1,
   432  		}, {
   433  			Path:     &path,
   434  			Body:     &body,
   435  			Position: &pos1,
   436  		}}}
   437  
   438  	_, _, err := client.PullRequests.CreateReview(ctx, "o", "r", 1, badReview)
   439  	if err == nil {
   440  		t.Errorf("CreateReview badReview err = nil, want err")
   441  	}
   442  }
   443  
   444  func TestPullRequestsService_CreateReview_addHeader(t *testing.T) {
   445  	t.Parallel()
   446  	client, mux, _ := setup(t)
   447  
   448  	path := "path/to/file.go"
   449  	body := "this is a comment body"
   450  	left, right := "LEFT", "RIGHT"
   451  	line1, line2, line3 := 11, 22, 33
   452  	input := &PullRequestReviewRequest{
   453  		Comments: []*DraftReviewComment{{
   454  			Path: &path,
   455  			Body: &body,
   456  			Side: &right,
   457  			Line: &line1,
   458  		}, {
   459  			Path: &path,
   460  			Body: &body,
   461  			Side: &left,
   462  			Line: &line2,
   463  		}, {
   464  			Path: &path,
   465  			Body: &body,
   466  			Side: &right,
   467  			Line: &line3,
   468  		}},
   469  	}
   470  
   471  	mux.HandleFunc("/repos/o/r/pulls/1/reviews", func(w http.ResponseWriter, r *http.Request) {
   472  		v := new(PullRequestReviewRequest)
   473  		assertNilError(t, json.NewDecoder(r.Body).Decode(v))
   474  
   475  		testMethod(t, r, "POST")
   476  		if !cmp.Equal(v, input) {
   477  			t.Errorf("Request body = %+v, want %+v", v, input)
   478  		}
   479  
   480  		fmt.Fprint(w, `{"id":1}`)
   481  	})
   482  
   483  	ctx := context.Background()
   484  
   485  	_, _, err := client.PullRequests.CreateReview(ctx, "o", "r", 1, input)
   486  	if err != nil {
   487  		t.Errorf("CreateReview addHeader err = %v, want nil", err)
   488  	}
   489  }
   490  
   491  func TestPullRequestsService_UpdateReview(t *testing.T) {
   492  	t.Parallel()
   493  	client, mux, _ := setup(t)
   494  
   495  	mux.HandleFunc("/repos/o/r/pulls/1/reviews/1", func(w http.ResponseWriter, r *http.Request) {
   496  		testMethod(t, r, "PUT")
   497  		fmt.Fprintf(w, `{"id":1}`)
   498  	})
   499  
   500  	ctx := context.Background()
   501  	got, _, err := client.PullRequests.UpdateReview(ctx, "o", "r", 1, 1, "updated_body")
   502  	if err != nil {
   503  		t.Errorf("PullRequests.UpdateReview returned error: %v", err)
   504  	}
   505  
   506  	want := &PullRequestReview{ID: Ptr(int64(1))}
   507  	if !cmp.Equal(got, want) {
   508  		t.Errorf("PullRequests.UpdateReview = %+v, want %+v", got, want)
   509  	}
   510  
   511  	const methodName = "UpdateReview"
   512  	testBadOptions(t, methodName, func() (err error) {
   513  		_, _, err = client.PullRequests.UpdateReview(ctx, "\n", "\n", -1, -1, "updated_body")
   514  		return err
   515  	})
   516  
   517  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   518  		got, resp, err := client.PullRequests.UpdateReview(ctx, "o", "r", 1, 1, "updated_body")
   519  		if got != nil {
   520  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   521  		}
   522  		return resp, err
   523  	})
   524  }
   525  
   526  func TestPullRequestsService_SubmitReview(t *testing.T) {
   527  	t.Parallel()
   528  	client, mux, _ := setup(t)
   529  
   530  	input := &PullRequestReviewRequest{
   531  		Body:  Ptr("b"),
   532  		Event: Ptr("APPROVE"),
   533  	}
   534  
   535  	mux.HandleFunc("/repos/o/r/pulls/1/reviews/1/events", func(w http.ResponseWriter, r *http.Request) {
   536  		v := new(PullRequestReviewRequest)
   537  		assertNilError(t, json.NewDecoder(r.Body).Decode(v))
   538  
   539  		testMethod(t, r, "POST")
   540  		if !cmp.Equal(v, input) {
   541  			t.Errorf("Request body = %+v, want %+v", v, input)
   542  		}
   543  
   544  		fmt.Fprint(w, `{"id":1}`)
   545  	})
   546  
   547  	ctx := context.Background()
   548  	review, _, err := client.PullRequests.SubmitReview(ctx, "o", "r", 1, 1, input)
   549  	if err != nil {
   550  		t.Errorf("PullRequests.SubmitReview returned error: %v", err)
   551  	}
   552  
   553  	want := &PullRequestReview{ID: Ptr(int64(1))}
   554  	if !cmp.Equal(review, want) {
   555  		t.Errorf("PullRequests.SubmitReview returned %+v, want %+v", review, want)
   556  	}
   557  
   558  	const methodName = "SubmitReview"
   559  	testBadOptions(t, methodName, func() (err error) {
   560  		_, _, err = client.PullRequests.SubmitReview(ctx, "\n", "\n", -1, -1, input)
   561  		return err
   562  	})
   563  
   564  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   565  		got, resp, err := client.PullRequests.SubmitReview(ctx, "o", "r", 1, 1, input)
   566  		if got != nil {
   567  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   568  		}
   569  		return resp, err
   570  	})
   571  }
   572  
   573  func TestPullRequestsService_SubmitReview_invalidOwner(t *testing.T) {
   574  	t.Parallel()
   575  	client, _, _ := setup(t)
   576  
   577  	ctx := context.Background()
   578  	_, _, err := client.PullRequests.SubmitReview(ctx, "%", "r", 1, 1, &PullRequestReviewRequest{})
   579  	testURLParseError(t, err)
   580  }
   581  
   582  func TestPullRequestsService_DismissReview(t *testing.T) {
   583  	t.Parallel()
   584  	client, mux, _ := setup(t)
   585  
   586  	input := &PullRequestReviewDismissalRequest{Message: Ptr("m")}
   587  
   588  	mux.HandleFunc("/repos/o/r/pulls/1/reviews/1/dismissals", func(w http.ResponseWriter, r *http.Request) {
   589  		v := new(PullRequestReviewDismissalRequest)
   590  		assertNilError(t, json.NewDecoder(r.Body).Decode(v))
   591  
   592  		testMethod(t, r, "PUT")
   593  		if !cmp.Equal(v, input) {
   594  			t.Errorf("Request body = %+v, want %+v", v, input)
   595  		}
   596  
   597  		fmt.Fprint(w, `{"id":1}`)
   598  	})
   599  
   600  	ctx := context.Background()
   601  	review, _, err := client.PullRequests.DismissReview(ctx, "o", "r", 1, 1, input)
   602  	if err != nil {
   603  		t.Errorf("PullRequests.DismissReview returned error: %v", err)
   604  	}
   605  
   606  	want := &PullRequestReview{ID: Ptr(int64(1))}
   607  	if !cmp.Equal(review, want) {
   608  		t.Errorf("PullRequests.DismissReview returned %+v, want %+v", review, want)
   609  	}
   610  
   611  	const methodName = "ListReviews"
   612  	testBadOptions(t, methodName, func() (err error) {
   613  		_, _, err = client.PullRequests.DismissReview(ctx, "\n", "\n", -1, -1, input)
   614  		return err
   615  	})
   616  
   617  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   618  		got, resp, err := client.PullRequests.DismissReview(ctx, "o", "r", 1, 1, input)
   619  		if got != nil {
   620  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   621  		}
   622  		return resp, err
   623  	})
   624  }
   625  
   626  func TestPullRequestsService_DismissReview_invalidOwner(t *testing.T) {
   627  	t.Parallel()
   628  	client, _, _ := setup(t)
   629  
   630  	ctx := context.Background()
   631  	_, _, err := client.PullRequests.DismissReview(ctx, "%", "r", 1, 1, &PullRequestReviewDismissalRequest{})
   632  	testURLParseError(t, err)
   633  }
   634  
   635  func TestPullRequestReviewDismissalRequest_Marshal(t *testing.T) {
   636  	t.Parallel()
   637  	testJSONMarshal(t, &PullRequestReviewDismissalRequest{}, "{}")
   638  
   639  	u := &PullRequestReviewDismissalRequest{
   640  		Message: Ptr("msg"),
   641  	}
   642  
   643  	want := `{
   644  		"message": "msg"
   645  	}`
   646  
   647  	testJSONMarshal(t, u, want)
   648  }
   649  
   650  func TestDraftReviewComment_Marshal(t *testing.T) {
   651  	t.Parallel()
   652  	testJSONMarshal(t, &DraftReviewComment{}, "{}")
   653  
   654  	u := &DraftReviewComment{
   655  		Path:      Ptr("path"),
   656  		Position:  Ptr(1),
   657  		Body:      Ptr("body"),
   658  		StartSide: Ptr("ss"),
   659  		Side:      Ptr("side"),
   660  		StartLine: Ptr(1),
   661  		Line:      Ptr(1),
   662  	}
   663  
   664  	want := `{
   665  		"path": "path",
   666  		"position": 1,
   667  		"body": "body",
   668  		"start_side": "ss",
   669  		"side": "side",
   670  		"start_line": 1,
   671  		"line": 1
   672  	}`
   673  
   674  	testJSONMarshal(t, u, want)
   675  }
   676  
   677  func TestPullRequestReviewRequest_Marshal(t *testing.T) {
   678  	t.Parallel()
   679  	testJSONMarshal(t, &PullRequestReviewRequest{}, "{}")
   680  
   681  	u := &PullRequestReviewRequest{
   682  		NodeID:   Ptr("nodeid"),
   683  		CommitID: Ptr("cid"),
   684  		Body:     Ptr("body"),
   685  		Event:    Ptr("event"),
   686  		Comments: []*DraftReviewComment{
   687  			{
   688  				Path:      Ptr("path"),
   689  				Position:  Ptr(1),
   690  				Body:      Ptr("body"),
   691  				StartSide: Ptr("ss"),
   692  				Side:      Ptr("side"),
   693  				StartLine: Ptr(1),
   694  				Line:      Ptr(1),
   695  			},
   696  		},
   697  	}
   698  
   699  	want := `{
   700  		"node_id": "nodeid",
   701  		"commit_id": "cid",
   702  		"body": "body",
   703  		"event": "event",
   704  		"comments": [
   705  			{
   706  				"path": "path",
   707  				"position": 1,
   708  				"body": "body",
   709  				"start_side": "ss",
   710  				"side": "side",
   711  				"start_line": 1,
   712  				"line": 1
   713  			}
   714  		]
   715  	}`
   716  
   717  	testJSONMarshal(t, u, want)
   718  }
   719  
   720  func TestPullRequestReview_Marshal(t *testing.T) {
   721  	t.Parallel()
   722  	testJSONMarshal(t, &PullRequestReview{}, "{}")
   723  
   724  	u := &PullRequestReview{
   725  		ID:     Ptr(int64(1)),
   726  		NodeID: Ptr("nid"),
   727  		User: &User{
   728  			Login:           Ptr("l"),
   729  			ID:              Ptr(int64(1)),
   730  			URL:             Ptr("u"),
   731  			AvatarURL:       Ptr("a"),
   732  			GravatarID:      Ptr("g"),
   733  			Name:            Ptr("n"),
   734  			Company:         Ptr("c"),
   735  			Blog:            Ptr("b"),
   736  			Location:        Ptr("l"),
   737  			Email:           Ptr("e"),
   738  			Hireable:        Ptr(true),
   739  			Bio:             Ptr("b"),
   740  			TwitterUsername: Ptr("t"),
   741  			PublicRepos:     Ptr(1),
   742  			Followers:       Ptr(1),
   743  			Following:       Ptr(1),
   744  			CreatedAt:       &Timestamp{referenceTime},
   745  			SuspendedAt:     &Timestamp{referenceTime},
   746  		},
   747  		Body:              Ptr("body"),
   748  		SubmittedAt:       &Timestamp{referenceTime},
   749  		CommitID:          Ptr("cid"),
   750  		HTMLURL:           Ptr("hurl"),
   751  		PullRequestURL:    Ptr("prurl"),
   752  		State:             Ptr("state"),
   753  		AuthorAssociation: Ptr("aa"),
   754  	}
   755  
   756  	want := `{
   757  		"id": 1,
   758  		"node_id": "nid",
   759  		"user": {
   760  			"login": "l",
   761  			"id": 1,
   762  			"avatar_url": "a",
   763  			"gravatar_id": "g",
   764  			"name": "n",
   765  			"company": "c",
   766  			"blog": "b",
   767  			"location": "l",
   768  			"email": "e",
   769  			"hireable": true,
   770  			"bio": "b",
   771  			"twitter_username": "t",
   772  			"public_repos": 1,
   773  			"followers": 1,
   774  			"following": 1,
   775  			"created_at": ` + referenceTimeStr + `,
   776  			"suspended_at": ` + referenceTimeStr + `,
   777  			"url": "u"
   778  		},
   779  		"body": "body",
   780  		"submitted_at": ` + referenceTimeStr + `,
   781  		"commit_id": "cid",
   782  		"html_url": "hurl",
   783  		"pull_request_url": "prurl",
   784  		"state": "state",
   785  		"author_association": "aa"
   786  	}`
   787  
   788  	testJSONMarshal(t, u, want)
   789  }