github.com/google/go-github/v68@v68.0.0/github/orgs_personal_access_tokens_test.go (about)

     1  // Copyright 2023 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 TestOrganizationsService_ListFineGrainedPersonalAccessTokens(t *testing.T) {
    20  	t.Parallel()
    21  	client, mux, _ := setup(t)
    22  
    23  	mux.HandleFunc("/orgs/o/personal-access-tokens", func(w http.ResponseWriter, r *http.Request) {
    24  		testMethod(t, r, "GET")
    25  		expectedQuery := map[string][]string{
    26  			"per_page":  {"2"},
    27  			"page":      {"2"},
    28  			"sort":      {"created_at"},
    29  			"direction": {"desc"},
    30  			"owner[]":   {"octocat", "octodog", "otherbot"},
    31  		}
    32  
    33  		query := r.URL.Query()
    34  		for key, expectedValues := range expectedQuery {
    35  			actualValues := query[key]
    36  			if len(actualValues) != len(expectedValues) {
    37  				t.Errorf("Expected %d values for query param %s, got %d", len(expectedValues), key, len(actualValues))
    38  			}
    39  			for i, expectedValue := range expectedValues {
    40  				if actualValues[i] != expectedValue {
    41  					t.Errorf("Expected query param %s to be %s, got %s", key, expectedValue, actualValues[i])
    42  				}
    43  			}
    44  		}
    45  
    46  		fmt.Fprint(w, `
    47  		[
    48  			{
    49  				"id": 25381,
    50  				"owner": {
    51  					"login": "octocat",
    52  					"id": 1,
    53  					"node_id": "MDQ6VXNlcjE=",
    54  					"avatar_url": "https://github.com/images/error/octocat_happy.gif",
    55  					"gravatar_id": "",
    56  					"url": "https://api.github.com/users/octocat",
    57  					"html_url": "https://github.com/octocat",
    58  					"followers_url": "https://api.github.com/users/octocat/followers",
    59  					"following_url": "https://api.github.com/users/octocat/following{/other_user}",
    60  					"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
    61  					"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
    62  					"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
    63  					"organizations_url": "https://api.github.com/users/octocat/orgs",
    64  					"repos_url": "https://api.github.com/users/octocat/repos",
    65  					"events_url": "https://api.github.com/users/octocat/events{/privacy}",
    66  					"received_events_url": "https://api.github.com/users/octocat/received_events",
    67  					"type": "User",
    68  					"site_admin": false
    69  				},
    70  				"repository_selection": "all",
    71  				"repositories_url": "https://api.github.com/organizations/652551/personal-access-tokens/25381/repositories",
    72  				"permissions": {
    73  					"organization": {
    74  						"members": "read"
    75  					},
    76  					"repository": {
    77  						"metadata": "read"
    78  					}
    79  				},
    80  				"access_granted_at": "2023-05-16T08:47:09.000-07:00",
    81  				"token_expired": false,
    82  				"token_expires_at": "2023-11-16T08:47:09.000-07:00",
    83  				"token_last_used_at": null
    84  			}
    85  		]`)
    86  	})
    87  
    88  	opts := &ListFineGrainedPATOptions{
    89  		ListOptions: ListOptions{Page: 2, PerPage: 2},
    90  		Sort:        "created_at",
    91  		Direction:   "desc",
    92  		Owner:       []string{"octocat", "octodog", "otherbot"},
    93  	}
    94  	ctx := context.Background()
    95  	tokens, resp, err := client.Organizations.ListFineGrainedPersonalAccessTokens(ctx, "o", opts)
    96  	if err != nil {
    97  		t.Errorf("Organizations.ListFineGrainedPersonalAccessTokens returned error: %v", err)
    98  	}
    99  
   100  	want := []*PersonalAccessToken{
   101  		{
   102  			ID: Ptr(int64(25381)),
   103  			Owner: &User{
   104  				Login:             Ptr("octocat"),
   105  				ID:                Ptr(int64(1)),
   106  				NodeID:            Ptr("MDQ6VXNlcjE="),
   107  				AvatarURL:         Ptr("https://github.com/images/error/octocat_happy.gif"),
   108  				GravatarID:        Ptr(""),
   109  				URL:               Ptr("https://api.github.com/users/octocat"),
   110  				HTMLURL:           Ptr("https://github.com/octocat"),
   111  				FollowersURL:      Ptr("https://api.github.com/users/octocat/followers"),
   112  				FollowingURL:      Ptr("https://api.github.com/users/octocat/following{/other_user}"),
   113  				GistsURL:          Ptr("https://api.github.com/users/octocat/gists{/gist_id}"),
   114  				StarredURL:        Ptr("https://api.github.com/users/octocat/starred{/owner}{/repo}"),
   115  				SubscriptionsURL:  Ptr("https://api.github.com/users/octocat/subscriptions"),
   116  				OrganizationsURL:  Ptr("https://api.github.com/users/octocat/orgs"),
   117  				ReposURL:          Ptr("https://api.github.com/users/octocat/repos"),
   118  				EventsURL:         Ptr("https://api.github.com/users/octocat/events{/privacy}"),
   119  				ReceivedEventsURL: Ptr("https://api.github.com/users/octocat/received_events"),
   120  				Type:              Ptr("User"),
   121  				SiteAdmin:         Ptr(false),
   122  			},
   123  			RepositorySelection: Ptr("all"),
   124  			RepositoriesURL:     Ptr("https://api.github.com/organizations/652551/personal-access-tokens/25381/repositories"),
   125  			Permissions: &PersonalAccessTokenPermissions{
   126  				Org:  map[string]string{"members": "read"},
   127  				Repo: map[string]string{"metadata": "read"},
   128  			},
   129  			AccessGrantedAt: &Timestamp{time.Date(2023, time.May, 16, 8, 47, 9, 0, time.FixedZone("PDT", -7*60*60))},
   130  			TokenExpired:    Ptr(false),
   131  			TokenExpiresAt:  &Timestamp{time.Date(2023, time.November, 16, 8, 47, 9, 0, time.FixedZone("PDT", -7*60*60))},
   132  			TokenLastUsedAt: nil,
   133  		},
   134  	}
   135  	if !cmp.Equal(tokens, want) {
   136  		t.Errorf("Organizations.ListFineGrainedPersonalAccessTokens returned %+v, want %+v", tokens, want)
   137  	}
   138  
   139  	if resp == nil {
   140  		t.Error("Organizations.ListFineGrainedPersonalAccessTokens returned nil response")
   141  	}
   142  
   143  	const methodName = "ListFineGrainedPersonalAccessTokens"
   144  	testBadOptions(t, methodName, func() (err error) {
   145  		_, _, err = client.Organizations.ListFineGrainedPersonalAccessTokens(ctx, "\n", opts)
   146  		return err
   147  	})
   148  
   149  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   150  		got, resp, err := client.Organizations.ListFineGrainedPersonalAccessTokens(ctx, "o", opts)
   151  		if got != nil {
   152  			t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
   153  		}
   154  		return resp, err
   155  	})
   156  }
   157  
   158  func TestOrganizationsService_ReviewPersonalAccessTokenRequest(t *testing.T) {
   159  	t.Parallel()
   160  	client, mux, _ := setup(t)
   161  
   162  	input := ReviewPersonalAccessTokenRequestOptions{
   163  		Action: "a",
   164  		Reason: Ptr("r"),
   165  	}
   166  
   167  	mux.HandleFunc("/orgs/o/personal-access-token-requests/1", func(w http.ResponseWriter, r *http.Request) {
   168  		v := new(ReviewPersonalAccessTokenRequestOptions)
   169  		assertNilError(t, json.NewDecoder(r.Body).Decode(v))
   170  
   171  		testMethod(t, r, http.MethodPost)
   172  		if !cmp.Equal(v, &input) {
   173  			t.Errorf("Request body = %+v, want %+v", v, input)
   174  		}
   175  
   176  		w.WriteHeader(http.StatusNoContent)
   177  	})
   178  
   179  	ctx := context.Background()
   180  	res, err := client.Organizations.ReviewPersonalAccessTokenRequest(ctx, "o", 1, input)
   181  	if err != nil {
   182  		t.Errorf("Organizations.ReviewPersonalAccessTokenRequest returned error: %v", err)
   183  	}
   184  
   185  	if res.StatusCode != http.StatusNoContent {
   186  		t.Errorf("Organizations.ReviewPersonalAccessTokenRequest returned %v, want %v", res.StatusCode, http.StatusNoContent)
   187  	}
   188  
   189  	const methodName = "ReviewPersonalAccessTokenRequest"
   190  	testBadOptions(t, methodName, func() (err error) {
   191  		_, err = client.Organizations.ReviewPersonalAccessTokenRequest(ctx, "\n", 0, input)
   192  		return err
   193  	})
   194  
   195  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   196  		return client.Organizations.ReviewPersonalAccessTokenRequest(ctx, "o", 1, input)
   197  	})
   198  }
   199  
   200  func TestReviewPersonalAccessTokenRequestOptions_Marshal(t *testing.T) {
   201  	t.Parallel()
   202  	testJSONMarshal(t, &ReviewPersonalAccessTokenRequestOptions{}, "{}")
   203  
   204  	u := &ReviewPersonalAccessTokenRequestOptions{
   205  		Action: "a",
   206  		Reason: Ptr("r"),
   207  	}
   208  
   209  	want := `{
   210  		"action": "a",
   211  		"reason": "r"
   212  	}`
   213  
   214  	testJSONMarshal(t, u, want)
   215  }