github.com/google/go-github/v49@v49.1.0/github/search_test.go (about) 1 // Copyright 2013 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 "fmt" 11 "net/http" 12 "strings" 13 "testing" 14 15 "github.com/google/go-cmp/cmp" 16 ) 17 18 func TestSearchService_Repositories(t *testing.T) { 19 client, mux, _, teardown := setup() 20 defer teardown() 21 22 mux.HandleFunc("/search/repositories", func(w http.ResponseWriter, r *http.Request) { 23 testMethod(t, r, "GET") 24 testFormValues(t, r, values{ 25 "q": "blah", 26 "sort": "forks", 27 "order": "desc", 28 "page": "2", 29 "per_page": "2", 30 }) 31 32 fmt.Fprint(w, `{"total_count": 4, "incomplete_results": false, "items": [{"id":1},{"id":2}]}`) 33 }) 34 35 opts := &SearchOptions{Sort: "forks", Order: "desc", ListOptions: ListOptions{Page: 2, PerPage: 2}} 36 ctx := context.Background() 37 result, _, err := client.Search.Repositories(ctx, "blah", opts) 38 if err != nil { 39 t.Errorf("Search.Repositories returned error: %v", err) 40 } 41 42 want := &RepositoriesSearchResult{ 43 Total: Int(4), 44 IncompleteResults: Bool(false), 45 Repositories: []*Repository{{ID: Int64(1)}, {ID: Int64(2)}}, 46 } 47 if !cmp.Equal(result, want) { 48 t.Errorf("Search.Repositories returned %+v, want %+v", result, want) 49 } 50 } 51 52 func TestSearchService_Repositories_coverage(t *testing.T) { 53 client, _, _, teardown := setup() 54 defer teardown() 55 56 ctx := context.Background() 57 58 const methodName = "Repositories" 59 testBadOptions(t, methodName, func() (err error) { 60 _, _, err = client.Search.Repositories(ctx, "\n", nil) 61 return err 62 }) 63 } 64 65 func TestSearchService_RepositoriesTextMatch(t *testing.T) { 66 client, mux, _, teardown := setup() 67 defer teardown() 68 69 mux.HandleFunc("/search/repositories", func(w http.ResponseWriter, r *http.Request) { 70 testMethod(t, r, "GET") 71 textMatchResponse := ` 72 { 73 "total_count": 1, 74 "incomplete_results": false, 75 "items": [ 76 { 77 "name":"gopher1" 78 } 79 ] 80 } 81 ` 82 list := strings.Split(r.Header.Get("Accept"), ",") 83 aMap := make(map[string]struct{}) 84 for _, s := range list { 85 aMap[strings.TrimSpace(s)] = struct{}{} 86 } 87 if _, ok := aMap["application/vnd.github.v3.text-match+json"]; ok { 88 textMatchResponse = ` 89 { 90 "total_count": 1, 91 "incomplete_results": false, 92 "items": [ 93 { 94 "name":"gopher1", 95 "text_matches": [ 96 { 97 "fragment": "I'm afraid my friend what you have found\nIs a gopher who lives to feed", 98 "matches": [ 99 { 100 "text": "gopher", 101 "indices": [ 102 14, 103 21 104 ] 105 } 106 ] 107 } 108 ] 109 } 110 ] 111 } 112 ` 113 } 114 115 fmt.Fprint(w, textMatchResponse) 116 }) 117 118 opts := &SearchOptions{Sort: "forks", Order: "desc", ListOptions: ListOptions{Page: 2, PerPage: 2}, TextMatch: true} 119 ctx := context.Background() 120 result, _, err := client.Search.Repositories(ctx, "blah", opts) 121 if err != nil { 122 t.Errorf("Search.Code returned error: %v", err) 123 } 124 125 wantedRepoResult := &Repository{ 126 Name: String("gopher1"), 127 TextMatches: []*TextMatch{{ 128 Fragment: String("I'm afraid my friend what you have found\nIs a gopher who lives to feed"), 129 Matches: []*Match{{Text: String("gopher"), Indices: []int{14, 21}}}, 130 }, 131 }, 132 } 133 134 want := &RepositoriesSearchResult{ 135 Total: Int(1), 136 IncompleteResults: Bool(false), 137 Repositories: []*Repository{wantedRepoResult}, 138 } 139 if !cmp.Equal(result, want) { 140 t.Errorf("Search.Repo returned %+v, want %+v", result, want) 141 } 142 } 143 144 func TestSearchService_Topics(t *testing.T) { 145 client, mux, _, teardown := setup() 146 defer teardown() 147 148 mux.HandleFunc("/search/topics", func(w http.ResponseWriter, r *http.Request) { 149 testMethod(t, r, "GET") 150 testFormValues(t, r, values{ 151 "q": "blah", 152 "page": "2", 153 "per_page": "2", 154 }) 155 156 fmt.Fprint(w, `{"total_count": 4, "incomplete_results": false, "items": [{"name":"blah"},{"name":"blahblah"}]}`) 157 }) 158 159 opts := &SearchOptions{ListOptions: ListOptions{Page: 2, PerPage: 2}} 160 ctx := context.Background() 161 result, _, err := client.Search.Topics(ctx, "blah", opts) 162 if err != nil { 163 t.Errorf("Search.Topics returned error: %v", err) 164 } 165 166 want := &TopicsSearchResult{ 167 Total: Int(4), 168 IncompleteResults: Bool(false), 169 Topics: []*TopicResult{{Name: String("blah")}, {Name: String("blahblah")}}, 170 } 171 if !cmp.Equal(result, want) { 172 t.Errorf("Search.Topics returned %+v, want %+v", result, want) 173 } 174 } 175 176 func TestSearchService_Topics_coverage(t *testing.T) { 177 client, _, _, teardown := setup() 178 defer teardown() 179 180 ctx := context.Background() 181 182 const methodName = "Topics" 183 testBadOptions(t, methodName, func() (err error) { 184 _, _, err = client.Search.Topics(ctx, "\n", nil) 185 return err 186 }) 187 } 188 189 func TestSearchService_Commits(t *testing.T) { 190 client, mux, _, teardown := setup() 191 defer teardown() 192 193 mux.HandleFunc("/search/commits", func(w http.ResponseWriter, r *http.Request) { 194 testMethod(t, r, "GET") 195 testFormValues(t, r, values{ 196 "q": "blah", 197 "sort": "author-date", 198 "order": "desc", 199 }) 200 201 fmt.Fprint(w, `{"total_count": 4, "incomplete_results": false, "items": [{"sha":"random_hash1"},{"sha":"random_hash2"}]}`) 202 }) 203 204 opts := &SearchOptions{Sort: "author-date", Order: "desc"} 205 ctx := context.Background() 206 result, _, err := client.Search.Commits(ctx, "blah", opts) 207 if err != nil { 208 t.Errorf("Search.Commits returned error: %v", err) 209 } 210 211 want := &CommitsSearchResult{ 212 Total: Int(4), 213 IncompleteResults: Bool(false), 214 Commits: []*CommitResult{{SHA: String("random_hash1")}, {SHA: String("random_hash2")}}, 215 } 216 if !cmp.Equal(result, want) { 217 t.Errorf("Search.Commits returned %+v, want %+v", result, want) 218 } 219 } 220 221 func TestSearchService_Commits_coverage(t *testing.T) { 222 client, _, _, teardown := setup() 223 defer teardown() 224 225 ctx := context.Background() 226 227 const methodName = "Commits" 228 testBadOptions(t, methodName, func() (err error) { 229 _, _, err = client.Search.Commits(ctx, "\n", nil) 230 return err 231 }) 232 } 233 234 func TestSearchService_Issues(t *testing.T) { 235 client, mux, _, teardown := setup() 236 defer teardown() 237 238 mux.HandleFunc("/search/issues", func(w http.ResponseWriter, r *http.Request) { 239 testMethod(t, r, "GET") 240 testFormValues(t, r, values{ 241 "q": "blah", 242 "sort": "forks", 243 "order": "desc", 244 "page": "2", 245 "per_page": "2", 246 }) 247 248 fmt.Fprint(w, `{"total_count": 4, "incomplete_results": true, "items": [{"number":1},{"number":2}]}`) 249 }) 250 251 opts := &SearchOptions{Sort: "forks", Order: "desc", ListOptions: ListOptions{Page: 2, PerPage: 2}} 252 ctx := context.Background() 253 result, _, err := client.Search.Issues(ctx, "blah", opts) 254 if err != nil { 255 t.Errorf("Search.Issues returned error: %v", err) 256 } 257 258 want := &IssuesSearchResult{ 259 Total: Int(4), 260 IncompleteResults: Bool(true), 261 Issues: []*Issue{{Number: Int(1)}, {Number: Int(2)}}, 262 } 263 if !cmp.Equal(result, want) { 264 t.Errorf("Search.Issues returned %+v, want %+v", result, want) 265 } 266 } 267 268 func TestSearchService_Issues_coverage(t *testing.T) { 269 client, _, _, teardown := setup() 270 defer teardown() 271 272 ctx := context.Background() 273 274 const methodName = "Issues" 275 testBadOptions(t, methodName, func() (err error) { 276 _, _, err = client.Search.Issues(ctx, "\n", nil) 277 return err 278 }) 279 } 280 281 func TestSearchService_Issues_withQualifiersNoOpts(t *testing.T) { 282 client, mux, _, teardown := setup() 283 defer teardown() 284 285 const q = "gopher is:issue label:bug language:c++ pushed:>=2018-01-01 stars:>=200" 286 287 var requestURI string 288 mux.HandleFunc("/search/issues", func(w http.ResponseWriter, r *http.Request) { 289 testMethod(t, r, "GET") 290 testFormValues(t, r, values{ 291 "q": q, 292 }) 293 requestURI = r.RequestURI 294 295 fmt.Fprint(w, `{"total_count": 4, "incomplete_results": true, "items": [{"number":1},{"number":2}]}`) 296 }) 297 298 opts := &SearchOptions{} 299 ctx := context.Background() 300 result, _, err := client.Search.Issues(ctx, q, opts) 301 if err != nil { 302 t.Errorf("Search.Issues returned error: %v", err) 303 } 304 305 if want := "/api-v3/search/issues?q=gopher+is%3Aissue+label%3Abug+language%3Ac%2B%2B+pushed%3A%3E%3D2018-01-01+stars%3A%3E%3D200"; requestURI != want { 306 t.Fatalf("URI encoding failed: got %v, want %v", requestURI, want) 307 } 308 309 want := &IssuesSearchResult{ 310 Total: Int(4), 311 IncompleteResults: Bool(true), 312 Issues: []*Issue{{Number: Int(1)}, {Number: Int(2)}}, 313 } 314 if !cmp.Equal(result, want) { 315 t.Errorf("Search.Issues returned %+v, want %+v", result, want) 316 } 317 } 318 319 func TestSearchService_Issues_withQualifiersAndOpts(t *testing.T) { 320 client, mux, _, teardown := setup() 321 defer teardown() 322 323 const q = "gopher is:issue label:bug language:c++ pushed:>=2018-01-01 stars:>=200" 324 325 var requestURI string 326 mux.HandleFunc("/search/issues", func(w http.ResponseWriter, r *http.Request) { 327 testMethod(t, r, "GET") 328 testFormValues(t, r, values{ 329 "q": q, 330 "sort": "forks", 331 }) 332 requestURI = r.RequestURI 333 334 fmt.Fprint(w, `{"total_count": 4, "incomplete_results": true, "items": [{"number":1},{"number":2}]}`) 335 }) 336 337 opts := &SearchOptions{Sort: "forks"} 338 ctx := context.Background() 339 result, _, err := client.Search.Issues(ctx, q, opts) 340 if err != nil { 341 t.Errorf("Search.Issues returned error: %v", err) 342 } 343 344 if want := "/api-v3/search/issues?q=gopher+is%3Aissue+label%3Abug+language%3Ac%2B%2B+pushed%3A%3E%3D2018-01-01+stars%3A%3E%3D200&sort=forks"; requestURI != want { 345 t.Fatalf("URI encoding failed: got %v, want %v", requestURI, want) 346 } 347 348 want := &IssuesSearchResult{ 349 Total: Int(4), 350 IncompleteResults: Bool(true), 351 Issues: []*Issue{{Number: Int(1)}, {Number: Int(2)}}, 352 } 353 if !cmp.Equal(result, want) { 354 t.Errorf("Search.Issues returned %+v, want %+v", result, want) 355 } 356 } 357 358 func TestSearchService_Users(t *testing.T) { 359 client, mux, _, teardown := setup() 360 defer teardown() 361 362 mux.HandleFunc("/search/users", func(w http.ResponseWriter, r *http.Request) { 363 testMethod(t, r, "GET") 364 testFormValues(t, r, values{ 365 "q": "blah", 366 "sort": "forks", 367 "order": "desc", 368 "page": "2", 369 "per_page": "2", 370 }) 371 372 fmt.Fprint(w, `{"total_count": 4, "incomplete_results": false, "items": [{"id":1},{"id":2}]}`) 373 }) 374 375 opts := &SearchOptions{Sort: "forks", Order: "desc", ListOptions: ListOptions{Page: 2, PerPage: 2}} 376 ctx := context.Background() 377 result, _, err := client.Search.Users(ctx, "blah", opts) 378 if err != nil { 379 t.Errorf("Search.Issues returned error: %v", err) 380 } 381 382 want := &UsersSearchResult{ 383 Total: Int(4), 384 IncompleteResults: Bool(false), 385 Users: []*User{{ID: Int64(1)}, {ID: Int64(2)}}, 386 } 387 if !cmp.Equal(result, want) { 388 t.Errorf("Search.Users returned %+v, want %+v", result, want) 389 } 390 } 391 392 func TestSearchService_Users_coverage(t *testing.T) { 393 client, _, _, teardown := setup() 394 defer teardown() 395 396 ctx := context.Background() 397 398 const methodName = "Users" 399 testBadOptions(t, methodName, func() (err error) { 400 _, _, err = client.Search.Users(ctx, "\n", nil) 401 return err 402 }) 403 } 404 405 func TestSearchService_Code(t *testing.T) { 406 client, mux, _, teardown := setup() 407 defer teardown() 408 409 mux.HandleFunc("/search/code", func(w http.ResponseWriter, r *http.Request) { 410 testMethod(t, r, "GET") 411 testFormValues(t, r, values{ 412 "q": "blah", 413 "sort": "forks", 414 "order": "desc", 415 "page": "2", 416 "per_page": "2", 417 }) 418 419 fmt.Fprint(w, `{"total_count": 4, "incomplete_results": false, "items": [{"name":"1"},{"name":"2"}]}`) 420 }) 421 422 opts := &SearchOptions{Sort: "forks", Order: "desc", ListOptions: ListOptions{Page: 2, PerPage: 2}} 423 ctx := context.Background() 424 result, _, err := client.Search.Code(ctx, "blah", opts) 425 if err != nil { 426 t.Errorf("Search.Code returned error: %v", err) 427 } 428 429 want := &CodeSearchResult{ 430 Total: Int(4), 431 IncompleteResults: Bool(false), 432 CodeResults: []*CodeResult{{Name: String("1")}, {Name: String("2")}}, 433 } 434 if !cmp.Equal(result, want) { 435 t.Errorf("Search.Code returned %+v, want %+v", result, want) 436 } 437 } 438 439 func TestSearchService_Code_coverage(t *testing.T) { 440 client, _, _, teardown := setup() 441 defer teardown() 442 443 ctx := context.Background() 444 445 const methodName = "Code" 446 testBadOptions(t, methodName, func() (err error) { 447 _, _, err = client.Search.Code(ctx, "\n", nil) 448 return err 449 }) 450 } 451 452 func TestSearchService_CodeTextMatch(t *testing.T) { 453 client, mux, _, teardown := setup() 454 defer teardown() 455 456 mux.HandleFunc("/search/code", func(w http.ResponseWriter, r *http.Request) { 457 testMethod(t, r, "GET") 458 459 textMatchResponse := ` 460 { 461 "total_count": 1, 462 "incomplete_results": false, 463 "items": [ 464 { 465 "name":"gopher1", 466 "text_matches": [ 467 { 468 "fragment": "I'm afraid my friend what you have found\nIs a gopher who lives to feed", 469 "matches": [ 470 { 471 "text": "gopher", 472 "indices": [ 473 14, 474 21 475 ] 476 } 477 ] 478 } 479 ] 480 } 481 ] 482 } 483 ` 484 485 fmt.Fprint(w, textMatchResponse) 486 }) 487 488 opts := &SearchOptions{Sort: "forks", Order: "desc", ListOptions: ListOptions{Page: 2, PerPage: 2}, TextMatch: true} 489 ctx := context.Background() 490 result, _, err := client.Search.Code(ctx, "blah", opts) 491 if err != nil { 492 t.Errorf("Search.Code returned error: %v", err) 493 } 494 495 wantedCodeResult := &CodeResult{ 496 Name: String("gopher1"), 497 TextMatches: []*TextMatch{{ 498 Fragment: String("I'm afraid my friend what you have found\nIs a gopher who lives to feed"), 499 Matches: []*Match{{Text: String("gopher"), Indices: []int{14, 21}}}, 500 }, 501 }, 502 } 503 504 want := &CodeSearchResult{ 505 Total: Int(1), 506 IncompleteResults: Bool(false), 507 CodeResults: []*CodeResult{wantedCodeResult}, 508 } 509 if !cmp.Equal(result, want) { 510 t.Errorf("Search.Code returned %+v, want %+v", result, want) 511 } 512 } 513 514 func TestSearchService_Labels(t *testing.T) { 515 client, mux, _, teardown := setup() 516 defer teardown() 517 518 mux.HandleFunc("/search/labels", func(w http.ResponseWriter, r *http.Request) { 519 testMethod(t, r, "GET") 520 testFormValues(t, r, values{ 521 "repository_id": "1234", 522 "q": "blah", 523 "sort": "updated", 524 "order": "desc", 525 "page": "2", 526 "per_page": "2", 527 }) 528 529 fmt.Fprint(w, `{"total_count": 4, "incomplete_results": false, "items": [{"id": 1234, "name":"bug", "description": "some text"},{"id": 4567, "name":"feature"}]}`) 530 }) 531 532 opts := &SearchOptions{Sort: "updated", Order: "desc", ListOptions: ListOptions{Page: 2, PerPage: 2}} 533 ctx := context.Background() 534 result, _, err := client.Search.Labels(ctx, 1234, "blah", opts) 535 if err != nil { 536 t.Errorf("Search.Code returned error: %v", err) 537 } 538 539 want := &LabelsSearchResult{ 540 Total: Int(4), 541 IncompleteResults: Bool(false), 542 Labels: []*LabelResult{ 543 {ID: Int64(1234), Name: String("bug"), Description: String("some text")}, 544 {ID: Int64(4567), Name: String("feature")}, 545 }, 546 } 547 if !cmp.Equal(result, want) { 548 t.Errorf("Search.Labels returned %+v, want %+v", result, want) 549 } 550 } 551 552 func TestSearchService_Labels_coverage(t *testing.T) { 553 client, _, _, teardown := setup() 554 defer teardown() 555 556 ctx := context.Background() 557 558 const methodName = "Labels" 559 testBadOptions(t, methodName, func() (err error) { 560 _, _, err = client.Search.Labels(ctx, -1234, "\n", nil) 561 return err 562 }) 563 } 564 565 func TestMatch_Marshal(t *testing.T) { 566 testJSONMarshal(t, &Match{}, "{}") 567 568 u := &Match{ 569 Text: String("txt"), 570 Indices: []int{1}, 571 } 572 573 want := `{ 574 "text": "txt", 575 "indices": [1] 576 }` 577 578 testJSONMarshal(t, u, want) 579 } 580 581 func TestTextMatch_Marshal(t *testing.T) { 582 testJSONMarshal(t, &TextMatch{}, "{}") 583 584 u := &TextMatch{ 585 ObjectURL: String("ourl"), 586 ObjectType: String("otype"), 587 Property: String("prop"), 588 Fragment: String("fragment"), 589 Matches: []*Match{ 590 { 591 Text: String("txt"), 592 Indices: []int{1}, 593 }, 594 }, 595 } 596 597 want := `{ 598 "object_url": "ourl", 599 "object_type": "otype", 600 "property": "prop", 601 "fragment": "fragment", 602 "matches": [{ 603 "text": "txt", 604 "indices": [1] 605 }] 606 }` 607 608 testJSONMarshal(t, u, want) 609 } 610 611 func TestTopicResult_Marshal(t *testing.T) { 612 testJSONMarshal(t, &TopicResult{}, "{}") 613 614 u := &TopicResult{ 615 Name: String("name"), 616 DisplayName: String("displayName"), 617 ShortDescription: String("shortDescription"), 618 Description: String("description"), 619 CreatedBy: String("createdBy"), 620 UpdatedAt: String("2021-10-26"), 621 Featured: Bool(false), 622 Curated: Bool(true), 623 Score: Float64(99.9), 624 } 625 626 want := `{ 627 "name": "name", 628 "display_name": "displayName", 629 "short_description": "shortDescription", 630 "description": "description", 631 "created_by": "createdBy", 632 "updated_at": "2021-10-26", 633 "featured": false, 634 "curated": true, 635 "score": 99.9 636 }` 637 638 testJSONMarshal(t, u, want) 639 } 640 641 func TestRepositoriesSearchResult_Marshal(t *testing.T) { 642 testJSONMarshal(t, &RepositoriesSearchResult{}, "{}") 643 644 u := &RepositoriesSearchResult{ 645 Total: Int(0), 646 IncompleteResults: Bool(true), 647 Repositories: []*Repository{{ID: Int64(1)}}, 648 } 649 650 want := `{ 651 "total_count" : 0, 652 "incomplete_results" : true, 653 "items" : [{"id":1}] 654 }` 655 656 testJSONMarshal(t, u, want) 657 } 658 659 func TestCommitsSearchResult_Marshal(t *testing.T) { 660 testJSONMarshal(t, &CommitsSearchResult{}, "{}") 661 662 c := &CommitsSearchResult{ 663 Total: Int(0), 664 IncompleteResults: Bool(true), 665 Commits: []*CommitResult{{ 666 SHA: String("s"), 667 }}, 668 } 669 670 want := `{ 671 "total_count" : 0, 672 "incomplete_results" : true, 673 "items" : [{"sha" : "s"}] 674 }` 675 676 testJSONMarshal(t, c, want) 677 } 678 679 func TestTopicsSearchResult_Marshal(t *testing.T) { 680 testJSONMarshal(t, &TopicsSearchResult{}, "{}") 681 682 u := &TopicsSearchResult{ 683 Total: Int(2), 684 IncompleteResults: Bool(false), 685 Topics: []*TopicResult{ 686 { 687 Name: String("t1"), 688 DisplayName: String("tt"), 689 ShortDescription: String("t desc"), 690 Description: String("desc"), 691 CreatedBy: String("mi"), 692 CreatedAt: &Timestamp{referenceTime}, 693 UpdatedAt: String("2006-01-02T15:04:05Z"), 694 Featured: Bool(true), 695 Curated: Bool(true), 696 Score: Float64(123), 697 }, 698 }, 699 } 700 701 want := `{ 702 "total_count" : 2, 703 "incomplete_results" : false, 704 "items" : [ 705 { 706 "name" : "t1", 707 "display_name":"tt", 708 "short_description":"t desc", 709 "description":"desc", 710 "created_by":"mi", 711 "created_at":` + referenceTimeStr + `, 712 "updated_at":"2006-01-02T15:04:05Z", 713 "featured":true, 714 "curated":true, 715 "score":123 716 } 717 ] 718 }` 719 720 testJSONMarshal(t, u, want) 721 } 722 723 func TestLabelResult_Marshal(t *testing.T) { 724 testJSONMarshal(t, &LabelResult{}, "{}") 725 726 u := &LabelResult{ 727 ID: Int64(11), 728 URL: String("url"), 729 Name: String("label"), 730 Color: String("green"), 731 Default: Bool(true), 732 Description: String("desc"), 733 Score: Float64(123), 734 } 735 736 want := `{ 737 "id":11, 738 "url":"url", 739 "name":"label", 740 "color":"green", 741 "default":true, 742 "description":"desc", 743 "score":123 744 }` 745 746 testJSONMarshal(t, u, want) 747 } 748 749 func TestSearchOptions_Marshal(t *testing.T) { 750 testJSONMarshal(t, &SearchOptions{}, "{}") 751 752 u := &SearchOptions{ 753 Sort: "author-date", 754 Order: "asc", 755 TextMatch: false, 756 ListOptions: ListOptions{ 757 Page: int(1), 758 PerPage: int(10), 759 }, 760 } 761 762 want := `{ 763 "sort": "author-date", 764 "order": "asc", 765 "page": 1, 766 "perPage": 10 767 }` 768 769 testJSONMarshal(t, u, want) 770 } 771 772 func TestIssuesSearchResult_Marshal(t *testing.T) { 773 testJSONMarshal(t, &IssuesSearchResult{}, "{}") 774 775 u := &IssuesSearchResult{ 776 Total: Int(48), 777 IncompleteResults: Bool(false), 778 Issues: []*Issue{ 779 { 780 ID: Int64(1), 781 Number: Int(1), 782 State: String("s"), 783 Locked: Bool(false), 784 Title: String("title"), 785 Body: String("body"), 786 AuthorAssociation: String("aa"), 787 User: &User{ID: Int64(1)}, 788 Labels: []*Label{{ID: Int64(1)}}, 789 Assignee: &User{ID: Int64(1)}, 790 Comments: Int(1), 791 ClosedAt: &referenceTime, 792 CreatedAt: &referenceTime, 793 UpdatedAt: &referenceTime, 794 ClosedBy: &User{ID: Int64(1)}, 795 URL: String("url"), 796 HTMLURL: String("hurl"), 797 CommentsURL: String("curl"), 798 EventsURL: String("eurl"), 799 LabelsURL: String("lurl"), 800 RepositoryURL: String("rurl"), 801 Milestone: &Milestone{ID: Int64(1)}, 802 PullRequestLinks: &PullRequestLinks{URL: String("url")}, 803 Repository: &Repository{ID: Int64(1)}, 804 Reactions: &Reactions{TotalCount: Int(1)}, 805 Assignees: []*User{{ID: Int64(1)}}, 806 NodeID: String("nid"), 807 TextMatches: []*TextMatch{{ObjectURL: String("ourl")}}, 808 ActiveLockReason: String("alr"), 809 }, 810 }, 811 } 812 813 want := `{ 814 "total_count": 48, 815 "incomplete_results": false, 816 "items": [ 817 { 818 "id": 1, 819 "number": 1, 820 "state": "s", 821 "locked": false, 822 "title": "title", 823 "body": "body", 824 "author_association": "aa", 825 "user": { 826 "id": 1 827 }, 828 "labels": [ 829 { 830 "id": 1 831 } 832 ], 833 "assignee": { 834 "id": 1 835 }, 836 "comments": 1, 837 "closed_at": ` + referenceTimeStr + `, 838 "created_at": ` + referenceTimeStr + `, 839 "updated_at": ` + referenceTimeStr + `, 840 "closed_by": { 841 "id": 1 842 }, 843 "url": "url", 844 "html_url": "hurl", 845 "comments_url": "curl", 846 "events_url": "eurl", 847 "labels_url": "lurl", 848 "repository_url": "rurl", 849 "milestone": { 850 "id": 1 851 }, 852 "pull_request": { 853 "url": "url" 854 }, 855 "repository": { 856 "id": 1 857 }, 858 "reactions": { 859 "total_count": 1 860 }, 861 "assignees": [ 862 { 863 "id": 1 864 } 865 ], 866 "node_id": "nid", 867 "text_matches": [ 868 { 869 "object_url": "ourl" 870 } 871 ], 872 "active_lock_reason": "alr" 873 } 874 ] 875 }` 876 877 testJSONMarshal(t, u, want) 878 } 879 880 func TestLabelsSearchResult_Marshal(t *testing.T) { 881 testJSONMarshal(t, &LabelsSearchResult{}, "{}") 882 883 u := &LabelsSearchResult{ 884 Total: Int(5), 885 IncompleteResults: Bool(false), 886 Labels: []*LabelResult{ 887 { 888 ID: Int64(1), 889 URL: String("https://www.test-url.com"), 890 Name: String("test name"), 891 Color: String("green"), 892 Default: Bool(true), 893 Description: String("testDescription"), 894 Score: Float64(1), 895 }, 896 }, 897 } 898 899 want := `{ 900 "total_count": 5, 901 "incomplete_results": false, 902 "items": [ 903 { 904 "id": 1, 905 "url": "https://www.test-url.com", 906 "name": "test name", 907 "color": "green", 908 "default": true, 909 "description": "testDescription", 910 "score": 1 911 } 912 ] 913 }` 914 915 testJSONMarshal(t, u, want) 916 } 917 918 func TestCommitResult_Marshal(t *testing.T) { 919 testJSONMarshal(t, &CommitResult{}, "{}") 920 921 c := &CommitResult{ 922 SHA: String("test"), 923 HTMLURL: String("hurl"), 924 CommentsURL: String("curl"), 925 URL: String("url"), 926 Repository: &Repository{ID: Int64(1)}, 927 Score: Float64(123), 928 Commit: &Commit{SHA: String("test")}, 929 Author: &User{ID: Int64(1)}, 930 Committer: &User{ID: Int64(1)}, 931 Parents: []*Commit{}, 932 } 933 934 want := `{ 935 "sha": "test", 936 "commit": { 937 "sha": "test" 938 }, 939 "author": { 940 "id": 1 941 }, 942 "committer": { 943 "id": 1 944 }, 945 "html_url": "hurl", 946 "url": "url", 947 "comments_url": "curl", 948 "repository": { 949 "id": 1 950 }, 951 "score": 123 952 }` 953 954 testJSONMarshal(t, c, want) 955 } 956 957 func TestUsersSearchResult_Marshal(t *testing.T) { 958 testJSONMarshal(t, &UsersSearchResult{}, "{}") 959 960 u := &UsersSearchResult{ 961 Total: Int(2), 962 IncompleteResults: Bool(false), 963 Users: []*User{{ 964 Login: String("loginTest"), 965 ID: Int64(1), 966 NodeID: String("NodeTest"), 967 AvatarURL: String("AvatarURLTest"), 968 HTMLURL: String("Hurl"), 969 GravatarID: String("gravatarIDTest"), 970 Name: String("nameTest"), 971 }}, 972 } 973 974 want := `{ 975 "total_count": 2, 976 "incomplete_results": false, 977 "items": [ 978 { 979 "login": "loginTest", 980 "id": 1, 981 "node_id": "NodeTest", 982 "avatar_url": "AvatarURLTest", 983 "html_url": "Hurl", 984 "gravatar_id": "gravatarIDTest", 985 "name": "nameTest" 986 } 987 ] 988 }` 989 990 testJSONMarshal(t, u, want) 991 } 992 993 func TestCodeSearchResult_Marshal(t *testing.T) { 994 testJSONMarshal(t, &CodeSearchResult{}, "{}") 995 996 u := &CodeSearchResult{ 997 Total: Int(4), 998 IncompleteResults: Bool(false), 999 CodeResults: []*CodeResult{{Name: String("n")}}, 1000 } 1001 1002 want := `{ 1003 "total_count" : 4, 1004 "incomplete_results" : false, 1005 "items" : [{"name": "n"}] 1006 }` 1007 1008 testJSONMarshal(t, u, want) 1009 }