@@ -2287,6 +2287,171 @@ func Test_GetLatestRelease(t *testing.T) {
2287
2287
}
2288
2288
}
2289
2289
2290
+ func Test_GetReleaseByTag (t * testing.T ) {
2291
+ mockClient := github .NewClient (nil )
2292
+ tool , _ := GetReleaseByTag (stubGetClientFn (mockClient ), translations .NullTranslationHelper )
2293
+ require .NoError (t , toolsnaps .Test (tool .Name , tool ))
2294
+
2295
+ assert .Equal (t , "get_release_by_tag" , tool .Name )
2296
+ assert .NotEmpty (t , tool .Description )
2297
+ assert .Contains (t , tool .InputSchema .Properties , "owner" )
2298
+ assert .Contains (t , tool .InputSchema .Properties , "repo" )
2299
+ assert .Contains (t , tool .InputSchema .Properties , "tag" )
2300
+ assert .ElementsMatch (t , tool .InputSchema .Required , []string {"owner" , "repo" , "tag" })
2301
+
2302
+ mockRelease := & github.RepositoryRelease {
2303
+ ID : github .Ptr (int64 (1 )),
2304
+ TagName : github .Ptr ("v1.0.0" ),
2305
+ Name : github .Ptr ("Release v1.0.0" ),
2306
+ Body : github .Ptr ("This is the first stable release." ),
2307
+ Assets : []* github.ReleaseAsset {
2308
+ {
2309
+ ID : github .Ptr (int64 (1 )),
2310
+ Name : github .Ptr ("release-v1.0.0.tar.gz" ),
2311
+ },
2312
+ },
2313
+ }
2314
+
2315
+ tests := []struct {
2316
+ name string
2317
+ mockedClient * http.Client
2318
+ requestArgs map [string ]interface {}
2319
+ expectError bool
2320
+ expectedResult * github.RepositoryRelease
2321
+ expectedErrMsg string
2322
+ }{
2323
+ {
2324
+ name : "successful release by tag fetch" ,
2325
+ mockedClient : mock .NewMockedHTTPClient (
2326
+ mock .WithRequestMatch (
2327
+ mock .GetReposReleasesTagsByOwnerByRepoByTag ,
2328
+ mockRelease ,
2329
+ ),
2330
+ ),
2331
+ requestArgs : map [string ]interface {}{
2332
+ "owner" : "owner" ,
2333
+ "repo" : "repo" ,
2334
+ "tag" : "v1.0.0" ,
2335
+ },
2336
+ expectError : false ,
2337
+ expectedResult : mockRelease ,
2338
+ },
2339
+ {
2340
+ name : "missing owner parameter" ,
2341
+ mockedClient : mock .NewMockedHTTPClient (),
2342
+ requestArgs : map [string ]interface {}{
2343
+ "repo" : "repo" ,
2344
+ "tag" : "v1.0.0" ,
2345
+ },
2346
+ expectError : false , // Returns tool error, not Go error
2347
+ expectedErrMsg : "missing required parameter: owner" ,
2348
+ },
2349
+ {
2350
+ name : "missing repo parameter" ,
2351
+ mockedClient : mock .NewMockedHTTPClient (),
2352
+ requestArgs : map [string ]interface {}{
2353
+ "owner" : "owner" ,
2354
+ "tag" : "v1.0.0" ,
2355
+ },
2356
+ expectError : false , // Returns tool error, not Go error
2357
+ expectedErrMsg : "missing required parameter: repo" ,
2358
+ },
2359
+ {
2360
+ name : "missing tag parameter" ,
2361
+ mockedClient : mock .NewMockedHTTPClient (),
2362
+ requestArgs : map [string ]interface {}{
2363
+ "owner" : "owner" ,
2364
+ "repo" : "repo" ,
2365
+ },
2366
+ expectError : false , // Returns tool error, not Go error
2367
+ expectedErrMsg : "missing required parameter: tag" ,
2368
+ },
2369
+ {
2370
+ name : "release by tag not found" ,
2371
+ mockedClient : mock .NewMockedHTTPClient (
2372
+ mock .WithRequestMatchHandler (
2373
+ mock .GetReposReleasesTagsByOwnerByRepoByTag ,
2374
+ http .HandlerFunc (func (w http.ResponseWriter , _ * http.Request ) {
2375
+ w .WriteHeader (http .StatusNotFound )
2376
+ _ , _ = w .Write ([]byte (`{"message": "Not Found"}` ))
2377
+ }),
2378
+ ),
2379
+ ),
2380
+ requestArgs : map [string ]interface {}{
2381
+ "owner" : "owner" ,
2382
+ "repo" : "repo" ,
2383
+ "tag" : "v999.0.0" ,
2384
+ },
2385
+ expectError : false , // API errors return tool errors, not Go errors
2386
+ expectedErrMsg : "failed to get release by tag: v999.0.0" ,
2387
+ },
2388
+ {
2389
+ name : "server error" ,
2390
+ mockedClient : mock .NewMockedHTTPClient (
2391
+ mock .WithRequestMatchHandler (
2392
+ mock .GetReposReleasesTagsByOwnerByRepoByTag ,
2393
+ http .HandlerFunc (func (w http.ResponseWriter , _ * http.Request ) {
2394
+ w .WriteHeader (http .StatusInternalServerError )
2395
+ _ , _ = w .Write ([]byte (`{"message": "Internal Server Error"}` ))
2396
+ }),
2397
+ ),
2398
+ ),
2399
+ requestArgs : map [string ]interface {}{
2400
+ "owner" : "owner" ,
2401
+ "repo" : "repo" ,
2402
+ "tag" : "v1.0.0" ,
2403
+ },
2404
+ expectError : false , // API errors return tool errors, not Go errors
2405
+ expectedErrMsg : "failed to get release by tag: v1.0.0" ,
2406
+ },
2407
+ }
2408
+
2409
+ for _ , tc := range tests {
2410
+ t .Run (tc .name , func (t * testing.T ) {
2411
+ client := github .NewClient (tc .mockedClient )
2412
+ _ , handler := GetReleaseByTag (stubGetClientFn (client ), translations .NullTranslationHelper )
2413
+
2414
+ request := createMCPRequest (tc .requestArgs )
2415
+
2416
+ result , err := handler (context .Background (), request )
2417
+
2418
+ if tc .expectError {
2419
+ require .Error (t , err )
2420
+ assert .Contains (t , err .Error (), tc .expectedErrMsg )
2421
+ return
2422
+ }
2423
+
2424
+ require .NoError (t , err )
2425
+
2426
+ if tc .expectedErrMsg != "" {
2427
+ require .True (t , result .IsError )
2428
+ errorContent := getErrorResult (t , result )
2429
+ assert .Contains (t , errorContent .Text , tc .expectedErrMsg )
2430
+ return
2431
+ }
2432
+
2433
+ require .False (t , result .IsError )
2434
+
2435
+ textContent := getTextResult (t , result )
2436
+
2437
+ var returnedRelease github.RepositoryRelease
2438
+ err = json .Unmarshal ([]byte (textContent .Text ), & returnedRelease )
2439
+ require .NoError (t , err )
2440
+
2441
+ assert .Equal (t , * tc .expectedResult .ID , * returnedRelease .ID )
2442
+ assert .Equal (t , * tc .expectedResult .TagName , * returnedRelease .TagName )
2443
+ assert .Equal (t , * tc .expectedResult .Name , * returnedRelease .Name )
2444
+ if tc .expectedResult .Body != nil {
2445
+ assert .Equal (t , * tc .expectedResult .Body , * returnedRelease .Body )
2446
+ }
2447
+ if len (tc .expectedResult .Assets ) > 0 {
2448
+ require .Len (t , returnedRelease .Assets , len (tc .expectedResult .Assets ))
2449
+ assert .Equal (t , * tc .expectedResult .Assets [0 ].Name , * returnedRelease .Assets [0 ].Name )
2450
+ }
2451
+ })
2452
+ }
2453
+ }
2454
+
2290
2455
func Test_filterPaths (t * testing.T ) {
2291
2456
tests := []struct {
2292
2457
name string
0 commit comments