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