@@ -989,3 +989,201 @@ func Test_GetPullRequestReviews(t *testing.T) {
989
989
})
990
990
}
991
991
}
992
+
993
+ func Test_CreatePullRequestReview (t * testing.T ) {
994
+ // Verify tool definition once
995
+ mockClient := github .NewClient (nil )
996
+ tool , _ := createPullRequestReview (mockClient , translations .NullTranslationHelper )
997
+
998
+ assert .Equal (t , "create_pull_request_review" , tool .Name )
999
+ assert .NotEmpty (t , tool .Description )
1000
+ assert .Contains (t , tool .InputSchema .Properties , "owner" )
1001
+ assert .Contains (t , tool .InputSchema .Properties , "repo" )
1002
+ assert .Contains (t , tool .InputSchema .Properties , "pull_number" )
1003
+ assert .Contains (t , tool .InputSchema .Properties , "body" )
1004
+ assert .Contains (t , tool .InputSchema .Properties , "event" )
1005
+ assert .Contains (t , tool .InputSchema .Properties , "commit_id" )
1006
+ assert .Contains (t , tool .InputSchema .Properties , "comments" )
1007
+ assert .ElementsMatch (t , tool .InputSchema .Required , []string {"owner" , "repo" , "pull_number" , "event" })
1008
+
1009
+ // Setup mock review for success case
1010
+ mockReview := & github.PullRequestReview {
1011
+ ID : github .Ptr (int64 (301 )),
1012
+ State : github .Ptr ("APPROVED" ),
1013
+ Body : github .Ptr ("Looks good!" ),
1014
+ HTMLURL : github .Ptr ("https://github.com/owner/repo/pull/42#pullrequestreview-301" ),
1015
+ User : & github.User {
1016
+ Login : github .Ptr ("reviewer" ),
1017
+ },
1018
+ CommitID : github .Ptr ("abcdef123456" ),
1019
+ SubmittedAt : & github.Timestamp {Time : time .Now ()},
1020
+ }
1021
+
1022
+ tests := []struct {
1023
+ name string
1024
+ mockedClient * http.Client
1025
+ requestArgs map [string ]interface {}
1026
+ expectError bool
1027
+ expectedReview * github.PullRequestReview
1028
+ expectedErrMsg string
1029
+ }{
1030
+ {
1031
+ name : "successful review creation with body only" ,
1032
+ mockedClient : mock .NewMockedHTTPClient (
1033
+ mock .WithRequestMatch (
1034
+ mock .PostReposPullsReviewsByOwnerByRepoByPullNumber ,
1035
+ mockReview ,
1036
+ ),
1037
+ ),
1038
+ requestArgs : map [string ]interface {}{
1039
+ "owner" : "owner" ,
1040
+ "repo" : "repo" ,
1041
+ "pull_number" : float64 (42 ),
1042
+ "body" : "Looks good!" ,
1043
+ "event" : "APPROVE" ,
1044
+ },
1045
+ expectError : false ,
1046
+ expectedReview : mockReview ,
1047
+ },
1048
+ {
1049
+ name : "successful review creation with commit_id" ,
1050
+ mockedClient : mock .NewMockedHTTPClient (
1051
+ mock .WithRequestMatch (
1052
+ mock .PostReposPullsReviewsByOwnerByRepoByPullNumber ,
1053
+ mockReview ,
1054
+ ),
1055
+ ),
1056
+ requestArgs : map [string ]interface {}{
1057
+ "owner" : "owner" ,
1058
+ "repo" : "repo" ,
1059
+ "pull_number" : float64 (42 ),
1060
+ "body" : "Looks good!" ,
1061
+ "event" : "APPROVE" ,
1062
+ "commit_id" : "abcdef123456" ,
1063
+ },
1064
+ expectError : false ,
1065
+ expectedReview : mockReview ,
1066
+ },
1067
+ {
1068
+ name : "successful review creation with comments" ,
1069
+ mockedClient : mock .NewMockedHTTPClient (
1070
+ mock .WithRequestMatch (
1071
+ mock .PostReposPullsReviewsByOwnerByRepoByPullNumber ,
1072
+ mockReview ,
1073
+ ),
1074
+ ),
1075
+ requestArgs : map [string ]interface {}{
1076
+ "owner" : "owner" ,
1077
+ "repo" : "repo" ,
1078
+ "pull_number" : float64 (42 ),
1079
+ "body" : "Some issues to fix" ,
1080
+ "event" : "REQUEST_CHANGES" ,
1081
+ "comments" : []interface {}{
1082
+ map [string ]interface {}{
1083
+ "path" : "file1.go" ,
1084
+ "position" : float64 (10 ),
1085
+ "body" : "This needs to be fixed" ,
1086
+ },
1087
+ map [string ]interface {}{
1088
+ "path" : "file2.go" ,
1089
+ "position" : float64 (20 ),
1090
+ "body" : "Consider a different approach here" ,
1091
+ },
1092
+ },
1093
+ },
1094
+ expectError : false ,
1095
+ expectedReview : mockReview ,
1096
+ },
1097
+ {
1098
+ name : "invalid comment format" ,
1099
+ mockedClient : mock .NewMockedHTTPClient (
1100
+ mock .WithRequestMatchHandler (
1101
+ mock .PostReposPullsReviewsByOwnerByRepoByPullNumber ,
1102
+ http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
1103
+ w .WriteHeader (http .StatusUnprocessableEntity )
1104
+ _ , _ = w .Write ([]byte (`{"message": "Invalid comment format"}` ))
1105
+ }),
1106
+ ),
1107
+ ),
1108
+ requestArgs : map [string ]interface {}{
1109
+ "owner" : "owner" ,
1110
+ "repo" : "repo" ,
1111
+ "pull_number" : float64 (42 ),
1112
+ "event" : "REQUEST_CHANGES" ,
1113
+ "comments" : []interface {}{
1114
+ map [string ]interface {}{
1115
+ "path" : "file1.go" ,
1116
+ // missing position
1117
+ "body" : "This needs to be fixed" ,
1118
+ },
1119
+ },
1120
+ },
1121
+ expectError : false ,
1122
+ expectedErrMsg : "each comment must have a position" ,
1123
+ },
1124
+ {
1125
+ name : "review creation fails" ,
1126
+ mockedClient : mock .NewMockedHTTPClient (
1127
+ mock .WithRequestMatchHandler (
1128
+ mock .PostReposPullsReviewsByOwnerByRepoByPullNumber ,
1129
+ http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
1130
+ w .WriteHeader (http .StatusUnprocessableEntity )
1131
+ _ , _ = w .Write ([]byte (`{"message": "Invalid comment format"}` ))
1132
+ }),
1133
+ ),
1134
+ ),
1135
+ requestArgs : map [string ]interface {}{
1136
+ "owner" : "owner" ,
1137
+ "repo" : "repo" ,
1138
+ "pull_number" : float64 (42 ),
1139
+ "body" : "Looks good!" ,
1140
+ "event" : "APPROVE" ,
1141
+ },
1142
+ expectError : true ,
1143
+ expectedErrMsg : "failed to create pull request review" ,
1144
+ },
1145
+ }
1146
+
1147
+ for _ , tc := range tests {
1148
+ t .Run (tc .name , func (t * testing.T ) {
1149
+ // Setup client with mock
1150
+ client := github .NewClient (tc .mockedClient )
1151
+ _ , handler := createPullRequestReview (client , translations .NullTranslationHelper )
1152
+
1153
+ // Create call request
1154
+ request := createMCPRequest (tc .requestArgs )
1155
+
1156
+ // Call handler
1157
+ result , err := handler (context .Background (), request )
1158
+
1159
+ // Verify results
1160
+ if tc .expectError {
1161
+ require .Error (t , err )
1162
+ assert .Contains (t , err .Error (), tc .expectedErrMsg )
1163
+ return
1164
+ }
1165
+
1166
+ require .NoError (t , err )
1167
+
1168
+ // For error messages in the result
1169
+ if tc .expectedErrMsg != "" {
1170
+ textContent := getTextResult (t , result )
1171
+ assert .Contains (t , textContent .Text , tc .expectedErrMsg )
1172
+ return
1173
+ }
1174
+
1175
+ // Parse the result and get the text content if no error
1176
+ textContent := getTextResult (t , result )
1177
+
1178
+ // Unmarshal and verify the result
1179
+ var returnedReview github.PullRequestReview
1180
+ err = json .Unmarshal ([]byte (textContent .Text ), & returnedReview )
1181
+ require .NoError (t , err )
1182
+ assert .Equal (t , * tc .expectedReview .ID , * returnedReview .ID )
1183
+ assert .Equal (t , * tc .expectedReview .State , * returnedReview .State )
1184
+ assert .Equal (t , * tc .expectedReview .Body , * returnedReview .Body )
1185
+ assert .Equal (t , * tc .expectedReview .User .Login , * returnedReview .User .Login )
1186
+ assert .Equal (t , * tc .expectedReview .HTMLURL , * returnedReview .HTMLURL )
1187
+ })
1188
+ }
1189
+ }
0 commit comments