github.com/google/go-github/v74@v74.0.0/github/copilot_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  	"log"
    13  	"net/http"
    14  	"testing"
    15  	"time"
    16  
    17  	"github.com/google/go-cmp/cmp"
    18  )
    19  
    20  // Test invalid JSON responses, valid responses are covered in the other tests.
    21  func TestCopilotSeatDetails_UnmarshalJSON(t *testing.T) {
    22  	t.Parallel()
    23  	tests := []struct {
    24  		name    string
    25  		data    string
    26  		want    *CopilotSeatDetails
    27  		wantErr bool
    28  	}{
    29  		{
    30  			name: "Invalid JSON",
    31  			data: `{`,
    32  			want: &CopilotSeatDetails{
    33  				Assignee: nil,
    34  			},
    35  			wantErr: true,
    36  		},
    37  		{
    38  			name: "Invalid top level type",
    39  			data: `{
    40  					"assignee": {
    41  						"type": "User",
    42  						"name": "octokittens",
    43  						"id": 1
    44  					},
    45  					"assigning_team": "this should be an object"
    46  				}`,
    47  			want:    &CopilotSeatDetails{},
    48  			wantErr: true,
    49  		},
    50  		{
    51  			name: "No Type Field",
    52  			data: `{
    53  					"assignee": {
    54  						"name": "octokittens",
    55  						"id": 1
    56  					}
    57  				}`,
    58  			want:    &CopilotSeatDetails{},
    59  			wantErr: true,
    60  		},
    61  		{
    62  			name: "Null Assignee",
    63  			data: `{
    64  					"assignee": null
    65  				}`,
    66  			want: &CopilotSeatDetails{
    67  				Assignee: nil,
    68  			},
    69  			wantErr: false,
    70  		},
    71  		{
    72  			name: "Invalid Assignee Field Type",
    73  			data: `{
    74  					"assignee": "test"
    75  				}`,
    76  			want:    &CopilotSeatDetails{},
    77  			wantErr: true,
    78  		},
    79  		{
    80  			name: "Invalid Assignee Type",
    81  			data: `{
    82  					"assignee": {
    83  						"name": "octokittens",
    84  						"id": 1,
    85  						"type": []
    86  					}
    87  				}`,
    88  			want:    &CopilotSeatDetails{},
    89  			wantErr: true,
    90  		},
    91  		{
    92  			name: "Invalid User",
    93  			data: `{
    94  					"assignee": {
    95  						"type": "User",
    96  						"id": "bad"
    97  					}
    98  				}`,
    99  			want:    &CopilotSeatDetails{},
   100  			wantErr: true,
   101  		},
   102  		{
   103  			name: "Invalid Team",
   104  			data: `{
   105  					"assignee": {
   106  						"type": "Team",
   107  						"id": "bad"
   108  					}
   109  				}`,
   110  			want:    &CopilotSeatDetails{},
   111  			wantErr: true,
   112  		},
   113  		{
   114  			name: "Invalid Organization",
   115  			data: `{
   116  					"assignee": {
   117  						"type": "Organization",
   118  						"id": "bad"
   119  					}
   120  				}`,
   121  			want:    &CopilotSeatDetails{},
   122  			wantErr: true,
   123  		},
   124  	}
   125  
   126  	for _, tc := range tests {
   127  		seatDetails := &CopilotSeatDetails{}
   128  
   129  		t.Run(tc.name, func(t *testing.T) {
   130  			t.Parallel()
   131  			err := json.Unmarshal([]byte(tc.data), seatDetails)
   132  			if err == nil && tc.wantErr {
   133  				t.Error("CopilotSeatDetails.UnmarshalJSON returned nil instead of an error")
   134  			}
   135  			if err != nil && !tc.wantErr {
   136  				t.Errorf("CopilotSeatDetails.UnmarshalJSON returned an unexpected error: %v", err)
   137  			}
   138  			if !cmp.Equal(tc.want, seatDetails) {
   139  				t.Errorf("CopilotSeatDetails.UnmarshalJSON expected %+v, got %+v", tc.want, seatDetails)
   140  			}
   141  		})
   142  	}
   143  }
   144  
   145  func TestCopilotService_GetSeatDetailsUser(t *testing.T) {
   146  	t.Parallel()
   147  	data := `{
   148  				"assignee": {
   149  					"type": "User",
   150  					"id": 1
   151  				}
   152  			}`
   153  
   154  	seatDetails := &CopilotSeatDetails{}
   155  
   156  	err := json.Unmarshal([]byte(data), seatDetails)
   157  	if err != nil {
   158  		t.Errorf("CopilotSeatDetails.UnmarshalJSON returned an unexpected error: %v", err)
   159  	}
   160  
   161  	want := &User{
   162  		ID:   Ptr(int64(1)),
   163  		Type: Ptr("User"),
   164  	}
   165  
   166  	if got, ok := seatDetails.GetUser(); ok && !cmp.Equal(got, want) {
   167  		t.Errorf("CopilotSeatDetails.GetTeam returned %+v, want %+v", got, want)
   168  	} else if !ok {
   169  		t.Error("CopilotSeatDetails.GetUser returned false, expected true")
   170  	}
   171  
   172  	data = `{
   173  				"assignee": {
   174  					"type": "Organization",
   175  					"id": 1
   176  				}
   177  			}`
   178  
   179  	bad := &Organization{
   180  		ID:   Ptr(int64(1)),
   181  		Type: Ptr("Organization"),
   182  	}
   183  
   184  	err = json.Unmarshal([]byte(data), seatDetails)
   185  	if err != nil {
   186  		t.Errorf("CopilotSeatDetails.UnmarshalJSON returned an unexpected error: %v", err)
   187  	}
   188  
   189  	if got, ok := seatDetails.GetUser(); ok {
   190  		t.Errorf("CopilotSeatDetails.GetUser returned true, expected false. Returned %v, expected %v", got, bad)
   191  	}
   192  }
   193  
   194  func TestCopilotService_GetSeatDetailsTeam(t *testing.T) {
   195  	t.Parallel()
   196  	data := `{
   197  				"assignee": {
   198  					"type": "Team",
   199  					"id": 1
   200  				}
   201  			}`
   202  
   203  	seatDetails := &CopilotSeatDetails{}
   204  
   205  	err := json.Unmarshal([]byte(data), seatDetails)
   206  	if err != nil {
   207  		t.Errorf("CopilotSeatDetails.UnmarshalJSON returned an unexpected error: %v", err)
   208  	}
   209  
   210  	want := &Team{
   211  		ID: Ptr(int64(1)),
   212  	}
   213  
   214  	if got, ok := seatDetails.GetTeam(); ok && !cmp.Equal(got, want) {
   215  		t.Errorf("CopilotSeatDetails.GetTeam returned %+v, want %+v", got, want)
   216  	} else if !ok {
   217  		t.Error("CopilotSeatDetails.GetTeam returned false, expected true")
   218  	}
   219  
   220  	data = `{
   221  				"assignee": {
   222  					"type": "User",
   223  					"id": 1
   224  				}
   225  			}`
   226  
   227  	bad := &User{
   228  		ID:   Ptr(int64(1)),
   229  		Type: Ptr("User"),
   230  	}
   231  
   232  	err = json.Unmarshal([]byte(data), seatDetails)
   233  	if err != nil {
   234  		t.Errorf("CopilotSeatDetails.UnmarshalJSON returned an unexpected error: %v", err)
   235  	}
   236  
   237  	if got, ok := seatDetails.GetTeam(); ok {
   238  		t.Errorf("CopilotSeatDetails.GetTeam returned true, expected false. Returned %v, expected %v", got, bad)
   239  	}
   240  }
   241  
   242  func TestCopilotService_GetSeatDetailsOrganization(t *testing.T) {
   243  	t.Parallel()
   244  	data := `{
   245  				"assignee": {
   246  					"type": "Organization",
   247  					"id": 1
   248  				}
   249  			}`
   250  
   251  	seatDetails := &CopilotSeatDetails{}
   252  
   253  	err := json.Unmarshal([]byte(data), seatDetails)
   254  	if err != nil {
   255  		t.Errorf("CopilotSeatDetails.UnmarshalJSON returned an unexpected error: %v", err)
   256  	}
   257  
   258  	want := &Organization{
   259  		ID:   Ptr(int64(1)),
   260  		Type: Ptr("Organization"),
   261  	}
   262  
   263  	if got, ok := seatDetails.GetOrganization(); ok && !cmp.Equal(got, want) {
   264  		t.Errorf("CopilotSeatDetails.GetOrganization returned %+v, want %+v", got, want)
   265  	} else if !ok {
   266  		t.Error("CopilotSeatDetails.GetOrganization returned false, expected true")
   267  	}
   268  
   269  	data = `{
   270  				"assignee": {
   271  					"type": "Team",
   272  					"id": 1
   273  				}
   274  			}`
   275  
   276  	bad := &Team{
   277  		ID: Ptr(int64(1)),
   278  	}
   279  
   280  	err = json.Unmarshal([]byte(data), seatDetails)
   281  	if err != nil {
   282  		t.Errorf("CopilotSeatDetails.UnmarshalJSON returned an unexpected error: %v", err)
   283  	}
   284  
   285  	if got, ok := seatDetails.GetOrganization(); ok {
   286  		t.Errorf("CopilotSeatDetails.GetOrganization returned true, expected false. Returned %v, expected %v", got, bad)
   287  	}
   288  }
   289  
   290  func TestCopilotService_GetCopilotBilling(t *testing.T) {
   291  	t.Parallel()
   292  	client, mux, _ := setup(t)
   293  
   294  	mux.HandleFunc("/orgs/o/copilot/billing", func(w http.ResponseWriter, r *http.Request) {
   295  		testMethod(t, r, "GET")
   296  		fmt.Fprint(w, `{
   297  			"seat_breakdown": {
   298  				"total": 12,
   299  				"added_this_cycle": 9,
   300  				"pending_invitation": 0,
   301  				"pending_cancellation": 0,
   302  				"active_this_cycle": 12,
   303  				"inactive_this_cycle": 11
   304  			},
   305  			"seat_management_setting": "assign_selected",
   306  			"public_code_suggestions": "block"
   307  			}`)
   308  	})
   309  
   310  	ctx := context.Background()
   311  	got, _, err := client.Copilot.GetCopilotBilling(ctx, "o")
   312  	if err != nil {
   313  		t.Errorf("Copilot.GetCopilotBilling returned error: %v", err)
   314  	}
   315  
   316  	want := &CopilotOrganizationDetails{
   317  		SeatBreakdown: &CopilotSeatBreakdown{
   318  			Total:               12,
   319  			AddedThisCycle:      9,
   320  			PendingInvitation:   0,
   321  			PendingCancellation: 0,
   322  			ActiveThisCycle:     12,
   323  			InactiveThisCycle:   11,
   324  		},
   325  		PublicCodeSuggestions: "block",
   326  		CopilotChat:           "",
   327  		SeatManagementSetting: "assign_selected",
   328  	}
   329  	if !cmp.Equal(got, want) {
   330  		t.Errorf("Copilot.GetCopilotBilling returned %+v, want %+v", got, want)
   331  	}
   332  
   333  	const methodName = "GetCopilotBilling"
   334  
   335  	testBadOptions(t, methodName, func() (err error) {
   336  		_, _, err = client.Copilot.GetCopilotBilling(ctx, "\n")
   337  		return err
   338  	})
   339  
   340  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   341  		got, resp, err := client.Copilot.GetCopilotBilling(ctx, "o")
   342  		if got != nil {
   343  			t.Errorf("Copilot.GetCopilotBilling returned %+v, want nil", got)
   344  		}
   345  		return resp, err
   346  	})
   347  }
   348  
   349  func TestCopilotService_ListCopilotSeats(t *testing.T) {
   350  	t.Parallel()
   351  	client, mux, _ := setup(t)
   352  
   353  	mux.HandleFunc("/orgs/o/copilot/billing/seats", func(w http.ResponseWriter, r *http.Request) {
   354  		testMethod(t, r, "GET")
   355  		testFormValues(t, r, values{
   356  			"per_page": "100",
   357  			"page":     "1",
   358  		})
   359  		fmt.Fprint(w, `{
   360  				"total_seats": 4,
   361  				"seats": [
   362  					{
   363  						"created_at": "2021-08-03T18:00:00-06:00",
   364  						"updated_at": "2021-09-23T15:00:00-06:00",
   365  						"pending_cancellation_date": null,
   366  						"last_activity_at": "2021-10-14T00:53:32-06:00",
   367  						"last_activity_editor": "vscode/1.77.3/copilot/1.86.82",
   368  						"assignee": {
   369  							"login": "octocat",
   370  							"id": 1,
   371  							"node_id": "MDQ6VXNlcjE=",
   372  							"avatar_url": "https://github.com/images/error/octocat_happy.gif",
   373  							"gravatar_id": "",
   374  							"url": "https://api.github.com/users/octocat",
   375  							"html_url": "https://github.com/octocat",
   376  							"followers_url": "https://api.github.com/users/octocat/followers",
   377  							"following_url": "https://api.github.com/users/octocat/following{/other_user}",
   378  							"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
   379  							"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
   380  							"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
   381  							"organizations_url": "https://api.github.com/users/octocat/orgs",
   382  							"repos_url": "https://api.github.com/users/octocat/repos",
   383  							"events_url": "https://api.github.com/users/octocat/events{/privacy}",
   384  							"received_events_url": "https://api.github.com/users/octocat/received_events",
   385  							"type": "User",
   386  							"site_admin": false
   387  						},
   388  						"assigning_team": {
   389  							"id": 1,
   390  							"node_id": "MDQ6VGVhbTE=",
   391  							"url": "https://api.github.com/teams/1",
   392  							"html_url": "https://github.com/orgs/github/teams/justice-league",
   393  							"name": "Justice League",
   394  							"slug": "justice-league",
   395  							"description": "A great team.",
   396  							"privacy": "closed",
   397  							"notification_setting": "notifications_enabled",
   398  							"permission": "admin",
   399  							"members_url": "https://api.github.com/teams/1/members{/member}",
   400  							"repositories_url": "https://api.github.com/teams/1/repos",
   401  							"parent": null
   402  						}
   403  					},
   404  					{
   405  						"created_at": "2021-09-23T18:00:00-06:00",
   406  						"updated_at": "2021-09-23T15:00:00-06:00",
   407  						"pending_cancellation_date": "2021-11-01",
   408  						"last_activity_at": "2021-10-13T00:53:32-06:00",
   409  						"last_activity_editor": "vscode/1.77.3/copilot/1.86.82",
   410  						"assignee": {
   411  							"login": "octokitten",
   412  							"id": 1,
   413  							"node_id": "MDQ76VNlcjE=",
   414  							"avatar_url": "https://github.com/images/error/octokitten_happy.gif",
   415  							"gravatar_id": "",
   416  							"url": "https://api.github.com/users/octokitten",
   417  							"html_url": "https://github.com/octokitten",
   418  							"followers_url": "https://api.github.com/users/octokitten/followers",
   419  							"following_url": "https://api.github.com/users/octokitten/following{/other_user}",
   420  							"gists_url": "https://api.github.com/users/octokitten/gists{/gist_id}",
   421  							"starred_url": "https://api.github.com/users/octokitten/starred{/owner}{/repo}",
   422  							"subscriptions_url": "https://api.github.com/users/octokitten/subscriptions",
   423  							"organizations_url": "https://api.github.com/users/octokitten/orgs",
   424  							"repos_url": "https://api.github.com/users/octokitten/repos",
   425  							"events_url": "https://api.github.com/users/octokitten/events{/privacy}",
   426  							"received_events_url": "https://api.github.com/users/octokitten/received_events",
   427  							"type": "User",
   428  							"site_admin": false
   429  						}
   430  					},
   431  					{
   432  						"created_at": "2021-09-23T18:00:00-06:00",
   433  						"updated_at": "2021-09-23T15:00:00-06:00",
   434  						"pending_cancellation_date": "2021-11-01",
   435  						"last_activity_at": "2021-10-13T00:53:32-06:00",
   436  						"last_activity_editor": "vscode/1.77.3/copilot/1.86.82",
   437  						"assignee": {
   438  							"name": "octokittens",
   439  							"id": 1,
   440  							"type": "Team"
   441  						}
   442  					},
   443  					{
   444  						"created_at": "2021-09-23T18:00:00-06:00",
   445  						"updated_at": "2021-09-23T15:00:00-06:00",
   446  						"pending_cancellation_date": "2021-11-01",
   447  						"last_activity_at": "2021-10-13T00:53:32-06:00",
   448  						"last_activity_editor": "vscode/1.77.3/copilot/1.86.82",
   449  						"assignee": {
   450  							"name": "octocats",
   451  							"id": 1,
   452  							"type": "Organization"
   453  						}
   454  					}
   455  				]
   456  			}`)
   457  	})
   458  
   459  	tmp, err := time.Parse(time.RFC3339, "2021-08-03T18:00:00-06:00")
   460  	if err != nil {
   461  		panic(err)
   462  	}
   463  	createdAt1 := Timestamp{tmp}
   464  
   465  	tmp, err = time.Parse(time.RFC3339, "2021-09-23T15:00:00-06:00")
   466  	if err != nil {
   467  		panic(err)
   468  	}
   469  	updatedAt1 := Timestamp{tmp}
   470  
   471  	tmp, err = time.Parse(time.RFC3339, "2021-10-14T00:53:32-06:00")
   472  	if err != nil {
   473  		panic(err)
   474  	}
   475  	lastActivityAt1 := Timestamp{tmp}
   476  
   477  	tmp, err = time.Parse(time.RFC3339, "2021-09-23T18:00:00-06:00")
   478  	if err != nil {
   479  		panic(err)
   480  	}
   481  	createdAt2 := Timestamp{tmp}
   482  
   483  	tmp, err = time.Parse(time.RFC3339, "2021-09-23T15:00:00-06:00")
   484  	if err != nil {
   485  		panic(err)
   486  	}
   487  	updatedAt2 := Timestamp{tmp}
   488  
   489  	tmp, err = time.Parse(time.RFC3339, "2021-10-13T00:53:32-06:00")
   490  	if err != nil {
   491  		panic(err)
   492  	}
   493  	lastActivityAt2 := Timestamp{tmp}
   494  
   495  	ctx := context.Background()
   496  	opts := &ListOptions{Page: 1, PerPage: 100}
   497  	got, _, err := client.Copilot.ListCopilotSeats(ctx, "o", opts)
   498  	if err != nil {
   499  		t.Errorf("Copilot.ListCopilotSeats returned error: %v", err)
   500  	}
   501  
   502  	want := &ListCopilotSeatsResponse{
   503  		TotalSeats: 4,
   504  		Seats: []*CopilotSeatDetails{
   505  			{
   506  				Assignee: &User{
   507  					Login:             Ptr("octocat"),
   508  					ID:                Ptr(int64(1)),
   509  					NodeID:            Ptr("MDQ6VXNlcjE="),
   510  					AvatarURL:         Ptr("https://github.com/images/error/octocat_happy.gif"),
   511  					GravatarID:        Ptr(""),
   512  					URL:               Ptr("https://api.github.com/users/octocat"),
   513  					HTMLURL:           Ptr("https://github.com/octocat"),
   514  					FollowersURL:      Ptr("https://api.github.com/users/octocat/followers"),
   515  					FollowingURL:      Ptr("https://api.github.com/users/octocat/following{/other_user}"),
   516  					GistsURL:          Ptr("https://api.github.com/users/octocat/gists{/gist_id}"),
   517  					StarredURL:        Ptr("https://api.github.com/users/octocat/starred{/owner}{/repo}"),
   518  					SubscriptionsURL:  Ptr("https://api.github.com/users/octocat/subscriptions"),
   519  					OrganizationsURL:  Ptr("https://api.github.com/users/octocat/orgs"),
   520  					ReposURL:          Ptr("https://api.github.com/users/octocat/repos"),
   521  					EventsURL:         Ptr("https://api.github.com/users/octocat/events{/privacy}"),
   522  					ReceivedEventsURL: Ptr("https://api.github.com/users/octocat/received_events"),
   523  					Type:              Ptr("User"),
   524  					SiteAdmin:         Ptr(false),
   525  				},
   526  				AssigningTeam: &Team{
   527  					ID:                  Ptr(int64(1)),
   528  					NodeID:              Ptr("MDQ6VGVhbTE="),
   529  					URL:                 Ptr("https://api.github.com/teams/1"),
   530  					HTMLURL:             Ptr("https://github.com/orgs/github/teams/justice-league"),
   531  					Name:                Ptr("Justice League"),
   532  					Slug:                Ptr("justice-league"),
   533  					Description:         Ptr("A great team."),
   534  					Privacy:             Ptr("closed"),
   535  					Permission:          Ptr("admin"),
   536  					NotificationSetting: Ptr("notifications_enabled"),
   537  					MembersURL:          Ptr("https://api.github.com/teams/1/members{/member}"),
   538  					RepositoriesURL:     Ptr("https://api.github.com/teams/1/repos"),
   539  					Parent:              nil,
   540  				},
   541  				CreatedAt:               &createdAt1,
   542  				UpdatedAt:               &updatedAt1,
   543  				PendingCancellationDate: nil,
   544  				LastActivityAt:          &lastActivityAt1,
   545  				LastActivityEditor:      Ptr("vscode/1.77.3/copilot/1.86.82"),
   546  			},
   547  			{
   548  				Assignee: &User{
   549  					Login:             Ptr("octokitten"),
   550  					ID:                Ptr(int64(1)),
   551  					NodeID:            Ptr("MDQ76VNlcjE="),
   552  					AvatarURL:         Ptr("https://github.com/images/error/octokitten_happy.gif"),
   553  					GravatarID:        Ptr(""),
   554  					URL:               Ptr("https://api.github.com/users/octokitten"),
   555  					HTMLURL:           Ptr("https://github.com/octokitten"),
   556  					FollowersURL:      Ptr("https://api.github.com/users/octokitten/followers"),
   557  					FollowingURL:      Ptr("https://api.github.com/users/octokitten/following{/other_user}"),
   558  					GistsURL:          Ptr("https://api.github.com/users/octokitten/gists{/gist_id}"),
   559  					StarredURL:        Ptr("https://api.github.com/users/octokitten/starred{/owner}{/repo}"),
   560  					SubscriptionsURL:  Ptr("https://api.github.com/users/octokitten/subscriptions"),
   561  					OrganizationsURL:  Ptr("https://api.github.com/users/octokitten/orgs"),
   562  					ReposURL:          Ptr("https://api.github.com/users/octokitten/repos"),
   563  					EventsURL:         Ptr("https://api.github.com/users/octokitten/events{/privacy}"),
   564  					ReceivedEventsURL: Ptr("https://api.github.com/users/octokitten/received_events"),
   565  					Type:              Ptr("User"),
   566  					SiteAdmin:         Ptr(false),
   567  				},
   568  				AssigningTeam:           nil,
   569  				CreatedAt:               &createdAt2,
   570  				UpdatedAt:               &updatedAt2,
   571  				PendingCancellationDate: Ptr("2021-11-01"),
   572  				LastActivityAt:          &lastActivityAt2,
   573  				LastActivityEditor:      Ptr("vscode/1.77.3/copilot/1.86.82"),
   574  			},
   575  			{
   576  				Assignee: &Team{
   577  					ID:   Ptr(int64(1)),
   578  					Name: Ptr("octokittens"),
   579  				},
   580  				AssigningTeam:           nil,
   581  				CreatedAt:               &createdAt2,
   582  				UpdatedAt:               &updatedAt2,
   583  				PendingCancellationDate: Ptr("2021-11-01"),
   584  				LastActivityAt:          &lastActivityAt2,
   585  				LastActivityEditor:      Ptr("vscode/1.77.3/copilot/1.86.82"),
   586  			},
   587  			{
   588  				Assignee: &Organization{
   589  					ID:   Ptr(int64(1)),
   590  					Name: Ptr("octocats"),
   591  					Type: Ptr("Organization"),
   592  				},
   593  				AssigningTeam:           nil,
   594  				CreatedAt:               &createdAt2,
   595  				UpdatedAt:               &updatedAt2,
   596  				PendingCancellationDate: Ptr("2021-11-01"),
   597  				LastActivityAt:          &lastActivityAt2,
   598  				LastActivityEditor:      Ptr("vscode/1.77.3/copilot/1.86.82"),
   599  			},
   600  		},
   601  	}
   602  
   603  	if !cmp.Equal(got, want) {
   604  		t.Errorf("Copilot.ListCopilotSeats returned %+v, want %+v", got, want)
   605  	}
   606  
   607  	const methodName = "ListCopilotSeats"
   608  
   609  	testBadOptions(t, methodName, func() (err error) {
   610  		_, _, err = client.Copilot.ListCopilotSeats(ctx, "\n", opts)
   611  		return err
   612  	})
   613  
   614  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   615  		got, resp, err := client.Copilot.ListCopilotSeats(ctx, "o", opts)
   616  		if got != nil {
   617  			t.Errorf("Copilot.ListCopilotSeats returned %+v, want nil", got)
   618  		}
   619  		return resp, err
   620  	})
   621  }
   622  
   623  func TestCopilotService_ListCopilotEnterpriseSeats(t *testing.T) {
   624  	t.Parallel()
   625  	client, mux, _ := setup(t)
   626  
   627  	mux.HandleFunc("/enterprises/e/copilot/billing/seats", func(w http.ResponseWriter, r *http.Request) {
   628  		testMethod(t, r, "GET")
   629  		testFormValues(t, r, values{
   630  			"per_page": "100",
   631  			"page":     "1",
   632  		})
   633  		fmt.Fprint(w, `{
   634  			"total_seats": 2,
   635  			"seats": [
   636  				{
   637  					"created_at": "2021-08-03T18:00:00-06:00",
   638  					"updated_at": "2021-09-23T15:00:00-06:00",
   639  					"pending_cancellation_date": null,
   640  					"last_activity_at": "2021-10-14T00:53:32-06:00",
   641  					"last_activity_editor": "vscode/1.77.3/copilot/1.86.82",
   642  					"plan_type": "business",
   643  					"assignee": {
   644  						"login": "octocat",
   645  						"id": 1,
   646  						"node_id": "MDQ6VXNlcjE=",
   647  						"avatar_url": "https://github.com/images/error/octocat_happy.gif",
   648  						"gravatar_id": "",
   649  						"url": "https://api.github.com/users/octocat",
   650  						"html_url": "https://github.com/octocat",
   651  						"followers_url": "https://api.github.com/users/octocat/followers",
   652  						"following_url": "https://api.github.com/users/octocat/following{/other_user}",
   653  						"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
   654  						"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
   655  						"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
   656  						"organizations_url": "https://api.github.com/users/octocat/orgs",
   657  						"repos_url": "https://api.github.com/users/octocat/repos",
   658  						"events_url": "https://api.github.com/users/octocat/events{/privacy}",
   659  						"received_events_url": "https://api.github.com/users/octocat/received_events",
   660  						"type": "User",
   661  						"site_admin": false
   662  					},
   663  					"assigning_team": {
   664  						"id": 1,
   665  						"node_id": "MDQ6VGVhbTE=",
   666  						"url": "https://api.github.com/teams/1",
   667  						"html_url": "https://github.com/orgs/github/teams/justice-league",
   668  						"name": "Justice League",
   669  						"slug": "justice-league",
   670  						"description": "A great team.",
   671  						"privacy": "closed",
   672  						"notification_setting": "notifications_enabled",
   673  						"permission": "admin",
   674  						"members_url": "https://api.github.com/teams/1/members{/member}",
   675  						"repositories_url": "https://api.github.com/teams/1/repos",
   676  						"parent": null
   677  					}
   678  				},
   679  				{
   680  					"created_at": "2021-09-23T18:00:00-06:00",
   681  					"updated_at": "2021-09-23T15:00:00-06:00",
   682  					"pending_cancellation_date": "2021-11-01",
   683  					"last_activity_at": "2021-10-13T00:53:32-06:00",
   684  					"last_activity_editor": "vscode/1.77.3/copilot/1.86.82",
   685  					"assignee": {
   686  						"login": "octokitten",
   687  						"id": 1,
   688  						"node_id": "MDQ76VNlcjE=",
   689  						"avatar_url": "https://github.com/images/error/octokitten_happy.gif",
   690  						"gravatar_id": "",
   691  						"url": "https://api.github.com/users/octokitten",
   692  						"html_url": "https://github.com/octokitten",
   693  						"followers_url": "https://api.github.com/users/octokitten/followers",
   694  						"following_url": "https://api.github.com/users/octokitten/following{/other_user}",
   695  						"gists_url": "https://api.github.com/users/octokitten/gists{/gist_id}",
   696  						"starred_url": "https://api.github.com/users/octokitten/starred{/owner}{/repo}",
   697  						"subscriptions_url": "https://api.github.com/users/octokitten/subscriptions",
   698  						"organizations_url": "https://api.github.com/users/octokitten/orgs",
   699  						"repos_url": "https://api.github.com/users/octokitten/repos",
   700  						"events_url": "https://api.github.com/users/octokitten/events{/privacy}",
   701  						"received_events_url": "https://api.github.com/users/octokitten/received_events",
   702  						"type": "User",
   703  						"site_admin": false
   704  					}
   705  				}
   706  			]
   707  		}`)
   708  	})
   709  
   710  	tmp, err := time.Parse(time.RFC3339, "2021-08-03T18:00:00-06:00")
   711  	if err != nil {
   712  		panic(err)
   713  	}
   714  	createdAt1 := Timestamp{tmp}
   715  
   716  	tmp, err = time.Parse(time.RFC3339, "2021-09-23T15:00:00-06:00")
   717  	if err != nil {
   718  		panic(err)
   719  	}
   720  	updatedAt1 := Timestamp{tmp}
   721  
   722  	tmp, err = time.Parse(time.RFC3339, "2021-10-14T00:53:32-06:00")
   723  	if err != nil {
   724  		panic(err)
   725  	}
   726  	lastActivityAt1 := Timestamp{tmp}
   727  
   728  	tmp, err = time.Parse(time.RFC3339, "2021-09-23T18:00:00-06:00")
   729  	if err != nil {
   730  		panic(err)
   731  	}
   732  	createdAt2 := Timestamp{tmp}
   733  
   734  	tmp, err = time.Parse(time.RFC3339, "2021-09-23T15:00:00-06:00")
   735  	if err != nil {
   736  		panic(err)
   737  	}
   738  	updatedAt2 := Timestamp{tmp}
   739  
   740  	tmp, err = time.Parse(time.RFC3339, "2021-10-13T00:53:32-06:00")
   741  	if err != nil {
   742  		panic(err)
   743  	}
   744  	lastActivityAt2 := Timestamp{tmp}
   745  
   746  	ctx := context.Background()
   747  	opts := &ListOptions{Page: 1, PerPage: 100}
   748  	got, _, err := client.Copilot.ListCopilotEnterpriseSeats(ctx, "e", opts)
   749  	if err != nil {
   750  		t.Errorf("Copilot.ListCopilotEnterpriseSeats returned error: %v", err)
   751  	}
   752  
   753  	want := &ListCopilotSeatsResponse{
   754  		TotalSeats: 2,
   755  		Seats: []*CopilotSeatDetails{
   756  			{
   757  				Assignee: &User{
   758  					Login:             Ptr("octocat"),
   759  					ID:                Ptr(int64(1)),
   760  					NodeID:            Ptr("MDQ6VXNlcjE="),
   761  					AvatarURL:         Ptr("https://github.com/images/error/octocat_happy.gif"),
   762  					GravatarID:        Ptr(""),
   763  					URL:               Ptr("https://api.github.com/users/octocat"),
   764  					HTMLURL:           Ptr("https://github.com/octocat"),
   765  					FollowersURL:      Ptr("https://api.github.com/users/octocat/followers"),
   766  					FollowingURL:      Ptr("https://api.github.com/users/octocat/following{/other_user}"),
   767  					GistsURL:          Ptr("https://api.github.com/users/octocat/gists{/gist_id}"),
   768  					StarredURL:        Ptr("https://api.github.com/users/octocat/starred{/owner}{/repo}"),
   769  					SubscriptionsURL:  Ptr("https://api.github.com/users/octocat/subscriptions"),
   770  					OrganizationsURL:  Ptr("https://api.github.com/users/octocat/orgs"),
   771  					ReposURL:          Ptr("https://api.github.com/users/octocat/repos"),
   772  					EventsURL:         Ptr("https://api.github.com/users/octocat/events{/privacy}"),
   773  					ReceivedEventsURL: Ptr("https://api.github.com/users/octocat/received_events"),
   774  					Type:              Ptr("User"),
   775  					SiteAdmin:         Ptr(false),
   776  				},
   777  				AssigningTeam: &Team{
   778  					ID:                  Ptr(int64(1)),
   779  					NodeID:              Ptr("MDQ6VGVhbTE="),
   780  					URL:                 Ptr("https://api.github.com/teams/1"),
   781  					HTMLURL:             Ptr("https://github.com/orgs/github/teams/justice-league"),
   782  					Name:                Ptr("Justice League"),
   783  					Slug:                Ptr("justice-league"),
   784  					Description:         Ptr("A great team."),
   785  					Privacy:             Ptr("closed"),
   786  					NotificationSetting: Ptr("notifications_enabled"),
   787  					Permission:          Ptr("admin"),
   788  					MembersURL:          Ptr("https://api.github.com/teams/1/members{/member}"),
   789  					RepositoriesURL:     Ptr("https://api.github.com/teams/1/repos"),
   790  					Parent:              nil,
   791  				},
   792  				CreatedAt:               &createdAt1,
   793  				UpdatedAt:               &updatedAt1,
   794  				PendingCancellationDate: nil,
   795  				LastActivityAt:          &lastActivityAt1,
   796  				LastActivityEditor:      Ptr("vscode/1.77.3/copilot/1.86.82"),
   797  				PlanType:                Ptr("business"),
   798  			},
   799  			{
   800  				Assignee: &User{
   801  					Login:             Ptr("octokitten"),
   802  					ID:                Ptr(int64(1)),
   803  					NodeID:            Ptr("MDQ76VNlcjE="),
   804  					AvatarURL:         Ptr("https://github.com/images/error/octokitten_happy.gif"),
   805  					GravatarID:        Ptr(""),
   806  					URL:               Ptr("https://api.github.com/users/octokitten"),
   807  					HTMLURL:           Ptr("https://github.com/octokitten"),
   808  					FollowersURL:      Ptr("https://api.github.com/users/octokitten/followers"),
   809  					FollowingURL:      Ptr("https://api.github.com/users/octokitten/following{/other_user}"),
   810  					GistsURL:          Ptr("https://api.github.com/users/octokitten/gists{/gist_id}"),
   811  					StarredURL:        Ptr("https://api.github.com/users/octokitten/starred{/owner}{/repo}"),
   812  					SubscriptionsURL:  Ptr("https://api.github.com/users/octokitten/subscriptions"),
   813  					OrganizationsURL:  Ptr("https://api.github.com/users/octokitten/orgs"),
   814  					ReposURL:          Ptr("https://api.github.com/users/octokitten/repos"),
   815  					EventsURL:         Ptr("https://api.github.com/users/octokitten/events{/privacy}"),
   816  					ReceivedEventsURL: Ptr("https://api.github.com/users/octokitten/received_events"),
   817  					Type:              Ptr("User"),
   818  					SiteAdmin:         Ptr(false),
   819  				},
   820  				AssigningTeam:           nil,
   821  				CreatedAt:               &createdAt2,
   822  				UpdatedAt:               &updatedAt2,
   823  				PendingCancellationDate: Ptr("2021-11-01"),
   824  				LastActivityAt:          &lastActivityAt2,
   825  				LastActivityEditor:      Ptr("vscode/1.77.3/copilot/1.86.82"),
   826  				PlanType:                nil,
   827  			},
   828  		},
   829  	}
   830  
   831  	if !cmp.Equal(got, want) {
   832  		log.Printf("got: %+v", got.Seats[1])
   833  		log.Printf("want: %+v", want.Seats[1])
   834  		t.Errorf("Copilot.ListCopilotEnterpriseSeats returned %+v, want %+v", got, want)
   835  	}
   836  
   837  	const methodName = "ListCopilotEnterpriseSeats"
   838  
   839  	testBadOptions(t, methodName, func() (err error) {
   840  		_, _, err = client.Copilot.ListCopilotEnterpriseSeats(ctx, "\n", opts)
   841  		return err
   842  	})
   843  
   844  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   845  		got, resp, err := client.Copilot.ListCopilotEnterpriseSeats(ctx, "e", opts)
   846  		if got != nil {
   847  			t.Errorf("Copilot.ListCopilotEnterpriseSeats returned %+v, want nil", got)
   848  		}
   849  		return resp, err
   850  	})
   851  }
   852  
   853  func TestCopilotService_AddCopilotTeams(t *testing.T) {
   854  	t.Parallel()
   855  	client, mux, _ := setup(t)
   856  
   857  	mux.HandleFunc("/orgs/o/copilot/billing/selected_teams", func(w http.ResponseWriter, r *http.Request) {
   858  		testMethod(t, r, "POST")
   859  		testBody(t, r, `{"selected_teams":["team1","team2"]}`+"\n")
   860  		fmt.Fprint(w, `{"seats_created": 2}`)
   861  	})
   862  
   863  	ctx := context.Background()
   864  	got, _, err := client.Copilot.AddCopilotTeams(ctx, "o", []string{"team1", "team2"})
   865  	if err != nil {
   866  		t.Errorf("Copilot.AddCopilotTeams returned error: %v", err)
   867  	}
   868  
   869  	want := &SeatAssignments{SeatsCreated: 2}
   870  
   871  	if !cmp.Equal(got, want) {
   872  		t.Errorf("Copilot.AddCopilotTeams returned %+v, want %+v", got, want)
   873  	}
   874  
   875  	const methodName = "AddCopilotTeams"
   876  
   877  	testBadOptions(t, methodName, func() (err error) {
   878  		_, _, err = client.Copilot.AddCopilotTeams(ctx, "\n", []string{"team1", "team2"})
   879  		return err
   880  	})
   881  
   882  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   883  		got, resp, err := client.Copilot.AddCopilotTeams(ctx, "o", []string{"team1", "team2"})
   884  		if got != nil {
   885  			t.Errorf("Copilot.AddCopilotTeams returned %+v, want nil", got)
   886  		}
   887  		return resp, err
   888  	})
   889  }
   890  
   891  func TestCopilotService_RemoveCopilotTeams(t *testing.T) {
   892  	t.Parallel()
   893  	client, mux, _ := setup(t)
   894  
   895  	mux.HandleFunc("/orgs/o/copilot/billing/selected_teams", func(w http.ResponseWriter, r *http.Request) {
   896  		testMethod(t, r, "DELETE")
   897  		testBody(t, r, `{"selected_teams":["team1","team2"]}`+"\n")
   898  		fmt.Fprint(w, `{"seats_cancelled": 2}`)
   899  	})
   900  
   901  	ctx := context.Background()
   902  	got, _, err := client.Copilot.RemoveCopilotTeams(ctx, "o", []string{"team1", "team2"})
   903  	if err != nil {
   904  		t.Errorf("Copilot.RemoveCopilotTeams returned error: %v", err)
   905  	}
   906  
   907  	want := &SeatCancellations{SeatsCancelled: 2}
   908  
   909  	if !cmp.Equal(got, want) {
   910  		t.Errorf("Copilot.RemoveCopilotTeams returned %+v, want %+v", got, want)
   911  	}
   912  
   913  	const methodName = "RemoveCopilotTeams"
   914  
   915  	testBadOptions(t, methodName, func() (err error) {
   916  		_, _, err = client.Copilot.RemoveCopilotTeams(ctx, "\n", []string{"team1", "team2"})
   917  		return err
   918  	})
   919  
   920  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   921  		got, resp, err := client.Copilot.RemoveCopilotTeams(ctx, "o", []string{"team1", "team2"})
   922  		if got != nil {
   923  			t.Errorf("Copilot.RemoveCopilotTeams returned %+v, want nil", got)
   924  		}
   925  		return resp, err
   926  	})
   927  }
   928  
   929  func TestCopilotService_AddCopilotUsers(t *testing.T) {
   930  	t.Parallel()
   931  	client, mux, _ := setup(t)
   932  
   933  	mux.HandleFunc("/orgs/o/copilot/billing/selected_users", func(w http.ResponseWriter, r *http.Request) {
   934  		testMethod(t, r, "POST")
   935  		testBody(t, r, `{"selected_usernames":["user1","user2"]}`+"\n")
   936  		fmt.Fprint(w, `{"seats_created": 2}`)
   937  	})
   938  
   939  	ctx := context.Background()
   940  	got, _, err := client.Copilot.AddCopilotUsers(ctx, "o", []string{"user1", "user2"})
   941  	if err != nil {
   942  		t.Errorf("Copilot.AddCopilotUsers returned error: %v", err)
   943  	}
   944  
   945  	want := &SeatAssignments{SeatsCreated: 2}
   946  
   947  	if !cmp.Equal(got, want) {
   948  		t.Errorf("Copilot.AddCopilotUsers returned %+v, want %+v", got, want)
   949  	}
   950  
   951  	const methodName = "AddCopilotUsers"
   952  
   953  	testBadOptions(t, methodName, func() (err error) {
   954  		_, _, err = client.Copilot.AddCopilotUsers(ctx, "\n", []string{"user1", "user2"})
   955  		return err
   956  	})
   957  
   958  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   959  		got, resp, err := client.Copilot.AddCopilotUsers(ctx, "o", []string{"user1", "user2"})
   960  		if got != nil {
   961  			t.Errorf("Copilot.AddCopilotUsers returned %+v, want nil", got)
   962  		}
   963  		return resp, err
   964  	})
   965  }
   966  
   967  func TestCopilotService_RemoveCopilotUsers(t *testing.T) {
   968  	t.Parallel()
   969  	client, mux, _ := setup(t)
   970  
   971  	mux.HandleFunc("/orgs/o/copilot/billing/selected_users", func(w http.ResponseWriter, r *http.Request) {
   972  		testMethod(t, r, "DELETE")
   973  		testBody(t, r, `{"selected_usernames":["user1","user2"]}`+"\n")
   974  		fmt.Fprint(w, `{"seats_cancelled": 2}`)
   975  	})
   976  
   977  	ctx := context.Background()
   978  	got, _, err := client.Copilot.RemoveCopilotUsers(ctx, "o", []string{"user1", "user2"})
   979  	if err != nil {
   980  		t.Errorf("Copilot.RemoveCopilotUsers returned error: %v", err)
   981  	}
   982  
   983  	want := &SeatCancellations{SeatsCancelled: 2}
   984  
   985  	if !cmp.Equal(got, want) {
   986  		t.Errorf("Copilot.RemoveCopilotUsers returned %+v, want %+v", got, want)
   987  	}
   988  
   989  	const methodName = "RemoveCopilotUsers"
   990  
   991  	testBadOptions(t, methodName, func() (err error) {
   992  		_, _, err = client.Copilot.RemoveCopilotUsers(ctx, "\n", []string{"user1", "user2"})
   993  		return err
   994  	})
   995  
   996  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
   997  		got, resp, err := client.Copilot.RemoveCopilotUsers(ctx, "o", []string{"user1", "user2"})
   998  		if got != nil {
   999  			t.Errorf("Copilot.RemoveCopilotUsers returned %+v, want nil", got)
  1000  		}
  1001  		return resp, err
  1002  	})
  1003  }
  1004  
  1005  func TestCopilotService_GetSeatDetails(t *testing.T) {
  1006  	t.Parallel()
  1007  	client, mux, _ := setup(t)
  1008  
  1009  	mux.HandleFunc("/orgs/o/members/u/copilot", func(w http.ResponseWriter, r *http.Request) {
  1010  		testMethod(t, r, "GET")
  1011  		fmt.Fprint(w, `{
  1012  				"created_at": "2021-08-03T18:00:00-06:00",
  1013  				"updated_at": "2021-09-23T15:00:00-06:00",
  1014  				"pending_cancellation_date": null,
  1015  				"last_activity_at": "2021-10-14T00:53:32-06:00",
  1016  				"last_activity_editor": "vscode/1.77.3/copilot/1.86.82",
  1017  				"assignee": {
  1018  					"login": "octocat",
  1019  					"id": 1,
  1020  					"node_id": "MDQ6VXNlcjE=",
  1021  					"avatar_url": "https://github.com/images/error/octocat_happy.gif",
  1022  					"gravatar_id": "",
  1023  					"url": "https://api.github.com/users/octocat",
  1024  					"html_url": "https://github.com/octocat",
  1025  					"followers_url": "https://api.github.com/users/octocat/followers",
  1026  					"following_url": "https://api.github.com/users/octocat/following{/other_user}",
  1027  					"gists_url": "https://api.github.com/users/octocat/gists{/gist_id}",
  1028  					"starred_url": "https://api.github.com/users/octocat/starred{/owner}{/repo}",
  1029  					"subscriptions_url": "https://api.github.com/users/octocat/subscriptions",
  1030  					"organizations_url": "https://api.github.com/users/octocat/orgs",
  1031  					"repos_url": "https://api.github.com/users/octocat/repos",
  1032  					"events_url": "https://api.github.com/users/octocat/events{/privacy}",
  1033  					"received_events_url": "https://api.github.com/users/octocat/received_events",
  1034  					"type": "User",
  1035  					"site_admin": false
  1036  				},
  1037  				"assigning_team": {
  1038  					"id": 1,
  1039  					"node_id": "MDQ6VGVhbTE=",
  1040  					"url": "https://api.github.com/teams/1",
  1041  					"html_url": "https://github.com/orgs/github/teams/justice-league",
  1042  					"name": "Justice League",
  1043  					"slug": "justice-league",
  1044  					"description": "A great team.",
  1045  					"privacy": "closed",
  1046  					"notification_setting": "notifications_enabled",
  1047  					"permission": "admin",
  1048  					"members_url": "https://api.github.com/teams/1/members{/member}",
  1049  					"repositories_url": "https://api.github.com/teams/1/repos",
  1050  					"parent": null
  1051  				}
  1052  			}`)
  1053  	})
  1054  
  1055  	tmp, err := time.Parse(time.RFC3339, "2021-08-03T18:00:00-06:00")
  1056  	if err != nil {
  1057  		panic(err)
  1058  	}
  1059  	createdAt := Timestamp{tmp}
  1060  
  1061  	tmp, err = time.Parse(time.RFC3339, "2021-09-23T15:00:00-06:00")
  1062  	if err != nil {
  1063  		panic(err)
  1064  	}
  1065  	updatedAt := Timestamp{tmp}
  1066  
  1067  	tmp, err = time.Parse(time.RFC3339, "2021-10-14T00:53:32-06:00")
  1068  	if err != nil {
  1069  		panic(err)
  1070  	}
  1071  	lastActivityAt := Timestamp{tmp}
  1072  
  1073  	ctx := context.Background()
  1074  	got, _, err := client.Copilot.GetSeatDetails(ctx, "o", "u")
  1075  	if err != nil {
  1076  		t.Errorf("Copilot.GetSeatDetails returned error: %v", err)
  1077  	}
  1078  
  1079  	want := &CopilotSeatDetails{
  1080  		Assignee: &User{
  1081  			Login:             Ptr("octocat"),
  1082  			ID:                Ptr(int64(1)),
  1083  			NodeID:            Ptr("MDQ6VXNlcjE="),
  1084  			AvatarURL:         Ptr("https://github.com/images/error/octocat_happy.gif"),
  1085  			GravatarID:        Ptr(""),
  1086  			URL:               Ptr("https://api.github.com/users/octocat"),
  1087  			HTMLURL:           Ptr("https://github.com/octocat"),
  1088  			FollowersURL:      Ptr("https://api.github.com/users/octocat/followers"),
  1089  			FollowingURL:      Ptr("https://api.github.com/users/octocat/following{/other_user}"),
  1090  			GistsURL:          Ptr("https://api.github.com/users/octocat/gists{/gist_id}"),
  1091  			StarredURL:        Ptr("https://api.github.com/users/octocat/starred{/owner}{/repo}"),
  1092  			SubscriptionsURL:  Ptr("https://api.github.com/users/octocat/subscriptions"),
  1093  			OrganizationsURL:  Ptr("https://api.github.com/users/octocat/orgs"),
  1094  			ReposURL:          Ptr("https://api.github.com/users/octocat/repos"),
  1095  			EventsURL:         Ptr("https://api.github.com/users/octocat/events{/privacy}"),
  1096  			ReceivedEventsURL: Ptr("https://api.github.com/users/octocat/received_events"),
  1097  			Type:              Ptr("User"),
  1098  			SiteAdmin:         Ptr(false),
  1099  		},
  1100  		AssigningTeam: &Team{
  1101  			ID:                  Ptr(int64(1)),
  1102  			NodeID:              Ptr("MDQ6VGVhbTE="),
  1103  			URL:                 Ptr("https://api.github.com/teams/1"),
  1104  			HTMLURL:             Ptr("https://github.com/orgs/github/teams/justice-league"),
  1105  			Name:                Ptr("Justice League"),
  1106  			Slug:                Ptr("justice-league"),
  1107  			Description:         Ptr("A great team."),
  1108  			Privacy:             Ptr("closed"),
  1109  			NotificationSetting: Ptr("notifications_enabled"),
  1110  			Permission:          Ptr("admin"),
  1111  			MembersURL:          Ptr("https://api.github.com/teams/1/members{/member}"),
  1112  			RepositoriesURL:     Ptr("https://api.github.com/teams/1/repos"),
  1113  			Parent:              nil,
  1114  		},
  1115  		CreatedAt:               &createdAt,
  1116  		UpdatedAt:               &updatedAt,
  1117  		PendingCancellationDate: nil,
  1118  		LastActivityAt:          &lastActivityAt,
  1119  		LastActivityEditor:      Ptr("vscode/1.77.3/copilot/1.86.82"),
  1120  	}
  1121  
  1122  	if !cmp.Equal(got, want) {
  1123  		t.Errorf("Copilot.GetSeatDetails returned %+v, want %+v", got, want)
  1124  	}
  1125  
  1126  	const methodName = "GetSeatDetails"
  1127  
  1128  	testBadOptions(t, methodName, func() (err error) {
  1129  		_, _, err = client.Copilot.GetSeatDetails(ctx, "\n", "u")
  1130  		return err
  1131  	})
  1132  
  1133  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  1134  		got, resp, err := client.Copilot.GetSeatDetails(ctx, "o", "u")
  1135  		if got != nil {
  1136  			t.Errorf("Copilot.GetSeatDetails returned %+v, want nil", got)
  1137  		}
  1138  		return resp, err
  1139  	})
  1140  }
  1141  
  1142  func TestCopilotService_GetEnterpriseMetrics(t *testing.T) {
  1143  	t.Parallel()
  1144  	client, mux, _ := setup(t)
  1145  
  1146  	mux.HandleFunc("/enterprises/e/copilot/metrics", func(w http.ResponseWriter, r *http.Request) {
  1147  		testMethod(t, r, "GET")
  1148  		fmt.Fprint(w, `[
  1149  			{
  1150  				"date": "2024-06-24",
  1151  				"total_active_users": 24,
  1152  				"total_engaged_users": 20,
  1153  				"copilot_ide_code_completions": {
  1154  				"total_engaged_users": 20,
  1155  				"languages": [
  1156  					{
  1157  					"name": "python",
  1158  					"total_engaged_users": 10
  1159  					},
  1160  					{
  1161  					"name": "ruby",
  1162  					"total_engaged_users": 10
  1163  					}
  1164  				],
  1165  				"editors": [
  1166  					{
  1167  					"name": "vscode",
  1168  					"total_engaged_users": 13,
  1169  					"models": [
  1170  						{
  1171  						"name": "default",
  1172  						"is_custom_model": false,
  1173  						"custom_model_training_date": null,
  1174  						"total_engaged_users": 13,
  1175  						"languages": [
  1176  							{
  1177  							"name": "python",
  1178  							"total_engaged_users": 6,
  1179  							"total_code_suggestions": 249,
  1180  							"total_code_acceptances": 123,
  1181  							"total_code_lines_suggested": 225,
  1182  							"total_code_lines_accepted": 135
  1183  							},
  1184  							{
  1185  							"name": "ruby",
  1186  							"total_engaged_users": 7,
  1187  							"total_code_suggestions": 496,
  1188  							"total_code_acceptances": 253,
  1189  							"total_code_lines_suggested": 520,
  1190  							"total_code_lines_accepted": 270
  1191  							}
  1192  						]
  1193  						}
  1194  					]
  1195  					},
  1196  					{
  1197  					"name": "neovim",
  1198  					"total_engaged_users": 7,
  1199  					"models": [
  1200  						{
  1201  						"name": "a-custom-model",
  1202  						"is_custom_model": true,
  1203  						"custom_model_training_date": "2024-02-01",
  1204  						"languages": [
  1205  							{
  1206  							"name": "typescript",
  1207  							"total_engaged_users": 3,
  1208  							"total_code_suggestions": 112,
  1209  							"total_code_acceptances": 56,
  1210  							"total_code_lines_suggested": 143,
  1211  							"total_code_lines_accepted": 61
  1212  							},
  1213  							{
  1214  							"name": "go",
  1215  							"total_engaged_users": 4,
  1216  							"total_code_suggestions": 132,
  1217  							"total_code_acceptances": 67,
  1218  							"total_code_lines_suggested": 154,
  1219  							"total_code_lines_accepted": 72
  1220  							}
  1221  						]
  1222  						}
  1223  					]
  1224  					}
  1225  				]
  1226  				},
  1227  				"copilot_ide_chat": {
  1228  				"total_engaged_users": 13,
  1229  				"editors": [
  1230  					{
  1231  					"name": "vscode",
  1232  					"total_engaged_users": 13,
  1233  					"models": [
  1234  						{
  1235  						"name": "default",
  1236  						"is_custom_model": false,
  1237  						"custom_model_training_date": null,
  1238  						"total_engaged_users": 12,
  1239  						"total_chats": 45,
  1240  						"total_chat_insertion_events": 12,
  1241  						"total_chat_copy_events": 16
  1242  						},
  1243  						{
  1244  						"name": "a-custom-model",
  1245  						"is_custom_model": true,
  1246  						"custom_model_training_date": "2024-02-01",
  1247  						"total_engaged_users": 1,
  1248  						"total_chats": 10,
  1249  						"total_chat_insertion_events": 11,
  1250  						"total_chat_copy_events": 3
  1251  						}
  1252  					]
  1253  					}
  1254  				]
  1255  				},
  1256  				"copilot_dotcom_chat": {
  1257  				"total_engaged_users": 14,
  1258  				"models": [
  1259  					{
  1260  					"name": "default",
  1261  					"is_custom_model": false,
  1262  					"custom_model_training_date": null,
  1263  					"total_engaged_users": 14,
  1264  					"total_chats": 38
  1265  					}
  1266  				]
  1267  				},
  1268  				"copilot_dotcom_pull_requests": {
  1269  				"total_engaged_users": 12,
  1270  				"repositories": [
  1271  					{
  1272  					"name": "demo/repo1",
  1273  					"total_engaged_users": 8,
  1274  					"models": [
  1275  						{
  1276  						"name": "default",
  1277  						"is_custom_model": false,
  1278  						"custom_model_training_date": null,
  1279  						"total_pr_summaries_created": 6,
  1280  						"total_engaged_users": 8
  1281  						}
  1282  					]
  1283  					},
  1284  					{
  1285  					"name": "demo/repo2",
  1286  					"total_engaged_users": 4,
  1287  					"models": [
  1288  						{
  1289  						"name": "a-custom-model",
  1290  						"is_custom_model": true,
  1291  						"custom_model_training_date": "2024-02-01",
  1292  						"total_pr_summaries_created": 10,
  1293  						"total_engaged_users": 4
  1294  						}
  1295  					]
  1296  					}
  1297  				]
  1298  				}
  1299  			}
  1300  		]`)
  1301  	})
  1302  
  1303  	ctx := context.Background()
  1304  	got, _, err := client.Copilot.GetEnterpriseMetrics(ctx, "e", &CopilotMetricsListOptions{})
  1305  	if err != nil {
  1306  		t.Errorf("Copilot.GetEnterpriseMetrics returned error: %v", err)
  1307  	}
  1308  
  1309  	totalActiveUsers := 24
  1310  	totalEngagedUsers := 20
  1311  	want := []*CopilotMetrics{
  1312  		{
  1313  			Date:              "2024-06-24",
  1314  			TotalActiveUsers:  &totalActiveUsers,
  1315  			TotalEngagedUsers: &totalEngagedUsers,
  1316  			CopilotIDECodeCompletions: &CopilotIDECodeCompletions{
  1317  				TotalEngagedUsers: 20,
  1318  				Languages: []*CopilotIDECodeCompletionsLanguage{
  1319  					{
  1320  						Name:              "python",
  1321  						TotalEngagedUsers: 10,
  1322  					},
  1323  					{
  1324  						Name:              "ruby",
  1325  						TotalEngagedUsers: 10,
  1326  					},
  1327  				},
  1328  				Editors: []*CopilotIDECodeCompletionsEditor{
  1329  					{
  1330  						Name:              "vscode",
  1331  						TotalEngagedUsers: 13,
  1332  						Models: []*CopilotIDECodeCompletionsModel{
  1333  							{
  1334  								Name:                    "default",
  1335  								IsCustomModel:           false,
  1336  								CustomModelTrainingDate: nil,
  1337  								TotalEngagedUsers:       13,
  1338  								Languages: []*CopilotIDECodeCompletionsModelLanguage{
  1339  									{
  1340  										Name:                    "python",
  1341  										TotalEngagedUsers:       6,
  1342  										TotalCodeSuggestions:    249,
  1343  										TotalCodeAcceptances:    123,
  1344  										TotalCodeLinesSuggested: 225,
  1345  										TotalCodeLinesAccepted:  135,
  1346  									},
  1347  									{
  1348  										Name:                    "ruby",
  1349  										TotalEngagedUsers:       7,
  1350  										TotalCodeSuggestions:    496,
  1351  										TotalCodeAcceptances:    253,
  1352  										TotalCodeLinesSuggested: 520,
  1353  										TotalCodeLinesAccepted:  270,
  1354  									},
  1355  								},
  1356  							},
  1357  						},
  1358  					},
  1359  					{
  1360  						Name:              "neovim",
  1361  						TotalEngagedUsers: 7,
  1362  						Models: []*CopilotIDECodeCompletionsModel{
  1363  							{
  1364  								Name:                    "a-custom-model",
  1365  								IsCustomModel:           true,
  1366  								CustomModelTrainingDate: Ptr("2024-02-01"),
  1367  								Languages: []*CopilotIDECodeCompletionsModelLanguage{
  1368  									{
  1369  										Name:                    "typescript",
  1370  										TotalEngagedUsers:       3,
  1371  										TotalCodeSuggestions:    112,
  1372  										TotalCodeAcceptances:    56,
  1373  										TotalCodeLinesSuggested: 143,
  1374  										TotalCodeLinesAccepted:  61,
  1375  									},
  1376  									{
  1377  										Name:                    "go",
  1378  										TotalEngagedUsers:       4,
  1379  										TotalCodeSuggestions:    132,
  1380  										TotalCodeAcceptances:    67,
  1381  										TotalCodeLinesSuggested: 154,
  1382  										TotalCodeLinesAccepted:  72,
  1383  									},
  1384  								},
  1385  							},
  1386  						},
  1387  					},
  1388  				},
  1389  			},
  1390  			CopilotIDEChat: &CopilotIDEChat{
  1391  				TotalEngagedUsers: 13,
  1392  				Editors: []*CopilotIDEChatEditor{
  1393  					{
  1394  						Name:              "vscode",
  1395  						TotalEngagedUsers: 13,
  1396  						Models: []*CopilotIDEChatModel{
  1397  							{
  1398  								Name:                     "default",
  1399  								IsCustomModel:            false,
  1400  								CustomModelTrainingDate:  nil,
  1401  								TotalEngagedUsers:        12,
  1402  								TotalChats:               45,
  1403  								TotalChatInsertionEvents: 12,
  1404  								TotalChatCopyEvents:      16,
  1405  							},
  1406  							{
  1407  								Name:                     "a-custom-model",
  1408  								IsCustomModel:            true,
  1409  								CustomModelTrainingDate:  Ptr("2024-02-01"),
  1410  								TotalEngagedUsers:        1,
  1411  								TotalChats:               10,
  1412  								TotalChatInsertionEvents: 11,
  1413  								TotalChatCopyEvents:      3,
  1414  							},
  1415  						},
  1416  					},
  1417  				},
  1418  			},
  1419  			CopilotDotcomChat: &CopilotDotcomChat{
  1420  				TotalEngagedUsers: 14,
  1421  				Models: []*CopilotDotcomChatModel{
  1422  					{
  1423  						Name:                    "default",
  1424  						IsCustomModel:           false,
  1425  						CustomModelTrainingDate: nil,
  1426  						TotalEngagedUsers:       14,
  1427  						TotalChats:              38,
  1428  					},
  1429  				},
  1430  			},
  1431  			CopilotDotcomPullRequests: &CopilotDotcomPullRequests{
  1432  				TotalEngagedUsers: 12,
  1433  				Repositories: []*CopilotDotcomPullRequestsRepository{
  1434  					{
  1435  						Name:              "demo/repo1",
  1436  						TotalEngagedUsers: 8,
  1437  						Models: []*CopilotDotcomPullRequestsModel{
  1438  							{
  1439  								Name:                    "default",
  1440  								IsCustomModel:           false,
  1441  								CustomModelTrainingDate: nil,
  1442  								TotalPRSummariesCreated: 6,
  1443  								TotalEngagedUsers:       8,
  1444  							},
  1445  						},
  1446  					},
  1447  					{
  1448  						Name:              "demo/repo2",
  1449  						TotalEngagedUsers: 4,
  1450  						Models: []*CopilotDotcomPullRequestsModel{
  1451  							{
  1452  								Name:                    "a-custom-model",
  1453  								IsCustomModel:           true,
  1454  								CustomModelTrainingDate: Ptr("2024-02-01"),
  1455  								TotalPRSummariesCreated: 10,
  1456  								TotalEngagedUsers:       4,
  1457  							},
  1458  						},
  1459  					},
  1460  				},
  1461  			},
  1462  		},
  1463  	}
  1464  
  1465  	if !cmp.Equal(got, want) {
  1466  		t.Errorf("Copilot.GetEnterpriseMetrics returned %+v, want %+v", got, want)
  1467  	}
  1468  
  1469  	const methodName = "GetEnterpriseMetrics"
  1470  
  1471  	testBadOptions(t, methodName, func() (err error) {
  1472  		_, _, err = client.Copilot.GetEnterpriseMetrics(ctx, "\n", &CopilotMetricsListOptions{})
  1473  		return err
  1474  	})
  1475  
  1476  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  1477  		got, resp, err := client.Copilot.GetEnterpriseMetrics(ctx, "e", &CopilotMetricsListOptions{})
  1478  		if got != nil {
  1479  			t.Errorf("Copilot.GetEnterpriseMetrics returned %+v, want nil", got)
  1480  		}
  1481  		return resp, err
  1482  	})
  1483  }
  1484  
  1485  func TestCopilotService_GetEnterpriseTeamMetrics(t *testing.T) {
  1486  	t.Parallel()
  1487  	client, mux, _ := setup(t)
  1488  
  1489  	mux.HandleFunc("/enterprises/e/team/t/copilot/metrics", func(w http.ResponseWriter, r *http.Request) {
  1490  		testMethod(t, r, "GET")
  1491  		fmt.Fprint(w, `[
  1492  			{
  1493  				"date": "2024-06-24",
  1494  				"total_active_users": 24,
  1495  				"total_engaged_users": 20,
  1496  				"copilot_ide_code_completions": {
  1497  				"total_engaged_users": 20,
  1498  				"languages": [
  1499  					{
  1500  					"name": "python",
  1501  					"total_engaged_users": 10
  1502  					},
  1503  					{
  1504  					"name": "ruby",
  1505  					"total_engaged_users": 10
  1506  					}
  1507  				],
  1508  				"editors": [
  1509  					{
  1510  					"name": "vscode",
  1511  					"total_engaged_users": 13,
  1512  					"models": [
  1513  						{
  1514  						"name": "default",
  1515  						"is_custom_model": false,
  1516  						"custom_model_training_date": null,
  1517  						"total_engaged_users": 13,
  1518  						"languages": [
  1519  							{
  1520  							"name": "python",
  1521  							"total_engaged_users": 6,
  1522  							"total_code_suggestions": 249,
  1523  							"total_code_acceptances": 123,
  1524  							"total_code_lines_suggested": 225,
  1525  							"total_code_lines_accepted": 135
  1526  							},
  1527  							{
  1528  							"name": "ruby",
  1529  							"total_engaged_users": 7,
  1530  							"total_code_suggestions": 496,
  1531  							"total_code_acceptances": 253,
  1532  							"total_code_lines_suggested": 520,
  1533  							"total_code_lines_accepted": 270
  1534  							}
  1535  						]
  1536  						}
  1537  					]
  1538  					},
  1539  					{
  1540  					"name": "neovim",
  1541  					"total_engaged_users": 7,
  1542  					"models": [
  1543  						{
  1544  						"name": "a-custom-model",
  1545  						"is_custom_model": true,
  1546  						"custom_model_training_date": "2024-02-01",
  1547  						"languages": [
  1548  							{
  1549  							"name": "typescript",
  1550  							"total_engaged_users": 3,
  1551  							"total_code_suggestions": 112,
  1552  							"total_code_acceptances": 56,
  1553  							"total_code_lines_suggested": 143,
  1554  							"total_code_lines_accepted": 61
  1555  							},
  1556  							{
  1557  							"name": "go",
  1558  							"total_engaged_users": 4,
  1559  							"total_code_suggestions": 132,
  1560  							"total_code_acceptances": 67,
  1561  							"total_code_lines_suggested": 154,
  1562  							"total_code_lines_accepted": 72
  1563  							}
  1564  						]
  1565  						}
  1566  					]
  1567  					}
  1568  				]
  1569  				},
  1570  				"copilot_ide_chat": {
  1571  				"total_engaged_users": 13,
  1572  				"editors": [
  1573  					{
  1574  					"name": "vscode",
  1575  					"total_engaged_users": 13,
  1576  					"models": [
  1577  						{
  1578  						"name": "default",
  1579  						"is_custom_model": false,
  1580  						"custom_model_training_date": null,
  1581  						"total_engaged_users": 12,
  1582  						"total_chats": 45,
  1583  						"total_chat_insertion_events": 12,
  1584  						"total_chat_copy_events": 16
  1585  						},
  1586  						{
  1587  						"name": "a-custom-model",
  1588  						"is_custom_model": true,
  1589  						"custom_model_training_date": "2024-02-01",
  1590  						"total_engaged_users": 1,
  1591  						"total_chats": 10,
  1592  						"total_chat_insertion_events": 11,
  1593  						"total_chat_copy_events": 3
  1594  						}
  1595  					]
  1596  					}
  1597  				]
  1598  				},
  1599  				"copilot_dotcom_chat": {
  1600  				"total_engaged_users": 14,
  1601  				"models": [
  1602  					{
  1603  					"name": "default",
  1604  					"is_custom_model": false,
  1605  					"custom_model_training_date": null,
  1606  					"total_engaged_users": 14,
  1607  					"total_chats": 38
  1608  					}
  1609  				]
  1610  				},
  1611  				"copilot_dotcom_pull_requests": {
  1612  				"total_engaged_users": 12,
  1613  				"repositories": [
  1614  					{
  1615  					"name": "demo/repo1",
  1616  					"total_engaged_users": 8,
  1617  					"models": [
  1618  						{
  1619  						"name": "default",
  1620  						"is_custom_model": false,
  1621  						"custom_model_training_date": null,
  1622  						"total_pr_summaries_created": 6,
  1623  						"total_engaged_users": 8
  1624  						}
  1625  					]
  1626  					},
  1627  					{
  1628  					"name": "demo/repo2",
  1629  					"total_engaged_users": 4,
  1630  					"models": [
  1631  						{
  1632  						"name": "a-custom-model",
  1633  						"is_custom_model": true,
  1634  						"custom_model_training_date": "2024-02-01",
  1635  						"total_pr_summaries_created": 10,
  1636  						"total_engaged_users": 4
  1637  						}
  1638  					]
  1639  					}
  1640  				]
  1641  				}
  1642  			}
  1643  		]`)
  1644  	})
  1645  
  1646  	ctx := context.Background()
  1647  	got, _, err := client.Copilot.GetEnterpriseTeamMetrics(ctx, "e", "t", &CopilotMetricsListOptions{})
  1648  	if err != nil {
  1649  		t.Errorf("Copilot.GetEnterpriseTeamMetrics returned error: %v", err)
  1650  	}
  1651  
  1652  	totalActiveUsers := 24
  1653  	totalEngagedUsers := 20
  1654  	want := []*CopilotMetrics{
  1655  		{
  1656  			Date:              "2024-06-24",
  1657  			TotalActiveUsers:  &totalActiveUsers,
  1658  			TotalEngagedUsers: &totalEngagedUsers,
  1659  			CopilotIDECodeCompletions: &CopilotIDECodeCompletions{
  1660  				TotalEngagedUsers: 20,
  1661  				Languages: []*CopilotIDECodeCompletionsLanguage{
  1662  					{
  1663  						Name:              "python",
  1664  						TotalEngagedUsers: 10,
  1665  					},
  1666  					{
  1667  						Name:              "ruby",
  1668  						TotalEngagedUsers: 10,
  1669  					},
  1670  				},
  1671  				Editors: []*CopilotIDECodeCompletionsEditor{
  1672  					{
  1673  						Name:              "vscode",
  1674  						TotalEngagedUsers: 13,
  1675  						Models: []*CopilotIDECodeCompletionsModel{
  1676  							{
  1677  								Name:                    "default",
  1678  								IsCustomModel:           false,
  1679  								CustomModelTrainingDate: nil,
  1680  								TotalEngagedUsers:       13,
  1681  								Languages: []*CopilotIDECodeCompletionsModelLanguage{
  1682  									{
  1683  										Name:                    "python",
  1684  										TotalEngagedUsers:       6,
  1685  										TotalCodeSuggestions:    249,
  1686  										TotalCodeAcceptances:    123,
  1687  										TotalCodeLinesSuggested: 225,
  1688  										TotalCodeLinesAccepted:  135,
  1689  									},
  1690  									{
  1691  										Name:                    "ruby",
  1692  										TotalEngagedUsers:       7,
  1693  										TotalCodeSuggestions:    496,
  1694  										TotalCodeAcceptances:    253,
  1695  										TotalCodeLinesSuggested: 520,
  1696  										TotalCodeLinesAccepted:  270,
  1697  									},
  1698  								},
  1699  							},
  1700  						},
  1701  					},
  1702  					{
  1703  						Name:              "neovim",
  1704  						TotalEngagedUsers: 7,
  1705  						Models: []*CopilotIDECodeCompletionsModel{
  1706  							{
  1707  								Name:                    "a-custom-model",
  1708  								IsCustomModel:           true,
  1709  								CustomModelTrainingDate: Ptr("2024-02-01"),
  1710  								Languages: []*CopilotIDECodeCompletionsModelLanguage{
  1711  									{
  1712  										Name:                    "typescript",
  1713  										TotalEngagedUsers:       3,
  1714  										TotalCodeSuggestions:    112,
  1715  										TotalCodeAcceptances:    56,
  1716  										TotalCodeLinesSuggested: 143,
  1717  										TotalCodeLinesAccepted:  61,
  1718  									},
  1719  									{
  1720  										Name:                    "go",
  1721  										TotalEngagedUsers:       4,
  1722  										TotalCodeSuggestions:    132,
  1723  										TotalCodeAcceptances:    67,
  1724  										TotalCodeLinesSuggested: 154,
  1725  										TotalCodeLinesAccepted:  72,
  1726  									},
  1727  								},
  1728  							},
  1729  						},
  1730  					},
  1731  				},
  1732  			},
  1733  			CopilotIDEChat: &CopilotIDEChat{
  1734  				TotalEngagedUsers: 13,
  1735  				Editors: []*CopilotIDEChatEditor{
  1736  					{
  1737  						Name:              "vscode",
  1738  						TotalEngagedUsers: 13,
  1739  						Models: []*CopilotIDEChatModel{
  1740  							{
  1741  								Name:                     "default",
  1742  								IsCustomModel:            false,
  1743  								CustomModelTrainingDate:  nil,
  1744  								TotalEngagedUsers:        12,
  1745  								TotalChats:               45,
  1746  								TotalChatInsertionEvents: 12,
  1747  								TotalChatCopyEvents:      16,
  1748  							},
  1749  							{
  1750  								Name:                     "a-custom-model",
  1751  								IsCustomModel:            true,
  1752  								CustomModelTrainingDate:  Ptr("2024-02-01"),
  1753  								TotalEngagedUsers:        1,
  1754  								TotalChats:               10,
  1755  								TotalChatInsertionEvents: 11,
  1756  								TotalChatCopyEvents:      3,
  1757  							},
  1758  						},
  1759  					},
  1760  				},
  1761  			},
  1762  			CopilotDotcomChat: &CopilotDotcomChat{
  1763  				TotalEngagedUsers: 14,
  1764  				Models: []*CopilotDotcomChatModel{
  1765  					{
  1766  						Name:                    "default",
  1767  						IsCustomModel:           false,
  1768  						CustomModelTrainingDate: nil,
  1769  						TotalEngagedUsers:       14,
  1770  						TotalChats:              38,
  1771  					},
  1772  				},
  1773  			},
  1774  			CopilotDotcomPullRequests: &CopilotDotcomPullRequests{
  1775  				TotalEngagedUsers: 12,
  1776  				Repositories: []*CopilotDotcomPullRequestsRepository{
  1777  					{
  1778  						Name:              "demo/repo1",
  1779  						TotalEngagedUsers: 8,
  1780  						Models: []*CopilotDotcomPullRequestsModel{
  1781  							{
  1782  								Name:                    "default",
  1783  								IsCustomModel:           false,
  1784  								CustomModelTrainingDate: nil,
  1785  								TotalPRSummariesCreated: 6,
  1786  								TotalEngagedUsers:       8,
  1787  							},
  1788  						},
  1789  					},
  1790  					{
  1791  						Name:              "demo/repo2",
  1792  						TotalEngagedUsers: 4,
  1793  						Models: []*CopilotDotcomPullRequestsModel{
  1794  							{
  1795  								Name:                    "a-custom-model",
  1796  								IsCustomModel:           true,
  1797  								CustomModelTrainingDate: Ptr("2024-02-01"),
  1798  								TotalPRSummariesCreated: 10,
  1799  								TotalEngagedUsers:       4,
  1800  							},
  1801  						},
  1802  					},
  1803  				},
  1804  			},
  1805  		},
  1806  	}
  1807  
  1808  	if !cmp.Equal(got, want) {
  1809  		t.Errorf("Copilot.GetEnterpriseTeamMetrics returned %+v, want %+v", got, want)
  1810  	}
  1811  
  1812  	const methodName = "GetEnterpriseTeamMetrics"
  1813  
  1814  	testBadOptions(t, methodName, func() (err error) {
  1815  		_, _, err = client.Copilot.GetEnterpriseTeamMetrics(ctx, "\n", "t", &CopilotMetricsListOptions{})
  1816  		return err
  1817  	})
  1818  
  1819  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  1820  		got, resp, err := client.Copilot.GetEnterpriseTeamMetrics(ctx, "e", "t", &CopilotMetricsListOptions{})
  1821  		if got != nil {
  1822  			t.Errorf("Copilot.GetEnterpriseTeamMetrics returned %+v, want nil", got)
  1823  		}
  1824  		return resp, err
  1825  	})
  1826  }
  1827  
  1828  func TestCopilotService_GetOrganizationMetrics(t *testing.T) {
  1829  	t.Parallel()
  1830  	client, mux, _ := setup(t)
  1831  
  1832  	mux.HandleFunc("/orgs/o/copilot/metrics", func(w http.ResponseWriter, r *http.Request) {
  1833  		testMethod(t, r, "GET")
  1834  		fmt.Fprint(w, `[
  1835  			{
  1836  				"date": "2024-06-24",
  1837  				"total_active_users": 24,
  1838  				"total_engaged_users": 20,
  1839  				"copilot_ide_code_completions": {
  1840  				"total_engaged_users": 20,
  1841  				"languages": [
  1842  					{
  1843  					"name": "python",
  1844  					"total_engaged_users": 10
  1845  					},
  1846  					{
  1847  					"name": "ruby",
  1848  					"total_engaged_users": 10
  1849  					}
  1850  				],
  1851  				"editors": [
  1852  					{
  1853  					"name": "vscode",
  1854  					"total_engaged_users": 13,
  1855  					"models": [
  1856  						{
  1857  						"name": "default",
  1858  						"is_custom_model": false,
  1859  						"custom_model_training_date": null,
  1860  						"total_engaged_users": 13,
  1861  						"languages": [
  1862  							{
  1863  							"name": "python",
  1864  							"total_engaged_users": 6,
  1865  							"total_code_suggestions": 249,
  1866  							"total_code_acceptances": 123,
  1867  							"total_code_lines_suggested": 225,
  1868  							"total_code_lines_accepted": 135
  1869  							},
  1870  							{
  1871  							"name": "ruby",
  1872  							"total_engaged_users": 7,
  1873  							"total_code_suggestions": 496,
  1874  							"total_code_acceptances": 253,
  1875  							"total_code_lines_suggested": 520,
  1876  							"total_code_lines_accepted": 270
  1877  							}
  1878  						]
  1879  						}
  1880  					]
  1881  					},
  1882  					{
  1883  					"name": "neovim",
  1884  					"total_engaged_users": 7,
  1885  					"models": [
  1886  						{
  1887  						"name": "a-custom-model",
  1888  						"is_custom_model": true,
  1889  						"custom_model_training_date": "2024-02-01",
  1890  						"languages": [
  1891  							{
  1892  							"name": "typescript",
  1893  							"total_engaged_users": 3,
  1894  							"total_code_suggestions": 112,
  1895  							"total_code_acceptances": 56,
  1896  							"total_code_lines_suggested": 143,
  1897  							"total_code_lines_accepted": 61
  1898  							},
  1899  							{
  1900  							"name": "go",
  1901  							"total_engaged_users": 4,
  1902  							"total_code_suggestions": 132,
  1903  							"total_code_acceptances": 67,
  1904  							"total_code_lines_suggested": 154,
  1905  							"total_code_lines_accepted": 72
  1906  							}
  1907  						]
  1908  						}
  1909  					]
  1910  					}
  1911  				]
  1912  				},
  1913  				"copilot_ide_chat": {
  1914  				"total_engaged_users": 13,
  1915  				"editors": [
  1916  					{
  1917  					"name": "vscode",
  1918  					"total_engaged_users": 13,
  1919  					"models": [
  1920  						{
  1921  						"name": "default",
  1922  						"is_custom_model": false,
  1923  						"custom_model_training_date": null,
  1924  						"total_engaged_users": 12,
  1925  						"total_chats": 45,
  1926  						"total_chat_insertion_events": 12,
  1927  						"total_chat_copy_events": 16
  1928  						},
  1929  						{
  1930  						"name": "a-custom-model",
  1931  						"is_custom_model": true,
  1932  						"custom_model_training_date": "2024-02-01",
  1933  						"total_engaged_users": 1,
  1934  						"total_chats": 10,
  1935  						"total_chat_insertion_events": 11,
  1936  						"total_chat_copy_events": 3
  1937  						}
  1938  					]
  1939  					}
  1940  				]
  1941  				},
  1942  				"copilot_dotcom_chat": {
  1943  				"total_engaged_users": 14,
  1944  				"models": [
  1945  					{
  1946  					"name": "default",
  1947  					"is_custom_model": false,
  1948  					"custom_model_training_date": null,
  1949  					"total_engaged_users": 14,
  1950  					"total_chats": 38
  1951  					}
  1952  				]
  1953  				},
  1954  				"copilot_dotcom_pull_requests": {
  1955  				"total_engaged_users": 12,
  1956  				"repositories": [
  1957  					{
  1958  					"name": "demo/repo1",
  1959  					"total_engaged_users": 8,
  1960  					"models": [
  1961  						{
  1962  						"name": "default",
  1963  						"is_custom_model": false,
  1964  						"custom_model_training_date": null,
  1965  						"total_pr_summaries_created": 6,
  1966  						"total_engaged_users": 8
  1967  						}
  1968  					]
  1969  					},
  1970  					{
  1971  					"name": "demo/repo2",
  1972  					"total_engaged_users": 4,
  1973  					"models": [
  1974  						{
  1975  						"name": "a-custom-model",
  1976  						"is_custom_model": true,
  1977  						"custom_model_training_date": "2024-02-01",
  1978  						"total_pr_summaries_created": 10,
  1979  						"total_engaged_users": 4
  1980  						}
  1981  					]
  1982  					}
  1983  				]
  1984  				}
  1985  			}
  1986  		]`)
  1987  	})
  1988  
  1989  	ctx := context.Background()
  1990  	got, _, err := client.Copilot.GetOrganizationMetrics(ctx, "o", &CopilotMetricsListOptions{})
  1991  	if err != nil {
  1992  		t.Errorf("Copilot.GetOrganizationMetrics returned error: %v", err)
  1993  	}
  1994  
  1995  	totalActiveUsers := 24
  1996  	totalEngagedUsers := 20
  1997  	want := []*CopilotMetrics{
  1998  		{
  1999  			Date:              "2024-06-24",
  2000  			TotalActiveUsers:  &totalActiveUsers,
  2001  			TotalEngagedUsers: &totalEngagedUsers,
  2002  			CopilotIDECodeCompletions: &CopilotIDECodeCompletions{
  2003  				TotalEngagedUsers: 20,
  2004  				Languages: []*CopilotIDECodeCompletionsLanguage{
  2005  					{
  2006  						Name:              "python",
  2007  						TotalEngagedUsers: 10,
  2008  					},
  2009  					{
  2010  						Name:              "ruby",
  2011  						TotalEngagedUsers: 10,
  2012  					},
  2013  				},
  2014  				Editors: []*CopilotIDECodeCompletionsEditor{
  2015  					{
  2016  						Name:              "vscode",
  2017  						TotalEngagedUsers: 13,
  2018  						Models: []*CopilotIDECodeCompletionsModel{
  2019  							{
  2020  								Name:                    "default",
  2021  								IsCustomModel:           false,
  2022  								CustomModelTrainingDate: nil,
  2023  								TotalEngagedUsers:       13,
  2024  								Languages: []*CopilotIDECodeCompletionsModelLanguage{
  2025  									{
  2026  										Name:                    "python",
  2027  										TotalEngagedUsers:       6,
  2028  										TotalCodeSuggestions:    249,
  2029  										TotalCodeAcceptances:    123,
  2030  										TotalCodeLinesSuggested: 225,
  2031  										TotalCodeLinesAccepted:  135,
  2032  									},
  2033  									{
  2034  										Name:                    "ruby",
  2035  										TotalEngagedUsers:       7,
  2036  										TotalCodeSuggestions:    496,
  2037  										TotalCodeAcceptances:    253,
  2038  										TotalCodeLinesSuggested: 520,
  2039  										TotalCodeLinesAccepted:  270,
  2040  									},
  2041  								},
  2042  							},
  2043  						},
  2044  					},
  2045  					{
  2046  						Name:              "neovim",
  2047  						TotalEngagedUsers: 7,
  2048  						Models: []*CopilotIDECodeCompletionsModel{
  2049  							{
  2050  								Name:                    "a-custom-model",
  2051  								IsCustomModel:           true,
  2052  								CustomModelTrainingDate: Ptr("2024-02-01"),
  2053  								Languages: []*CopilotIDECodeCompletionsModelLanguage{
  2054  									{
  2055  										Name:                    "typescript",
  2056  										TotalEngagedUsers:       3,
  2057  										TotalCodeSuggestions:    112,
  2058  										TotalCodeAcceptances:    56,
  2059  										TotalCodeLinesSuggested: 143,
  2060  										TotalCodeLinesAccepted:  61,
  2061  									},
  2062  									{
  2063  										Name:                    "go",
  2064  										TotalEngagedUsers:       4,
  2065  										TotalCodeSuggestions:    132,
  2066  										TotalCodeAcceptances:    67,
  2067  										TotalCodeLinesSuggested: 154,
  2068  										TotalCodeLinesAccepted:  72,
  2069  									},
  2070  								},
  2071  							},
  2072  						},
  2073  					},
  2074  				},
  2075  			},
  2076  			CopilotIDEChat: &CopilotIDEChat{
  2077  				TotalEngagedUsers: 13,
  2078  				Editors: []*CopilotIDEChatEditor{
  2079  					{
  2080  						Name:              "vscode",
  2081  						TotalEngagedUsers: 13,
  2082  						Models: []*CopilotIDEChatModel{
  2083  							{
  2084  								Name:                     "default",
  2085  								IsCustomModel:            false,
  2086  								CustomModelTrainingDate:  nil,
  2087  								TotalEngagedUsers:        12,
  2088  								TotalChats:               45,
  2089  								TotalChatInsertionEvents: 12,
  2090  								TotalChatCopyEvents:      16,
  2091  							},
  2092  							{
  2093  								Name:                     "a-custom-model",
  2094  								IsCustomModel:            true,
  2095  								CustomModelTrainingDate:  Ptr("2024-02-01"),
  2096  								TotalEngagedUsers:        1,
  2097  								TotalChats:               10,
  2098  								TotalChatInsertionEvents: 11,
  2099  								TotalChatCopyEvents:      3,
  2100  							},
  2101  						},
  2102  					},
  2103  				},
  2104  			},
  2105  			CopilotDotcomChat: &CopilotDotcomChat{
  2106  				TotalEngagedUsers: 14,
  2107  				Models: []*CopilotDotcomChatModel{
  2108  					{
  2109  						Name:                    "default",
  2110  						IsCustomModel:           false,
  2111  						CustomModelTrainingDate: nil,
  2112  						TotalEngagedUsers:       14,
  2113  						TotalChats:              38,
  2114  					},
  2115  				},
  2116  			},
  2117  			CopilotDotcomPullRequests: &CopilotDotcomPullRequests{
  2118  				TotalEngagedUsers: 12,
  2119  				Repositories: []*CopilotDotcomPullRequestsRepository{
  2120  					{
  2121  						Name:              "demo/repo1",
  2122  						TotalEngagedUsers: 8,
  2123  						Models: []*CopilotDotcomPullRequestsModel{
  2124  							{
  2125  								Name:                    "default",
  2126  								IsCustomModel:           false,
  2127  								CustomModelTrainingDate: nil,
  2128  								TotalPRSummariesCreated: 6,
  2129  								TotalEngagedUsers:       8,
  2130  							},
  2131  						},
  2132  					},
  2133  					{
  2134  						Name:              "demo/repo2",
  2135  						TotalEngagedUsers: 4,
  2136  						Models: []*CopilotDotcomPullRequestsModel{
  2137  							{
  2138  								Name:                    "a-custom-model",
  2139  								IsCustomModel:           true,
  2140  								CustomModelTrainingDate: Ptr("2024-02-01"),
  2141  								TotalPRSummariesCreated: 10,
  2142  								TotalEngagedUsers:       4,
  2143  							},
  2144  						},
  2145  					},
  2146  				},
  2147  			},
  2148  		},
  2149  	}
  2150  
  2151  	if !cmp.Equal(got, want) {
  2152  		t.Errorf("Copilot.GetOrganizationMetrics returned %+v, want %+v", got, want)
  2153  	}
  2154  
  2155  	const methodName = "GetOrganizationMetrics"
  2156  
  2157  	testBadOptions(t, methodName, func() (err error) {
  2158  		_, _, err = client.Copilot.GetOrganizationMetrics(ctx, "\n", &CopilotMetricsListOptions{})
  2159  		return err
  2160  	})
  2161  
  2162  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  2163  		got, resp, err := client.Copilot.GetOrganizationMetrics(ctx, "o", &CopilotMetricsListOptions{})
  2164  		if got != nil {
  2165  			t.Errorf("Copilot.GetOrganizationMetrics returned %+v, want nil", got)
  2166  		}
  2167  		return resp, err
  2168  	})
  2169  }
  2170  
  2171  func TestCopilotService_GetOrganizationTeamMetrics(t *testing.T) {
  2172  	t.Parallel()
  2173  	client, mux, _ := setup(t)
  2174  
  2175  	mux.HandleFunc("/orgs/o/team/t/copilot/metrics", func(w http.ResponseWriter, r *http.Request) {
  2176  		testMethod(t, r, "GET")
  2177  		fmt.Fprint(w, `[
  2178  			{
  2179  				"date": "2024-06-24",
  2180  				"total_active_users": 24,
  2181  				"total_engaged_users": 20,
  2182  				"copilot_ide_code_completions": {
  2183  					"total_engaged_users": 20,
  2184  					"languages": [
  2185  						{
  2186  							"name": "python",
  2187  							"total_engaged_users": 10
  2188  						},
  2189  						{
  2190  							"name": "ruby",
  2191  							"total_engaged_users": 10
  2192  						}
  2193  					],
  2194  					"editors": [
  2195  						{
  2196  							"name": "vscode",
  2197  							"total_engaged_users": 13,
  2198  							"models": [
  2199  								{
  2200  									"name": "default",
  2201  									"is_custom_model": false,
  2202  									"custom_model_training_date": null,
  2203  									"total_engaged_users": 13,
  2204  									"languages": [
  2205  										{
  2206  											"name": "python",
  2207  											"total_engaged_users": 6,
  2208  											"total_code_suggestions": 249,
  2209  											"total_code_acceptances": 123,
  2210  											"total_code_lines_suggested": 225,
  2211  											"total_code_lines_accepted": 135
  2212  										},
  2213  										{
  2214  											"name": "ruby",
  2215  											"total_engaged_users": 7,
  2216  											"total_code_suggestions": 496,
  2217  											"total_code_acceptances": 253,
  2218  											"total_code_lines_suggested": 520,
  2219  											"total_code_lines_accepted": 270
  2220  										}
  2221  									]
  2222  								}
  2223  							]
  2224  						},
  2225  						{
  2226  							"name": "neovim",
  2227  							"total_engaged_users": 7,
  2228  							"models": [
  2229  								{
  2230  									"name": "a-custom-model",
  2231  									"is_custom_model": true,
  2232  									"custom_model_training_date": "2024-02-01",
  2233  									"languages": [
  2234  										{
  2235  											"name": "typescript",
  2236  											"total_engaged_users": 3,
  2237  											"total_code_suggestions": 112,
  2238  											"total_code_acceptances": 56,
  2239  											"total_code_lines_suggested": 143,
  2240  											"total_code_lines_accepted": 61
  2241  										},
  2242  										{
  2243  											"name": "go",
  2244  											"total_engaged_users": 4,
  2245  											"total_code_suggestions": 132,
  2246  											"total_code_acceptances": 67,
  2247  											"total_code_lines_suggested": 154,
  2248  											"total_code_lines_accepted": 72
  2249  										}
  2250  									]
  2251  								}
  2252  							]
  2253  						}
  2254  					]
  2255  				},
  2256  				"copilot_ide_chat": {
  2257  					"total_engaged_users": 13,
  2258  					"editors": [
  2259  						{
  2260  							"name": "vscode",
  2261  							"total_engaged_users": 13,
  2262  							"models": [
  2263  								{
  2264  									"name": "default",
  2265  									"is_custom_model": false,
  2266  									"custom_model_training_date": null,
  2267  									"total_engaged_users": 12,
  2268  									"total_chats": 45,
  2269  									"total_chat_insertion_events": 12,
  2270  									"total_chat_copy_events": 16
  2271  								},
  2272  								{
  2273  									"name": "a-custom-model",
  2274  									"is_custom_model": true,
  2275  									"custom_model_training_date": "2024-02-01",
  2276  									"total_engaged_users": 1,
  2277  									"total_chats": 10,
  2278  									"total_chat_insertion_events": 11,
  2279  									"total_chat_copy_events": 3
  2280  								}
  2281  							]
  2282  						}
  2283  					]
  2284  				},
  2285  				"copilot_dotcom_chat": {
  2286  					"total_engaged_users": 14,
  2287  					"models": [
  2288  						{
  2289  							"name": "default",
  2290  							"is_custom_model": false,
  2291  							"custom_model_training_date": null,
  2292  							"total_engaged_users": 14,
  2293  							"total_chats": 38
  2294  						}
  2295  					]
  2296  				},
  2297  				"copilot_dotcom_pull_requests": {
  2298  					"total_engaged_users": 12,
  2299  					"repositories": [
  2300  						{
  2301  							"name": "demo/repo1",
  2302  							"total_engaged_users": 8,
  2303  							"models": [
  2304  								{
  2305  									"name": "default",
  2306  									"is_custom_model": false,
  2307  									"custom_model_training_date": null,
  2308  									"total_pr_summaries_created": 6,
  2309  									"total_engaged_users": 8
  2310  								}
  2311  							]
  2312  						},
  2313  						{
  2314  							"name": "demo/repo2",
  2315  							"total_engaged_users": 4,
  2316  							"models": [
  2317  								{
  2318  									"name": "a-custom-model",
  2319  									"is_custom_model": true,
  2320  									"custom_model_training_date": "2024-02-01",
  2321  									"total_pr_summaries_created": 10,
  2322  									"total_engaged_users": 4
  2323  								}
  2324  							]
  2325  						}
  2326  					]
  2327  				}
  2328  			}
  2329  		]`)
  2330  	})
  2331  
  2332  	ctx := context.Background()
  2333  	got, _, err := client.Copilot.GetOrganizationTeamMetrics(ctx, "o", "t", &CopilotMetricsListOptions{})
  2334  	if err != nil {
  2335  		t.Errorf("Copilot.GetOrganizationTeamMetrics returned error: %v", err)
  2336  	}
  2337  
  2338  	totalActiveUsers := 24
  2339  	totalEngagedUsers := 20
  2340  	want := []*CopilotMetrics{
  2341  		{
  2342  			Date:              "2024-06-24",
  2343  			TotalActiveUsers:  &totalActiveUsers,
  2344  			TotalEngagedUsers: &totalEngagedUsers,
  2345  			CopilotIDECodeCompletions: &CopilotIDECodeCompletions{
  2346  				TotalEngagedUsers: 20,
  2347  				Languages: []*CopilotIDECodeCompletionsLanguage{
  2348  					{
  2349  						Name:              "python",
  2350  						TotalEngagedUsers: 10,
  2351  					},
  2352  					{
  2353  						Name:              "ruby",
  2354  						TotalEngagedUsers: 10,
  2355  					},
  2356  				},
  2357  				Editors: []*CopilotIDECodeCompletionsEditor{
  2358  					{
  2359  						Name:              "vscode",
  2360  						TotalEngagedUsers: 13,
  2361  						Models: []*CopilotIDECodeCompletionsModel{
  2362  							{
  2363  								Name:                    "default",
  2364  								IsCustomModel:           false,
  2365  								CustomModelTrainingDate: nil,
  2366  								TotalEngagedUsers:       13,
  2367  								Languages: []*CopilotIDECodeCompletionsModelLanguage{
  2368  									{
  2369  										Name:                    "python",
  2370  										TotalEngagedUsers:       6,
  2371  										TotalCodeSuggestions:    249,
  2372  										TotalCodeAcceptances:    123,
  2373  										TotalCodeLinesSuggested: 225,
  2374  										TotalCodeLinesAccepted:  135,
  2375  									},
  2376  									{
  2377  										Name:                    "ruby",
  2378  										TotalEngagedUsers:       7,
  2379  										TotalCodeSuggestions:    496,
  2380  										TotalCodeAcceptances:    253,
  2381  										TotalCodeLinesSuggested: 520,
  2382  										TotalCodeLinesAccepted:  270,
  2383  									},
  2384  								},
  2385  							},
  2386  						},
  2387  					},
  2388  					{
  2389  						Name:              "neovim",
  2390  						TotalEngagedUsers: 7,
  2391  						Models: []*CopilotIDECodeCompletionsModel{
  2392  							{
  2393  								Name:                    "a-custom-model",
  2394  								IsCustomModel:           true,
  2395  								CustomModelTrainingDate: Ptr("2024-02-01"),
  2396  								Languages: []*CopilotIDECodeCompletionsModelLanguage{
  2397  									{
  2398  										Name:                    "typescript",
  2399  										TotalEngagedUsers:       3,
  2400  										TotalCodeSuggestions:    112,
  2401  										TotalCodeAcceptances:    56,
  2402  										TotalCodeLinesSuggested: 143,
  2403  										TotalCodeLinesAccepted:  61,
  2404  									},
  2405  									{
  2406  										Name:                    "go",
  2407  										TotalEngagedUsers:       4,
  2408  										TotalCodeSuggestions:    132,
  2409  										TotalCodeAcceptances:    67,
  2410  										TotalCodeLinesSuggested: 154,
  2411  										TotalCodeLinesAccepted:  72,
  2412  									},
  2413  								},
  2414  							},
  2415  						},
  2416  					},
  2417  				},
  2418  			},
  2419  			CopilotIDEChat: &CopilotIDEChat{
  2420  				TotalEngagedUsers: 13,
  2421  				Editors: []*CopilotIDEChatEditor{
  2422  					{
  2423  						Name:              "vscode",
  2424  						TotalEngagedUsers: 13,
  2425  						Models: []*CopilotIDEChatModel{
  2426  							{
  2427  								Name:                     "default",
  2428  								IsCustomModel:            false,
  2429  								CustomModelTrainingDate:  nil,
  2430  								TotalEngagedUsers:        12,
  2431  								TotalChats:               45,
  2432  								TotalChatInsertionEvents: 12,
  2433  								TotalChatCopyEvents:      16,
  2434  							},
  2435  							{
  2436  								Name:                     "a-custom-model",
  2437  								IsCustomModel:            true,
  2438  								CustomModelTrainingDate:  Ptr("2024-02-01"),
  2439  								TotalEngagedUsers:        1,
  2440  								TotalChats:               10,
  2441  								TotalChatInsertionEvents: 11,
  2442  								TotalChatCopyEvents:      3,
  2443  							},
  2444  						},
  2445  					},
  2446  				},
  2447  			},
  2448  			CopilotDotcomChat: &CopilotDotcomChat{
  2449  				TotalEngagedUsers: 14,
  2450  				Models: []*CopilotDotcomChatModel{
  2451  					{
  2452  						Name:                    "default",
  2453  						IsCustomModel:           false,
  2454  						CustomModelTrainingDate: nil,
  2455  						TotalEngagedUsers:       14,
  2456  						TotalChats:              38,
  2457  					},
  2458  				},
  2459  			},
  2460  			CopilotDotcomPullRequests: &CopilotDotcomPullRequests{
  2461  				TotalEngagedUsers: 12,
  2462  				Repositories: []*CopilotDotcomPullRequestsRepository{
  2463  					{
  2464  						Name:              "demo/repo1",
  2465  						TotalEngagedUsers: 8,
  2466  						Models: []*CopilotDotcomPullRequestsModel{
  2467  							{
  2468  								Name:                    "default",
  2469  								IsCustomModel:           false,
  2470  								CustomModelTrainingDate: nil,
  2471  								TotalPRSummariesCreated: 6,
  2472  								TotalEngagedUsers:       8,
  2473  							},
  2474  						},
  2475  					},
  2476  					{
  2477  						Name:              "demo/repo2",
  2478  						TotalEngagedUsers: 4,
  2479  						Models: []*CopilotDotcomPullRequestsModel{
  2480  							{
  2481  								Name:                    "a-custom-model",
  2482  								IsCustomModel:           true,
  2483  								CustomModelTrainingDate: Ptr("2024-02-01"),
  2484  								TotalPRSummariesCreated: 10,
  2485  								TotalEngagedUsers:       4,
  2486  							},
  2487  						},
  2488  					},
  2489  				},
  2490  			},
  2491  		},
  2492  	}
  2493  
  2494  	if !cmp.Equal(got, want) {
  2495  		t.Errorf("Copilot.GetOrganizationTeamMetrics returned %+v, want %+v", got, want)
  2496  	}
  2497  
  2498  	const methodName = "GetOrganizationTeamMetrics"
  2499  
  2500  	testBadOptions(t, methodName, func() (err error) {
  2501  		_, _, err = client.Copilot.GetOrganizationTeamMetrics(ctx, "\n", "\n", &CopilotMetricsListOptions{})
  2502  		return err
  2503  	})
  2504  
  2505  	testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
  2506  		got, resp, err := client.Copilot.GetOrganizationTeamMetrics(ctx, "o", "t", &CopilotMetricsListOptions{})
  2507  		if got != nil {
  2508  			t.Errorf("Copilot.GetOrganizationTeamMetrics returned %+v, want nil", got)
  2509  		}
  2510  		return resp, err
  2511  	})
  2512  }