github.com/google/go-github/v57@v57.0.0/github/apps_test.go (about)

     1  // Copyright 2016 The go-github AUTHORS. All rights reserved.
     2  //
     3  // Use of this source code is governed by a BSD-style
     4  // license that can be found in the LICENSE file.
     5  
     6  package github
     7  
     8  import (
     9  	"context"
    10  	"encoding/json"
    11  	"fmt"
    12  	"net/http"
    13  	"testing"
    14  	"time"
    15  
    16  	"github.com/google/go-cmp/cmp"
    17  )
    18  
    19  func TestAppsService_Get_authenticatedApp(t *testing.T) {
    20  	client, mux, _, teardown := setup()
    21  	defer teardown()
    22  
    23  	mux.HandleFunc("/app", func(w http.ResponseWriter, r *http.Request) {
    24  		testMethod(t, r, "GET")
    25  		fmt.Fprint(w, `{"id":1}`)
    26  	})
    27  
    28  	ctx := context.Background()
    29  	app, _, err := client.Apps.Get(ctx, "")
    30  	if err != nil {
    31  		t.Errorf("Apps.Get returned error: %v", err)
    32  	}
    33  
    34  	want := &App{ID: Int64(1)}
    35  	if !cmp.Equal(app, want) {
    36  		t.Errorf("Apps.Get returned %+v, want %+v", app, want)
    37  	}
    38  
    39  	const methodName = "Get"
    40  	testBadOptions(t, methodName, func() (err error) {
    41  		_, _, err = client.Apps.Get(ctx, "\n")
    42  		return err
    43  	})
    44  
    45  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
    46  		got, resp, err := client.Apps.Get(ctx, "")
    47  		if got != nil {
    48  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
    49  		}
    50  		return resp, err
    51  	})
    52  }
    53  
    54  func TestAppsService_Get_specifiedApp(t *testing.T) {
    55  	client, mux, _, teardown := setup()
    56  	defer teardown()
    57  
    58  	mux.HandleFunc("/apps/a", func(w http.ResponseWriter, r *http.Request) {
    59  		testMethod(t, r, "GET")
    60  		fmt.Fprint(w, `{"html_url":"https://github.com/apps/a"}`)
    61  	})
    62  
    63  	ctx := context.Background()
    64  	app, _, err := client.Apps.Get(ctx, "a")
    65  	if err != nil {
    66  		t.Errorf("Apps.Get returned error: %v", err)
    67  	}
    68  
    69  	want := &App{HTMLURL: String("https://github.com/apps/a")}
    70  	if !cmp.Equal(app, want) {
    71  		t.Errorf("Apps.Get returned %+v, want %+v", *app.HTMLURL, *want.HTMLURL)
    72  	}
    73  }
    74  
    75  func TestAppsService_ListInstallationRequests(t *testing.T) {
    76  	client, mux, _, teardown := setup()
    77  	defer teardown()
    78  
    79  	mux.HandleFunc("/app/installation-requests", func(w http.ResponseWriter, r *http.Request) {
    80  		testMethod(t, r, "GET")
    81  		testFormValues(t, r, values{
    82  			"page":     "1",
    83  			"per_page": "2",
    84  		})
    85  		fmt.Fprint(w, `[{
    86  			"id": 1,
    87  			"account": { "id": 2 },
    88  			"requester": { "id": 3 },
    89  			"created_at": "2018-01-01T00:00:00Z"
    90  		}]`,
    91  		)
    92  	})
    93  
    94  	opt := &ListOptions{Page: 1, PerPage: 2}
    95  	ctx := context.Background()
    96  	installationRequests, _, err := client.Apps.ListInstallationRequests(ctx, opt)
    97  	if err != nil {
    98  		t.Errorf("Apps.ListInstallations returned error: %v", err)
    99  	}
   100  
   101  	date := Timestamp{Time: time.Date(2018, time.January, 1, 0, 0, 0, 0, time.UTC)}
   102  	want := []*InstallationRequest{{
   103  		ID:        Int64(1),
   104  		Account:   &User{ID: Int64(2)},
   105  		Requester: &User{ID: Int64(3)},
   106  		CreatedAt: &date,
   107  	}}
   108  	if !cmp.Equal(installationRequests, want) {
   109  		t.Errorf("Apps.ListInstallationRequests returned %+v, want %+v", installationRequests, want)
   110  	}
   111  
   112  	const methodName = "ListInstallationRequests"
   113  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   114  		got, resp, err := client.Apps.ListInstallationRequests(ctx, opt)
   115  		if got != nil {
   116  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   117  		}
   118  		return resp, err
   119  	})
   120  }
   121  
   122  func TestAppsService_ListInstallations(t *testing.T) {
   123  	client, mux, _, teardown := setup()
   124  	defer teardown()
   125  
   126  	mux.HandleFunc("/app/installations", func(w http.ResponseWriter, r *http.Request) {
   127  		testMethod(t, r, "GET")
   128  		testFormValues(t, r, values{
   129  			"page":     "1",
   130  			"per_page": "2",
   131  		})
   132  		fmt.Fprint(w, `[{
   133                                     "id":1,
   134                                     "app_id":1,
   135                                     "target_id":1,
   136                                     "target_type": "Organization",
   137                                     "permissions": {
   138                                         "actions": "read",
   139                                         "administration": "read",
   140                                         "checks": "read",
   141                                         "contents": "read",
   142                                         "content_references": "read",
   143                                         "deployments": "read",
   144                                         "environments": "read",
   145                                         "issues": "write",
   146                                         "metadata": "read",
   147                                         "members": "read",
   148                                         "organization_administration": "write",
   149                                         "organization_custom_roles": "write",
   150                                         "organization_hooks": "write",
   151                                         "organization_packages": "write",
   152                                         "organization_plan": "read",
   153                                         "organization_pre_receive_hooks": "write",
   154                                         "organization_projects": "read",
   155                                         "organization_secrets": "read",
   156                                         "organization_self_hosted_runners": "read",
   157                                         "organization_user_blocking": "write",
   158                                         "packages": "read",
   159                                         "pages": "read",
   160                                         "pull_requests": "write",
   161                                         "repository_hooks": "write",
   162                                         "repository_projects": "read",
   163                                         "repository_pre_receive_hooks": "read",
   164                                         "secrets": "read",
   165                                         "secret_scanning_alerts": "read",
   166                                         "security_events": "read",
   167                                         "single_file": "write",
   168                                         "statuses": "write",
   169                                         "team_discussions": "read",
   170                                         "vulnerability_alerts": "read",
   171                                         "workflows": "write"
   172                                     },
   173                                    "events": [
   174                                        "push",
   175                                        "pull_request"
   176                                    ],
   177                                   "single_file_name": "config.yml",
   178                                   "repository_selection": "selected",
   179                                   "created_at": "2018-01-01T00:00:00Z",
   180                                   "updated_at": "2018-01-01T00:00:00Z"}]`,
   181  		)
   182  	})
   183  
   184  	opt := &ListOptions{Page: 1, PerPage: 2}
   185  	ctx := context.Background()
   186  	installations, _, err := client.Apps.ListInstallations(ctx, opt)
   187  	if err != nil {
   188  		t.Errorf("Apps.ListInstallations returned error: %v", err)
   189  	}
   190  
   191  	date := Timestamp{Time: time.Date(2018, time.January, 1, 0, 0, 0, 0, time.UTC)}
   192  	want := []*Installation{{
   193  		ID:                  Int64(1),
   194  		AppID:               Int64(1),
   195  		TargetID:            Int64(1),
   196  		TargetType:          String("Organization"),
   197  		SingleFileName:      String("config.yml"),
   198  		RepositorySelection: String("selected"),
   199  		Permissions: &InstallationPermissions{
   200  			Actions:                       String("read"),
   201  			Administration:                String("read"),
   202  			Checks:                        String("read"),
   203  			Contents:                      String("read"),
   204  			ContentReferences:             String("read"),
   205  			Deployments:                   String("read"),
   206  			Environments:                  String("read"),
   207  			Issues:                        String("write"),
   208  			Metadata:                      String("read"),
   209  			Members:                       String("read"),
   210  			OrganizationAdministration:    String("write"),
   211  			OrganizationCustomRoles:       String("write"),
   212  			OrganizationHooks:             String("write"),
   213  			OrganizationPackages:          String("write"),
   214  			OrganizationPlan:              String("read"),
   215  			OrganizationPreReceiveHooks:   String("write"),
   216  			OrganizationProjects:          String("read"),
   217  			OrganizationSecrets:           String("read"),
   218  			OrganizationSelfHostedRunners: String("read"),
   219  			OrganizationUserBlocking:      String("write"),
   220  			Packages:                      String("read"),
   221  			Pages:                         String("read"),
   222  			PullRequests:                  String("write"),
   223  			RepositoryHooks:               String("write"),
   224  			RepositoryProjects:            String("read"),
   225  			RepositoryPreReceiveHooks:     String("read"),
   226  			Secrets:                       String("read"),
   227  			SecretScanningAlerts:          String("read"),
   228  			SecurityEvents:                String("read"),
   229  			SingleFile:                    String("write"),
   230  			Statuses:                      String("write"),
   231  			TeamDiscussions:               String("read"),
   232  			VulnerabilityAlerts:           String("read"),
   233  			Workflows:                     String("write")},
   234  		Events:    []string{"push", "pull_request"},
   235  		CreatedAt: &date,
   236  		UpdatedAt: &date,
   237  	}}
   238  	if !cmp.Equal(installations, want) {
   239  		t.Errorf("Apps.ListInstallations returned %+v, want %+v", installations, want)
   240  	}
   241  
   242  	const methodName = "ListInstallations"
   243  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   244  		got, resp, err := client.Apps.ListInstallations(ctx, opt)
   245  		if got != nil {
   246  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   247  		}
   248  		return resp, err
   249  	})
   250  }
   251  
   252  func TestAppsService_GetInstallation(t *testing.T) {
   253  	client, mux, _, teardown := setup()
   254  	defer teardown()
   255  
   256  	mux.HandleFunc("/app/installations/1", func(w http.ResponseWriter, r *http.Request) {
   257  		testMethod(t, r, "GET")
   258  		fmt.Fprint(w, `{"id":1, "app_id":1, "target_id":1, "target_type": "Organization"}`)
   259  	})
   260  
   261  	ctx := context.Background()
   262  	installation, _, err := client.Apps.GetInstallation(ctx, 1)
   263  	if err != nil {
   264  		t.Errorf("Apps.GetInstallation returned error: %v", err)
   265  	}
   266  
   267  	want := &Installation{ID: Int64(1), AppID: Int64(1), TargetID: Int64(1), TargetType: String("Organization")}
   268  	if !cmp.Equal(installation, want) {
   269  		t.Errorf("Apps.GetInstallation returned %+v, want %+v", installation, want)
   270  	}
   271  
   272  	const methodName = "GetInstallation"
   273  	testBadOptions(t, methodName, func() (err error) {
   274  		_, _, err = client.Apps.GetInstallation(ctx, -1)
   275  		return err
   276  	})
   277  
   278  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   279  		got, resp, err := client.Apps.GetInstallation(ctx, 1)
   280  		if got != nil {
   281  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   282  		}
   283  		return resp, err
   284  	})
   285  }
   286  
   287  func TestAppsService_ListUserInstallations(t *testing.T) {
   288  	client, mux, _, teardown := setup()
   289  	defer teardown()
   290  
   291  	mux.HandleFunc("/user/installations", func(w http.ResponseWriter, r *http.Request) {
   292  		testMethod(t, r, "GET")
   293  		testFormValues(t, r, values{
   294  			"page":     "1",
   295  			"per_page": "2",
   296  		})
   297  		fmt.Fprint(w, `{"installations":[{"id":1, "app_id":1, "target_id":1, "target_type": "Organization"}]}`)
   298  	})
   299  
   300  	opt := &ListOptions{Page: 1, PerPage: 2}
   301  	ctx := context.Background()
   302  	installations, _, err := client.Apps.ListUserInstallations(ctx, opt)
   303  	if err != nil {
   304  		t.Errorf("Apps.ListUserInstallations returned error: %v", err)
   305  	}
   306  
   307  	want := []*Installation{{ID: Int64(1), AppID: Int64(1), TargetID: Int64(1), TargetType: String("Organization")}}
   308  	if !cmp.Equal(installations, want) {
   309  		t.Errorf("Apps.ListUserInstallations returned %+v, want %+v", installations, want)
   310  	}
   311  
   312  	const methodName = "ListUserInstallations"
   313  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   314  		got, resp, err := client.Apps.ListUserInstallations(ctx, opt)
   315  		if got != nil {
   316  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   317  		}
   318  		return resp, err
   319  	})
   320  }
   321  
   322  func TestAppsService_SuspendInstallation(t *testing.T) {
   323  	client, mux, _, teardown := setup()
   324  	defer teardown()
   325  
   326  	mux.HandleFunc("/app/installations/1/suspended", func(w http.ResponseWriter, r *http.Request) {
   327  		testMethod(t, r, "PUT")
   328  
   329  		w.WriteHeader(http.StatusNoContent)
   330  	})
   331  
   332  	ctx := context.Background()
   333  	if _, err := client.Apps.SuspendInstallation(ctx, 1); err != nil {
   334  		t.Errorf("Apps.SuspendInstallation returned error: %v", err)
   335  	}
   336  
   337  	const methodName = "SuspendInstallation"
   338  	testBadOptions(t, methodName, func() (err error) {
   339  		_, err = client.Apps.SuspendInstallation(ctx, -1)
   340  		return err
   341  	})
   342  
   343  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   344  		return client.Apps.SuspendInstallation(ctx, 1)
   345  	})
   346  }
   347  
   348  func TestAppsService_UnsuspendInstallation(t *testing.T) {
   349  	client, mux, _, teardown := setup()
   350  	defer teardown()
   351  
   352  	mux.HandleFunc("/app/installations/1/suspended", func(w http.ResponseWriter, r *http.Request) {
   353  		testMethod(t, r, "DELETE")
   354  
   355  		w.WriteHeader(http.StatusNoContent)
   356  	})
   357  
   358  	ctx := context.Background()
   359  	if _, err := client.Apps.UnsuspendInstallation(ctx, 1); err != nil {
   360  		t.Errorf("Apps.UnsuspendInstallation returned error: %v", err)
   361  	}
   362  
   363  	const methodName = "UnsuspendInstallation"
   364  	testBadOptions(t, methodName, func() (err error) {
   365  		_, err = client.Apps.UnsuspendInstallation(ctx, -1)
   366  		return err
   367  	})
   368  
   369  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   370  		return client.Apps.UnsuspendInstallation(ctx, 1)
   371  	})
   372  }
   373  
   374  func TestAppsService_DeleteInstallation(t *testing.T) {
   375  	client, mux, _, teardown := setup()
   376  	defer teardown()
   377  
   378  	mux.HandleFunc("/app/installations/1", func(w http.ResponseWriter, r *http.Request) {
   379  		testMethod(t, r, "DELETE")
   380  		w.WriteHeader(http.StatusNoContent)
   381  	})
   382  
   383  	ctx := context.Background()
   384  	_, err := client.Apps.DeleteInstallation(ctx, 1)
   385  	if err != nil {
   386  		t.Errorf("Apps.DeleteInstallation returned error: %v", err)
   387  	}
   388  
   389  	const methodName = "DeleteInstallation"
   390  	testBadOptions(t, methodName, func() (err error) {
   391  		_, err = client.Apps.DeleteInstallation(ctx, -1)
   392  		return err
   393  	})
   394  
   395  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   396  		return client.Apps.DeleteInstallation(ctx, 1)
   397  	})
   398  }
   399  
   400  func TestAppsService_CreateInstallationToken(t *testing.T) {
   401  	client, mux, _, teardown := setup()
   402  	defer teardown()
   403  
   404  	mux.HandleFunc("/app/installations/1/access_tokens", func(w http.ResponseWriter, r *http.Request) {
   405  		testMethod(t, r, "POST")
   406  		fmt.Fprint(w, `{"token":"t"}`)
   407  	})
   408  
   409  	ctx := context.Background()
   410  	token, _, err := client.Apps.CreateInstallationToken(ctx, 1, nil)
   411  	if err != nil {
   412  		t.Errorf("Apps.CreateInstallationToken returned error: %v", err)
   413  	}
   414  
   415  	want := &InstallationToken{Token: String("t")}
   416  	if !cmp.Equal(token, want) {
   417  		t.Errorf("Apps.CreateInstallationToken returned %+v, want %+v", token, want)
   418  	}
   419  
   420  	const methodName = "CreateInstallationToken"
   421  	testBadOptions(t, methodName, func() (err error) {
   422  		_, _, err = client.Apps.CreateInstallationToken(ctx, -1, nil)
   423  		return err
   424  	})
   425  
   426  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   427  		got, resp, err := client.Apps.CreateInstallationToken(ctx, 1, nil)
   428  		if got != nil {
   429  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   430  		}
   431  		return resp, err
   432  	})
   433  }
   434  
   435  func TestAppsService_CreateInstallationTokenWithOptions(t *testing.T) {
   436  	client, mux, _, teardown := setup()
   437  	defer teardown()
   438  
   439  	installationTokenOptions := &InstallationTokenOptions{
   440  		RepositoryIDs: []int64{1234},
   441  		Repositories:  []string{"foo"},
   442  		Permissions: &InstallationPermissions{
   443  			Contents: String("write"),
   444  			Issues:   String("read"),
   445  		},
   446  	}
   447  
   448  	mux.HandleFunc("/app/installations/1/access_tokens", func(w http.ResponseWriter, r *http.Request) {
   449  		v := new(InstallationTokenOptions)
   450  		assertNilError(t, json.NewDecoder(r.Body).Decode(v))
   451  
   452  		if !cmp.Equal(v, installationTokenOptions) {
   453  			t.Errorf("request sent %+v, want %+v", v, installationTokenOptions)
   454  		}
   455  
   456  		testMethod(t, r, "POST")
   457  		fmt.Fprint(w, `{"token":"t"}`)
   458  	})
   459  
   460  	ctx := context.Background()
   461  	token, _, err := client.Apps.CreateInstallationToken(ctx, 1, installationTokenOptions)
   462  	if err != nil {
   463  		t.Errorf("Apps.CreateInstallationToken returned error: %v", err)
   464  	}
   465  
   466  	want := &InstallationToken{Token: String("t")}
   467  	if !cmp.Equal(token, want) {
   468  		t.Errorf("Apps.CreateInstallationToken returned %+v, want %+v", token, want)
   469  	}
   470  }
   471  
   472  func TestAppsService_CreateAttachement(t *testing.T) {
   473  	client, mux, _, teardown := setup()
   474  	defer teardown()
   475  
   476  	mux.HandleFunc("/content_references/11/attachments", func(w http.ResponseWriter, r *http.Request) {
   477  		testMethod(t, r, "POST")
   478  		testHeader(t, r, "Accept", mediaTypeContentAttachmentsPreview)
   479  
   480  		w.WriteHeader(http.StatusOK)
   481  		assertWrite(t, w, []byte(`{"id":1,"title":"title1","body":"body1"}`))
   482  	})
   483  
   484  	ctx := context.Background()
   485  	got, _, err := client.Apps.CreateAttachment(ctx, 11, "title1", "body1")
   486  	if err != nil {
   487  		t.Errorf("CreateAttachment returned error: %v", err)
   488  	}
   489  
   490  	want := &Attachment{ID: Int64(1), Title: String("title1"), Body: String("body1")}
   491  	if !cmp.Equal(got, want) {
   492  		t.Errorf("CreateAttachment = %+v, want %+v", got, want)
   493  	}
   494  
   495  	const methodName = "CreateAttachment"
   496  	testBadOptions(t, methodName, func() (err error) {
   497  		_, _, err = client.Apps.CreateAttachment(ctx, -11, "\n", "\n")
   498  		return err
   499  	})
   500  
   501  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   502  		got, resp, err := client.Apps.CreateAttachment(ctx, 11, "title1", "body1")
   503  		if got != nil {
   504  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   505  		}
   506  		return resp, err
   507  	})
   508  }
   509  
   510  func TestAppsService_FindOrganizationInstallation(t *testing.T) {
   511  	client, mux, _, teardown := setup()
   512  	defer teardown()
   513  
   514  	mux.HandleFunc("/orgs/o/installation", func(w http.ResponseWriter, r *http.Request) {
   515  		testMethod(t, r, "GET")
   516  		fmt.Fprint(w, `{"id":1, "app_id":1, "target_id":1, "target_type": "Organization"}`)
   517  	})
   518  
   519  	ctx := context.Background()
   520  	installation, _, err := client.Apps.FindOrganizationInstallation(ctx, "o")
   521  	if err != nil {
   522  		t.Errorf("Apps.FindOrganizationInstallation returned error: %v", err)
   523  	}
   524  
   525  	want := &Installation{ID: Int64(1), AppID: Int64(1), TargetID: Int64(1), TargetType: String("Organization")}
   526  	if !cmp.Equal(installation, want) {
   527  		t.Errorf("Apps.FindOrganizationInstallation returned %+v, want %+v", installation, want)
   528  	}
   529  
   530  	const methodName = "FindOrganizationInstallation"
   531  	testBadOptions(t, methodName, func() (err error) {
   532  		_, _, err = client.Apps.FindOrganizationInstallation(ctx, "\n")
   533  		return err
   534  	})
   535  
   536  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   537  		got, resp, err := client.Apps.FindOrganizationInstallation(ctx, "o")
   538  		if got != nil {
   539  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   540  		}
   541  		return resp, err
   542  	})
   543  }
   544  
   545  func TestAppsService_FindRepositoryInstallation(t *testing.T) {
   546  	client, mux, _, teardown := setup()
   547  	defer teardown()
   548  
   549  	mux.HandleFunc("/repos/o/r/installation", func(w http.ResponseWriter, r *http.Request) {
   550  		testMethod(t, r, "GET")
   551  		fmt.Fprint(w, `{"id":1, "app_id":1, "target_id":1, "target_type": "Organization"}`)
   552  	})
   553  
   554  	ctx := context.Background()
   555  	installation, _, err := client.Apps.FindRepositoryInstallation(ctx, "o", "r")
   556  	if err != nil {
   557  		t.Errorf("Apps.FindRepositoryInstallation returned error: %v", err)
   558  	}
   559  
   560  	want := &Installation{ID: Int64(1), AppID: Int64(1), TargetID: Int64(1), TargetType: String("Organization")}
   561  	if !cmp.Equal(installation, want) {
   562  		t.Errorf("Apps.FindRepositoryInstallation returned %+v, want %+v", installation, want)
   563  	}
   564  
   565  	const methodName = "FindRepositoryInstallation"
   566  	testBadOptions(t, methodName, func() (err error) {
   567  		_, _, err = client.Apps.FindRepositoryInstallation(ctx, "\n", "\n")
   568  		return err
   569  	})
   570  
   571  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   572  		got, resp, err := client.Apps.FindRepositoryInstallation(ctx, "o", "r")
   573  		if got != nil {
   574  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   575  		}
   576  		return resp, err
   577  	})
   578  }
   579  
   580  func TestAppsService_FindRepositoryInstallationByID(t *testing.T) {
   581  	client, mux, _, teardown := setup()
   582  	defer teardown()
   583  
   584  	mux.HandleFunc("/repositories/1/installation", func(w http.ResponseWriter, r *http.Request) {
   585  		testMethod(t, r, "GET")
   586  		fmt.Fprint(w, `{"id":1, "app_id":1, "target_id":1, "target_type": "Organization"}`)
   587  	})
   588  
   589  	ctx := context.Background()
   590  	installation, _, err := client.Apps.FindRepositoryInstallationByID(ctx, 1)
   591  	if err != nil {
   592  		t.Errorf("Apps.FindRepositoryInstallationByID returned error: %v", err)
   593  	}
   594  
   595  	want := &Installation{ID: Int64(1), AppID: Int64(1), TargetID: Int64(1), TargetType: String("Organization")}
   596  	if !cmp.Equal(installation, want) {
   597  		t.Errorf("Apps.FindRepositoryInstallationByID returned %+v, want %+v", installation, want)
   598  	}
   599  
   600  	const methodName = "FindRepositoryInstallationByID"
   601  	testBadOptions(t, methodName, func() (err error) {
   602  		_, _, err = client.Apps.FindRepositoryInstallationByID(ctx, -1)
   603  		return err
   604  	})
   605  
   606  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   607  		got, resp, err := client.Apps.FindRepositoryInstallationByID(ctx, 1)
   608  		if got != nil {
   609  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   610  		}
   611  		return resp, err
   612  	})
   613  }
   614  
   615  func TestAppsService_FindUserInstallation(t *testing.T) {
   616  	client, mux, _, teardown := setup()
   617  	defer teardown()
   618  
   619  	mux.HandleFunc("/users/u/installation", func(w http.ResponseWriter, r *http.Request) {
   620  		testMethod(t, r, "GET")
   621  		fmt.Fprint(w, `{"id":1, "app_id":1, "target_id":1, "target_type": "User"}`)
   622  	})
   623  
   624  	ctx := context.Background()
   625  	installation, _, err := client.Apps.FindUserInstallation(ctx, "u")
   626  	if err != nil {
   627  		t.Errorf("Apps.FindUserInstallation returned error: %v", err)
   628  	}
   629  
   630  	want := &Installation{ID: Int64(1), AppID: Int64(1), TargetID: Int64(1), TargetType: String("User")}
   631  	if !cmp.Equal(installation, want) {
   632  		t.Errorf("Apps.FindUserInstallation returned %+v, want %+v", installation, want)
   633  	}
   634  
   635  	const methodName = "FindUserInstallation"
   636  	testBadOptions(t, methodName, func() (err error) {
   637  		_, _, err = client.Apps.FindUserInstallation(ctx, "\n")
   638  		return err
   639  	})
   640  
   641  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   642  		got, resp, err := client.Apps.FindUserInstallation(ctx, "u")
   643  		if got != nil {
   644  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   645  		}
   646  		return resp, err
   647  	})
   648  }
   649  
   650  func TestContentReference_Marshal(t *testing.T) {
   651  	testJSONMarshal(t, &ContentReference{}, "{}")
   652  
   653  	u := &ContentReference{
   654  		ID:        Int64(1),
   655  		NodeID:    String("nid"),
   656  		Reference: String("r"),
   657  	}
   658  
   659  	want := `{
   660  		"id": 1,
   661  		"node_id": "nid",
   662  		"reference": "r"
   663  	}`
   664  
   665  	testJSONMarshal(t, u, want)
   666  }
   667  
   668  func TestAttachment_Marshal(t *testing.T) {
   669  	testJSONMarshal(t, &Attachment{}, "{}")
   670  
   671  	u := &Attachment{
   672  		ID:    Int64(1),
   673  		Title: String("t"),
   674  		Body:  String("b"),
   675  	}
   676  
   677  	want := `{
   678  		"id": 1,
   679  		"title": "t",
   680  		"body": "b"
   681  	}`
   682  
   683  	testJSONMarshal(t, u, want)
   684  }
   685  
   686  func TestInstallationPermissions_Marshal(t *testing.T) {
   687  	testJSONMarshal(t, &InstallationPermissions{}, "{}")
   688  
   689  	u := &InstallationPermissions{
   690  		Actions:                       String("a"),
   691  		Administration:                String("ad"),
   692  		Checks:                        String("c"),
   693  		Contents:                      String("co"),
   694  		ContentReferences:             String("cr"),
   695  		Deployments:                   String("d"),
   696  		Environments:                  String("e"),
   697  		Issues:                        String("i"),
   698  		Metadata:                      String("md"),
   699  		Members:                       String("m"),
   700  		OrganizationAdministration:    String("oa"),
   701  		OrganizationHooks:             String("oh"),
   702  		OrganizationPlan:              String("op"),
   703  		OrganizationPreReceiveHooks:   String("opr"),
   704  		OrganizationProjects:          String("op"),
   705  		OrganizationSecrets:           String("os"),
   706  		OrganizationSelfHostedRunners: String("osh"),
   707  		OrganizationUserBlocking:      String("oub"),
   708  		Packages:                      String("pkg"),
   709  		Pages:                         String("pg"),
   710  		PullRequests:                  String("pr"),
   711  		RepositoryHooks:               String("rh"),
   712  		RepositoryProjects:            String("rp"),
   713  		RepositoryPreReceiveHooks:     String("rprh"),
   714  		Secrets:                       String("s"),
   715  		SecretScanningAlerts:          String("ssa"),
   716  		SecurityEvents:                String("se"),
   717  		SingleFile:                    String("sf"),
   718  		Statuses:                      String("s"),
   719  		TeamDiscussions:               String("td"),
   720  		VulnerabilityAlerts:           String("va"),
   721  		Workflows:                     String("w"),
   722  	}
   723  
   724  	want := `{
   725  		"actions": "a",
   726  		"administration": "ad",
   727  		"checks": "c",
   728  		"contents": "co",
   729  		"content_references": "cr",
   730  		"deployments": "d",
   731  		"environments": "e",
   732  		"issues": "i",
   733  		"metadata": "md",
   734  		"members": "m",
   735  		"organization_administration": "oa",
   736  		"organization_hooks": "oh",
   737  		"organization_plan": "op",
   738  		"organization_pre_receive_hooks": "opr",
   739  		"organization_projects": "op",
   740  		"organization_secrets": "os",
   741  		"organization_self_hosted_runners": "osh",
   742  		"organization_user_blocking": "oub",
   743  		"packages": "pkg",
   744  		"pages": "pg",
   745  		"pull_requests": "pr",
   746  		"repository_hooks": "rh",
   747  		"repository_projects": "rp",
   748  		"repository_pre_receive_hooks": "rprh",
   749  		"secrets": "s",
   750  		"secret_scanning_alerts": "ssa",
   751  		"security_events": "se",
   752  		"single_file": "sf",
   753  		"statuses": "s",
   754  		"team_discussions": "td",
   755  		"vulnerability_alerts":"va",
   756  		"workflows": "w"
   757  	}`
   758  
   759  	testJSONMarshal(t, u, want)
   760  }
   761  
   762  func TestInstallation_Marshal(t *testing.T) {
   763  	testJSONMarshal(t, &Installation{}, "{}")
   764  
   765  	u := &Installation{
   766  		ID:       Int64(1),
   767  		NodeID:   String("nid"),
   768  		AppID:    Int64(1),
   769  		AppSlug:  String("as"),
   770  		TargetID: Int64(1),
   771  		Account: &User{
   772  			Login:           String("l"),
   773  			ID:              Int64(1),
   774  			URL:             String("u"),
   775  			AvatarURL:       String("a"),
   776  			GravatarID:      String("g"),
   777  			Name:            String("n"),
   778  			Company:         String("c"),
   779  			Blog:            String("b"),
   780  			Location:        String("l"),
   781  			Email:           String("e"),
   782  			Hireable:        Bool(true),
   783  			Bio:             String("b"),
   784  			TwitterUsername: String("t"),
   785  			PublicRepos:     Int(1),
   786  			Followers:       Int(1),
   787  			Following:       Int(1),
   788  			CreatedAt:       &Timestamp{referenceTime},
   789  			SuspendedAt:     &Timestamp{referenceTime},
   790  		},
   791  		AccessTokensURL:     String("atu"),
   792  		RepositoriesURL:     String("ru"),
   793  		HTMLURL:             String("hu"),
   794  		TargetType:          String("tt"),
   795  		SingleFileName:      String("sfn"),
   796  		RepositorySelection: String("rs"),
   797  		Events:              []string{"e"},
   798  		SingleFilePaths:     []string{"s"},
   799  		Permissions: &InstallationPermissions{
   800  			Actions:                       String("a"),
   801  			Administration:                String("ad"),
   802  			Checks:                        String("c"),
   803  			Contents:                      String("co"),
   804  			ContentReferences:             String("cr"),
   805  			Deployments:                   String("d"),
   806  			Environments:                  String("e"),
   807  			Issues:                        String("i"),
   808  			Metadata:                      String("md"),
   809  			Members:                       String("m"),
   810  			OrganizationAdministration:    String("oa"),
   811  			OrganizationHooks:             String("oh"),
   812  			OrganizationPlan:              String("op"),
   813  			OrganizationPreReceiveHooks:   String("opr"),
   814  			OrganizationProjects:          String("op"),
   815  			OrganizationSecrets:           String("os"),
   816  			OrganizationSelfHostedRunners: String("osh"),
   817  			OrganizationUserBlocking:      String("oub"),
   818  			Packages:                      String("pkg"),
   819  			Pages:                         String("pg"),
   820  			PullRequests:                  String("pr"),
   821  			RepositoryHooks:               String("rh"),
   822  			RepositoryProjects:            String("rp"),
   823  			RepositoryPreReceiveHooks:     String("rprh"),
   824  			Secrets:                       String("s"),
   825  			SecretScanningAlerts:          String("ssa"),
   826  			SecurityEvents:                String("se"),
   827  			SingleFile:                    String("sf"),
   828  			Statuses:                      String("s"),
   829  			TeamDiscussions:               String("td"),
   830  			VulnerabilityAlerts:           String("va"),
   831  			Workflows:                     String("w"),
   832  		},
   833  		CreatedAt:              &Timestamp{referenceTime},
   834  		UpdatedAt:              &Timestamp{referenceTime},
   835  		HasMultipleSingleFiles: Bool(false),
   836  		SuspendedBy: &User{
   837  			Login:           String("l"),
   838  			ID:              Int64(1),
   839  			URL:             String("u"),
   840  			AvatarURL:       String("a"),
   841  			GravatarID:      String("g"),
   842  			Name:            String("n"),
   843  			Company:         String("c"),
   844  			Blog:            String("b"),
   845  			Location:        String("l"),
   846  			Email:           String("e"),
   847  			Hireable:        Bool(true),
   848  			Bio:             String("b"),
   849  			TwitterUsername: String("t"),
   850  			PublicRepos:     Int(1),
   851  			Followers:       Int(1),
   852  			Following:       Int(1),
   853  			CreatedAt:       &Timestamp{referenceTime},
   854  			SuspendedAt:     &Timestamp{referenceTime},
   855  		},
   856  		SuspendedAt: &Timestamp{referenceTime},
   857  	}
   858  
   859  	want := `{
   860  		"id": 1,
   861  		"node_id": "nid",
   862  		"app_id": 1,
   863  		"app_slug": "as",
   864  		"target_id": 1,
   865  		"account": {
   866  			"login": "l",
   867  			"id": 1,
   868  			"avatar_url": "a",
   869  			"gravatar_id": "g",
   870  			"name": "n",
   871  			"company": "c",
   872  			"blog": "b",
   873  			"location": "l",
   874  			"email": "e",
   875  			"hireable": true,
   876  			"bio": "b",
   877  			"twitter_username": "t",
   878  			"public_repos": 1,
   879  			"followers": 1,
   880  			"following": 1,
   881  			"created_at": ` + referenceTimeStr + `,
   882  			"suspended_at": ` + referenceTimeStr + `,
   883  			"url": "u"
   884  		},
   885  		"access_tokens_url": "atu",
   886  		"repositories_url": "ru",
   887  		"html_url": "hu",
   888  		"target_type": "tt",
   889  		"single_file_name": "sfn",
   890  		"repository_selection": "rs",
   891  		"events": [
   892  			"e"
   893  		],
   894  		"single_file_paths": [
   895  			"s"
   896  		],
   897  		"permissions": {
   898  			"actions": "a",
   899  			"administration": "ad",
   900  			"checks": "c",
   901  			"contents": "co",
   902  			"content_references": "cr",
   903  			"deployments": "d",
   904  			"environments": "e",
   905  			"issues": "i",
   906  			"metadata": "md",
   907  			"members": "m",
   908  			"organization_administration": "oa",
   909  			"organization_hooks": "oh",
   910  			"organization_plan": "op",
   911  			"organization_pre_receive_hooks": "opr",
   912  			"organization_projects": "op",
   913  			"organization_secrets": "os",
   914  			"organization_self_hosted_runners": "osh",
   915  			"organization_user_blocking": "oub",
   916  			"packages": "pkg",
   917  			"pages": "pg",
   918  			"pull_requests": "pr",
   919  			"repository_hooks": "rh",
   920  			"repository_projects": "rp",
   921  			"repository_pre_receive_hooks": "rprh",
   922  			"secrets": "s",
   923  			"secret_scanning_alerts": "ssa",
   924  			"security_events": "se",
   925  			"single_file": "sf",
   926  			"statuses": "s",
   927  			"team_discussions": "td",
   928  			"vulnerability_alerts": "va",
   929  			"workflows": "w"
   930  		},
   931  		"created_at": ` + referenceTimeStr + `,
   932  		"updated_at": ` + referenceTimeStr + `,
   933  		"has_multiple_single_files": false,
   934  		"suspended_by": {
   935  			"login": "l",
   936  			"id": 1,
   937  			"avatar_url": "a",
   938  			"gravatar_id": "g",
   939  			"name": "n",
   940  			"company": "c",
   941  			"blog": "b",
   942  			"location": "l",
   943  			"email": "e",
   944  			"hireable": true,
   945  			"bio": "b",
   946  			"twitter_username": "t",
   947  			"public_repos": 1,
   948  			"followers": 1,
   949  			"following": 1,
   950  			"created_at": ` + referenceTimeStr + `,
   951  			"suspended_at": ` + referenceTimeStr + `,
   952  			"url": "u"
   953  		},
   954  		"suspended_at": ` + referenceTimeStr + `
   955  	}`
   956  
   957  	testJSONMarshal(t, u, want)
   958  }
   959  
   960  func TestInstallationTokenOptions_Marshal(t *testing.T) {
   961  	testJSONMarshal(t, &InstallationTokenOptions{}, "{}")
   962  
   963  	u := &InstallationTokenOptions{
   964  		RepositoryIDs: []int64{1},
   965  		Permissions: &InstallationPermissions{
   966  			Actions:                       String("a"),
   967  			Administration:                String("ad"),
   968  			Checks:                        String("c"),
   969  			Contents:                      String("co"),
   970  			ContentReferences:             String("cr"),
   971  			Deployments:                   String("d"),
   972  			Environments:                  String("e"),
   973  			Issues:                        String("i"),
   974  			Metadata:                      String("md"),
   975  			Members:                       String("m"),
   976  			OrganizationAdministration:    String("oa"),
   977  			OrganizationHooks:             String("oh"),
   978  			OrganizationPlan:              String("op"),
   979  			OrganizationPreReceiveHooks:   String("opr"),
   980  			OrganizationProjects:          String("op"),
   981  			OrganizationSecrets:           String("os"),
   982  			OrganizationSelfHostedRunners: String("osh"),
   983  			OrganizationUserBlocking:      String("oub"),
   984  			Packages:                      String("pkg"),
   985  			Pages:                         String("pg"),
   986  			PullRequests:                  String("pr"),
   987  			RepositoryHooks:               String("rh"),
   988  			RepositoryProjects:            String("rp"),
   989  			RepositoryPreReceiveHooks:     String("rprh"),
   990  			Secrets:                       String("s"),
   991  			SecretScanningAlerts:          String("ssa"),
   992  			SecurityEvents:                String("se"),
   993  			SingleFile:                    String("sf"),
   994  			Statuses:                      String("s"),
   995  			TeamDiscussions:               String("td"),
   996  			VulnerabilityAlerts:           String("va"),
   997  			Workflows:                     String("w"),
   998  		},
   999  	}
  1000  
  1001  	want := `{
  1002  		"repository_ids": [1],
  1003  		"permissions": {
  1004  			"actions": "a",
  1005  			"administration": "ad",
  1006  			"checks": "c",
  1007  			"contents": "co",
  1008  			"content_references": "cr",
  1009  			"deployments": "d",
  1010  			"environments": "e",
  1011  			"issues": "i",
  1012  			"metadata": "md",
  1013  			"members": "m",
  1014  			"organization_administration": "oa",
  1015  			"organization_hooks": "oh",
  1016  			"organization_plan": "op",
  1017  			"organization_pre_receive_hooks": "opr",
  1018  			"organization_projects": "op",
  1019  			"organization_secrets": "os",
  1020  			"organization_self_hosted_runners": "osh",
  1021  			"organization_user_blocking": "oub",
  1022  			"packages": "pkg",
  1023  			"pages": "pg",
  1024  			"pull_requests": "pr",
  1025  			"repository_hooks": "rh",
  1026  			"repository_projects": "rp",
  1027  			"repository_pre_receive_hooks": "rprh",
  1028  			"secrets": "s",
  1029  			"secret_scanning_alerts": "ssa",
  1030  			"security_events": "se",
  1031  			"single_file": "sf",
  1032  			"statuses": "s",
  1033  			"team_discussions": "td",
  1034  			"vulnerability_alerts": "va",
  1035  			"workflows": "w"
  1036  		}
  1037  	}`
  1038  
  1039  	testJSONMarshal(t, u, want)
  1040  }
  1041  
  1042  func TestInstallationToken_Marshal(t *testing.T) {
  1043  	testJSONMarshal(t, &InstallationToken{}, "{}")
  1044  
  1045  	u := &InstallationToken{
  1046  		Token:     String("t"),
  1047  		ExpiresAt: &Timestamp{referenceTime},
  1048  		Permissions: &InstallationPermissions{
  1049  			Actions:                       String("a"),
  1050  			Administration:                String("ad"),
  1051  			Checks:                        String("c"),
  1052  			Contents:                      String("co"),
  1053  			ContentReferences:             String("cr"),
  1054  			Deployments:                   String("d"),
  1055  			Environments:                  String("e"),
  1056  			Issues:                        String("i"),
  1057  			Metadata:                      String("md"),
  1058  			Members:                       String("m"),
  1059  			OrganizationAdministration:    String("oa"),
  1060  			OrganizationHooks:             String("oh"),
  1061  			OrganizationPlan:              String("op"),
  1062  			OrganizationPreReceiveHooks:   String("opr"),
  1063  			OrganizationProjects:          String("op"),
  1064  			OrganizationSecrets:           String("os"),
  1065  			OrganizationSelfHostedRunners: String("osh"),
  1066  			OrganizationUserBlocking:      String("oub"),
  1067  			Packages:                      String("pkg"),
  1068  			Pages:                         String("pg"),
  1069  			PullRequests:                  String("pr"),
  1070  			RepositoryHooks:               String("rh"),
  1071  			RepositoryProjects:            String("rp"),
  1072  			RepositoryPreReceiveHooks:     String("rprh"),
  1073  			Secrets:                       String("s"),
  1074  			SecretScanningAlerts:          String("ssa"),
  1075  			SecurityEvents:                String("se"),
  1076  			SingleFile:                    String("sf"),
  1077  			Statuses:                      String("s"),
  1078  			TeamDiscussions:               String("td"),
  1079  			VulnerabilityAlerts:           String("va"),
  1080  			Workflows:                     String("w"),
  1081  		},
  1082  		Repositories: []*Repository{
  1083  			{
  1084  				ID:   Int64(1),
  1085  				URL:  String("u"),
  1086  				Name: String("n"),
  1087  			},
  1088  		},
  1089  	}
  1090  
  1091  	want := `{
  1092  		"token": "t",
  1093  		"expires_at": ` + referenceTimeStr + `,
  1094  		"permissions": {
  1095  			"actions": "a",
  1096  			"administration": "ad",
  1097  			"checks": "c",
  1098  			"contents": "co",
  1099  			"content_references": "cr",
  1100  			"deployments": "d",
  1101  			"environments": "e",
  1102  			"issues": "i",
  1103  			"metadata": "md",
  1104  			"members": "m",
  1105  			"organization_administration": "oa",
  1106  			"organization_hooks": "oh",
  1107  			"organization_plan": "op",
  1108  			"organization_pre_receive_hooks": "opr",
  1109  			"organization_projects": "op",
  1110  			"organization_secrets": "os",
  1111  			"organization_self_hosted_runners": "osh",
  1112  			"organization_user_blocking": "oub",
  1113  			"packages": "pkg",
  1114  			"pages": "pg",
  1115  			"pull_requests": "pr",
  1116  			"repository_hooks": "rh",
  1117  			"repository_projects": "rp",
  1118  			"repository_pre_receive_hooks": "rprh",
  1119  			"secrets": "s",
  1120  			"secret_scanning_alerts": "ssa",
  1121  			"security_events": "se",
  1122  			"single_file": "sf",
  1123  			"statuses": "s",
  1124  			"team_discussions": "td",
  1125  			"vulnerability_alerts": "va",
  1126  			"workflows": "w"
  1127  		},
  1128  		"repositories": [
  1129  			{
  1130  				"id": 1,
  1131  				"url": "u",
  1132  				"name": "n"
  1133  			}
  1134  		]
  1135  	}`
  1136  
  1137  	testJSONMarshal(t, u, want)
  1138  }
  1139  
  1140  func TestApp_Marshal(t *testing.T) {
  1141  	testJSONMarshal(t, &App{}, "{}")
  1142  
  1143  	u := &App{
  1144  		ID:     Int64(1),
  1145  		Slug:   String("s"),
  1146  		NodeID: String("nid"),
  1147  		Owner: &User{
  1148  			Login:           String("l"),
  1149  			ID:              Int64(1),
  1150  			URL:             String("u"),
  1151  			AvatarURL:       String("a"),
  1152  			GravatarID:      String("g"),
  1153  			Name:            String("n"),
  1154  			Company:         String("c"),
  1155  			Blog:            String("b"),
  1156  			Location:        String("l"),
  1157  			Email:           String("e"),
  1158  			Hireable:        Bool(true),
  1159  			Bio:             String("b"),
  1160  			TwitterUsername: String("t"),
  1161  			PublicRepos:     Int(1),
  1162  			Followers:       Int(1),
  1163  			Following:       Int(1),
  1164  			CreatedAt:       &Timestamp{referenceTime},
  1165  			SuspendedAt:     &Timestamp{referenceTime},
  1166  		},
  1167  		Name:        String("n"),
  1168  		Description: String("d"),
  1169  		ExternalURL: String("eu"),
  1170  		HTMLURL:     String("hu"),
  1171  		CreatedAt:   &Timestamp{referenceTime},
  1172  		UpdatedAt:   &Timestamp{referenceTime},
  1173  		Permissions: &InstallationPermissions{
  1174  			Actions:                       String("a"),
  1175  			Administration:                String("ad"),
  1176  			Checks:                        String("c"),
  1177  			Contents:                      String("co"),
  1178  			ContentReferences:             String("cr"),
  1179  			Deployments:                   String("d"),
  1180  			Environments:                  String("e"),
  1181  			Issues:                        String("i"),
  1182  			Metadata:                      String("md"),
  1183  			Members:                       String("m"),
  1184  			OrganizationAdministration:    String("oa"),
  1185  			OrganizationHooks:             String("oh"),
  1186  			OrganizationPlan:              String("op"),
  1187  			OrganizationPreReceiveHooks:   String("opr"),
  1188  			OrganizationProjects:          String("op"),
  1189  			OrganizationSecrets:           String("os"),
  1190  			OrganizationSelfHostedRunners: String("osh"),
  1191  			OrganizationUserBlocking:      String("oub"),
  1192  			Packages:                      String("pkg"),
  1193  			Pages:                         String("pg"),
  1194  			PullRequests:                  String("pr"),
  1195  			RepositoryHooks:               String("rh"),
  1196  			RepositoryProjects:            String("rp"),
  1197  			RepositoryPreReceiveHooks:     String("rprh"),
  1198  			Secrets:                       String("s"),
  1199  			SecretScanningAlerts:          String("ssa"),
  1200  			SecurityEvents:                String("se"),
  1201  			SingleFile:                    String("sf"),
  1202  			Statuses:                      String("s"),
  1203  			TeamDiscussions:               String("td"),
  1204  			VulnerabilityAlerts:           String("va"),
  1205  			Workflows:                     String("w"),
  1206  		},
  1207  		Events: []string{"s"},
  1208  	}
  1209  
  1210  	want := `{
  1211  		"id": 1,
  1212  		"slug": "s",
  1213  		"node_id": "nid",
  1214  		"owner": {
  1215  			"login": "l",
  1216  			"id": 1,
  1217  			"avatar_url": "a",
  1218  			"gravatar_id": "g",
  1219  			"name": "n",
  1220  			"company": "c",
  1221  			"blog": "b",
  1222  			"location": "l",
  1223  			"email": "e",
  1224  			"hireable": true,
  1225  			"bio": "b",
  1226  			"twitter_username": "t",
  1227  			"public_repos": 1,
  1228  			"followers": 1,
  1229  			"following": 1,
  1230  			"created_at": ` + referenceTimeStr + `,
  1231  			"suspended_at": ` + referenceTimeStr + `,
  1232  			"url": "u"
  1233  		},
  1234  		"name": "n",
  1235  		"description": "d",
  1236  		"external_url": "eu",
  1237  		"html_url": "hu",
  1238  		"created_at": ` + referenceTimeStr + `,
  1239  		"updated_at": ` + referenceTimeStr + `,
  1240  		"permissions": {
  1241  			"actions": "a",
  1242  			"administration": "ad",
  1243  			"checks": "c",
  1244  			"contents": "co",
  1245  			"content_references": "cr",
  1246  			"deployments": "d",
  1247  			"environments": "e",
  1248  			"issues": "i",
  1249  			"metadata": "md",
  1250  			"members": "m",
  1251  			"organization_administration": "oa",
  1252  			"organization_hooks": "oh",
  1253  			"organization_plan": "op",
  1254  			"organization_pre_receive_hooks": "opr",
  1255  			"organization_projects": "op",
  1256  			"organization_secrets": "os",
  1257  			"organization_self_hosted_runners": "osh",
  1258  			"organization_user_blocking": "oub",
  1259  			"packages": "pkg",
  1260  			"pages": "pg",
  1261  			"pull_requests": "pr",
  1262  			"repository_hooks": "rh",
  1263  			"repository_projects": "rp",
  1264  			"repository_pre_receive_hooks": "rprh",
  1265  			"secrets": "s",
  1266  			"secret_scanning_alerts": "ssa",
  1267  			"security_events": "se",
  1268  			"single_file": "sf",
  1269  			"statuses": "s",
  1270  			"team_discussions": "td",
  1271  			"vulnerability_alerts": "va",
  1272  			"workflows": "w"
  1273  		},
  1274  		"events": ["s"]
  1275  	}`
  1276  
  1277  	testJSONMarshal(t, u, want)
  1278  }