@@ -565,6 +565,162 @@ func Test_MergePullRequest(t *testing.T) {
565
565
}
566
566
}
567
567
568
+ func Test_SearchPullRequests (t * testing.T ) {
569
+ mockClient := github .NewClient (nil )
570
+ tool , _ := SearchPullRequests (stubGetClientFn (mockClient ), translations .NullTranslationHelper )
571
+ require .NoError (t , toolsnaps .Test (tool .Name , tool ))
572
+
573
+ assert .Equal (t , "search_pull_requests" , tool .Name )
574
+ assert .NotEmpty (t , tool .Description )
575
+ assert .Contains (t , tool .InputSchema .Properties , "q" )
576
+ assert .Contains (t , tool .InputSchema .Properties , "sort" )
577
+ assert .Contains (t , tool .InputSchema .Properties , "order" )
578
+ assert .Contains (t , tool .InputSchema .Properties , "perPage" )
579
+ assert .Contains (t , tool .InputSchema .Properties , "page" )
580
+ assert .ElementsMatch (t , tool .InputSchema .Required , []string {"q" })
581
+
582
+ mockSearchResult := & github.IssuesSearchResult {
583
+ Total : github .Ptr (2 ),
584
+ IncompleteResults : github .Ptr (false ),
585
+ Issues : []* github.Issue {
586
+ {
587
+ Number : github .Ptr (42 ),
588
+ Title : github .Ptr ("Test PR 1" ),
589
+ Body : github .Ptr ("Updated tests." ),
590
+ State : github .Ptr ("open" ),
591
+ HTMLURL : github .Ptr ("https://github.com/owner/repo/pull/1" ),
592
+ Comments : github .Ptr (5 ),
593
+ User : & github.User {
594
+ Login : github .Ptr ("user1" ),
595
+ },
596
+ },
597
+ {
598
+ Number : github .Ptr (43 ),
599
+ Title : github .Ptr ("Test PR 2" ),
600
+ Body : github .Ptr ("Updated build scripts." ),
601
+ State : github .Ptr ("open" ),
602
+ HTMLURL : github .Ptr ("https://github.com/owner/repo/pull/2" ),
603
+ Comments : github .Ptr (3 ),
604
+ User : & github.User {
605
+ Login : github .Ptr ("user2" ),
606
+ },
607
+ },
608
+ },
609
+ }
610
+
611
+ tests := []struct {
612
+ name string
613
+ mockedClient * http.Client
614
+ requestArgs map [string ]interface {}
615
+ expectError bool
616
+ expectedResult * github.IssuesSearchResult
617
+ expectedErrMsg string
618
+ }{
619
+ {
620
+ name : "successful pull request search with all parameters" ,
621
+ mockedClient : mock .NewMockedHTTPClient (
622
+ mock .WithRequestMatchHandler (
623
+ mock .GetSearchIssues ,
624
+ expectQueryParams (
625
+ t ,
626
+ map [string ]string {
627
+ "q" : "repo:owner/repo is:pr is:open" ,
628
+ "sort" : "created" ,
629
+ "order" : "desc" ,
630
+ "page" : "1" ,
631
+ "per_page" : "30" ,
632
+ },
633
+ ).andThen (
634
+ mockResponse (t , http .StatusOK , mockSearchResult ),
635
+ ),
636
+ ),
637
+ ),
638
+ requestArgs : map [string ]interface {}{
639
+ "q" : "repo:owner/repo is:pr is:open" ,
640
+ "sort" : "created" ,
641
+ "order" : "desc" ,
642
+ "page" : float64 (1 ),
643
+ "perPage" : float64 (30 ),
644
+ },
645
+ expectError : false ,
646
+ expectedResult : mockSearchResult ,
647
+ },
648
+ {
649
+ name : "pull request search with minimal parameters" ,
650
+ mockedClient : mock .NewMockedHTTPClient (
651
+ mock .WithRequestMatch (
652
+ mock .GetSearchIssues ,
653
+ mockSearchResult ,
654
+ ),
655
+ ),
656
+ requestArgs : map [string ]interface {}{
657
+ "q" : "repo:owner/repo is:pr is:open" ,
658
+ },
659
+ expectError : false ,
660
+ expectedResult : mockSearchResult ,
661
+ },
662
+ {
663
+ name : "search pull requests fails" ,
664
+ mockedClient : mock .NewMockedHTTPClient (
665
+ mock .WithRequestMatchHandler (
666
+ mock .GetSearchIssues ,
667
+ http .HandlerFunc (func (w http.ResponseWriter , _ * http.Request ) {
668
+ w .WriteHeader (http .StatusBadRequest )
669
+ _ , _ = w .Write ([]byte (`{"message": "Validation Failed"}` ))
670
+ }),
671
+ ),
672
+ ),
673
+ requestArgs : map [string ]interface {}{
674
+ "q" : "invalid:query" ,
675
+ },
676
+ expectError : true ,
677
+ expectedErrMsg : "failed to search issues" ,
678
+ },
679
+ }
680
+
681
+ for _ , tc := range tests {
682
+ t .Run (tc .name , func (t * testing.T ) {
683
+ // Setup client with mock
684
+ client := github .NewClient (tc .mockedClient )
685
+ _ , handler := SearchIssues (stubGetClientFn (client ), translations .NullTranslationHelper )
686
+
687
+ // Create call request
688
+ request := createMCPRequest (tc .requestArgs )
689
+
690
+ // Call handler
691
+ result , err := handler (context .Background (), request )
692
+
693
+ // Verify results
694
+ if tc .expectError {
695
+ require .Error (t , err )
696
+ assert .Contains (t , err .Error (), tc .expectedErrMsg )
697
+ return
698
+ }
699
+
700
+ require .NoError (t , err )
701
+
702
+ // Parse the result and get the text content if no error
703
+ textContent := getTextResult (t , result )
704
+
705
+ // Unmarshal and verify the result
706
+ var returnedResult github.IssuesSearchResult
707
+ err = json .Unmarshal ([]byte (textContent .Text ), & returnedResult )
708
+ require .NoError (t , err )
709
+ assert .Equal (t , * tc .expectedResult .Total , * returnedResult .Total )
710
+ assert .Equal (t , * tc .expectedResult .IncompleteResults , * returnedResult .IncompleteResults )
711
+ assert .Len (t , returnedResult .Issues , len (tc .expectedResult .Issues ))
712
+ for i , issue := range returnedResult .Issues {
713
+ assert .Equal (t , * tc .expectedResult .Issues [i ].Number , * issue .Number )
714
+ assert .Equal (t , * tc .expectedResult .Issues [i ].Title , * issue .Title )
715
+ assert .Equal (t , * tc .expectedResult .Issues [i ].State , * issue .State )
716
+ assert .Equal (t , * tc .expectedResult .Issues [i ].HTMLURL , * issue .HTMLURL )
717
+ assert .Equal (t , * tc .expectedResult .Issues [i ].User .Login , * issue .User .Login )
718
+ }
719
+ })
720
+ }
721
+
722
+ }
723
+
568
724
func Test_GetPullRequestFiles (t * testing.T ) {
569
725
// Verify tool definition once
570
726
mockClient := github .NewClient (nil )
0 commit comments