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

     1  // Copyright 2013 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  	"io"
    13  	"net/http"
    14  	"strings"
    15  	"testing"
    16  
    17  	"github.com/google/go-cmp/cmp"
    18  )
    19  
    20  func TestPullRequestsService_List(t *testing.T) {
    21  	t.Parallel()
    22  	client, mux, _ := setup(t)
    23  
    24  	mux.HandleFunc("/repos/o/r/pulls", func(w http.ResponseWriter, r *http.Request) {
    25  		testMethod(t, r, "GET")
    26  		testFormValues(t, r, values{
    27  			"state":     "closed",
    28  			"head":      "h",
    29  			"base":      "b",
    30  			"sort":      "created",
    31  			"direction": "desc",
    32  			"page":      "2",
    33  		})
    34  		fmt.Fprint(w, `[{"number":1}]`)
    35  	})
    36  
    37  	opts := &PullRequestListOptions{"closed", "h", "b", "created", "desc", ListOptions{Page: 2}}
    38  	ctx := context.Background()
    39  	pulls, _, err := client.PullRequests.List(ctx, "o", "r", opts)
    40  	if err != nil {
    41  		t.Errorf("PullRequests.List returned error: %v", err)
    42  	}
    43  
    44  	want := []*PullRequest{{Number: Ptr(1)}}
    45  	if !cmp.Equal(pulls, want) {
    46  		t.Errorf("PullRequests.List returned %+v, want %+v", pulls, want)
    47  	}
    48  
    49  	const methodName = "List"
    50  	testBadOptions(t, methodName, func() (err error) {
    51  		_, _, err = client.PullRequests.List(ctx, "\n", "\n", opts)
    52  		return err
    53  	})
    54  
    55  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
    56  		got, resp, err := client.PullRequests.List(ctx, "o", "r", opts)
    57  		if got != nil {
    58  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
    59  		}
    60  		return resp, err
    61  	})
    62  }
    63  
    64  func TestPullRequestsService_ListPullRequestsWithCommit(t *testing.T) {
    65  	t.Parallel()
    66  	client, mux, _ := setup(t)
    67  
    68  	mux.HandleFunc("/repos/o/r/commits/sha/pulls", func(w http.ResponseWriter, r *http.Request) {
    69  		testMethod(t, r, "GET")
    70  		testHeader(t, r, "Accept", mediaTypeListPullsOrBranchesForCommitPreview)
    71  		testFormValues(t, r, values{
    72  			"page": "2",
    73  		})
    74  		fmt.Fprint(w, `[{"number":1}]`)
    75  	})
    76  
    77  	opts := &ListOptions{Page: 2}
    78  	ctx := context.Background()
    79  	pulls, _, err := client.PullRequests.ListPullRequestsWithCommit(ctx, "o", "r", "sha", opts)
    80  	if err != nil {
    81  		t.Errorf("PullRequests.ListPullRequestsWithCommit returned error: %v", err)
    82  	}
    83  
    84  	want := []*PullRequest{{Number: Ptr(1)}}
    85  	if !cmp.Equal(pulls, want) {
    86  		t.Errorf("PullRequests.ListPullRequestsWithCommit returned %+v, want %+v", pulls, want)
    87  	}
    88  
    89  	const methodName = "ListPullRequestsWithCommit"
    90  	testBadOptions(t, methodName, func() (err error) {
    91  		_, _, err = client.PullRequests.ListPullRequestsWithCommit(ctx, "\n", "\n", "\n", opts)
    92  		return err
    93  	})
    94  
    95  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
    96  		got, resp, err := client.PullRequests.ListPullRequestsWithCommit(ctx, "o", "r", "sha", opts)
    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_List_invalidOwner(t *testing.T) {
   105  	t.Parallel()
   106  	client, _, _ := setup(t)
   107  
   108  	ctx := context.Background()
   109  	_, _, err := client.PullRequests.List(ctx, "%", "r", nil)
   110  	testURLParseError(t, err)
   111  }
   112  
   113  func TestPullRequestsService_Get(t *testing.T) {
   114  	t.Parallel()
   115  	client, mux, _ := setup(t)
   116  
   117  	mux.HandleFunc("/repos/o/r/pulls/1", func(w http.ResponseWriter, r *http.Request) {
   118  		testMethod(t, r, "GET")
   119  		fmt.Fprint(w, `{"number":1}`)
   120  	})
   121  
   122  	ctx := context.Background()
   123  	pull, _, err := client.PullRequests.Get(ctx, "o", "r", 1)
   124  	if err != nil {
   125  		t.Errorf("PullRequests.Get returned error: %v", err)
   126  	}
   127  
   128  	want := &PullRequest{Number: Ptr(1)}
   129  	if !cmp.Equal(pull, want) {
   130  		t.Errorf("PullRequests.Get returned %+v, want %+v", pull, want)
   131  	}
   132  
   133  	const methodName = "Get"
   134  	testBadOptions(t, methodName, func() (err error) {
   135  		_, _, err = client.PullRequests.Get(ctx, "\n", "\n", -1)
   136  		return err
   137  	})
   138  
   139  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   140  		got, resp, err := client.PullRequests.Get(ctx, "o", "r", 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_GetRaw_diff(t *testing.T) {
   149  	t.Parallel()
   150  	client, mux, _ := setup(t)
   151  
   152  	const rawStr = "@@diff content"
   153  
   154  	mux.HandleFunc("/repos/o/r/pulls/1", func(w http.ResponseWriter, r *http.Request) {
   155  		testMethod(t, r, "GET")
   156  		testHeader(t, r, "Accept", mediaTypeV3Diff)
   157  		fmt.Fprint(w, rawStr)
   158  	})
   159  
   160  	ctx := context.Background()
   161  	got, _, err := client.PullRequests.GetRaw(ctx, "o", "r", 1, RawOptions{Diff})
   162  	if err != nil {
   163  		t.Fatalf("PullRequests.GetRaw returned error: %v", err)
   164  	}
   165  	want := rawStr
   166  	if got != want {
   167  		t.Errorf("PullRequests.GetRaw returned %s want %s", got, want)
   168  	}
   169  
   170  	const methodName = "GetRaw"
   171  	testBadOptions(t, methodName, func() (err error) {
   172  		_, _, err = client.PullRequests.GetRaw(ctx, "\n", "\n", -1, RawOptions{Diff})
   173  		return err
   174  	})
   175  
   176  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   177  		got, resp, err := client.PullRequests.GetRaw(ctx, "o", "r", 1, RawOptions{Diff})
   178  		if got != "" {
   179  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   180  		}
   181  		return resp, err
   182  	})
   183  }
   184  
   185  func TestPullRequestsService_GetRaw_patch(t *testing.T) {
   186  	t.Parallel()
   187  	client, mux, _ := setup(t)
   188  
   189  	const rawStr = "@@patch content"
   190  
   191  	mux.HandleFunc("/repos/o/r/pulls/1", func(w http.ResponseWriter, r *http.Request) {
   192  		testMethod(t, r, "GET")
   193  		testHeader(t, r, "Accept", mediaTypeV3Patch)
   194  		fmt.Fprint(w, rawStr)
   195  	})
   196  
   197  	ctx := context.Background()
   198  	got, _, err := client.PullRequests.GetRaw(ctx, "o", "r", 1, RawOptions{Patch})
   199  	if err != nil {
   200  		t.Fatalf("PullRequests.GetRaw returned error: %v", err)
   201  	}
   202  	want := rawStr
   203  	if got != want {
   204  		t.Errorf("PullRequests.GetRaw returned %s want %s", got, want)
   205  	}
   206  }
   207  
   208  func TestPullRequestsService_GetRaw_invalid(t *testing.T) {
   209  	t.Parallel()
   210  	client, _, _ := setup(t)
   211  
   212  	ctx := context.Background()
   213  	_, _, err := client.PullRequests.GetRaw(ctx, "o", "r", 1, RawOptions{100})
   214  	if err == nil {
   215  		t.Fatal("PullRequests.GetRaw should return error")
   216  	}
   217  	if !strings.Contains(err.Error(), "unsupported raw type") {
   218  		t.Error("PullRequests.GetRaw should return unsupported raw type error")
   219  	}
   220  }
   221  
   222  func TestPullRequestsService_Get_links(t *testing.T) {
   223  	t.Parallel()
   224  	client, mux, _ := setup(t)
   225  
   226  	mux.HandleFunc("/repos/o/r/pulls/1", func(w http.ResponseWriter, r *http.Request) {
   227  		testMethod(t, r, "GET")
   228  		fmt.Fprint(w, `{
   229  			"number":1,
   230  			"_links":{
   231  				"self":{"href":"https://api.github.com/repos/octocat/Hello-World/pulls/1347"},
   232  				"html":{"href":"https://github.com/octocat/Hello-World/pull/1347"},
   233  				"issue":{"href":"https://api.github.com/repos/octocat/Hello-World/issues/1347"},
   234  				"comments":{"href":"https://api.github.com/repos/octocat/Hello-World/issues/1347/comments"},
   235  				"review_comments":{"href":"https://api.github.com/repos/octocat/Hello-World/pulls/1347/comments"},
   236  				"review_comment":{"href":"https://api.github.com/repos/octocat/Hello-World/pulls/comments{/number}"},
   237  				"commits":{"href":"https://api.github.com/repos/octocat/Hello-World/pulls/1347/commits"},
   238  				"statuses":{"href":"https://api.github.com/repos/octocat/Hello-World/statuses/6dcb09b5b57875f334f61aebed695e2e4193db5e"}
   239  				}
   240  			}`)
   241  	})
   242  
   243  	ctx := context.Background()
   244  	pull, _, err := client.PullRequests.Get(ctx, "o", "r", 1)
   245  	if err != nil {
   246  		t.Errorf("PullRequests.Get returned error: %v", err)
   247  	}
   248  
   249  	want := &PullRequest{
   250  		Number: Ptr(1),
   251  		Links: &PRLinks{
   252  			Self: &PRLink{
   253  				HRef: Ptr("https://api.github.com/repos/octocat/Hello-World/pulls/1347"),
   254  			}, HTML: &PRLink{
   255  				HRef: Ptr("https://github.com/octocat/Hello-World/pull/1347"),
   256  			}, Issue: &PRLink{
   257  				HRef: Ptr("https://api.github.com/repos/octocat/Hello-World/issues/1347"),
   258  			}, Comments: &PRLink{
   259  				HRef: Ptr("https://api.github.com/repos/octocat/Hello-World/issues/1347/comments"),
   260  			}, ReviewComments: &PRLink{
   261  				HRef: Ptr("https://api.github.com/repos/octocat/Hello-World/pulls/1347/comments"),
   262  			}, ReviewComment: &PRLink{
   263  				HRef: Ptr("https://api.github.com/repos/octocat/Hello-World/pulls/comments{/number}"),
   264  			}, Commits: &PRLink{
   265  				HRef: Ptr("https://api.github.com/repos/octocat/Hello-World/pulls/1347/commits"),
   266  			}, Statuses: &PRLink{
   267  				HRef: Ptr("https://api.github.com/repos/octocat/Hello-World/statuses/6dcb09b5b57875f334f61aebed695e2e4193db5e"),
   268  			},
   269  		},
   270  	}
   271  	if !cmp.Equal(pull, want) {
   272  		t.Errorf("PullRequests.Get returned %+v, want %+v", pull, want)
   273  	}
   274  }
   275  
   276  func TestPullRequestsService_Get_headAndBase(t *testing.T) {
   277  	t.Parallel()
   278  	client, mux, _ := setup(t)
   279  
   280  	mux.HandleFunc("/repos/o/r/pulls/1", func(w http.ResponseWriter, r *http.Request) {
   281  		testMethod(t, r, "GET")
   282  		fmt.Fprint(w, `{"number":1,"head":{"ref":"r2","repo":{"id":2}},"base":{"ref":"r1","repo":{"id":1}}}`)
   283  	})
   284  
   285  	ctx := context.Background()
   286  	pull, _, err := client.PullRequests.Get(ctx, "o", "r", 1)
   287  	if err != nil {
   288  		t.Errorf("PullRequests.Get returned error: %v", err)
   289  	}
   290  
   291  	want := &PullRequest{
   292  		Number: Ptr(1),
   293  		Head: &PullRequestBranch{
   294  			Ref:  Ptr("r2"),
   295  			Repo: &Repository{ID: Ptr(int64(2))},
   296  		},
   297  		Base: &PullRequestBranch{
   298  			Ref:  Ptr("r1"),
   299  			Repo: &Repository{ID: Ptr(int64(1))},
   300  		},
   301  	}
   302  	if !cmp.Equal(pull, want) {
   303  		t.Errorf("PullRequests.Get returned %+v, want %+v", pull, want)
   304  	}
   305  }
   306  
   307  func TestPullRequestsService_Get_urlFields(t *testing.T) {
   308  	t.Parallel()
   309  	client, mux, _ := setup(t)
   310  
   311  	mux.HandleFunc("/repos/o/r/pulls/1", func(w http.ResponseWriter, r *http.Request) {
   312  		testMethod(t, r, "GET")
   313  		fmt.Fprint(w, `{"number":1,
   314  			"url": "https://api.github.com/repos/octocat/Hello-World/pulls/1347",
   315  			"html_url": "https://github.com/octocat/Hello-World/pull/1347",
   316  			"issue_url": "https://api.github.com/repos/octocat/Hello-World/issues/1347",
   317  			"statuses_url": "https://api.github.com/repos/octocat/Hello-World/statuses/6dcb09b5b57875f334f61aebed695e2e4193db5e",
   318  			"diff_url": "https://github.com/octocat/Hello-World/pull/1347.diff",
   319  			"patch_url": "https://github.com/octocat/Hello-World/pull/1347.patch",
   320  			"review_comments_url": "https://api.github.com/repos/octocat/Hello-World/pulls/1347/comments",
   321  			"review_comment_url": "https://api.github.com/repos/octocat/Hello-World/pulls/comments{/number}"}`)
   322  	})
   323  
   324  	ctx := context.Background()
   325  	pull, _, err := client.PullRequests.Get(ctx, "o", "r", 1)
   326  	if err != nil {
   327  		t.Errorf("PullRequests.Get returned error: %v", err)
   328  	}
   329  
   330  	want := &PullRequest{
   331  		Number:            Ptr(1),
   332  		URL:               Ptr("https://api.github.com/repos/octocat/Hello-World/pulls/1347"),
   333  		HTMLURL:           Ptr("https://github.com/octocat/Hello-World/pull/1347"),
   334  		IssueURL:          Ptr("https://api.github.com/repos/octocat/Hello-World/issues/1347"),
   335  		StatusesURL:       Ptr("https://api.github.com/repos/octocat/Hello-World/statuses/6dcb09b5b57875f334f61aebed695e2e4193db5e"),
   336  		DiffURL:           Ptr("https://github.com/octocat/Hello-World/pull/1347.diff"),
   337  		PatchURL:          Ptr("https://github.com/octocat/Hello-World/pull/1347.patch"),
   338  		ReviewCommentsURL: Ptr("https://api.github.com/repos/octocat/Hello-World/pulls/1347/comments"),
   339  		ReviewCommentURL:  Ptr("https://api.github.com/repos/octocat/Hello-World/pulls/comments{/number}"),
   340  	}
   341  
   342  	if !cmp.Equal(pull, want) {
   343  		t.Errorf("PullRequests.Get returned %+v, want %+v", pull, want)
   344  	}
   345  }
   346  
   347  func TestPullRequestsService_Get_invalidOwner(t *testing.T) {
   348  	t.Parallel()
   349  	client, _, _ := setup(t)
   350  
   351  	ctx := context.Background()
   352  	_, _, err := client.PullRequests.Get(ctx, "%", "r", 1)
   353  	testURLParseError(t, err)
   354  }
   355  
   356  func TestPullRequestsService_Create(t *testing.T) {
   357  	t.Parallel()
   358  	client, mux, _ := setup(t)
   359  
   360  	input := &NewPullRequest{Title: Ptr("t")}
   361  
   362  	mux.HandleFunc("/repos/o/r/pulls", func(w http.ResponseWriter, r *http.Request) {
   363  		v := new(NewPullRequest)
   364  		assertNilError(t, json.NewDecoder(r.Body).Decode(v))
   365  
   366  		testMethod(t, r, "POST")
   367  		if !cmp.Equal(v, input) {
   368  			t.Errorf("Request body = %+v, want %+v", v, input)
   369  		}
   370  
   371  		fmt.Fprint(w, `{"number":1}`)
   372  	})
   373  
   374  	ctx := context.Background()
   375  	pull, _, err := client.PullRequests.Create(ctx, "o", "r", input)
   376  	if err != nil {
   377  		t.Errorf("PullRequests.Create returned error: %v", err)
   378  	}
   379  
   380  	want := &PullRequest{Number: Ptr(1)}
   381  	if !cmp.Equal(pull, want) {
   382  		t.Errorf("PullRequests.Create returned %+v, want %+v", pull, want)
   383  	}
   384  
   385  	const methodName = "Create"
   386  	testBadOptions(t, methodName, func() (err error) {
   387  		_, _, err = client.PullRequests.Create(ctx, "\n", "\n", input)
   388  		return err
   389  	})
   390  
   391  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   392  		got, resp, err := client.PullRequests.Create(ctx, "o", "r", input)
   393  		if got != nil {
   394  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   395  		}
   396  		return resp, err
   397  	})
   398  }
   399  
   400  func TestPullRequestsService_Create_invalidOwner(t *testing.T) {
   401  	t.Parallel()
   402  	client, _, _ := setup(t)
   403  
   404  	ctx := context.Background()
   405  	_, _, err := client.PullRequests.Create(ctx, "%", "r", nil)
   406  	testURLParseError(t, err)
   407  }
   408  
   409  func TestPullRequestsService_UpdateBranch(t *testing.T) {
   410  	t.Parallel()
   411  	client, mux, _ := setup(t)
   412  
   413  	mux.HandleFunc("/repos/o/r/pulls/1/update-branch", func(w http.ResponseWriter, r *http.Request) {
   414  		testMethod(t, r, "PUT")
   415  		testHeader(t, r, "Accept", mediaTypeUpdatePullRequestBranchPreview)
   416  		fmt.Fprint(w, `
   417  			{
   418  			  "message": "Updating pull request branch.",
   419  			  "url": "https://github.com/repos/o/r/pulls/1"
   420  			}`)
   421  	})
   422  
   423  	opts := &PullRequestBranchUpdateOptions{
   424  		ExpectedHeadSHA: Ptr("s"),
   425  	}
   426  
   427  	ctx := context.Background()
   428  	pull, _, err := client.PullRequests.UpdateBranch(ctx, "o", "r", 1, opts)
   429  	if err != nil {
   430  		t.Errorf("PullRequests.UpdateBranch returned error: %v", err)
   431  	}
   432  
   433  	want := &PullRequestBranchUpdateResponse{
   434  		Message: Ptr("Updating pull request branch."),
   435  		URL:     Ptr("https://github.com/repos/o/r/pulls/1"),
   436  	}
   437  
   438  	if !cmp.Equal(pull, want) {
   439  		t.Errorf("PullRequests.UpdateBranch returned %+v, want %+v", pull, want)
   440  	}
   441  
   442  	const methodName = "UpdateBranch"
   443  	testBadOptions(t, methodName, func() (err error) {
   444  		_, _, err = client.PullRequests.UpdateBranch(ctx, "\n", "\n", -1, opts)
   445  		return err
   446  	})
   447  
   448  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   449  		got, resp, err := client.PullRequests.UpdateBranch(ctx, "o", "r", 1, opts)
   450  		if got != nil {
   451  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   452  		}
   453  		return resp, err
   454  	})
   455  }
   456  
   457  func TestPullRequestsService_Edit(t *testing.T) {
   458  	t.Parallel()
   459  	client, mux, _ := setup(t)
   460  
   461  	tests := []struct {
   462  		input        *PullRequest
   463  		sendResponse string
   464  
   465  		wantUpdate string
   466  		want       *PullRequest
   467  	}{
   468  		{
   469  			input:        &PullRequest{Title: Ptr("t")},
   470  			sendResponse: `{"number":1}`,
   471  			wantUpdate:   `{"title":"t"}`,
   472  			want:         &PullRequest{Number: Ptr(1)},
   473  		},
   474  		{
   475  			// base update
   476  			input:        &PullRequest{Base: &PullRequestBranch{Ref: Ptr("master")}},
   477  			sendResponse: `{"number":1,"base":{"ref":"master"}}`,
   478  			wantUpdate:   `{"base":"master"}`,
   479  			want: &PullRequest{
   480  				Number: Ptr(1),
   481  				Base:   &PullRequestBranch{Ref: Ptr("master")},
   482  			},
   483  		},
   484  	}
   485  
   486  	for i, tt := range tests {
   487  		madeRequest := false
   488  		mux.HandleFunc(fmt.Sprintf("/repos/o/r/pulls/%v", i), func(w http.ResponseWriter, r *http.Request) {
   489  			testMethod(t, r, "PATCH")
   490  			testBody(t, r, tt.wantUpdate+"\n")
   491  			_, err := io.WriteString(w, tt.sendResponse)
   492  			assertNilError(t, err)
   493  			madeRequest = true
   494  		})
   495  
   496  		ctx := context.Background()
   497  		pull, _, err := client.PullRequests.Edit(ctx, "o", "r", i, tt.input)
   498  		if err != nil {
   499  			t.Errorf("%d: PullRequests.Edit returned error: %v", i, err)
   500  		}
   501  
   502  		if !cmp.Equal(pull, tt.want) {
   503  			t.Errorf("%d: PullRequests.Edit returned %+v, want %+v", i, pull, tt.want)
   504  		}
   505  
   506  		if !madeRequest {
   507  			t.Errorf("%d: PullRequest.Edit did not make the expected request", i)
   508  		}
   509  
   510  		const methodName = "Edit"
   511  		testBadOptions(t, methodName, func() (err error) {
   512  			_, _, err = client.PullRequests.Edit(ctx, "\n", "\n", -i, tt.input)
   513  			return err
   514  		})
   515  	}
   516  }
   517  
   518  func TestPullRequestsService_Edit_invalidOwner(t *testing.T) {
   519  	t.Parallel()
   520  	client, _, _ := setup(t)
   521  
   522  	ctx := context.Background()
   523  	_, _, err := client.PullRequests.Edit(ctx, "%", "r", 1, &PullRequest{})
   524  	testURLParseError(t, err)
   525  }
   526  
   527  func TestPullRequestsService_ListCommits(t *testing.T) {
   528  	t.Parallel()
   529  	client, mux, _ := setup(t)
   530  
   531  	mux.HandleFunc("/repos/o/r/pulls/1/commits", func(w http.ResponseWriter, r *http.Request) {
   532  		testMethod(t, r, "GET")
   533  		testFormValues(t, r, values{"page": "2"})
   534  		fmt.Fprint(w, `
   535  			[
   536  			  {
   537  			    "sha": "3",
   538  			    "parents": [
   539  			      {
   540  			        "sha": "2"
   541  			      }
   542  			    ]
   543  			  },
   544  			  {
   545  			    "sha": "2",
   546  			    "parents": [
   547  			      {
   548  			        "sha": "1"
   549  			      }
   550  			    ]
   551  			  }
   552  			]`)
   553  	})
   554  
   555  	opts := &ListOptions{Page: 2}
   556  	ctx := context.Background()
   557  	commits, _, err := client.PullRequests.ListCommits(ctx, "o", "r", 1, opts)
   558  	if err != nil {
   559  		t.Errorf("PullRequests.ListCommits returned error: %v", err)
   560  	}
   561  
   562  	want := []*RepositoryCommit{
   563  		{
   564  			SHA: Ptr("3"),
   565  			Parents: []*Commit{
   566  				{
   567  					SHA: Ptr("2"),
   568  				},
   569  			},
   570  		},
   571  		{
   572  			SHA: Ptr("2"),
   573  			Parents: []*Commit{
   574  				{
   575  					SHA: Ptr("1"),
   576  				},
   577  			},
   578  		},
   579  	}
   580  	if !cmp.Equal(commits, want) {
   581  		t.Errorf("PullRequests.ListCommits returned %+v, want %+v", commits, want)
   582  	}
   583  
   584  	const methodName = "ListCommits"
   585  	testBadOptions(t, methodName, func() (err error) {
   586  		_, _, err = client.PullRequests.ListCommits(ctx, "\n", "\n", -1, opts)
   587  		return err
   588  	})
   589  
   590  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   591  		got, resp, err := client.PullRequests.ListCommits(ctx, "o", "r", 1, opts)
   592  		if got != nil {
   593  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   594  		}
   595  		return resp, err
   596  	})
   597  }
   598  
   599  func TestPullRequestsService_ListFiles(t *testing.T) {
   600  	t.Parallel()
   601  	client, mux, _ := setup(t)
   602  
   603  	mux.HandleFunc("/repos/o/r/pulls/1/files", func(w http.ResponseWriter, r *http.Request) {
   604  		testMethod(t, r, "GET")
   605  		testFormValues(t, r, values{"page": "2"})
   606  		fmt.Fprint(w, `
   607  			[
   608  			  {
   609  			    "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e",
   610  			    "filename": "file1.txt",
   611  			    "status": "added",
   612  			    "additions": 103,
   613  			    "deletions": 21,
   614  			    "changes": 124,
   615  			    "patch": "@@ -132,7 +132,7 @@ module Test @@ -1000,7 +1000,7 @@ module Test"
   616  			  },
   617  			  {
   618  			    "sha": "f61aebed695e2e4193db5e6dcb09b5b57875f334",
   619  			    "filename": "file2.txt",
   620  			    "status": "modified",
   621  			    "additions": 5,
   622  			    "deletions": 3,
   623  			    "changes": 103,
   624  			    "patch": "@@ -132,7 +132,7 @@ module Test @@ -1000,7 +1000,7 @@ module Test"
   625  			  }
   626  			]`)
   627  	})
   628  
   629  	opts := &ListOptions{Page: 2}
   630  	ctx := context.Background()
   631  	commitFiles, _, err := client.PullRequests.ListFiles(ctx, "o", "r", 1, opts)
   632  	if err != nil {
   633  		t.Errorf("PullRequests.ListFiles returned error: %v", err)
   634  	}
   635  
   636  	want := []*CommitFile{
   637  		{
   638  			SHA:       Ptr("6dcb09b5b57875f334f61aebed695e2e4193db5e"),
   639  			Filename:  Ptr("file1.txt"),
   640  			Additions: Ptr(103),
   641  			Deletions: Ptr(21),
   642  			Changes:   Ptr(124),
   643  			Status:    Ptr("added"),
   644  			Patch:     Ptr("@@ -132,7 +132,7 @@ module Test @@ -1000,7 +1000,7 @@ module Test"),
   645  		},
   646  		{
   647  			SHA:       Ptr("f61aebed695e2e4193db5e6dcb09b5b57875f334"),
   648  			Filename:  Ptr("file2.txt"),
   649  			Additions: Ptr(5),
   650  			Deletions: Ptr(3),
   651  			Changes:   Ptr(103),
   652  			Status:    Ptr("modified"),
   653  			Patch:     Ptr("@@ -132,7 +132,7 @@ module Test @@ -1000,7 +1000,7 @@ module Test"),
   654  		},
   655  	}
   656  
   657  	if !cmp.Equal(commitFiles, want) {
   658  		t.Errorf("PullRequests.ListFiles returned %+v, want %+v", commitFiles, want)
   659  	}
   660  
   661  	const methodName = "ListFiles"
   662  	testBadOptions(t, methodName, func() (err error) {
   663  		_, _, err = client.PullRequests.ListFiles(ctx, "\n", "\n", -1, opts)
   664  		return err
   665  	})
   666  
   667  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   668  		got, resp, err := client.PullRequests.ListFiles(ctx, "o", "r", 1, opts)
   669  		if got != nil {
   670  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   671  		}
   672  		return resp, err
   673  	})
   674  }
   675  
   676  func TestPullRequestsService_IsMerged(t *testing.T) {
   677  	t.Parallel()
   678  	client, mux, _ := setup(t)
   679  
   680  	mux.HandleFunc("/repos/o/r/pulls/1/merge", func(w http.ResponseWriter, r *http.Request) {
   681  		testMethod(t, r, "GET")
   682  		w.WriteHeader(http.StatusNoContent)
   683  	})
   684  
   685  	ctx := context.Background()
   686  	isMerged, _, err := client.PullRequests.IsMerged(ctx, "o", "r", 1)
   687  	if err != nil {
   688  		t.Errorf("PullRequests.IsMerged returned error: %v", err)
   689  	}
   690  
   691  	want := true
   692  	if !cmp.Equal(isMerged, want) {
   693  		t.Errorf("PullRequests.IsMerged returned %+v, want %+v", isMerged, want)
   694  	}
   695  
   696  	const methodName = "IsMerged"
   697  	testBadOptions(t, methodName, func() (err error) {
   698  		_, _, err = client.PullRequests.IsMerged(ctx, "\n", "\n", -1)
   699  		return err
   700  	})
   701  
   702  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   703  		got, resp, err := client.PullRequests.IsMerged(ctx, "o", "r", 1)
   704  		if got {
   705  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want false", methodName, got)
   706  		}
   707  		return resp, err
   708  	})
   709  }
   710  
   711  func TestPullRequestsService_Merge(t *testing.T) {
   712  	t.Parallel()
   713  	client, mux, _ := setup(t)
   714  
   715  	mux.HandleFunc("/repos/o/r/pulls/1/merge", func(w http.ResponseWriter, r *http.Request) {
   716  		testMethod(t, r, "PUT")
   717  		fmt.Fprint(w, `
   718  			{
   719  			  "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e",
   720  			  "merged": true,
   721  			  "message": "Pull Request successfully merged"
   722  			}`)
   723  	})
   724  
   725  	options := &PullRequestOptions{MergeMethod: "rebase"}
   726  	ctx := context.Background()
   727  	merge, _, err := client.PullRequests.Merge(ctx, "o", "r", 1, "merging pull request", options)
   728  	if err != nil {
   729  		t.Errorf("PullRequests.Merge returned error: %v", err)
   730  	}
   731  
   732  	want := &PullRequestMergeResult{
   733  		SHA:     Ptr("6dcb09b5b57875f334f61aebed695e2e4193db5e"),
   734  		Merged:  Ptr(true),
   735  		Message: Ptr("Pull Request successfully merged"),
   736  	}
   737  	if !cmp.Equal(merge, want) {
   738  		t.Errorf("PullRequests.Merge returned %+v, want %+v", merge, want)
   739  	}
   740  
   741  	const methodName = "Merge"
   742  	testBadOptions(t, methodName, func() (err error) {
   743  		_, _, err = client.PullRequests.Merge(ctx, "\n", "\n", -1, "\n", options)
   744  		return err
   745  	})
   746  
   747  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   748  		got, resp, err := client.PullRequests.Merge(ctx, "o", "r", 1, "merging pull request", options)
   749  		if got != nil {
   750  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   751  		}
   752  		return resp, err
   753  	})
   754  }
   755  
   756  // Test that different merge options produce expected PUT requests. See issue https://github.com/google/go-github/issues/500.
   757  func TestPullRequestsService_Merge_options(t *testing.T) {
   758  	t.Parallel()
   759  	client, mux, _ := setup(t)
   760  
   761  	tests := []struct {
   762  		options  *PullRequestOptions
   763  		wantBody string
   764  	}{
   765  		{
   766  			options:  nil,
   767  			wantBody: `{"commit_message":"merging pull request"}`,
   768  		},
   769  		{
   770  			options:  &PullRequestOptions{},
   771  			wantBody: `{"commit_message":"merging pull request"}`,
   772  		},
   773  		{
   774  			options:  &PullRequestOptions{MergeMethod: "rebase"},
   775  			wantBody: `{"commit_message":"merging pull request","merge_method":"rebase"}`,
   776  		},
   777  		{
   778  			options:  &PullRequestOptions{SHA: "6dcb09b5b57875f334f61aebed695e2e4193db5e"},
   779  			wantBody: `{"commit_message":"merging pull request","sha":"6dcb09b5b57875f334f61aebed695e2e4193db5e"}`,
   780  		},
   781  		{
   782  			options: &PullRequestOptions{
   783  				CommitTitle: "Extra detail",
   784  				SHA:         "6dcb09b5b57875f334f61aebed695e2e4193db5e",
   785  				MergeMethod: "squash",
   786  			},
   787  			wantBody: `{"commit_message":"merging pull request","commit_title":"Extra detail","merge_method":"squash","sha":"6dcb09b5b57875f334f61aebed695e2e4193db5e"}`,
   788  		},
   789  		{
   790  			options: &PullRequestOptions{
   791  				DontDefaultIfBlank: true,
   792  			},
   793  			wantBody: `{"commit_message":"merging pull request"}`,
   794  		},
   795  	}
   796  
   797  	for i, test := range tests {
   798  		madeRequest := false
   799  		mux.HandleFunc(fmt.Sprintf("/repos/o/r/pulls/%d/merge", i), func(w http.ResponseWriter, r *http.Request) {
   800  			testMethod(t, r, "PUT")
   801  			testBody(t, r, test.wantBody+"\n")
   802  			madeRequest = true
   803  		})
   804  		ctx := context.Background()
   805  		_, _, _ = client.PullRequests.Merge(ctx, "o", "r", i, "merging pull request", test.options)
   806  		if !madeRequest {
   807  			t.Errorf("%d: PullRequests.Merge(%#v): expected request was not made", i, test.options)
   808  		}
   809  	}
   810  }
   811  
   812  func TestPullRequestsService_Merge_Blank_Message(t *testing.T) {
   813  	t.Parallel()
   814  	client, mux, _ := setup(t)
   815  
   816  	madeRequest := false
   817  	expectedBody := ""
   818  	mux.HandleFunc("/repos/o/r/pulls/1/merge", func(w http.ResponseWriter, r *http.Request) {
   819  		testMethod(t, r, "PUT")
   820  		testBody(t, r, expectedBody+"\n")
   821  		madeRequest = true
   822  	})
   823  
   824  	ctx := context.Background()
   825  	expectedBody = `{}`
   826  	_, _, _ = client.PullRequests.Merge(ctx, "o", "r", 1, "", nil)
   827  	if !madeRequest {
   828  		t.Error("TestPullRequestsService_Merge_Blank_Message #1 did not make request")
   829  	}
   830  
   831  	madeRequest = false
   832  	opts := PullRequestOptions{
   833  		DontDefaultIfBlank: true,
   834  	}
   835  	expectedBody = `{"commit_message":""}`
   836  	_, _, _ = client.PullRequests.Merge(ctx, "o", "r", 1, "", &opts)
   837  	if !madeRequest {
   838  		t.Error("TestPullRequestsService_Merge_Blank_Message #2 did not make request")
   839  	}
   840  }
   841  
   842  func TestPullRequestMergeRequest_Marshal(t *testing.T) {
   843  	t.Parallel()
   844  	testJSONMarshal(t, &pullRequestMergeRequest{}, "{}")
   845  
   846  	u := &pullRequestMergeRequest{
   847  		CommitMessage: Ptr("cm"),
   848  		CommitTitle:   "ct",
   849  		MergeMethod:   "mm",
   850  		SHA:           "sha",
   851  	}
   852  
   853  	want := `{
   854  		"commit_message": "cm",
   855  		"commit_title": "ct",
   856  		"merge_method": "mm",
   857  		"sha": "sha"
   858  	}`
   859  
   860  	testJSONMarshal(t, u, want)
   861  }
   862  
   863  func TestPullRequestMergeResult_Marshal(t *testing.T) {
   864  	t.Parallel()
   865  	testJSONMarshal(t, &PullRequestMergeResult{}, "{}")
   866  
   867  	u := &PullRequestMergeResult{
   868  		SHA:     Ptr("sha"),
   869  		Merged:  Ptr(false),
   870  		Message: Ptr("msg"),
   871  	}
   872  
   873  	want := `{
   874  		"sha": "sha",
   875  		"merged": false,
   876  		"message": "msg"
   877  	}`
   878  
   879  	testJSONMarshal(t, u, want)
   880  }
   881  
   882  func TestPullRequestUpdate_Marshal(t *testing.T) {
   883  	t.Parallel()
   884  	testJSONMarshal(t, &pullRequestUpdate{}, "{}")
   885  
   886  	u := &pullRequestUpdate{
   887  		Title:               Ptr("title"),
   888  		Body:                Ptr("body"),
   889  		State:               Ptr("state"),
   890  		Base:                Ptr("base"),
   891  		MaintainerCanModify: Ptr(false),
   892  	}
   893  
   894  	want := `{
   895  		"title": "title",
   896  		"body": "body",
   897  		"state": "state",
   898  		"base": "base",
   899  		"maintainer_can_modify": false
   900  	}`
   901  
   902  	testJSONMarshal(t, u, want)
   903  }
   904  
   905  func TestPullRequestBranchUpdateResponse_Marshal(t *testing.T) {
   906  	t.Parallel()
   907  	testJSONMarshal(t, &PullRequestBranchUpdateResponse{}, "{}")
   908  
   909  	u := &PullRequestBranchUpdateResponse{
   910  		Message: Ptr("message"),
   911  		URL:     Ptr("url"),
   912  	}
   913  
   914  	want := `{
   915  		"message": "message",
   916  		"url": "url"
   917  	}`
   918  
   919  	testJSONMarshal(t, u, want)
   920  }
   921  
   922  func TestPullRequestBranchUpdateOptions_Marshal(t *testing.T) {
   923  	t.Parallel()
   924  	testJSONMarshal(t, &PullRequestBranchUpdateOptions{}, "{}")
   925  
   926  	u := &PullRequestBranchUpdateOptions{
   927  		ExpectedHeadSHA: Ptr("eh"),
   928  	}
   929  
   930  	want := `{
   931  		"expected_head_sha": "eh"
   932  	}`
   933  
   934  	testJSONMarshal(t, u, want)
   935  }
   936  
   937  func TestNewPullRequest_Marshal(t *testing.T) {
   938  	t.Parallel()
   939  	testJSONMarshal(t, &NewPullRequest{}, "{}")
   940  
   941  	u := &NewPullRequest{
   942  		Title:               Ptr("eh"),
   943  		Head:                Ptr("eh"),
   944  		HeadRepo:            Ptr("eh"),
   945  		Base:                Ptr("eh"),
   946  		Body:                Ptr("eh"),
   947  		Issue:               Ptr(1),
   948  		MaintainerCanModify: Ptr(false),
   949  		Draft:               Ptr(false),
   950  	}
   951  
   952  	want := `{
   953  		"title": "eh",
   954  		"head": "eh",
   955  		"head_repo": "eh",
   956  		"base": "eh",
   957  		"body": "eh",
   958  		"issue": 1,
   959  		"maintainer_can_modify": false,
   960  		"draft": false
   961  	}`
   962  
   963  	testJSONMarshal(t, u, want)
   964  }
   965  
   966  func TestPullRequestBranch_Marshal(t *testing.T) {
   967  	t.Parallel()
   968  	testJSONMarshal(t, &PullRequestBranch{}, "{}")
   969  
   970  	u := &PullRequestBranch{
   971  		Label: Ptr("label"),
   972  		Ref:   Ptr("ref"),
   973  		SHA:   Ptr("sha"),
   974  		Repo:  &Repository{ID: Ptr(int64(1))},
   975  		User: &User{
   976  			Login:           Ptr("l"),
   977  			ID:              Ptr(int64(1)),
   978  			URL:             Ptr("u"),
   979  			AvatarURL:       Ptr("a"),
   980  			GravatarID:      Ptr("g"),
   981  			Name:            Ptr("n"),
   982  			Company:         Ptr("c"),
   983  			Blog:            Ptr("b"),
   984  			Location:        Ptr("l"),
   985  			Email:           Ptr("e"),
   986  			Hireable:        Ptr(true),
   987  			Bio:             Ptr("b"),
   988  			TwitterUsername: Ptr("t"),
   989  			PublicRepos:     Ptr(1),
   990  			Followers:       Ptr(1),
   991  			Following:       Ptr(1),
   992  			CreatedAt:       &Timestamp{referenceTime},
   993  			SuspendedAt:     &Timestamp{referenceTime},
   994  		},
   995  	}
   996  
   997  	want := `{
   998  		"label": "label",
   999  		"ref": "ref",
  1000  		"sha": "sha",
  1001  		"repo": {
  1002  			"id": 1
  1003  		},
  1004  		"user": {
  1005  			"login": "l",
  1006  			"id": 1,
  1007  			"avatar_url": "a",
  1008  			"gravatar_id": "g",
  1009  			"name": "n",
  1010  			"company": "c",
  1011  			"blog": "b",
  1012  			"location": "l",
  1013  			"email": "e",
  1014  			"hireable": true,
  1015  			"bio": "b",
  1016  			"twitter_username": "t",
  1017  			"public_repos": 1,
  1018  			"followers": 1,
  1019  			"following": 1,
  1020  			"created_at": ` + referenceTimeStr + `,
  1021  			"suspended_at": ` + referenceTimeStr + `,
  1022  			"url": "u"
  1023  		}
  1024  	}`
  1025  
  1026  	testJSONMarshal(t, u, want)
  1027  }
  1028  
  1029  func TestPRLink_Marshal(t *testing.T) {
  1030  	t.Parallel()
  1031  	testJSONMarshal(t, &PRLink{}, "{}")
  1032  
  1033  	u := &PRLink{
  1034  		HRef: Ptr("href"),
  1035  	}
  1036  
  1037  	want := `{
  1038  		"href": "href"
  1039  	}`
  1040  
  1041  	testJSONMarshal(t, u, want)
  1042  }
  1043  
  1044  func TestPRLinks_Marshal(t *testing.T) {
  1045  	t.Parallel()
  1046  	testJSONMarshal(t, &PRLinks{}, "{}")
  1047  
  1048  	u := &PRLinks{
  1049  		Self: &PRLink{
  1050  			HRef: Ptr("href"),
  1051  		},
  1052  		HTML: &PRLink{
  1053  			HRef: Ptr("href"),
  1054  		},
  1055  		Issue: &PRLink{
  1056  			HRef: Ptr("href"),
  1057  		},
  1058  		Comments: &PRLink{
  1059  			HRef: Ptr("href"),
  1060  		},
  1061  		ReviewComments: &PRLink{
  1062  			HRef: Ptr("href"),
  1063  		},
  1064  		ReviewComment: &PRLink{
  1065  			HRef: Ptr("href"),
  1066  		},
  1067  		Commits: &PRLink{
  1068  			HRef: Ptr("href"),
  1069  		},
  1070  		Statuses: &PRLink{
  1071  			HRef: Ptr("href"),
  1072  		},
  1073  	}
  1074  
  1075  	want := `{
  1076  		"self": {
  1077  			"href": "href"
  1078  		},
  1079  		"html": {
  1080  			"href": "href"
  1081  		},
  1082  		"issue": {
  1083  			"href": "href"
  1084  		},
  1085  		"comments": {
  1086  			"href": "href"
  1087  		},
  1088  		"review_comments": {
  1089  			"href": "href"
  1090  		},
  1091  		"review_comment": {
  1092  			"href": "href"
  1093  		},
  1094  		"commits": {
  1095  			"href": "href"
  1096  		},
  1097  		"statuses": {
  1098  			"href": "href"
  1099  		}
  1100  	}`
  1101  
  1102  	testJSONMarshal(t, u, want)
  1103  }
  1104  
  1105  func TestPullRequestAutoMerge_Marshal(t *testing.T) {
  1106  	t.Parallel()
  1107  	testJSONMarshal(t, &PullRequestAutoMerge{}, "{}")
  1108  
  1109  	u := &PullRequestAutoMerge{
  1110  		EnabledBy: &User{
  1111  			Login:           Ptr("l"),
  1112  			ID:              Ptr(int64(1)),
  1113  			URL:             Ptr("u"),
  1114  			AvatarURL:       Ptr("a"),
  1115  			GravatarID:      Ptr("g"),
  1116  			Name:            Ptr("n"),
  1117  			Company:         Ptr("c"),
  1118  			Blog:            Ptr("b"),
  1119  			Location:        Ptr("l"),
  1120  			Email:           Ptr("e"),
  1121  			Hireable:        Ptr(true),
  1122  			Bio:             Ptr("b"),
  1123  			TwitterUsername: Ptr("t"),
  1124  			PublicRepos:     Ptr(1),
  1125  			Followers:       Ptr(1),
  1126  			Following:       Ptr(1),
  1127  			CreatedAt:       &Timestamp{referenceTime},
  1128  			SuspendedAt:     &Timestamp{referenceTime},
  1129  		},
  1130  		MergeMethod:   Ptr("mm"),
  1131  		CommitTitle:   Ptr("ct"),
  1132  		CommitMessage: Ptr("cm"),
  1133  	}
  1134  
  1135  	want := `{
  1136  		"enabled_by": {
  1137  			"login": "l",
  1138  			"id": 1,
  1139  			"avatar_url": "a",
  1140  			"gravatar_id": "g",
  1141  			"name": "n",
  1142  			"company": "c",
  1143  			"blog": "b",
  1144  			"location": "l",
  1145  			"email": "e",
  1146  			"hireable": true,
  1147  			"bio": "b",
  1148  			"twitter_username": "t",
  1149  			"public_repos": 1,
  1150  			"followers": 1,
  1151  			"following": 1,
  1152  			"created_at": ` + referenceTimeStr + `,
  1153  			"suspended_at": ` + referenceTimeStr + `,
  1154  			"url": "u"
  1155  		},
  1156  		"merge_method": "mm",
  1157  		"commit_title": "ct",
  1158  		"commit_message": "cm"
  1159  	}`
  1160  
  1161  	testJSONMarshal(t, u, want)
  1162  }
  1163  
  1164  func TestPullRequest_Marshal(t *testing.T) {
  1165  	t.Parallel()
  1166  	testJSONMarshal(t, &PullRequest{}, "{}")
  1167  
  1168  	u := &PullRequest{
  1169  		ID:        Ptr(int64(1)),
  1170  		Number:    Ptr(1),
  1171  		State:     Ptr("state"),
  1172  		Locked:    Ptr(false),
  1173  		Title:     Ptr("title"),
  1174  		Body:      Ptr("body"),
  1175  		CreatedAt: &Timestamp{referenceTime},
  1176  		UpdatedAt: &Timestamp{referenceTime},
  1177  		ClosedAt:  &Timestamp{referenceTime},
  1178  		MergedAt:  &Timestamp{referenceTime},
  1179  		Labels:    []*Label{{ID: Ptr(int64(1))}},
  1180  		User: &User{
  1181  			Login:           Ptr("l"),
  1182  			ID:              Ptr(int64(1)),
  1183  			URL:             Ptr("u"),
  1184  			AvatarURL:       Ptr("a"),
  1185  			GravatarID:      Ptr("g"),
  1186  			Name:            Ptr("n"),
  1187  			Company:         Ptr("c"),
  1188  			Blog:            Ptr("b"),
  1189  			Location:        Ptr("l"),
  1190  			Email:           Ptr("e"),
  1191  			Hireable:        Ptr(true),
  1192  			Bio:             Ptr("b"),
  1193  			TwitterUsername: Ptr("t"),
  1194  			PublicRepos:     Ptr(1),
  1195  			Followers:       Ptr(1),
  1196  			Following:       Ptr(1),
  1197  			CreatedAt:       &Timestamp{referenceTime},
  1198  			SuspendedAt:     &Timestamp{referenceTime},
  1199  		},
  1200  		Draft:          Ptr(false),
  1201  		Merged:         Ptr(false),
  1202  		Mergeable:      Ptr(false),
  1203  		MergeableState: Ptr("ms"),
  1204  		MergedBy: &User{
  1205  			Login:           Ptr("l"),
  1206  			ID:              Ptr(int64(1)),
  1207  			URL:             Ptr("u"),
  1208  			AvatarURL:       Ptr("a"),
  1209  			GravatarID:      Ptr("g"),
  1210  			Name:            Ptr("n"),
  1211  			Company:         Ptr("c"),
  1212  			Blog:            Ptr("b"),
  1213  			Location:        Ptr("l"),
  1214  			Email:           Ptr("e"),
  1215  			Hireable:        Ptr(true),
  1216  			Bio:             Ptr("b"),
  1217  			TwitterUsername: Ptr("t"),
  1218  			PublicRepos:     Ptr(1),
  1219  			Followers:       Ptr(1),
  1220  			Following:       Ptr(1),
  1221  			CreatedAt:       &Timestamp{referenceTime},
  1222  			SuspendedAt:     &Timestamp{referenceTime},
  1223  		},
  1224  		MergeCommitSHA:    Ptr("mcs"),
  1225  		Rebaseable:        Ptr(false),
  1226  		Comments:          Ptr(1),
  1227  		Commits:           Ptr(1),
  1228  		Additions:         Ptr(1),
  1229  		Deletions:         Ptr(1),
  1230  		ChangedFiles:      Ptr(1),
  1231  		URL:               Ptr("url"),
  1232  		HTMLURL:           Ptr("hurl"),
  1233  		IssueURL:          Ptr("iurl"),
  1234  		StatusesURL:       Ptr("surl"),
  1235  		DiffURL:           Ptr("durl"),
  1236  		PatchURL:          Ptr("purl"),
  1237  		CommitsURL:        Ptr("curl"),
  1238  		CommentsURL:       Ptr("comurl"),
  1239  		ReviewCommentsURL: Ptr("rcurls"),
  1240  		ReviewCommentURL:  Ptr("rcurl"),
  1241  		ReviewComments:    Ptr(1),
  1242  		Assignee: &User{
  1243  			Login:           Ptr("l"),
  1244  			ID:              Ptr(int64(1)),
  1245  			URL:             Ptr("u"),
  1246  			AvatarURL:       Ptr("a"),
  1247  			GravatarID:      Ptr("g"),
  1248  			Name:            Ptr("n"),
  1249  			Company:         Ptr("c"),
  1250  			Blog:            Ptr("b"),
  1251  			Location:        Ptr("l"),
  1252  			Email:           Ptr("e"),
  1253  			Hireable:        Ptr(true),
  1254  			Bio:             Ptr("b"),
  1255  			TwitterUsername: Ptr("t"),
  1256  			PublicRepos:     Ptr(1),
  1257  			Followers:       Ptr(1),
  1258  			Following:       Ptr(1),
  1259  			CreatedAt:       &Timestamp{referenceTime},
  1260  			SuspendedAt:     &Timestamp{referenceTime},
  1261  		},
  1262  		Assignees: []*User{
  1263  			{
  1264  				Login:           Ptr("l"),
  1265  				ID:              Ptr(int64(1)),
  1266  				URL:             Ptr("u"),
  1267  				AvatarURL:       Ptr("a"),
  1268  				GravatarID:      Ptr("g"),
  1269  				Name:            Ptr("n"),
  1270  				Company:         Ptr("c"),
  1271  				Blog:            Ptr("b"),
  1272  				Location:        Ptr("l"),
  1273  				Email:           Ptr("e"),
  1274  				Hireable:        Ptr(true),
  1275  				Bio:             Ptr("b"),
  1276  				TwitterUsername: Ptr("t"),
  1277  				PublicRepos:     Ptr(1),
  1278  				Followers:       Ptr(1),
  1279  				Following:       Ptr(1),
  1280  				CreatedAt:       &Timestamp{referenceTime},
  1281  				SuspendedAt:     &Timestamp{referenceTime},
  1282  			},
  1283  		},
  1284  		Milestone:           &Milestone{ID: Ptr(int64(1))},
  1285  		MaintainerCanModify: Ptr(true),
  1286  		AuthorAssociation:   Ptr("aa"),
  1287  		NodeID:              Ptr("nid"),
  1288  		RequestedReviewers: []*User{
  1289  			{
  1290  				Login:           Ptr("l"),
  1291  				ID:              Ptr(int64(1)),
  1292  				URL:             Ptr("u"),
  1293  				AvatarURL:       Ptr("a"),
  1294  				GravatarID:      Ptr("g"),
  1295  				Name:            Ptr("n"),
  1296  				Company:         Ptr("c"),
  1297  				Blog:            Ptr("b"),
  1298  				Location:        Ptr("l"),
  1299  				Email:           Ptr("e"),
  1300  				Hireable:        Ptr(true),
  1301  				Bio:             Ptr("b"),
  1302  				TwitterUsername: Ptr("t"),
  1303  				PublicRepos:     Ptr(1),
  1304  				Followers:       Ptr(1),
  1305  				Following:       Ptr(1),
  1306  				CreatedAt:       &Timestamp{referenceTime},
  1307  				SuspendedAt:     &Timestamp{referenceTime},
  1308  			},
  1309  		},
  1310  		AutoMerge: &PullRequestAutoMerge{
  1311  			EnabledBy: &User{
  1312  				Login:           Ptr("l"),
  1313  				ID:              Ptr(int64(1)),
  1314  				URL:             Ptr("u"),
  1315  				AvatarURL:       Ptr("a"),
  1316  				GravatarID:      Ptr("g"),
  1317  				Name:            Ptr("n"),
  1318  				Company:         Ptr("c"),
  1319  				Blog:            Ptr("b"),
  1320  				Location:        Ptr("l"),
  1321  				Email:           Ptr("e"),
  1322  				Hireable:        Ptr(true),
  1323  				Bio:             Ptr("b"),
  1324  				TwitterUsername: Ptr("t"),
  1325  				PublicRepos:     Ptr(1),
  1326  				Followers:       Ptr(1),
  1327  				Following:       Ptr(1),
  1328  				CreatedAt:       &Timestamp{referenceTime},
  1329  				SuspendedAt:     &Timestamp{referenceTime},
  1330  			},
  1331  			MergeMethod:   Ptr("mm"),
  1332  			CommitTitle:   Ptr("ct"),
  1333  			CommitMessage: Ptr("cm"),
  1334  		},
  1335  		RequestedTeams: []*Team{{ID: Ptr(int64(1))}},
  1336  		Links: &PRLinks{
  1337  			Self: &PRLink{
  1338  				HRef: Ptr("href"),
  1339  			},
  1340  			HTML: &PRLink{
  1341  				HRef: Ptr("href"),
  1342  			},
  1343  			Issue: &PRLink{
  1344  				HRef: Ptr("href"),
  1345  			},
  1346  			Comments: &PRLink{
  1347  				HRef: Ptr("href"),
  1348  			},
  1349  			ReviewComments: &PRLink{
  1350  				HRef: Ptr("href"),
  1351  			},
  1352  			ReviewComment: &PRLink{
  1353  				HRef: Ptr("href"),
  1354  			},
  1355  			Commits: &PRLink{
  1356  				HRef: Ptr("href"),
  1357  			},
  1358  			Statuses: &PRLink{
  1359  				HRef: Ptr("href"),
  1360  			},
  1361  		},
  1362  		Head: &PullRequestBranch{
  1363  			Ref:  Ptr("r2"),
  1364  			Repo: &Repository{ID: Ptr(int64(2))},
  1365  		},
  1366  		Base: &PullRequestBranch{
  1367  			Ref:  Ptr("r2"),
  1368  			Repo: &Repository{ID: Ptr(int64(2))},
  1369  		},
  1370  		ActiveLockReason: Ptr("alr"),
  1371  	}
  1372  
  1373  	want := `{
  1374  		"id": 1,
  1375  		"number": 1,
  1376  		"state": "state",
  1377  		"locked": false,
  1378  		"title": "title",
  1379  		"body": "body",
  1380  		"created_at": ` + referenceTimeStr + `,
  1381  		"updated_at": ` + referenceTimeStr + `,
  1382  		"closed_at": ` + referenceTimeStr + `,
  1383  		"merged_at": ` + referenceTimeStr + `,
  1384  		"labels": [
  1385  			{
  1386  				"id": 1
  1387  			}
  1388  		],
  1389  		"user": {
  1390  			"login": "l",
  1391  			"id": 1,
  1392  			"avatar_url": "a",
  1393  			"gravatar_id": "g",
  1394  			"name": "n",
  1395  			"company": "c",
  1396  			"blog": "b",
  1397  			"location": "l",
  1398  			"email": "e",
  1399  			"hireable": true,
  1400  			"bio": "b",
  1401  			"twitter_username": "t",
  1402  			"public_repos": 1,
  1403  			"followers": 1,
  1404  			"following": 1,
  1405  			"created_at": ` + referenceTimeStr + `,
  1406  			"suspended_at": ` + referenceTimeStr + `,
  1407  			"url": "u"
  1408  		},
  1409  		"draft": false,
  1410  		"merged": false,
  1411  		"mergeable": false,
  1412  		"mergeable_state": "ms",
  1413  		"merged_by": {
  1414  			"login": "l",
  1415  			"id": 1,
  1416  			"avatar_url": "a",
  1417  			"gravatar_id": "g",
  1418  			"name": "n",
  1419  			"company": "c",
  1420  			"blog": "b",
  1421  			"location": "l",
  1422  			"email": "e",
  1423  			"hireable": true,
  1424  			"bio": "b",
  1425  			"twitter_username": "t",
  1426  			"public_repos": 1,
  1427  			"followers": 1,
  1428  			"following": 1,
  1429  			"created_at": ` + referenceTimeStr + `,
  1430  			"suspended_at": ` + referenceTimeStr + `,
  1431  			"url": "u"
  1432  		},
  1433  		"merge_commit_sha": "mcs",
  1434  		"rebaseable": false,
  1435  		"comments": 1,
  1436  		"commits": 1,
  1437  		"additions": 1,
  1438  		"deletions": 1,
  1439  		"changed_files": 1,
  1440  		"url": "url",
  1441  		"html_url": "hurl",
  1442  		"issue_url": "iurl",
  1443  		"statuses_url": "surl",
  1444  		"diff_url": "durl",
  1445  		"patch_url": "purl",
  1446  		"commits_url": "curl",
  1447  		"comments_url": "comurl",
  1448  		"review_comments_url": "rcurls",
  1449  		"review_comment_url": "rcurl",
  1450  		"review_comments": 1,
  1451  		"assignee": {
  1452  			"login": "l",
  1453  			"id": 1,
  1454  			"avatar_url": "a",
  1455  			"gravatar_id": "g",
  1456  			"name": "n",
  1457  			"company": "c",
  1458  			"blog": "b",
  1459  			"location": "l",
  1460  			"email": "e",
  1461  			"hireable": true,
  1462  			"bio": "b",
  1463  			"twitter_username": "t",
  1464  			"public_repos": 1,
  1465  			"followers": 1,
  1466  			"following": 1,
  1467  			"created_at": ` + referenceTimeStr + `,
  1468  			"suspended_at": ` + referenceTimeStr + `,
  1469  			"url": "u"
  1470  		},
  1471  		"assignees": [
  1472  			{
  1473  				"login": "l",
  1474  				"id": 1,
  1475  				"avatar_url": "a",
  1476  				"gravatar_id": "g",
  1477  				"name": "n",
  1478  				"company": "c",
  1479  				"blog": "b",
  1480  				"location": "l",
  1481  				"email": "e",
  1482  				"hireable": true,
  1483  				"bio": "b",
  1484  				"twitter_username": "t",
  1485  				"public_repos": 1,
  1486  				"followers": 1,
  1487  				"following": 1,
  1488  				"created_at": ` + referenceTimeStr + `,
  1489  				"suspended_at": ` + referenceTimeStr + `,
  1490  				"url": "u"
  1491  			}
  1492  		],
  1493  		"milestone": {
  1494  			"id": 1
  1495  		},
  1496  		"maintainer_can_modify": true,
  1497  		"author_association": "aa",
  1498  		"node_id": "nid",
  1499  		"requested_reviewers": [
  1500  			{
  1501  				"login": "l",
  1502  				"id": 1,
  1503  				"avatar_url": "a",
  1504  				"gravatar_id": "g",
  1505  				"name": "n",
  1506  				"company": "c",
  1507  				"blog": "b",
  1508  				"location": "l",
  1509  				"email": "e",
  1510  				"hireable": true,
  1511  				"bio": "b",
  1512  				"twitter_username": "t",
  1513  				"public_repos": 1,
  1514  				"followers": 1,
  1515  				"following": 1,
  1516  				"created_at": ` + referenceTimeStr + `,
  1517  				"suspended_at": ` + referenceTimeStr + `,
  1518  				"url": "u"
  1519  			}
  1520  		],
  1521  		"auto_merge": {
  1522  			"enabled_by": {
  1523  				"login": "l",
  1524  				"id": 1,
  1525  				"avatar_url": "a",
  1526  				"gravatar_id": "g",
  1527  				"name": "n",
  1528  				"company": "c",
  1529  				"blog": "b",
  1530  				"location": "l",
  1531  				"email": "e",
  1532  				"hireable": true,
  1533  				"bio": "b",
  1534  				"twitter_username": "t",
  1535  				"public_repos": 1,
  1536  				"followers": 1,
  1537  				"following": 1,
  1538  				"created_at": ` + referenceTimeStr + `,
  1539  				"suspended_at": ` + referenceTimeStr + `,
  1540  				"url": "u"
  1541  			},
  1542  			"merge_method": "mm",
  1543  			"commit_title": "ct",
  1544  			"commit_message": "cm"
  1545  		},
  1546  		"requested_teams": [
  1547  			{
  1548  				"id": 1
  1549  			}
  1550  		],
  1551  		"_links": {
  1552  			"self": {
  1553  				"href": "href"
  1554  			},
  1555  			"html": {
  1556  				"href": "href"
  1557  			},
  1558  			"issue": {
  1559  				"href": "href"
  1560  			},
  1561  			"comments": {
  1562  				"href": "href"
  1563  			},
  1564  			"review_comments": {
  1565  				"href": "href"
  1566  			},
  1567  			"review_comment": {
  1568  				"href": "href"
  1569  			},
  1570  			"commits": {
  1571  				"href": "href"
  1572  			},
  1573  			"statuses": {
  1574  				"href": "href"
  1575  			}
  1576  		},
  1577  		"head": {
  1578  			"ref": "r2",
  1579  			"repo": {
  1580  				"id": 2
  1581  			}
  1582  		},
  1583  		"base": {
  1584  			"ref": "r2",
  1585  			"repo": {
  1586  				"id": 2
  1587  			}
  1588  		},
  1589  		"active_lock_reason": "alr"
  1590  	}`
  1591  
  1592  	testJSONMarshal(t, u, want)
  1593  }