github.com/google/go-github/v69@v69.2.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 }