github.com/google/go-github/v68@v68.0.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 t.Parallel() 20 client, mux, _ := setup(t) 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: Ptr(4), 44 IncompleteResults: Ptr(false), 45 Repositories: []*Repository{{ID: Ptr(int64(1))}, {ID: Ptr(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 t.Parallel() 54 client, _, _ := setup(t) 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 t.Parallel() 67 client, mux, _ := setup(t) 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: Ptr("gopher1"), 127 TextMatches: []*TextMatch{{ 128 Fragment: Ptr("I'm afraid my friend what you have found\nIs a gopher who lives to feed"), 129 Matches: []*Match{{Text: Ptr("gopher"), Indices: []int{14, 21}}}, 130 }, 131 }, 132 } 133 134 want := &RepositoriesSearchResult{ 135 Total: Ptr(1), 136 IncompleteResults: Ptr(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 t.Parallel() 146 client, mux, _ := setup(t) 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: Ptr(4), 168 IncompleteResults: Ptr(false), 169 Topics: []*TopicResult{{Name: Ptr("blah")}, {Name: Ptr("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 t.Parallel() 178 client, _, _ := setup(t) 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 t.Parallel() 191 client, mux, _ := setup(t) 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: Ptr(4), 213 IncompleteResults: Ptr(false), 214 Commits: []*CommitResult{{SHA: Ptr("random_hash1")}, {SHA: Ptr("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 t.Parallel() 223 client, _, _ := setup(t) 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 t.Parallel() 236 client, mux, _ := setup(t) 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: Ptr(4), 260 IncompleteResults: Ptr(true), 261 Issues: []*Issue{{Number: Ptr(1)}, {Number: Ptr(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 t.Parallel() 270 client, _, _ := setup(t) 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 t.Parallel() 283 client, mux, _ := setup(t) 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: Ptr(4), 311 IncompleteResults: Ptr(true), 312 Issues: []*Issue{{Number: Ptr(1)}, {Number: Ptr(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 t.Parallel() 321 client, mux, _ := setup(t) 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: Ptr(4), 350 IncompleteResults: Ptr(true), 351 Issues: []*Issue{{Number: Ptr(1)}, {Number: Ptr(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 t.Parallel() 360 client, mux, _ := setup(t) 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: Ptr(4), 384 IncompleteResults: Ptr(false), 385 Users: []*User{{ID: Ptr(int64(1))}, {ID: Ptr(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 t.Parallel() 394 client, _, _ := setup(t) 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 t.Parallel() 407 client, mux, _ := setup(t) 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: Ptr(4), 431 IncompleteResults: Ptr(false), 432 CodeResults: []*CodeResult{{Name: Ptr("1")}, {Name: Ptr("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 t.Parallel() 441 client, _, _ := setup(t) 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 t.Parallel() 454 client, mux, _ := setup(t) 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: Ptr("gopher1"), 497 TextMatches: []*TextMatch{{ 498 Fragment: Ptr("I'm afraid my friend what you have found\nIs a gopher who lives to feed"), 499 Matches: []*Match{{Text: Ptr("gopher"), Indices: []int{14, 21}}}, 500 }, 501 }, 502 } 503 504 want := &CodeSearchResult{ 505 Total: Ptr(1), 506 IncompleteResults: Ptr(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 t.Parallel() 516 client, mux, _ := setup(t) 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: Ptr(4), 541 IncompleteResults: Ptr(false), 542 Labels: []*LabelResult{ 543 {ID: Ptr(int64(1234)), Name: Ptr("bug"), Description: Ptr("some text")}, 544 {ID: Ptr(int64(4567)), Name: Ptr("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 t.Parallel() 554 client, _, _ := setup(t) 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 t.Parallel() 567 testJSONMarshal(t, &Match{}, "{}") 568 569 u := &Match{ 570 Text: Ptr("txt"), 571 Indices: []int{1}, 572 } 573 574 want := `{ 575 "text": "txt", 576 "indices": [1] 577 }` 578 579 testJSONMarshal(t, u, want) 580 } 581 582 func TestTextMatch_Marshal(t *testing.T) { 583 t.Parallel() 584 testJSONMarshal(t, &TextMatch{}, "{}") 585 586 u := &TextMatch{ 587 ObjectURL: Ptr("ourl"), 588 ObjectType: Ptr("otype"), 589 Property: Ptr("prop"), 590 Fragment: Ptr("fragment"), 591 Matches: []*Match{ 592 { 593 Text: Ptr("txt"), 594 Indices: []int{1}, 595 }, 596 }, 597 } 598 599 want := `{ 600 "object_url": "ourl", 601 "object_type": "otype", 602 "property": "prop", 603 "fragment": "fragment", 604 "matches": [{ 605 "text": "txt", 606 "indices": [1] 607 }] 608 }` 609 610 testJSONMarshal(t, u, want) 611 } 612 613 func TestTopicResult_Marshal(t *testing.T) { 614 t.Parallel() 615 testJSONMarshal(t, &TopicResult{}, "{}") 616 617 u := &TopicResult{ 618 Name: Ptr("name"), 619 DisplayName: Ptr("displayName"), 620 ShortDescription: Ptr("shortDescription"), 621 Description: Ptr("description"), 622 CreatedBy: Ptr("createdBy"), 623 UpdatedAt: Ptr("2021-10-26"), 624 Featured: Ptr(false), 625 Curated: Ptr(true), 626 Score: Ptr(99.9), 627 } 628 629 want := `{ 630 "name": "name", 631 "display_name": "displayName", 632 "short_description": "shortDescription", 633 "description": "description", 634 "created_by": "createdBy", 635 "updated_at": "2021-10-26", 636 "featured": false, 637 "curated": true, 638 "score": 99.9 639 }` 640 641 testJSONMarshal(t, u, want) 642 } 643 644 func TestRepositoriesSearchResult_Marshal(t *testing.T) { 645 t.Parallel() 646 testJSONMarshal(t, &RepositoriesSearchResult{}, "{}") 647 648 u := &RepositoriesSearchResult{ 649 Total: Ptr(0), 650 IncompleteResults: Ptr(true), 651 Repositories: []*Repository{{ID: Ptr(int64(1))}}, 652 } 653 654 want := `{ 655 "total_count" : 0, 656 "incomplete_results" : true, 657 "items" : [{"id":1}] 658 }` 659 660 testJSONMarshal(t, u, want) 661 } 662 663 func TestCommitsSearchResult_Marshal(t *testing.T) { 664 t.Parallel() 665 testJSONMarshal(t, &CommitsSearchResult{}, "{}") 666 667 c := &CommitsSearchResult{ 668 Total: Ptr(0), 669 IncompleteResults: Ptr(true), 670 Commits: []*CommitResult{{ 671 SHA: Ptr("s"), 672 }}, 673 } 674 675 want := `{ 676 "total_count" : 0, 677 "incomplete_results" : true, 678 "items" : [{"sha" : "s"}] 679 }` 680 681 testJSONMarshal(t, c, want) 682 } 683 684 func TestTopicsSearchResult_Marshal(t *testing.T) { 685 t.Parallel() 686 testJSONMarshal(t, &TopicsSearchResult{}, "{}") 687 688 u := &TopicsSearchResult{ 689 Total: Ptr(2), 690 IncompleteResults: Ptr(false), 691 Topics: []*TopicResult{ 692 { 693 Name: Ptr("t1"), 694 DisplayName: Ptr("tt"), 695 ShortDescription: Ptr("t desc"), 696 Description: Ptr("desc"), 697 CreatedBy: Ptr("mi"), 698 CreatedAt: &Timestamp{referenceTime}, 699 UpdatedAt: Ptr("2006-01-02T15:04:05Z"), 700 Featured: Ptr(true), 701 Curated: Ptr(true), 702 Score: Ptr(123.0), 703 }, 704 }, 705 } 706 707 want := `{ 708 "total_count" : 2, 709 "incomplete_results" : false, 710 "items" : [ 711 { 712 "name" : "t1", 713 "display_name":"tt", 714 "short_description":"t desc", 715 "description":"desc", 716 "created_by":"mi", 717 "created_at":` + referenceTimeStr + `, 718 "updated_at":"2006-01-02T15:04:05Z", 719 "featured":true, 720 "curated":true, 721 "score":123 722 } 723 ] 724 }` 725 726 testJSONMarshal(t, u, want) 727 } 728 729 func TestLabelResult_Marshal(t *testing.T) { 730 t.Parallel() 731 testJSONMarshal(t, &LabelResult{}, "{}") 732 733 u := &LabelResult{ 734 ID: Ptr(int64(11)), 735 URL: Ptr("url"), 736 Name: Ptr("label"), 737 Color: Ptr("green"), 738 Default: Ptr(true), 739 Description: Ptr("desc"), 740 Score: Ptr(123.0), 741 } 742 743 want := `{ 744 "id":11, 745 "url":"url", 746 "name":"label", 747 "color":"green", 748 "default":true, 749 "description":"desc", 750 "score":123 751 }` 752 753 testJSONMarshal(t, u, want) 754 } 755 756 func TestSearchOptions_Marshal(t *testing.T) { 757 t.Parallel() 758 testJSONMarshal(t, &SearchOptions{}, "{}") 759 760 u := &SearchOptions{ 761 Sort: "author-date", 762 Order: "asc", 763 TextMatch: false, 764 ListOptions: ListOptions{ 765 Page: int(1), 766 PerPage: int(10), 767 }, 768 } 769 770 want := `{ 771 "sort": "author-date", 772 "order": "asc", 773 "page": 1, 774 "perPage": 10 775 }` 776 777 testJSONMarshal(t, u, want) 778 } 779 780 func TestIssuesSearchResult_Marshal(t *testing.T) { 781 t.Parallel() 782 testJSONMarshal(t, &IssuesSearchResult{}, "{}") 783 784 u := &IssuesSearchResult{ 785 Total: Ptr(48), 786 IncompleteResults: Ptr(false), 787 Issues: []*Issue{ 788 { 789 ID: Ptr(int64(1)), 790 Number: Ptr(1), 791 State: Ptr("s"), 792 Locked: Ptr(false), 793 Title: Ptr("title"), 794 Body: Ptr("body"), 795 AuthorAssociation: Ptr("aa"), 796 User: &User{ID: Ptr(int64(1))}, 797 Labels: []*Label{{ID: Ptr(int64(1))}}, 798 Assignee: &User{ID: Ptr(int64(1))}, 799 Comments: Ptr(1), 800 ClosedAt: &Timestamp{referenceTime}, 801 CreatedAt: &Timestamp{referenceTime}, 802 UpdatedAt: &Timestamp{referenceTime}, 803 ClosedBy: &User{ID: Ptr(int64(1))}, 804 URL: Ptr("url"), 805 HTMLURL: Ptr("hurl"), 806 CommentsURL: Ptr("curl"), 807 EventsURL: Ptr("eurl"), 808 LabelsURL: Ptr("lurl"), 809 RepositoryURL: Ptr("rurl"), 810 Milestone: &Milestone{ID: Ptr(int64(1))}, 811 PullRequestLinks: &PullRequestLinks{URL: Ptr("url")}, 812 Repository: &Repository{ID: Ptr(int64(1))}, 813 Reactions: &Reactions{TotalCount: Ptr(1)}, 814 Assignees: []*User{{ID: Ptr(int64(1))}}, 815 NodeID: Ptr("nid"), 816 TextMatches: []*TextMatch{{ObjectURL: Ptr("ourl")}}, 817 ActiveLockReason: Ptr("alr"), 818 }, 819 }, 820 } 821 822 want := `{ 823 "total_count": 48, 824 "incomplete_results": false, 825 "items": [ 826 { 827 "id": 1, 828 "number": 1, 829 "state": "s", 830 "locked": false, 831 "title": "title", 832 "body": "body", 833 "author_association": "aa", 834 "user": { 835 "id": 1 836 }, 837 "labels": [ 838 { 839 "id": 1 840 } 841 ], 842 "assignee": { 843 "id": 1 844 }, 845 "comments": 1, 846 "closed_at": ` + referenceTimeStr + `, 847 "created_at": ` + referenceTimeStr + `, 848 "updated_at": ` + referenceTimeStr + `, 849 "closed_by": { 850 "id": 1 851 }, 852 "url": "url", 853 "html_url": "hurl", 854 "comments_url": "curl", 855 "events_url": "eurl", 856 "labels_url": "lurl", 857 "repository_url": "rurl", 858 "milestone": { 859 "id": 1 860 }, 861 "pull_request": { 862 "url": "url" 863 }, 864 "repository": { 865 "id": 1 866 }, 867 "reactions": { 868 "total_count": 1 869 }, 870 "assignees": [ 871 { 872 "id": 1 873 } 874 ], 875 "node_id": "nid", 876 "text_matches": [ 877 { 878 "object_url": "ourl" 879 } 880 ], 881 "active_lock_reason": "alr" 882 } 883 ] 884 }` 885 886 testJSONMarshal(t, u, want) 887 } 888 889 func TestLabelsSearchResult_Marshal(t *testing.T) { 890 t.Parallel() 891 testJSONMarshal(t, &LabelsSearchResult{}, "{}") 892 893 u := &LabelsSearchResult{ 894 Total: Ptr(5), 895 IncompleteResults: Ptr(false), 896 Labels: []*LabelResult{ 897 { 898 ID: Ptr(int64(1)), 899 URL: Ptr("https://www.test-url.com"), 900 Name: Ptr("test name"), 901 Color: Ptr("green"), 902 Default: Ptr(true), 903 Description: Ptr("testDescription"), 904 Score: Ptr(1.0), 905 }, 906 }, 907 } 908 909 want := `{ 910 "total_count": 5, 911 "incomplete_results": false, 912 "items": [ 913 { 914 "id": 1, 915 "url": "https://www.test-url.com", 916 "name": "test name", 917 "color": "green", 918 "default": true, 919 "description": "testDescription", 920 "score": 1 921 } 922 ] 923 }` 924 925 testJSONMarshal(t, u, want) 926 } 927 928 func TestCommitResult_Marshal(t *testing.T) { 929 t.Parallel() 930 testJSONMarshal(t, &CommitResult{}, "{}") 931 932 c := &CommitResult{ 933 SHA: Ptr("test"), 934 HTMLURL: Ptr("hurl"), 935 CommentsURL: Ptr("curl"), 936 URL: Ptr("url"), 937 Repository: &Repository{ID: Ptr(int64(1))}, 938 Score: Ptr(123.0), 939 Commit: &Commit{SHA: Ptr("test")}, 940 Author: &User{ID: Ptr(int64(1))}, 941 Committer: &User{ID: Ptr(int64(1))}, 942 Parents: []*Commit{}, 943 } 944 945 want := `{ 946 "sha": "test", 947 "commit": { 948 "sha": "test" 949 }, 950 "author": { 951 "id": 1 952 }, 953 "committer": { 954 "id": 1 955 }, 956 "html_url": "hurl", 957 "url": "url", 958 "comments_url": "curl", 959 "repository": { 960 "id": 1 961 }, 962 "score": 123 963 }` 964 965 testJSONMarshal(t, c, want) 966 } 967 968 func TestUsersSearchResult_Marshal(t *testing.T) { 969 t.Parallel() 970 testJSONMarshal(t, &UsersSearchResult{}, "{}") 971 972 u := &UsersSearchResult{ 973 Total: Ptr(2), 974 IncompleteResults: Ptr(false), 975 Users: []*User{{ 976 Login: Ptr("loginTest"), 977 ID: Ptr(int64(1)), 978 NodeID: Ptr("NodeTest"), 979 AvatarURL: Ptr("AvatarURLTest"), 980 HTMLURL: Ptr("Hurl"), 981 GravatarID: Ptr("gravatarIDTest"), 982 Name: Ptr("nameTest"), 983 }}, 984 } 985 986 want := `{ 987 "total_count": 2, 988 "incomplete_results": false, 989 "items": [ 990 { 991 "login": "loginTest", 992 "id": 1, 993 "node_id": "NodeTest", 994 "avatar_url": "AvatarURLTest", 995 "html_url": "Hurl", 996 "gravatar_id": "gravatarIDTest", 997 "name": "nameTest" 998 } 999 ] 1000 }` 1001 1002 testJSONMarshal(t, u, want) 1003 } 1004 1005 func TestCodeSearchResult_Marshal(t *testing.T) { 1006 t.Parallel() 1007 testJSONMarshal(t, &CodeSearchResult{}, "{}") 1008 1009 u := &CodeSearchResult{ 1010 Total: Ptr(4), 1011 IncompleteResults: Ptr(false), 1012 CodeResults: []*CodeResult{{Name: Ptr("n")}}, 1013 } 1014 1015 want := `{ 1016 "total_count" : 4, 1017 "incomplete_results" : false, 1018 "items" : [{"name": "n"}] 1019 }` 1020 1021 testJSONMarshal(t, u, want) 1022 }