@@ -924,3 +924,195 @@ func Test_ListDiscussionCategories(t *testing.T) {
924924 })
925925 }
926926}
927+
928+ func Test_AddDiscussionComment (t * testing.T ) {
929+ t .Parallel ()
930+
931+ // Verify tool definition and schema
932+ toolDef := AddDiscussionComment (translations .NullTranslationHelper )
933+ tool := toolDef .Tool
934+ require .NoError (t , toolsnaps .Test (tool .Name , tool ))
935+
936+ assert .Equal (t , "add_discussion_comment" , tool .Name )
937+ assert .NotEmpty (t , tool .Description )
938+ assert .False (t , tool .Annotations .ReadOnlyHint , "add_discussion_comment should not be read-only" )
939+ schema , ok := tool .InputSchema .(* jsonschema.Schema )
940+ require .True (t , ok , "InputSchema should be *jsonschema.Schema" )
941+ assert .Contains (t , schema .Properties , "owner" )
942+ assert .Contains (t , schema .Properties , "repo" )
943+ assert .Contains (t , schema .Properties , "discussionNumber" )
944+ assert .Contains (t , schema .Properties , "body" )
945+ assert .ElementsMatch (t , schema .Required , []string {"owner" , "repo" , "discussionNumber" , "body" })
946+
947+ tests := []struct {
948+ name string
949+ requestArgs map [string ]any
950+ mockedClient * http.Client
951+ expectToolError bool
952+ expectedErrMsg string
953+ expectedID string
954+ expectedURL string
955+ }{
956+ {
957+ name : "successful comment creation" ,
958+ requestArgs : map [string ]any {
959+ "owner" : "owner" ,
960+ "repo" : "repo" ,
961+ "discussionNumber" : int32 (1 ),
962+ "body" : "This is a test comment" ,
963+ },
964+ mockedClient : githubv4mock .NewMockedHTTPClient (
965+ githubv4mock .NewQueryMatcher (
966+ struct {
967+ Repository struct {
968+ Discussion struct {
969+ ID githubv4.ID
970+ } `graphql:"discussion(number: $discussionNumber)"`
971+ } `graphql:"repository(owner: $owner, name: $repo)"`
972+ }{},
973+ map [string ]any {
974+ "owner" : githubv4 .String ("owner" ),
975+ "repo" : githubv4 .String ("repo" ),
976+ "discussionNumber" : githubv4 .Int (1 ),
977+ },
978+ githubv4mock .DataResponse (map [string ]any {
979+ "repository" : map [string ]any {
980+ "discussion" : map [string ]any {
981+ "id" : "D_kwDOTest123" ,
982+ },
983+ },
984+ }),
985+ ),
986+ githubv4mock .NewMutationMatcher (
987+ struct {
988+ AddDiscussionComment struct {
989+ Comment struct {
990+ ID githubv4.ID
991+ URL githubv4.String `graphql:"url"`
992+ }
993+ } `graphql:"addDiscussionComment(input: $input)"`
994+ }{},
995+ githubv4.AddDiscussionCommentInput {
996+ DiscussionID : githubv4 .ID ("D_kwDOTest123" ),
997+ Body : githubv4 .String ("This is a test comment" ),
998+ },
999+ nil ,
1000+ githubv4mock .DataResponse (map [string ]any {
1001+ "addDiscussionComment" : map [string ]any {
1002+ "comment" : map [string ]any {
1003+ "id" : "DC_kwDOComment456" ,
1004+ "url" : "https://github.com/owner/repo/discussions/1#discussioncomment-456" ,
1005+ },
1006+ },
1007+ }),
1008+ ),
1009+ ),
1010+ expectToolError : false ,
1011+ expectedID : "DC_kwDOComment456" ,
1012+ expectedURL : "https://github.com/owner/repo/discussions/1#discussioncomment-456" ,
1013+ },
1014+ {
1015+ name : "discussion not found" ,
1016+ requestArgs : map [string ]any {
1017+ "owner" : "owner" ,
1018+ "repo" : "repo" ,
1019+ "discussionNumber" : int32 (999 ),
1020+ "body" : "This is a comment" ,
1021+ },
1022+ mockedClient : githubv4mock .NewMockedHTTPClient (
1023+ githubv4mock .NewQueryMatcher (
1024+ struct {
1025+ Repository struct {
1026+ Discussion struct {
1027+ ID githubv4.ID
1028+ } `graphql:"discussion(number: $discussionNumber)"`
1029+ } `graphql:"repository(owner: $owner, name: $repo)"`
1030+ }{},
1031+ map [string ]any {
1032+ "owner" : githubv4 .String ("owner" ),
1033+ "repo" : githubv4 .String ("repo" ),
1034+ "discussionNumber" : githubv4 .Int (999 ),
1035+ },
1036+ githubv4mock .ErrorResponse ("Could not resolve to a Discussion with the number of 999." ),
1037+ ),
1038+ ),
1039+ expectToolError : true ,
1040+ expectedErrMsg : "Could not resolve to a Discussion with the number of 999." ,
1041+ },
1042+ {
1043+ name : "mutation failure" ,
1044+ requestArgs : map [string ]any {
1045+ "owner" : "owner" ,
1046+ "repo" : "repo" ,
1047+ "discussionNumber" : int32 (1 ),
1048+ "body" : "This is a comment" ,
1049+ },
1050+ mockedClient : githubv4mock .NewMockedHTTPClient (
1051+ githubv4mock .NewQueryMatcher (
1052+ struct {
1053+ Repository struct {
1054+ Discussion struct {
1055+ ID githubv4.ID
1056+ } `graphql:"discussion(number: $discussionNumber)"`
1057+ } `graphql:"repository(owner: $owner, name: $repo)"`
1058+ }{},
1059+ map [string ]any {
1060+ "owner" : githubv4 .String ("owner" ),
1061+ "repo" : githubv4 .String ("repo" ),
1062+ "discussionNumber" : githubv4 .Int (1 ),
1063+ },
1064+ githubv4mock .DataResponse (map [string ]any {
1065+ "repository" : map [string ]any {
1066+ "discussion" : map [string ]any {
1067+ "id" : "D_kwDOTest123" ,
1068+ },
1069+ },
1070+ }),
1071+ ),
1072+ githubv4mock .NewMutationMatcher (
1073+ struct {
1074+ AddDiscussionComment struct {
1075+ Comment struct {
1076+ ID githubv4.ID
1077+ URL githubv4.String `graphql:"url"`
1078+ }
1079+ } `graphql:"addDiscussionComment(input: $input)"`
1080+ }{},
1081+ githubv4.AddDiscussionCommentInput {
1082+ DiscussionID : githubv4 .ID ("D_kwDOTest123" ),
1083+ Body : githubv4 .String ("This is a comment" ),
1084+ },
1085+ nil ,
1086+ githubv4mock .ErrorResponse ("insufficient permissions to comment on this discussion" ),
1087+ ),
1088+ ),
1089+ expectToolError : true ,
1090+ expectedErrMsg : "insufficient permissions to comment on this discussion" ,
1091+ },
1092+ }
1093+ for _ , tc := range tests {
1094+ t .Run (tc .name , func (t * testing.T ) {
1095+ gqlClient := githubv4 .NewClient (tc .mockedClient )
1096+ deps := BaseDeps {GQLClient : gqlClient }
1097+ handler := toolDef .Handler (deps )
1098+
1099+ req := createMCPRequest (tc .requestArgs )
1100+ res , err := handler (ContextWithDeps (context .Background (), deps ), & req )
1101+ require .NoError (t , err )
1102+
1103+ text := getTextResult (t , res ).Text
1104+
1105+ if tc .expectToolError {
1106+ require .True (t , res .IsError )
1107+ assert .Contains (t , text , tc .expectedErrMsg )
1108+ return
1109+ }
1110+
1111+ require .False (t , res .IsError )
1112+ var response MinimalResponse
1113+ require .NoError (t , json .Unmarshal ([]byte (text ), & response ))
1114+ assert .Equal (t , tc .expectedID , response .ID )
1115+ assert .Equal (t , tc .expectedURL , response .URL )
1116+ })
1117+ }
1118+ }
0 commit comments