github.com/google/go-github/v69@v69.2.0/github/actions_workflow_runs_test.go (about)

     1  // Copyright 2020 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  	"net/url"
    14  	"strings"
    15  	"testing"
    16  	"time"
    17  
    18  	"github.com/google/go-cmp/cmp"
    19  )
    20  
    21  func TestActionsService_ListWorkflowRunsByID(t *testing.T) {
    22  	t.Parallel()
    23  	client, mux, _ := setup(t)
    24  
    25  	mux.HandleFunc("/repos/o/r/actions/workflows/29679449/runs", func(w http.ResponseWriter, r *http.Request) {
    26  		testMethod(t, r, "GET")
    27  		testFormValues(t, r, values{"per_page": "2", "page": "2"})
    28  		fmt.Fprint(w, `{"total_count":4,"workflow_runs":[{"id":399444496,"run_number":296,"created_at":"2019-01-02T15:04:05Z","updated_at":"2020-01-02T15:04:05Z"},{"id":399444497,"run_number":296,"created_at":"2019-01-02T15:04:05Z","updated_at":"2020-01-02T15:04:05Z"}]}`)
    29  	})
    30  
    31  	opts := &ListWorkflowRunsOptions{ListOptions: ListOptions{Page: 2, PerPage: 2}}
    32  	ctx := context.Background()
    33  	runs, _, err := client.Actions.ListWorkflowRunsByID(ctx, "o", "r", 29679449, opts)
    34  	if err != nil {
    35  		t.Errorf("Actions.ListWorkFlowRunsByID returned error: %v", err)
    36  	}
    37  
    38  	want := &WorkflowRuns{
    39  		TotalCount: Ptr(4),
    40  		WorkflowRuns: []*WorkflowRun{
    41  			{ID: Ptr(int64(399444496)), RunNumber: Ptr(296), CreatedAt: &Timestamp{time.Date(2019, time.January, 02, 15, 04, 05, 0, time.UTC)}, UpdatedAt: &Timestamp{time.Date(2020, time.January, 02, 15, 04, 05, 0, time.UTC)}},
    42  			{ID: Ptr(int64(399444497)), RunNumber: Ptr(296), CreatedAt: &Timestamp{time.Date(2019, time.January, 02, 15, 04, 05, 0, time.UTC)}, UpdatedAt: &Timestamp{time.Date(2020, time.January, 02, 15, 04, 05, 0, time.UTC)}},
    43  		},
    44  	}
    45  	if !cmp.Equal(runs, want) {
    46  		t.Errorf("Actions.ListWorkflowRunsByID returned %+v, want %+v", runs, want)
    47  	}
    48  
    49  	const methodName = "ListWorkflowRunsByID"
    50  	testBadOptions(t, methodName, func() (err error) {
    51  		_, _, err = client.Actions.ListWorkflowRunsByID(ctx, "\n", "\n", 29679449, opts)
    52  		return err
    53  	})
    54  
    55  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
    56  		got, resp, err := client.Actions.ListWorkflowRunsByID(ctx, "o", "r", 29679449, 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 TestActionsService_ListWorkflowRunsFileName(t *testing.T) {
    65  	t.Parallel()
    66  	client, mux, _ := setup(t)
    67  
    68  	mux.HandleFunc("/repos/o/r/actions/workflows/29679449/runs", func(w http.ResponseWriter, r *http.Request) {
    69  		testMethod(t, r, "GET")
    70  		testFormValues(t, r, values{"per_page": "2", "page": "2"})
    71  		fmt.Fprint(w, `{"total_count":4,"workflow_runs":[{"id":399444496,"run_number":296,"created_at":"2019-01-02T15:04:05Z","updated_at":"2020-01-02T15:04:05Z"},{"id":399444497,"run_number":296,"created_at":"2019-01-02T15:04:05Z","updated_at":"2020-01-02T15:04:05Z"}]}`)
    72  	})
    73  
    74  	opts := &ListWorkflowRunsOptions{ListOptions: ListOptions{Page: 2, PerPage: 2}}
    75  	ctx := context.Background()
    76  	runs, _, err := client.Actions.ListWorkflowRunsByFileName(ctx, "o", "r", "29679449", opts)
    77  	if err != nil {
    78  		t.Errorf("Actions.ListWorkFlowRunsByFileName returned error: %v", err)
    79  	}
    80  
    81  	want := &WorkflowRuns{
    82  		TotalCount: Ptr(4),
    83  		WorkflowRuns: []*WorkflowRun{
    84  			{ID: Ptr(int64(399444496)), RunNumber: Ptr(296), CreatedAt: &Timestamp{time.Date(2019, time.January, 02, 15, 04, 05, 0, time.UTC)}, UpdatedAt: &Timestamp{time.Date(2020, time.January, 02, 15, 04, 05, 0, time.UTC)}},
    85  			{ID: Ptr(int64(399444497)), RunNumber: Ptr(296), CreatedAt: &Timestamp{time.Date(2019, time.January, 02, 15, 04, 05, 0, time.UTC)}, UpdatedAt: &Timestamp{time.Date(2020, time.January, 02, 15, 04, 05, 0, time.UTC)}},
    86  		},
    87  	}
    88  	if !cmp.Equal(runs, want) {
    89  		t.Errorf("Actions.ListWorkflowRunsByFileName returned %+v, want %+v", runs, want)
    90  	}
    91  
    92  	const methodName = "ListWorkflowRunsByFileName"
    93  	testBadOptions(t, methodName, func() (err error) {
    94  		_, _, err = client.Actions.ListWorkflowRunsByFileName(ctx, "\n", "\n", "29679449", opts)
    95  		return err
    96  	})
    97  
    98  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
    99  		got, resp, err := client.Actions.ListWorkflowRunsByFileName(ctx, "o", "r", "29679449", opts)
   100  		if got != nil {
   101  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   102  		}
   103  		return resp, err
   104  	})
   105  }
   106  
   107  func TestActionsService_GetWorkflowRunByID(t *testing.T) {
   108  	t.Parallel()
   109  	client, mux, _ := setup(t)
   110  
   111  	mux.HandleFunc("/repos/o/r/actions/runs/29679449", func(w http.ResponseWriter, r *http.Request) {
   112  		testMethod(t, r, "GET")
   113  		fmt.Fprint(w, `{"id":399444496,"run_number":296,"created_at":"2019-01-02T15:04:05Z","updated_at":"2020-01-02T15:04:05Z"}}`)
   114  	})
   115  
   116  	ctx := context.Background()
   117  	runs, _, err := client.Actions.GetWorkflowRunByID(ctx, "o", "r", 29679449)
   118  	if err != nil {
   119  		t.Errorf("Actions.GetWorkflowRunByID returned error: %v", err)
   120  	}
   121  
   122  	want := &WorkflowRun{
   123  		ID:        Ptr(int64(399444496)),
   124  		RunNumber: Ptr(296),
   125  		CreatedAt: &Timestamp{time.Date(2019, time.January, 02, 15, 04, 05, 0, time.UTC)},
   126  		UpdatedAt: &Timestamp{time.Date(2020, time.January, 02, 15, 04, 05, 0, time.UTC)},
   127  	}
   128  
   129  	if !cmp.Equal(runs, want) {
   130  		t.Errorf("Actions.GetWorkflowRunByID returned %+v, want %+v", runs, want)
   131  	}
   132  
   133  	const methodName = "GetWorkflowRunByID"
   134  	testBadOptions(t, methodName, func() (err error) {
   135  		_, _, err = client.Actions.GetWorkflowRunByID(ctx, "\n", "\n", 29679449)
   136  		return err
   137  	})
   138  
   139  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   140  		got, resp, err := client.Actions.GetWorkflowRunByID(ctx, "o", "r", 29679449)
   141  		if got != nil {
   142  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   143  		}
   144  		return resp, err
   145  	})
   146  }
   147  
   148  func TestActionsService_GetWorkflowRunAttempt(t *testing.T) {
   149  	t.Parallel()
   150  	client, mux, _ := setup(t)
   151  
   152  	mux.HandleFunc("/repos/o/r/actions/runs/29679449/attempts/3", func(w http.ResponseWriter, r *http.Request) {
   153  		testMethod(t, r, "GET")
   154  		testFormValues(t, r, values{"exclude_pull_requests": "true"})
   155  		fmt.Fprint(w, `{"id":399444496,"run_number":296,"run_attempt":3,"created_at":"2019-01-02T15:04:05Z","updated_at":"2020-01-02T15:04:05Z"}}`)
   156  	})
   157  
   158  	opts := &WorkflowRunAttemptOptions{ExcludePullRequests: Ptr(true)}
   159  	ctx := context.Background()
   160  	runs, _, err := client.Actions.GetWorkflowRunAttempt(ctx, "o", "r", 29679449, 3, opts)
   161  	if err != nil {
   162  		t.Errorf("Actions.GetWorkflowRunAttempt returned error: %v", err)
   163  	}
   164  
   165  	want := &WorkflowRun{
   166  		ID:         Ptr(int64(399444496)),
   167  		RunNumber:  Ptr(296),
   168  		RunAttempt: Ptr(3),
   169  		CreatedAt:  &Timestamp{time.Date(2019, time.January, 02, 15, 04, 05, 0, time.UTC)},
   170  		UpdatedAt:  &Timestamp{time.Date(2020, time.January, 02, 15, 04, 05, 0, time.UTC)},
   171  	}
   172  
   173  	if !cmp.Equal(runs, want) {
   174  		t.Errorf("Actions.GetWorkflowRunAttempt returned %+v, want %+v", runs, want)
   175  	}
   176  
   177  	const methodName = "GetWorkflowRunAttempt"
   178  	testBadOptions(t, methodName, func() (err error) {
   179  		_, _, err = client.Actions.GetWorkflowRunAttempt(ctx, "\n", "\n", 29679449, 3, opts)
   180  		return err
   181  	})
   182  
   183  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   184  		got, resp, err := client.Actions.GetWorkflowRunAttempt(ctx, "o", "r", 29679449, 3, opts)
   185  		if got != nil {
   186  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   187  		}
   188  		return resp, err
   189  	})
   190  }
   191  
   192  func TestActionsService_GetWorkflowRunAttemptLogs(t *testing.T) {
   193  	t.Parallel()
   194  	tcs := []struct {
   195  		name              string
   196  		respectRateLimits bool
   197  	}{
   198  		{
   199  			name:              "withoutRateLimits",
   200  			respectRateLimits: false,
   201  		},
   202  		{
   203  			name:              "withRateLimits",
   204  			respectRateLimits: true,
   205  		},
   206  	}
   207  
   208  	for _, tc := range tcs {
   209  		tc := tc
   210  		t.Run(tc.name, func(t *testing.T) {
   211  			t.Parallel()
   212  			client, mux, _ := setup(t)
   213  			client.RateLimitRedirectionalEndpoints = tc.respectRateLimits
   214  
   215  			mux.HandleFunc("/repos/o/r/actions/runs/399444496/attempts/2/logs", func(w http.ResponseWriter, r *http.Request) {
   216  				testMethod(t, r, "GET")
   217  				http.Redirect(w, r, "http://github.com/a", http.StatusFound)
   218  			})
   219  
   220  			ctx := context.Background()
   221  			url, resp, err := client.Actions.GetWorkflowRunAttemptLogs(ctx, "o", "r", 399444496, 2, 1)
   222  			if err != nil {
   223  				t.Errorf("Actions.GetWorkflowRunAttemptLogs returned error: %v", err)
   224  			}
   225  			if resp.StatusCode != http.StatusFound {
   226  				t.Errorf("Actions.GetWorkflowRunAttemptLogs returned status: %d, want %d", resp.StatusCode, http.StatusFound)
   227  			}
   228  			want := "http://github.com/a"
   229  			if url.String() != want {
   230  				t.Errorf("Actions.GetWorkflowRunAttemptLogs returned %+v, want %+v", url.String(), want)
   231  			}
   232  
   233  			const methodName = "GetWorkflowRunAttemptLogs"
   234  			testBadOptions(t, methodName, func() (err error) {
   235  				_, _, err = client.Actions.GetWorkflowRunAttemptLogs(ctx, "\n", "\n", 399444496, 2, 1)
   236  				return err
   237  			})
   238  		})
   239  	}
   240  }
   241  
   242  func TestActionsService_GetWorkflowRunAttemptLogs_StatusMovedPermanently_dontFollowRedirects(t *testing.T) {
   243  	t.Parallel()
   244  	tcs := []struct {
   245  		name              string
   246  		respectRateLimits bool
   247  	}{
   248  		{
   249  			name:              "withoutRateLimits",
   250  			respectRateLimits: false,
   251  		},
   252  		{
   253  			name:              "withRateLimits",
   254  			respectRateLimits: true,
   255  		},
   256  	}
   257  
   258  	for _, tc := range tcs {
   259  		tc := tc
   260  		t.Run(tc.name, func(t *testing.T) {
   261  			t.Parallel()
   262  			client, mux, _ := setup(t)
   263  			client.RateLimitRedirectionalEndpoints = tc.respectRateLimits
   264  
   265  			mux.HandleFunc("/repos/o/r/actions/runs/399444496/attempts/2/logs", func(w http.ResponseWriter, r *http.Request) {
   266  				testMethod(t, r, "GET")
   267  				http.Redirect(w, r, "http://github.com/a", http.StatusMovedPermanently)
   268  			})
   269  
   270  			ctx := context.Background()
   271  			_, resp, _ := client.Actions.GetWorkflowRunAttemptLogs(ctx, "o", "r", 399444496, 2, 0)
   272  			if resp.StatusCode != http.StatusMovedPermanently {
   273  				t.Errorf("Actions.GetWorkflowRunAttemptLogs returned status: %d, want %d", resp.StatusCode, http.StatusMovedPermanently)
   274  			}
   275  		})
   276  	}
   277  }
   278  
   279  func TestActionsService_GetWorkflowRunAttemptLogs_StatusMovedPermanently_followRedirects(t *testing.T) {
   280  	t.Parallel()
   281  	tcs := []struct {
   282  		name              string
   283  		respectRateLimits bool
   284  	}{
   285  		{
   286  			name:              "withoutRateLimits",
   287  			respectRateLimits: false,
   288  		},
   289  		{
   290  			name:              "withRateLimits",
   291  			respectRateLimits: true,
   292  		},
   293  	}
   294  
   295  	for _, tc := range tcs {
   296  		tc := tc
   297  		t.Run(tc.name, func(t *testing.T) {
   298  			t.Parallel()
   299  			client, mux, serverURL := setup(t)
   300  			client.RateLimitRedirectionalEndpoints = tc.respectRateLimits
   301  
   302  			// Mock a redirect link, which leads to an archive link
   303  			mux.HandleFunc("/repos/o/r/actions/runs/399444496/attempts/2/logs", func(w http.ResponseWriter, r *http.Request) {
   304  				testMethod(t, r, "GET")
   305  				redirectURL, _ := url.Parse(serverURL + baseURLPath + "/redirect")
   306  				http.Redirect(w, r, redirectURL.String(), http.StatusMovedPermanently)
   307  			})
   308  
   309  			mux.HandleFunc("/redirect", func(w http.ResponseWriter, r *http.Request) {
   310  				testMethod(t, r, "GET")
   311  				http.Redirect(w, r, "http://github.com/a", http.StatusFound)
   312  			})
   313  
   314  			ctx := context.Background()
   315  			url, resp, err := client.Actions.GetWorkflowRunAttemptLogs(ctx, "o", "r", 399444496, 2, 1)
   316  			if err != nil {
   317  				t.Errorf("Actions.GetWorkflowRunAttemptLogs returned error: %v", err)
   318  			}
   319  
   320  			if resp.StatusCode != http.StatusFound {
   321  				t.Errorf("Actions.GetWorkflowRunAttemptLogs returned status: %d, want %d", resp.StatusCode, http.StatusFound)
   322  			}
   323  
   324  			want := "http://github.com/a"
   325  			if url.String() != want {
   326  				t.Errorf("Actions.GetWorkflowRunAttemptLogs returned %+v, want %+v", url.String(), want)
   327  			}
   328  
   329  			const methodName = "GetWorkflowRunAttemptLogs"
   330  			testBadOptions(t, methodName, func() (err error) {
   331  				_, _, err = client.Actions.GetWorkflowRunAttemptLogs(ctx, "\n", "\n", 399444496, 2, 1)
   332  				return err
   333  			})
   334  		})
   335  	}
   336  }
   337  
   338  func TestActionsService_GetWorkflowRunAttemptLogs_unexpectedCode(t *testing.T) {
   339  	t.Parallel()
   340  	tcs := []struct {
   341  		name              string
   342  		respectRateLimits bool
   343  	}{
   344  		{
   345  			name:              "withoutRateLimits",
   346  			respectRateLimits: false,
   347  		},
   348  		{
   349  			name:              "withRateLimits",
   350  			respectRateLimits: true,
   351  		},
   352  	}
   353  
   354  	for _, tc := range tcs {
   355  		tc := tc
   356  		t.Run(tc.name, func(t *testing.T) {
   357  			t.Parallel()
   358  			client, mux, serverURL := setup(t)
   359  			client.RateLimitRedirectionalEndpoints = tc.respectRateLimits
   360  
   361  			// Mock a redirect link, which leads to an archive link
   362  			mux.HandleFunc("/repos/o/r/actions/runs/399444496/attempts/2/logs", func(w http.ResponseWriter, r *http.Request) {
   363  				testMethod(t, r, "GET")
   364  				redirectURL, _ := url.Parse(serverURL + baseURLPath + "/redirect")
   365  				http.Redirect(w, r, redirectURL.String(), http.StatusMovedPermanently)
   366  			})
   367  
   368  			mux.HandleFunc("/redirect", func(w http.ResponseWriter, r *http.Request) {
   369  				testMethod(t, r, "GET")
   370  				w.WriteHeader(http.StatusNoContent)
   371  			})
   372  
   373  			ctx := context.Background()
   374  			url, resp, err := client.Actions.GetWorkflowRunAttemptLogs(ctx, "o", "r", 399444496, 2, 1)
   375  			if err == nil {
   376  				t.Fatalf("Actions.GetWorkflowRunAttemptLogs should return error on unexpected code")
   377  			}
   378  			if !strings.Contains(err.Error(), "unexpected status code") {
   379  				t.Error("Actions.GetWorkflowRunAttemptLogs should return unexpected status code")
   380  			}
   381  			if got, want := resp.Response.StatusCode, http.StatusNoContent; got != want {
   382  				t.Errorf("Actions.GetWorkflowRunAttemptLogs return status %d, want %d", got, want)
   383  			}
   384  			if url != nil {
   385  				t.Errorf("Actions.GetWorkflowRunAttemptLogs return %+v, want nil", url)
   386  			}
   387  		})
   388  	}
   389  }
   390  
   391  func TestActionsService_RerunWorkflowRunByID(t *testing.T) {
   392  	t.Parallel()
   393  	client, mux, _ := setup(t)
   394  
   395  	mux.HandleFunc("/repos/o/r/actions/runs/3434/rerun", func(w http.ResponseWriter, r *http.Request) {
   396  		testMethod(t, r, "POST")
   397  		w.WriteHeader(http.StatusCreated)
   398  	})
   399  
   400  	ctx := context.Background()
   401  	resp, err := client.Actions.RerunWorkflowByID(ctx, "o", "r", 3434)
   402  	if err != nil {
   403  		t.Errorf("Actions.RerunWorkflowByID returned error: %v", err)
   404  	}
   405  	if resp.StatusCode != http.StatusCreated {
   406  		t.Errorf("Actions.RerunWorkflowRunByID returned status: %d, want %d", resp.StatusCode, http.StatusCreated)
   407  	}
   408  
   409  	const methodName = "RerunWorkflowByID"
   410  	testBadOptions(t, methodName, func() (err error) {
   411  		_, err = client.Actions.RerunWorkflowByID(ctx, "\n", "\n", 3434)
   412  		return err
   413  	})
   414  
   415  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   416  		return client.Actions.RerunWorkflowByID(ctx, "o", "r", 3434)
   417  	})
   418  }
   419  
   420  func TestActionsService_RerunFailedJobsByID(t *testing.T) {
   421  	t.Parallel()
   422  	client, mux, _ := setup(t)
   423  
   424  	mux.HandleFunc("/repos/o/r/actions/runs/3434/rerun-failed-jobs", func(w http.ResponseWriter, r *http.Request) {
   425  		testMethod(t, r, "POST")
   426  		w.WriteHeader(http.StatusCreated)
   427  	})
   428  
   429  	ctx := context.Background()
   430  	resp, err := client.Actions.RerunFailedJobsByID(ctx, "o", "r", 3434)
   431  	if err != nil {
   432  		t.Errorf("Actions.RerunFailedJobsByID returned error: %v", err)
   433  	}
   434  	if resp.StatusCode != http.StatusCreated {
   435  		t.Errorf("Actions.RerunFailedJobsByID returned status: %d, want %d", resp.StatusCode, http.StatusCreated)
   436  	}
   437  
   438  	const methodName = "RerunFailedJobsByID"
   439  	testBadOptions(t, methodName, func() (err error) {
   440  		_, err = client.Actions.RerunFailedJobsByID(ctx, "\n", "\n", 3434)
   441  		return err
   442  	})
   443  
   444  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   445  		return client.Actions.RerunFailedJobsByID(ctx, "o", "r", 3434)
   446  	})
   447  }
   448  
   449  func TestActionsService_RerunJobByID(t *testing.T) {
   450  	t.Parallel()
   451  	client, mux, _ := setup(t)
   452  
   453  	mux.HandleFunc("/repos/o/r/actions/jobs/3434/rerun", func(w http.ResponseWriter, r *http.Request) {
   454  		testMethod(t, r, "POST")
   455  		w.WriteHeader(http.StatusCreated)
   456  	})
   457  
   458  	ctx := context.Background()
   459  	resp, err := client.Actions.RerunJobByID(ctx, "o", "r", 3434)
   460  	if err != nil {
   461  		t.Errorf("Actions.RerunJobByID returned error: %v", err)
   462  	}
   463  	if resp.StatusCode != http.StatusCreated {
   464  		t.Errorf("Actions.RerunJobByID returned status: %d, want %d", resp.StatusCode, http.StatusCreated)
   465  	}
   466  
   467  	const methodName = "RerunJobByID"
   468  	testBadOptions(t, methodName, func() (err error) {
   469  		_, err = client.Actions.RerunJobByID(ctx, "\n", "\n", 3434)
   470  		return err
   471  	})
   472  
   473  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   474  		return client.Actions.RerunJobByID(ctx, "o", "r", 3434)
   475  	})
   476  }
   477  
   478  func TestActionsService_CancelWorkflowRunByID(t *testing.T) {
   479  	t.Parallel()
   480  	client, mux, _ := setup(t)
   481  
   482  	mux.HandleFunc("/repos/o/r/actions/runs/3434/cancel", func(w http.ResponseWriter, r *http.Request) {
   483  		testMethod(t, r, "POST")
   484  		w.WriteHeader(http.StatusAccepted)
   485  	})
   486  
   487  	ctx := context.Background()
   488  	resp, err := client.Actions.CancelWorkflowRunByID(ctx, "o", "r", 3434)
   489  	if _, ok := err.(*AcceptedError); !ok {
   490  		t.Errorf("Actions.CancelWorkflowRunByID returned error: %v (want AcceptedError)", err)
   491  	}
   492  	if resp.StatusCode != http.StatusAccepted {
   493  		t.Errorf("Actions.CancelWorkflowRunByID returned status: %d, want %d", resp.StatusCode, http.StatusAccepted)
   494  	}
   495  
   496  	const methodName = "CancelWorkflowRunByID"
   497  	testBadOptions(t, methodName, func() (err error) {
   498  		_, err = client.Actions.CancelWorkflowRunByID(ctx, "\n", "\n", 3434)
   499  		return err
   500  	})
   501  
   502  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   503  		return client.Actions.CancelWorkflowRunByID(ctx, "o", "r", 3434)
   504  	})
   505  }
   506  
   507  func TestActionsService_GetWorkflowRunLogs(t *testing.T) {
   508  	t.Parallel()
   509  	tcs := []struct {
   510  		name              string
   511  		respectRateLimits bool
   512  	}{
   513  		{
   514  			name:              "withoutRateLimits",
   515  			respectRateLimits: false,
   516  		},
   517  		{
   518  			name:              "withRateLimits",
   519  			respectRateLimits: true,
   520  		},
   521  	}
   522  
   523  	for _, tc := range tcs {
   524  		tc := tc
   525  		t.Run(tc.name, func(t *testing.T) {
   526  			t.Parallel()
   527  			client, mux, _ := setup(t)
   528  			client.RateLimitRedirectionalEndpoints = tc.respectRateLimits
   529  
   530  			mux.HandleFunc("/repos/o/r/actions/runs/399444496/logs", func(w http.ResponseWriter, r *http.Request) {
   531  				testMethod(t, r, "GET")
   532  				http.Redirect(w, r, "http://github.com/a", http.StatusFound)
   533  			})
   534  
   535  			ctx := context.Background()
   536  			url, resp, err := client.Actions.GetWorkflowRunLogs(ctx, "o", "r", 399444496, 1)
   537  			if err != nil {
   538  				t.Errorf("Actions.GetWorkflowRunLogs returned error: %v", err)
   539  			}
   540  			if resp.StatusCode != http.StatusFound {
   541  				t.Errorf("Actions.GetWorkflowRunLogs returned status: %d, want %d", resp.StatusCode, http.StatusFound)
   542  			}
   543  			want := "http://github.com/a"
   544  			if url.String() != want {
   545  				t.Errorf("Actions.GetWorkflowRunLogs returned %+v, want %+v", url.String(), want)
   546  			}
   547  
   548  			const methodName = "GetWorkflowRunLogs"
   549  			testBadOptions(t, methodName, func() (err error) {
   550  				_, _, err = client.Actions.GetWorkflowRunLogs(ctx, "\n", "\n", 399444496, 1)
   551  				return err
   552  			})
   553  		})
   554  	}
   555  }
   556  
   557  func TestActionsService_GetWorkflowRunLogs_StatusMovedPermanently_dontFollowRedirects(t *testing.T) {
   558  	t.Parallel()
   559  	tcs := []struct {
   560  		name              string
   561  		respectRateLimits bool
   562  	}{
   563  		{
   564  			name:              "withoutRateLimits",
   565  			respectRateLimits: false,
   566  		},
   567  		{
   568  			name:              "withRateLimits",
   569  			respectRateLimits: true,
   570  		},
   571  	}
   572  
   573  	for _, tc := range tcs {
   574  		tc := tc
   575  		t.Run(tc.name, func(t *testing.T) {
   576  			t.Parallel()
   577  			client, mux, _ := setup(t)
   578  			client.RateLimitRedirectionalEndpoints = tc.respectRateLimits
   579  
   580  			mux.HandleFunc("/repos/o/r/actions/runs/399444496/logs", func(w http.ResponseWriter, r *http.Request) {
   581  				testMethod(t, r, "GET")
   582  				http.Redirect(w, r, "http://github.com/a", http.StatusMovedPermanently)
   583  			})
   584  
   585  			ctx := context.Background()
   586  			_, resp, _ := client.Actions.GetWorkflowRunLogs(ctx, "o", "r", 399444496, 0)
   587  			if resp.StatusCode != http.StatusMovedPermanently {
   588  				t.Errorf("Actions.GetWorkflowJobLogs returned status: %d, want %d", resp.StatusCode, http.StatusMovedPermanently)
   589  			}
   590  		})
   591  	}
   592  }
   593  
   594  func TestActionsService_GetWorkflowRunLogs_StatusMovedPermanently_followRedirects(t *testing.T) {
   595  	t.Parallel()
   596  	tcs := []struct {
   597  		name              string
   598  		respectRateLimits bool
   599  	}{
   600  		{
   601  			name:              "withoutRateLimits",
   602  			respectRateLimits: false,
   603  		},
   604  		{
   605  			name:              "withRateLimits",
   606  			respectRateLimits: true,
   607  		},
   608  	}
   609  
   610  	for _, tc := range tcs {
   611  		tc := tc
   612  		t.Run(tc.name, func(t *testing.T) {
   613  			t.Parallel()
   614  			client, mux, serverURL := setup(t)
   615  			client.RateLimitRedirectionalEndpoints = tc.respectRateLimits
   616  
   617  			// Mock a redirect link, which leads to an archive link
   618  			mux.HandleFunc("/repos/o/r/actions/runs/399444496/logs", func(w http.ResponseWriter, r *http.Request) {
   619  				testMethod(t, r, "GET")
   620  				redirectURL, _ := url.Parse(serverURL + baseURLPath + "/redirect")
   621  				http.Redirect(w, r, redirectURL.String(), http.StatusMovedPermanently)
   622  			})
   623  
   624  			mux.HandleFunc("/redirect", func(w http.ResponseWriter, r *http.Request) {
   625  				testMethod(t, r, "GET")
   626  				http.Redirect(w, r, "http://github.com/a", http.StatusFound)
   627  			})
   628  
   629  			ctx := context.Background()
   630  			url, resp, err := client.Actions.GetWorkflowRunLogs(ctx, "o", "r", 399444496, 1)
   631  			if err != nil {
   632  				t.Errorf("Actions.GetWorkflowJobLogs returned error: %v", err)
   633  			}
   634  
   635  			if resp.StatusCode != http.StatusFound {
   636  				t.Errorf("Actions.GetWorkflowJobLogs returned status: %d, want %d", resp.StatusCode, http.StatusFound)
   637  			}
   638  
   639  			want := "http://github.com/a"
   640  			if url.String() != want {
   641  				t.Errorf("Actions.GetWorkflowJobLogs returned %+v, want %+v", url.String(), want)
   642  			}
   643  
   644  			const methodName = "GetWorkflowRunLogs"
   645  			testBadOptions(t, methodName, func() (err error) {
   646  				_, _, err = client.Actions.GetWorkflowRunLogs(ctx, "\n", "\n", 399444496, 1)
   647  				return err
   648  			})
   649  		})
   650  	}
   651  }
   652  
   653  func TestActionsService_GetWorkflowRunLogs_unexpectedCode(t *testing.T) {
   654  	t.Parallel()
   655  	tcs := []struct {
   656  		name              string
   657  		respectRateLimits bool
   658  	}{
   659  		{
   660  			name:              "withoutRateLimits",
   661  			respectRateLimits: false,
   662  		},
   663  		{
   664  			name:              "withRateLimits",
   665  			respectRateLimits: true,
   666  		},
   667  	}
   668  
   669  	for _, tc := range tcs {
   670  		tc := tc
   671  		t.Run(tc.name, func(t *testing.T) {
   672  			t.Parallel()
   673  			client, mux, serverURL := setup(t)
   674  			client.RateLimitRedirectionalEndpoints = tc.respectRateLimits
   675  
   676  			// Mock a redirect link, which leads to an archive link
   677  			mux.HandleFunc("/repos/o/r/actions/runs/399444496/logs", func(w http.ResponseWriter, r *http.Request) {
   678  				testMethod(t, r, "GET")
   679  				redirectURL, _ := url.Parse(serverURL + baseURLPath + "/redirect")
   680  				http.Redirect(w, r, redirectURL.String(), http.StatusMovedPermanently)
   681  			})
   682  
   683  			mux.HandleFunc("/redirect", func(w http.ResponseWriter, r *http.Request) {
   684  				testMethod(t, r, "GET")
   685  				w.WriteHeader(http.StatusNoContent)
   686  			})
   687  
   688  			ctx := context.Background()
   689  			url, resp, err := client.Actions.GetWorkflowRunLogs(ctx, "o", "r", 399444496, 1)
   690  			if err == nil {
   691  				t.Fatalf("Actions.GetWorkflowRunLogs should return error on unexpected code")
   692  			}
   693  			if !strings.Contains(err.Error(), "unexpected status code") {
   694  				t.Error("Actions.GetWorkflowRunLogs should return unexpected status code")
   695  			}
   696  			if got, want := resp.Response.StatusCode, http.StatusNoContent; got != want {
   697  				t.Errorf("Actions.GetWorkflowRunLogs return status %d, want %d", got, want)
   698  			}
   699  			if url != nil {
   700  				t.Errorf("Actions.GetWorkflowRunLogs return %+v, want nil", url)
   701  			}
   702  		})
   703  	}
   704  }
   705  
   706  func TestActionService_ListRepositoryWorkflowRuns(t *testing.T) {
   707  	t.Parallel()
   708  	client, mux, _ := setup(t)
   709  
   710  	mux.HandleFunc("/repos/o/r/actions/runs", func(w http.ResponseWriter, r *http.Request) {
   711  		testMethod(t, r, "GET")
   712  		testFormValues(t, r, values{"per_page": "2", "page": "2"})
   713  		fmt.Fprint(w, `{"total_count":2,
   714  		"workflow_runs":[
   715  			{"id":298499444,"run_number":301,"created_at":"2020-04-11T11:14:54Z","updated_at":"2020-04-11T11:14:54Z"},
   716  			{"id":298499445,"run_number":302,"created_at":"2020-04-11T11:14:54Z","updated_at":"2020-04-11T11:14:54Z"}]}`)
   717  	})
   718  
   719  	opts := &ListWorkflowRunsOptions{ListOptions: ListOptions{Page: 2, PerPage: 2}}
   720  	ctx := context.Background()
   721  	runs, _, err := client.Actions.ListRepositoryWorkflowRuns(ctx, "o", "r", opts)
   722  	if err != nil {
   723  		t.Errorf("Actions.ListRepositoryWorkflowRuns returned error: %v", err)
   724  	}
   725  
   726  	expected := &WorkflowRuns{
   727  		TotalCount: Ptr(2),
   728  		WorkflowRuns: []*WorkflowRun{
   729  			{ID: Ptr(int64(298499444)), RunNumber: Ptr(301), CreatedAt: &Timestamp{time.Date(2020, time.April, 11, 11, 14, 54, 0, time.UTC)}, UpdatedAt: &Timestamp{time.Date(2020, time.April, 11, 11, 14, 54, 0, time.UTC)}},
   730  			{ID: Ptr(int64(298499445)), RunNumber: Ptr(302), CreatedAt: &Timestamp{time.Date(2020, time.April, 11, 11, 14, 54, 0, time.UTC)}, UpdatedAt: &Timestamp{time.Date(2020, time.April, 11, 11, 14, 54, 0, time.UTC)}},
   731  		},
   732  	}
   733  
   734  	if !cmp.Equal(runs, expected) {
   735  		t.Errorf("Actions.ListRepositoryWorkflowRuns returned %+v, want %+v", runs, expected)
   736  	}
   737  
   738  	const methodName = "ListRepositoryWorkflowRuns"
   739  	testBadOptions(t, methodName, func() (err error) {
   740  		_, _, err = client.Actions.ListRepositoryWorkflowRuns(ctx, "\n", "\n", opts)
   741  
   742  		return err
   743  	})
   744  
   745  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   746  		got, resp, err := client.Actions.ListRepositoryWorkflowRuns(ctx, "o", "r", opts)
   747  
   748  		if got != nil {
   749  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   750  		}
   751  		return resp, err
   752  	})
   753  }
   754  
   755  func TestActionService_DeleteWorkflowRun(t *testing.T) {
   756  	t.Parallel()
   757  	client, mux, _ := setup(t)
   758  
   759  	mux.HandleFunc("/repos/o/r/actions/runs/399444496", func(w http.ResponseWriter, r *http.Request) {
   760  		testMethod(t, r, "DELETE")
   761  
   762  		w.WriteHeader(http.StatusNoContent)
   763  	})
   764  
   765  	ctx := context.Background()
   766  	if _, err := client.Actions.DeleteWorkflowRun(ctx, "o", "r", 399444496); err != nil {
   767  		t.Errorf("DeleteWorkflowRun returned error: %v", err)
   768  	}
   769  
   770  	const methodName = "DeleteWorkflowRun"
   771  	testBadOptions(t, methodName, func() (err error) {
   772  		_, err = client.Actions.DeleteWorkflowRun(ctx, "\n", "\n", 399444496)
   773  		return err
   774  	})
   775  
   776  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   777  		return client.Actions.DeleteWorkflowRun(ctx, "o", "r", 399444496)
   778  	})
   779  }
   780  
   781  func TestActionService_DeleteWorkflowRunLogs(t *testing.T) {
   782  	t.Parallel()
   783  	client, mux, _ := setup(t)
   784  
   785  	mux.HandleFunc("/repos/o/r/actions/runs/399444496/logs", func(w http.ResponseWriter, r *http.Request) {
   786  		testMethod(t, r, "DELETE")
   787  
   788  		w.WriteHeader(http.StatusNoContent)
   789  	})
   790  
   791  	ctx := context.Background()
   792  	if _, err := client.Actions.DeleteWorkflowRunLogs(ctx, "o", "r", 399444496); err != nil {
   793  		t.Errorf("DeleteWorkflowRunLogs returned error: %v", err)
   794  	}
   795  
   796  	const methodName = "DeleteWorkflowRunLogs"
   797  	testBadOptions(t, methodName, func() (err error) {
   798  		_, err = client.Actions.DeleteWorkflowRunLogs(ctx, "\n", "\n", 399444496)
   799  		return err
   800  	})
   801  
   802  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   803  		return client.Actions.DeleteWorkflowRunLogs(ctx, "o", "r", 399444496)
   804  	})
   805  }
   806  
   807  func TestPendingDeployment_Marshal(t *testing.T) {
   808  	t.Parallel()
   809  	testJSONMarshal(t, &PendingDeployment{}, "{}")
   810  
   811  	u := &PendingDeployment{
   812  		Environment: &PendingDeploymentEnvironment{
   813  			ID:      Ptr(int64(1)),
   814  			NodeID:  Ptr("nid"),
   815  			Name:    Ptr("n"),
   816  			URL:     Ptr("u"),
   817  			HTMLURL: Ptr("hu"),
   818  		},
   819  		WaitTimer:             Ptr(int64(100)),
   820  		WaitTimerStartedAt:    &Timestamp{referenceTime},
   821  		CurrentUserCanApprove: Ptr(false),
   822  		Reviewers: []*RequiredReviewer{
   823  			{
   824  				Type: Ptr("User"),
   825  				Reviewer: &User{
   826  					Login: Ptr("l"),
   827  				},
   828  			},
   829  			{
   830  				Type: Ptr("Team"),
   831  				Reviewer: &Team{
   832  					Name: Ptr("n"),
   833  				},
   834  			},
   835  		},
   836  	}
   837  	want := `{
   838  		"environment": {
   839  			"id": 1,
   840  			"node_id": "nid",
   841  			"name": "n",
   842  			"url": "u",
   843  			"html_url": "hu"
   844  		},
   845  		"wait_timer": 100,
   846  		"wait_timer_started_at": ` + referenceTimeStr + `,
   847  		"current_user_can_approve": false,
   848  		"reviewers": [
   849  			{
   850  				"type": "User",
   851  				"reviewer": {
   852  					"login": "l"
   853  				}
   854  			},
   855  			{
   856  				"type": "Team",
   857  				"reviewer": {
   858  					"name": "n"
   859  				}
   860  			}
   861  		]
   862  	}`
   863  	testJSONMarshal(t, u, want)
   864  }
   865  
   866  func TestActionsService_ReviewCustomDeploymentProtectionRule(t *testing.T) {
   867  	t.Parallel()
   868  	client, mux, _ := setup(t)
   869  
   870  	mux.HandleFunc("/repos/o/r/actions/runs/9444496/deployment_protection_rule", func(w http.ResponseWriter, r *http.Request) {
   871  		testMethod(t, r, "POST")
   872  
   873  		w.WriteHeader(http.StatusNoContent)
   874  	})
   875  
   876  	request := ReviewCustomDeploymentProtectionRuleRequest{
   877  		EnvironmentName: "production",
   878  		State:           "approved",
   879  		Comment:         "Approve deployment",
   880  	}
   881  
   882  	ctx := context.Background()
   883  	if _, err := client.Actions.ReviewCustomDeploymentProtectionRule(ctx, "o", "r", 9444496, &request); err != nil {
   884  		t.Errorf("ReviewCustomDeploymentProtectionRule returned error: %v", err)
   885  	}
   886  
   887  	const methodName = "ReviewCustomDeploymentProtectionRule"
   888  	testBadOptions(t, methodName, func() (err error) {
   889  		_, err = client.Actions.ReviewCustomDeploymentProtectionRule(ctx, "\n", "\n", 9444496, &request)
   890  		return err
   891  	})
   892  
   893  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   894  		return client.Actions.ReviewCustomDeploymentProtectionRule(ctx, "o", "r", 9444496, &request)
   895  	})
   896  }
   897  
   898  func TestReviewCustomDeploymentProtectionRuleRequest_Marshal(t *testing.T) {
   899  	t.Parallel()
   900  	testJSONMarshal(t, &ReviewCustomDeploymentProtectionRuleRequest{}, "{}")
   901  
   902  	r := &ReviewCustomDeploymentProtectionRuleRequest{
   903  		EnvironmentName: "e",
   904  		State:           "rejected",
   905  		Comment:         "c",
   906  	}
   907  	want := `{
   908  		"environment_name": "e",
   909  		"state": "rejected",
   910  		"comment": "c"
   911  	}`
   912  	testJSONMarshal(t, r, want)
   913  }
   914  
   915  func TestActionsService_GetWorkflowRunUsageByID(t *testing.T) {
   916  	t.Parallel()
   917  	client, mux, _ := setup(t)
   918  
   919  	mux.HandleFunc("/repos/o/r/actions/runs/29679449/timing", func(w http.ResponseWriter, r *http.Request) {
   920  		testMethod(t, r, "GET")
   921  		fmt.Fprint(w, `{"billable":{"UBUNTU":{"total_ms":180000,"jobs":1,"job_runs":[{"job_id":1,"duration_ms":60000}]},"MACOS":{"total_ms":240000,"jobs":2,"job_runs":[{"job_id":2,"duration_ms":30000},{"job_id":3,"duration_ms":10000}]},"WINDOWS":{"total_ms":300000,"jobs":2}},"run_duration_ms":500000}`)
   922  	})
   923  
   924  	ctx := context.Background()
   925  	workflowRunUsage, _, err := client.Actions.GetWorkflowRunUsageByID(ctx, "o", "r", 29679449)
   926  	if err != nil {
   927  		t.Errorf("Actions.GetWorkflowRunUsageByID returned error: %v", err)
   928  	}
   929  
   930  	want := &WorkflowRunUsage{
   931  		Billable: &WorkflowRunBillMap{
   932  			"UBUNTU": &WorkflowRunBill{
   933  				TotalMS: Ptr(int64(180000)),
   934  				Jobs:    Ptr(1),
   935  				JobRuns: []*WorkflowRunJobRun{
   936  					{
   937  						JobID:      Ptr(1),
   938  						DurationMS: Ptr(int64(60000)),
   939  					},
   940  				},
   941  			},
   942  			"MACOS": &WorkflowRunBill{
   943  				TotalMS: Ptr(int64(240000)),
   944  				Jobs:    Ptr(2),
   945  				JobRuns: []*WorkflowRunJobRun{
   946  					{
   947  						JobID:      Ptr(2),
   948  						DurationMS: Ptr(int64(30000)),
   949  					},
   950  					{
   951  						JobID:      Ptr(3),
   952  						DurationMS: Ptr(int64(10000)),
   953  					},
   954  				},
   955  			},
   956  			"WINDOWS": &WorkflowRunBill{
   957  				TotalMS: Ptr(int64(300000)),
   958  				Jobs:    Ptr(2),
   959  			},
   960  		},
   961  		RunDurationMS: Ptr(int64(500000)),
   962  	}
   963  
   964  	if !cmp.Equal(workflowRunUsage, want) {
   965  		t.Errorf("Actions.GetWorkflowRunUsageByID returned %+v, want %+v", workflowRunUsage, want)
   966  	}
   967  
   968  	const methodName = "GetWorkflowRunUsageByID"
   969  	testBadOptions(t, methodName, func() (err error) {
   970  		_, _, err = client.Actions.GetWorkflowRunUsageByID(ctx, "\n", "\n", 29679449)
   971  		return err
   972  	})
   973  
   974  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   975  		got, resp, err := client.Actions.GetWorkflowRunUsageByID(ctx, "o", "r", 29679449)
   976  		if got != nil {
   977  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   978  		}
   979  		return resp, err
   980  	})
   981  }
   982  
   983  func TestWorkflowRun_Marshal(t *testing.T) {
   984  	t.Parallel()
   985  	testJSONMarshal(t, &WorkflowRun{}, "{}")
   986  
   987  	u := &WorkflowRun{
   988  		ID:         Ptr(int64(1)),
   989  		Name:       Ptr("n"),
   990  		NodeID:     Ptr("nid"),
   991  		HeadBranch: Ptr("hb"),
   992  		HeadSHA:    Ptr("hs"),
   993  		Path:       Ptr("p"),
   994  		RunNumber:  Ptr(1),
   995  		RunAttempt: Ptr(1),
   996  		Event:      Ptr("e"),
   997  		Status:     Ptr("s"),
   998  		Conclusion: Ptr("c"),
   999  		WorkflowID: Ptr(int64(1)),
  1000  		URL:        Ptr("u"),
  1001  		HTMLURL:    Ptr("h"),
  1002  		PullRequests: []*PullRequest{
  1003  			{
  1004  				URL:    Ptr("u"),
  1005  				ID:     Ptr(int64(1)),
  1006  				Number: Ptr(1),
  1007  				Head: &PullRequestBranch{
  1008  					Ref: Ptr("r"),
  1009  					SHA: Ptr("s"),
  1010  					Repo: &Repository{
  1011  						ID:   Ptr(int64(1)),
  1012  						URL:  Ptr("s"),
  1013  						Name: Ptr("n"),
  1014  					},
  1015  				},
  1016  				Base: &PullRequestBranch{
  1017  					Ref: Ptr("r"),
  1018  					SHA: Ptr("s"),
  1019  					Repo: &Repository{
  1020  						ID:   Ptr(int64(1)),
  1021  						URL:  Ptr("u"),
  1022  						Name: Ptr("n"),
  1023  					},
  1024  				},
  1025  			},
  1026  		},
  1027  		CreatedAt:          &Timestamp{referenceTime},
  1028  		UpdatedAt:          &Timestamp{referenceTime},
  1029  		RunStartedAt:       &Timestamp{referenceTime},
  1030  		JobsURL:            Ptr("j"),
  1031  		LogsURL:            Ptr("l"),
  1032  		CheckSuiteURL:      Ptr("c"),
  1033  		ArtifactsURL:       Ptr("a"),
  1034  		CancelURL:          Ptr("c"),
  1035  		RerunURL:           Ptr("r"),
  1036  		PreviousAttemptURL: Ptr("p"),
  1037  		HeadCommit: &HeadCommit{
  1038  			Message: Ptr("m"),
  1039  			Author: &CommitAuthor{
  1040  				Name:  Ptr("n"),
  1041  				Email: Ptr("e"),
  1042  				Login: Ptr("l"),
  1043  			},
  1044  			URL:       Ptr("u"),
  1045  			Distinct:  Ptr(false),
  1046  			SHA:       Ptr("s"),
  1047  			ID:        Ptr("i"),
  1048  			TreeID:    Ptr("tid"),
  1049  			Timestamp: &Timestamp{referenceTime},
  1050  			Committer: &CommitAuthor{
  1051  				Name:  Ptr("n"),
  1052  				Email: Ptr("e"),
  1053  				Login: Ptr("l"),
  1054  			},
  1055  		},
  1056  		WorkflowURL: Ptr("w"),
  1057  		Repository: &Repository{
  1058  			ID:   Ptr(int64(1)),
  1059  			URL:  Ptr("u"),
  1060  			Name: Ptr("n"),
  1061  		},
  1062  		HeadRepository: &Repository{
  1063  			ID:   Ptr(int64(1)),
  1064  			URL:  Ptr("u"),
  1065  			Name: Ptr("n"),
  1066  		},
  1067  		Actor: &User{
  1068  			Login:           Ptr("l"),
  1069  			ID:              Ptr(int64(1)),
  1070  			AvatarURL:       Ptr("a"),
  1071  			GravatarID:      Ptr("g"),
  1072  			Name:            Ptr("n"),
  1073  			Company:         Ptr("c"),
  1074  			Blog:            Ptr("b"),
  1075  			Location:        Ptr("l"),
  1076  			Email:           Ptr("e"),
  1077  			Hireable:        Ptr(true),
  1078  			Bio:             Ptr("b"),
  1079  			TwitterUsername: Ptr("t"),
  1080  			PublicRepos:     Ptr(1),
  1081  			Followers:       Ptr(1),
  1082  			Following:       Ptr(1),
  1083  			CreatedAt:       &Timestamp{referenceTime},
  1084  			SuspendedAt:     &Timestamp{referenceTime},
  1085  			URL:             Ptr("u"),
  1086  		},
  1087  		TriggeringActor: &User{
  1088  			Login:           Ptr("l2"),
  1089  			ID:              Ptr(int64(2)),
  1090  			AvatarURL:       Ptr("a2"),
  1091  			GravatarID:      Ptr("g2"),
  1092  			Name:            Ptr("n2"),
  1093  			Company:         Ptr("c2"),
  1094  			Blog:            Ptr("b2"),
  1095  			Location:        Ptr("l2"),
  1096  			Email:           Ptr("e2"),
  1097  			Hireable:        Ptr(false),
  1098  			Bio:             Ptr("b2"),
  1099  			TwitterUsername: Ptr("t2"),
  1100  			PublicRepos:     Ptr(2),
  1101  			Followers:       Ptr(2),
  1102  			Following:       Ptr(2),
  1103  			CreatedAt:       &Timestamp{referenceTime},
  1104  			SuspendedAt:     &Timestamp{referenceTime},
  1105  			URL:             Ptr("u2"),
  1106  		},
  1107  		ReferencedWorkflows: []*ReferencedWorkflow{
  1108  			{
  1109  				Path: Ptr("rwfp"),
  1110  				SHA:  Ptr("rwfsha"),
  1111  				Ref:  Ptr("rwfref"),
  1112  			},
  1113  		},
  1114  	}
  1115  
  1116  	want := `{
  1117  		"id": 1,
  1118  		"name": "n",
  1119  		"node_id": "nid",
  1120  		"head_branch": "hb",
  1121  		"head_sha": "hs",
  1122  		"path": "p",
  1123  		"run_number": 1,
  1124  		"run_attempt": 1,
  1125  		"event": "e",
  1126  		"status": "s",
  1127  		"conclusion": "c",
  1128  		"workflow_id": 1,
  1129  		"url": "u",
  1130  		"html_url": "h",
  1131  		"pull_requests": [
  1132  			{
  1133  				"id":1,
  1134  				"number":1,
  1135  				"url":"u",
  1136  				"head":{
  1137  					"ref":"r",
  1138  					"sha":"s",
  1139  					"repo": {
  1140  						"id":1,
  1141  						"name":"n",
  1142  						"url":"s"
  1143  						}
  1144  					},
  1145  					"base": {
  1146  						"ref":"r",
  1147  						"sha":"s",
  1148  						"repo": {
  1149  							"id":1,
  1150  							"name":"n",
  1151  							"url":"u"
  1152  						}
  1153  					}
  1154  			}
  1155  		],
  1156  		"created_at": ` + referenceTimeStr + `,
  1157  		"updated_at": ` + referenceTimeStr + `,
  1158  		"run_started_at": ` + referenceTimeStr + `,
  1159  		"jobs_url": "j",
  1160  		"logs_url": "l",
  1161  		"check_suite_url": "c",
  1162  		"artifacts_url": "a",
  1163  		"cancel_url": "c",
  1164  		"rerun_url": "r",
  1165  		"previous_attempt_url": "p",
  1166  		"head_commit": {
  1167  			"message": "m",
  1168  			"author": {
  1169  				"name": "n",
  1170  				"email": "e",
  1171  				"username": "l"
  1172  			},
  1173  			"url": "u",
  1174  			"distinct": false,
  1175  			"sha": "s",
  1176  			"id": "i",
  1177  			"tree_id": "tid",
  1178  			"timestamp": ` + referenceTimeStr + `,
  1179  			"committer": {
  1180  				"name": "n",
  1181  				"email": "e",
  1182  				"username": "l"
  1183  			}
  1184  		},
  1185  		"workflow_url": "w",
  1186  		"repository": {
  1187  			"id": 1,
  1188  			"url": "u",
  1189  			"name": "n"
  1190  		},
  1191  		"head_repository": {
  1192  			"id": 1,
  1193  			"url": "u",
  1194  			"name": "n"
  1195  		},
  1196  		"actor": {
  1197  			"login": "l",
  1198  			"id": 1,
  1199  			"avatar_url": "a",
  1200  			"gravatar_id": "g",
  1201  			"name": "n",
  1202  			"company": "c",
  1203  			"blog": "b",
  1204  			"location": "l",
  1205  			"email": "e",
  1206  			"hireable": true,
  1207  			"bio": "b",
  1208  			"twitter_username": "t",
  1209  			"public_repos": 1,
  1210  			"followers": 1,
  1211  			"following": 1,
  1212  			"created_at": ` + referenceTimeStr + `,
  1213  			"suspended_at": ` + referenceTimeStr + `,
  1214  			"url": "u"
  1215  		},
  1216  		"triggering_actor": {
  1217  			"login": "l2",
  1218  			"id": 2,
  1219  			"avatar_url": "a2",
  1220  			"gravatar_id": "g2",
  1221  			"name": "n2",
  1222  			"company": "c2",
  1223  			"blog": "b2",
  1224  			"location": "l2",
  1225  			"email": "e2",
  1226  			"hireable": false,
  1227  			"bio": "b2",
  1228  			"twitter_username": "t2",
  1229  			"public_repos": 2,
  1230  			"followers": 2,
  1231  			"following": 2,
  1232  			"created_at": ` + referenceTimeStr + `,
  1233  			"suspended_at": ` + referenceTimeStr + `,
  1234  			"url": "u2"
  1235  		},
  1236  		"referenced_workflows": [
  1237  			{
  1238  				"path": "rwfp",
  1239  				"sha": "rwfsha",
  1240  				"ref": "rwfref"
  1241  			}
  1242  		]
  1243  	}`
  1244  
  1245  	testJSONMarshal(t, u, want)
  1246  }
  1247  
  1248  func TestWorkflowRuns_Marshal(t *testing.T) {
  1249  	t.Parallel()
  1250  	testJSONMarshal(t, &WorkflowRuns{}, "{}")
  1251  
  1252  	u := &WorkflowRuns{
  1253  		TotalCount: Ptr(1),
  1254  		WorkflowRuns: []*WorkflowRun{
  1255  			{
  1256  				ID:         Ptr(int64(1)),
  1257  				Name:       Ptr("n"),
  1258  				NodeID:     Ptr("nid"),
  1259  				HeadBranch: Ptr("hb"),
  1260  				HeadSHA:    Ptr("hs"),
  1261  				RunNumber:  Ptr(1),
  1262  				RunAttempt: Ptr(1),
  1263  				Event:      Ptr("e"),
  1264  				Status:     Ptr("s"),
  1265  				Conclusion: Ptr("c"),
  1266  				WorkflowID: Ptr(int64(1)),
  1267  				URL:        Ptr("u"),
  1268  				HTMLURL:    Ptr("h"),
  1269  				PullRequests: []*PullRequest{
  1270  					{
  1271  						URL:    Ptr("u"),
  1272  						ID:     Ptr(int64(1)),
  1273  						Number: Ptr(1),
  1274  						Head: &PullRequestBranch{
  1275  							Ref: Ptr("r"),
  1276  							SHA: Ptr("s"),
  1277  							Repo: &Repository{
  1278  								ID:   Ptr(int64(1)),
  1279  								URL:  Ptr("s"),
  1280  								Name: Ptr("n"),
  1281  							},
  1282  						},
  1283  						Base: &PullRequestBranch{
  1284  							Ref: Ptr("r"),
  1285  							SHA: Ptr("s"),
  1286  							Repo: &Repository{
  1287  								ID:   Ptr(int64(1)),
  1288  								URL:  Ptr("u"),
  1289  								Name: Ptr("n"),
  1290  							},
  1291  						},
  1292  					},
  1293  				},
  1294  				CreatedAt:          &Timestamp{referenceTime},
  1295  				UpdatedAt:          &Timestamp{referenceTime},
  1296  				RunStartedAt:       &Timestamp{referenceTime},
  1297  				JobsURL:            Ptr("j"),
  1298  				LogsURL:            Ptr("l"),
  1299  				CheckSuiteURL:      Ptr("c"),
  1300  				ArtifactsURL:       Ptr("a"),
  1301  				CancelURL:          Ptr("c"),
  1302  				RerunURL:           Ptr("r"),
  1303  				PreviousAttemptURL: Ptr("p"),
  1304  				HeadCommit: &HeadCommit{
  1305  					Message: Ptr("m"),
  1306  					Author: &CommitAuthor{
  1307  						Name:  Ptr("n"),
  1308  						Email: Ptr("e"),
  1309  						Login: Ptr("l"),
  1310  					},
  1311  					URL:       Ptr("u"),
  1312  					Distinct:  Ptr(false),
  1313  					SHA:       Ptr("s"),
  1314  					ID:        Ptr("i"),
  1315  					TreeID:    Ptr("tid"),
  1316  					Timestamp: &Timestamp{referenceTime},
  1317  					Committer: &CommitAuthor{
  1318  						Name:  Ptr("n"),
  1319  						Email: Ptr("e"),
  1320  						Login: Ptr("l"),
  1321  					},
  1322  				},
  1323  				WorkflowURL: Ptr("w"),
  1324  				Repository: &Repository{
  1325  					ID:   Ptr(int64(1)),
  1326  					URL:  Ptr("u"),
  1327  					Name: Ptr("n"),
  1328  				},
  1329  				HeadRepository: &Repository{
  1330  					ID:   Ptr(int64(1)),
  1331  					URL:  Ptr("u"),
  1332  					Name: Ptr("n"),
  1333  				},
  1334  				Actor: &User{
  1335  					Login:           Ptr("l"),
  1336  					ID:              Ptr(int64(1)),
  1337  					AvatarURL:       Ptr("a"),
  1338  					GravatarID:      Ptr("g"),
  1339  					Name:            Ptr("n"),
  1340  					Company:         Ptr("c"),
  1341  					Blog:            Ptr("b"),
  1342  					Location:        Ptr("l"),
  1343  					Email:           Ptr("e"),
  1344  					Hireable:        Ptr(true),
  1345  					Bio:             Ptr("b"),
  1346  					TwitterUsername: Ptr("t"),
  1347  					PublicRepos:     Ptr(1),
  1348  					Followers:       Ptr(1),
  1349  					Following:       Ptr(1),
  1350  					CreatedAt:       &Timestamp{referenceTime},
  1351  					SuspendedAt:     &Timestamp{referenceTime},
  1352  					URL:             Ptr("u"),
  1353  				},
  1354  				TriggeringActor: &User{
  1355  					Login:           Ptr("l2"),
  1356  					ID:              Ptr(int64(2)),
  1357  					AvatarURL:       Ptr("a2"),
  1358  					GravatarID:      Ptr("g2"),
  1359  					Name:            Ptr("n2"),
  1360  					Company:         Ptr("c2"),
  1361  					Blog:            Ptr("b2"),
  1362  					Location:        Ptr("l2"),
  1363  					Email:           Ptr("e2"),
  1364  					Hireable:        Ptr(false),
  1365  					Bio:             Ptr("b2"),
  1366  					TwitterUsername: Ptr("t2"),
  1367  					PublicRepos:     Ptr(2),
  1368  					Followers:       Ptr(2),
  1369  					Following:       Ptr(2),
  1370  					CreatedAt:       &Timestamp{referenceTime},
  1371  					SuspendedAt:     &Timestamp{referenceTime},
  1372  					URL:             Ptr("u2"),
  1373  				},
  1374  			},
  1375  		},
  1376  	}
  1377  
  1378  	want := `{
  1379  		"total_count": 1,
  1380  		"workflow_runs": [
  1381  			{
  1382  				"id": 1,
  1383  				"name": "n",
  1384  				"node_id": "nid",
  1385  				"head_branch": "hb",
  1386  				"head_sha": "hs",
  1387  				"run_number": 1,
  1388  				"run_attempt": 1,
  1389  				"event": "e",
  1390  				"status": "s",
  1391  				"conclusion": "c",
  1392  				"workflow_id": 1,
  1393  				"url": "u",
  1394  				"html_url": "h",
  1395  				"pull_requests": [
  1396  					{
  1397  						"id":1,
  1398  						"number":1,
  1399  						"url":"u",
  1400  						"head":{
  1401  							"ref":"r",
  1402  							"sha":"s",
  1403  							"repo": {
  1404  								"id":1,
  1405  								"name":"n",
  1406  								"url":"s"
  1407  								}
  1408  							},
  1409  							"base": {
  1410  								"ref":"r",
  1411  								"sha":"s",
  1412  								"repo": {
  1413  									"id":1,
  1414  									"name":"n",
  1415  									"url":"u"
  1416  								}
  1417  							}
  1418  					}
  1419  				],
  1420  				"created_at": ` + referenceTimeStr + `,
  1421  				"updated_at": ` + referenceTimeStr + `,
  1422  				"run_started_at": ` + referenceTimeStr + `,
  1423  				"jobs_url": "j",
  1424  				"logs_url": "l",
  1425  				"check_suite_url": "c",
  1426  				"artifacts_url": "a",
  1427  				"cancel_url": "c",
  1428  				"rerun_url": "r",
  1429  				"previous_attempt_url": "p",
  1430  				"head_commit": {
  1431  					"message": "m",
  1432  					"author": {
  1433  						"name": "n",
  1434  						"email": "e",
  1435  						"username": "l"
  1436  					},
  1437  					"url": "u",
  1438  					"distinct": false,
  1439  					"sha": "s",
  1440  					"id": "i",
  1441  					"tree_id": "tid",
  1442  					"timestamp": ` + referenceTimeStr + `,
  1443  					"committer": {
  1444  						"name": "n",
  1445  						"email": "e",
  1446  						"username": "l"
  1447  					}
  1448  				},
  1449  				"workflow_url": "w",
  1450  				"repository": {
  1451  					"id": 1,
  1452  					"url": "u",
  1453  					"name": "n"
  1454  				},
  1455  				"head_repository": {
  1456  					"id": 1,
  1457  					"url": "u",
  1458  					"name": "n"
  1459  				},
  1460  				"actor": {
  1461  					"login": "l",
  1462  					"id": 1,
  1463  					"avatar_url": "a",
  1464  					"gravatar_id": "g",
  1465  					"name": "n",
  1466  					"company": "c",
  1467  					"blog": "b",
  1468  					"location": "l",
  1469  					"email": "e",
  1470  					"hireable": true,
  1471  					"bio": "b",
  1472  					"twitter_username": "t",
  1473  					"public_repos": 1,
  1474  					"followers": 1,
  1475  					"following": 1,
  1476  					"created_at": ` + referenceTimeStr + `,
  1477  					"suspended_at": ` + referenceTimeStr + `,
  1478  					"url": "u"
  1479  				},
  1480  				"triggering_actor": {
  1481  					"login": "l2",
  1482  					"id": 2,
  1483  					"avatar_url": "a2",
  1484  					"gravatar_id": "g2",
  1485  					"name": "n2",
  1486  					"company": "c2",
  1487  					"blog": "b2",
  1488  					"location": "l2",
  1489  					"email": "e2",
  1490  					"hireable": false,
  1491  					"bio": "b2",
  1492  					"twitter_username": "t2",
  1493  					"public_repos": 2,
  1494  					"followers": 2,
  1495  					"following": 2,
  1496  					"created_at": ` + referenceTimeStr + `,
  1497  					"suspended_at": ` + referenceTimeStr + `,
  1498  					"url": "u2"
  1499  				}
  1500  			}
  1501  		]
  1502  	}`
  1503  
  1504  	testJSONMarshal(t, u, want)
  1505  }
  1506  
  1507  func TestWorkflowRunBill_Marshal(t *testing.T) {
  1508  	t.Parallel()
  1509  	testJSONMarshal(t, &WorkflowRunBill{}, "{}")
  1510  
  1511  	u := &WorkflowRunBill{
  1512  		TotalMS: Ptr(int64(1)),
  1513  		Jobs:    Ptr(1),
  1514  	}
  1515  
  1516  	want := `{
  1517  		"total_ms": 1,
  1518  		"jobs": 1
  1519  	}`
  1520  
  1521  	testJSONMarshal(t, u, want)
  1522  }
  1523  
  1524  func TestWorkflowRunBillMap_Marshal(t *testing.T) {
  1525  	t.Parallel()
  1526  	testJSONMarshal(t, &WorkflowRunBillMap{}, "{}")
  1527  
  1528  	u := &WorkflowRunBillMap{
  1529  		"UBUNTU": &WorkflowRunBill{
  1530  			TotalMS: Ptr(int64(1)),
  1531  			Jobs:    Ptr(1),
  1532  		},
  1533  		"MACOS": &WorkflowRunBill{
  1534  			TotalMS: Ptr(int64(1)),
  1535  			Jobs:    Ptr(1),
  1536  		},
  1537  		"WINDOWS": &WorkflowRunBill{
  1538  			TotalMS: Ptr(int64(1)),
  1539  			Jobs:    Ptr(1),
  1540  		},
  1541  	}
  1542  
  1543  	want := `{
  1544  		"UBUNTU": {
  1545  			"total_ms": 1,
  1546  			"jobs": 1
  1547  		},
  1548  		"MACOS": {
  1549  			"total_ms": 1,
  1550  			"jobs": 1
  1551  		},
  1552  		"WINDOWS": {
  1553  			"total_ms": 1,
  1554  			"jobs": 1
  1555  		}
  1556  	}`
  1557  
  1558  	testJSONMarshal(t, u, want)
  1559  }
  1560  
  1561  func TestWorkflowRunUsage_Marshal(t *testing.T) {
  1562  	t.Parallel()
  1563  	testJSONMarshal(t, &WorkflowRunUsage{}, "{}")
  1564  
  1565  	u := &WorkflowRunUsage{
  1566  		Billable: &WorkflowRunBillMap{
  1567  			"UBUNTU": &WorkflowRunBill{
  1568  				TotalMS: Ptr(int64(1)),
  1569  				Jobs:    Ptr(1),
  1570  			},
  1571  			"MACOS": &WorkflowRunBill{
  1572  				TotalMS: Ptr(int64(1)),
  1573  				Jobs:    Ptr(1),
  1574  			},
  1575  			"WINDOWS": &WorkflowRunBill{
  1576  				TotalMS: Ptr(int64(1)),
  1577  				Jobs:    Ptr(1),
  1578  			},
  1579  		},
  1580  		RunDurationMS: Ptr(int64(1)),
  1581  	}
  1582  
  1583  	want := `{
  1584  		"billable": {
  1585  			"UBUNTU": {
  1586  				"total_ms": 1,
  1587  				"jobs": 1
  1588  			},
  1589  			"MACOS": {
  1590  				"total_ms": 1,
  1591  				"jobs": 1
  1592  			},
  1593  			"WINDOWS": {
  1594  				"total_ms": 1,
  1595  				"jobs": 1
  1596  			}
  1597  		},
  1598  		"run_duration_ms": 1
  1599  	}`
  1600  
  1601  	testJSONMarshal(t, u, want)
  1602  }
  1603  
  1604  func TestActionService_PendingDeployments(t *testing.T) {
  1605  	t.Parallel()
  1606  	client, mux, _ := setup(t)
  1607  
  1608  	input := &PendingDeploymentsRequest{EnvironmentIDs: []int64{3, 4}, State: "approved", Comment: ""}
  1609  
  1610  	mux.HandleFunc("/repos/o/r/actions/runs/399444496/pending_deployments", func(w http.ResponseWriter, r *http.Request) {
  1611  		v := new(PendingDeploymentsRequest)
  1612  		assertNilError(t, json.NewDecoder(r.Body).Decode(v))
  1613  
  1614  		testMethod(t, r, "POST")
  1615  		if !cmp.Equal(v, input) {
  1616  			t.Errorf("Request body = %+v, want %+v", v, input)
  1617  		}
  1618  
  1619  		fmt.Fprint(w, `[{"id":1}, {"id":2}]`)
  1620  	})
  1621  
  1622  	ctx := context.Background()
  1623  	deployments, _, err := client.Actions.PendingDeployments(ctx, "o", "r", 399444496, input)
  1624  	if err != nil {
  1625  		t.Errorf("Actions.PendingDeployments returned error: %v", err)
  1626  	}
  1627  
  1628  	want := []*Deployment{{ID: Ptr(int64(1))}, {ID: Ptr(int64(2))}}
  1629  	if !cmp.Equal(deployments, want) {
  1630  		t.Errorf("Actions.PendingDeployments returned %+v, want %+v", deployments, want)
  1631  	}
  1632  
  1633  	const methodName = "PendingDeployments"
  1634  	testBadOptions(t, methodName, func() (err error) {
  1635  		_, _, err = client.Actions.PendingDeployments(ctx, "\n", "\n", 399444496, input)
  1636  		return err
  1637  	})
  1638  
  1639  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  1640  		got, resp, err := client.Actions.PendingDeployments(ctx, "o", "r", 399444496, input)
  1641  		if got != nil {
  1642  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  1643  		}
  1644  		return resp, err
  1645  	})
  1646  }
  1647  
  1648  func TestActionService_GetPendingDeployments(t *testing.T) {
  1649  	t.Parallel()
  1650  	client, mux, _ := setup(t)
  1651  
  1652  	mux.HandleFunc("/repos/o/r/actions/runs/399444496/pending_deployments", func(w http.ResponseWriter, r *http.Request) {
  1653  		testMethod(t, r, "GET")
  1654  		fmt.Fprint(w, `[
  1655  			{
  1656  				"environment": {
  1657  					"id": 1,
  1658  					"node_id": "nid",
  1659  					"name": "n",
  1660  					"url": "u",
  1661  					"html_url": "hu"
  1662  				},
  1663  				"wait_timer": 0,
  1664  				"wait_timer_started_at": `+referenceTimeStr+`,
  1665  				"current_user_can_approve": false,
  1666  				"reviewers": []
  1667  			},
  1668  			{
  1669  				"environment": {
  1670  					"id": 2,
  1671  					"node_id": "nid",
  1672  					"name": "n",
  1673  					"url": "u",
  1674  					"html_url": "hu"
  1675  				},
  1676  				"wait_timer": 13,
  1677  				"wait_timer_started_at": `+referenceTimeStr+`,
  1678  				"current_user_can_approve": true,
  1679  				"reviewers": [
  1680  					{
  1681  						"type": "User",
  1682  						"reviewer": {
  1683  							"login": "l"
  1684  						}
  1685  					},
  1686  					{
  1687  						"type": "Team",
  1688  						"reviewer": {
  1689  							"name": "t",
  1690  							"slug": "s"
  1691  						}
  1692  					}
  1693  				]
  1694  			}
  1695  		]`)
  1696  	})
  1697  
  1698  	ctx := context.Background()
  1699  	deployments, _, err := client.Actions.GetPendingDeployments(ctx, "o", "r", 399444496)
  1700  	if err != nil {
  1701  		t.Errorf("Actions.GetPendingDeployments returned error: %v", err)
  1702  	}
  1703  
  1704  	want := []*PendingDeployment{
  1705  		{
  1706  			Environment: &PendingDeploymentEnvironment{
  1707  				ID:      Ptr(int64(1)),
  1708  				NodeID:  Ptr("nid"),
  1709  				Name:    Ptr("n"),
  1710  				URL:     Ptr("u"),
  1711  				HTMLURL: Ptr("hu"),
  1712  			},
  1713  			WaitTimer:             Ptr(int64(0)),
  1714  			WaitTimerStartedAt:    &Timestamp{referenceTime},
  1715  			CurrentUserCanApprove: Ptr(false),
  1716  			Reviewers:             []*RequiredReviewer{},
  1717  		},
  1718  		{
  1719  			Environment: &PendingDeploymentEnvironment{
  1720  				ID:      Ptr(int64(2)),
  1721  				NodeID:  Ptr("nid"),
  1722  				Name:    Ptr("n"),
  1723  				URL:     Ptr("u"),
  1724  				HTMLURL: Ptr("hu"),
  1725  			},
  1726  			WaitTimer:             Ptr(int64(13)),
  1727  			WaitTimerStartedAt:    &Timestamp{referenceTime},
  1728  			CurrentUserCanApprove: Ptr(true),
  1729  			Reviewers: []*RequiredReviewer{
  1730  				{
  1731  					Type: Ptr("User"),
  1732  					Reviewer: &User{
  1733  						Login: Ptr("l"),
  1734  					},
  1735  				},
  1736  				{
  1737  					Type: Ptr("Team"),
  1738  					Reviewer: &Team{
  1739  						Name: Ptr("t"),
  1740  						Slug: Ptr("s"),
  1741  					},
  1742  				},
  1743  			},
  1744  		},
  1745  	}
  1746  
  1747  	if !cmp.Equal(deployments, want) {
  1748  		t.Errorf("Actions.GetPendingDeployments returned %+v, want %+v", deployments, want)
  1749  	}
  1750  
  1751  	const methodName = "GetPendingDeployments"
  1752  	testBadOptions(t, methodName, func() (err error) {
  1753  		_, _, err = client.Actions.GetPendingDeployments(ctx, "\n", "\n", 399444496)
  1754  		return err
  1755  	})
  1756  
  1757  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  1758  		got, resp, err := client.Actions.GetPendingDeployments(ctx, "o", "r", 399444496)
  1759  		if got != nil {
  1760  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
  1761  		}
  1762  		return resp, err
  1763  	})
  1764  }