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