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