@@ -3192,3 +3192,178 @@ func Test_UnstarRepository(t *testing.T) {
31923192 })
31933193 }
31943194}
3195+
3196+ func Test_GetRepositoryTree (t * testing.T ) {
3197+ // Verify tool definition once
3198+ mockClient := github .NewClient (nil )
3199+ tool , _ := GetRepositoryTree (stubGetClientFn (mockClient ), translations .NullTranslationHelper )
3200+ require .NoError (t , toolsnaps .Test (tool .Name , tool ))
3201+
3202+ assert .Equal (t , "get_repository_tree" , tool .Name )
3203+ assert .NotEmpty (t , tool .Description )
3204+ assert .Contains (t , tool .InputSchema .Properties , "owner" )
3205+ assert .Contains (t , tool .InputSchema .Properties , "repo" )
3206+ assert .Contains (t , tool .InputSchema .Properties , "tree_sha" )
3207+ assert .Contains (t , tool .InputSchema .Properties , "recursive" )
3208+ assert .Contains (t , tool .InputSchema .Properties , "path_filter" )
3209+ assert .ElementsMatch (t , tool .InputSchema .Required , []string {"owner" , "repo" })
3210+
3211+ // Setup mock data
3212+ mockRepo := & github.Repository {
3213+ DefaultBranch : github .Ptr ("main" ),
3214+ }
3215+ mockTree := & github.Tree {
3216+ SHA : github .Ptr ("abc123" ),
3217+ Truncated : github .Ptr (false ),
3218+ Entries : []* github.TreeEntry {
3219+ {
3220+ Path : github .Ptr ("README.md" ),
3221+ Mode : github .Ptr ("100644" ),
3222+ Type : github .Ptr ("blob" ),
3223+ SHA : github .Ptr ("file1sha" ),
3224+ Size : github .Ptr (123 ),
3225+ URL : github .Ptr ("https://api.github.com/repos/owner/repo/git/blobs/file1sha" ),
3226+ },
3227+ {
3228+ Path : github .Ptr ("src/main.go" ),
3229+ Mode : github .Ptr ("100644" ),
3230+ Type : github .Ptr ("blob" ),
3231+ SHA : github .Ptr ("file2sha" ),
3232+ Size : github .Ptr (456 ),
3233+ URL : github .Ptr ("https://api.github.com/repos/owner/repo/git/blobs/file2sha" ),
3234+ },
3235+ },
3236+ }
3237+
3238+ tests := []struct {
3239+ name string
3240+ mockedClient * http.Client
3241+ requestArgs map [string ]interface {}
3242+ expectError bool
3243+ expectedErrMsg string
3244+ }{
3245+ {
3246+ name : "successfully get repository tree" ,
3247+ mockedClient : mock .NewMockedHTTPClient (
3248+ mock .WithRequestMatchHandler (
3249+ mock .GetReposByOwnerByRepo ,
3250+ mockResponse (t , http .StatusOK , mockRepo ),
3251+ ),
3252+ mock .WithRequestMatchHandler (
3253+ mock .GetReposGitTreesByOwnerByRepoByTreeSha ,
3254+ mockResponse (t , http .StatusOK , mockTree ),
3255+ ),
3256+ ),
3257+ requestArgs : map [string ]interface {}{
3258+ "owner" : "owner" ,
3259+ "repo" : "repo" ,
3260+ },
3261+ },
3262+ {
3263+ name : "successfully get repository tree with path filter" ,
3264+ mockedClient : mock .NewMockedHTTPClient (
3265+ mock .WithRequestMatchHandler (
3266+ mock .GetReposByOwnerByRepo ,
3267+ mockResponse (t , http .StatusOK , mockRepo ),
3268+ ),
3269+ mock .WithRequestMatchHandler (
3270+ mock .GetReposGitTreesByOwnerByRepoByTreeSha ,
3271+ mockResponse (t , http .StatusOK , mockTree ),
3272+ ),
3273+ ),
3274+ requestArgs : map [string ]interface {}{
3275+ "owner" : "owner" ,
3276+ "repo" : "repo" ,
3277+ "path_filter" : "src/" ,
3278+ },
3279+ },
3280+ {
3281+ name : "repository not found" ,
3282+ mockedClient : mock .NewMockedHTTPClient (
3283+ mock .WithRequestMatchHandler (
3284+ mock .GetReposByOwnerByRepo ,
3285+ http .HandlerFunc (func (w http.ResponseWriter , _ * http.Request ) {
3286+ w .WriteHeader (http .StatusNotFound )
3287+ _ , _ = w .Write ([]byte (`{"message": "Not Found"}` ))
3288+ }),
3289+ ),
3290+ ),
3291+ requestArgs : map [string ]interface {}{
3292+ "owner" : "owner" ,
3293+ "repo" : "nonexistent" ,
3294+ },
3295+ expectError : true ,
3296+ expectedErrMsg : "failed to get repository info" ,
3297+ },
3298+ {
3299+ name : "tree not found" ,
3300+ mockedClient : mock .NewMockedHTTPClient (
3301+ mock .WithRequestMatchHandler (
3302+ mock .GetReposByOwnerByRepo ,
3303+ mockResponse (t , http .StatusOK , mockRepo ),
3304+ ),
3305+ mock .WithRequestMatchHandler (
3306+ mock .GetReposGitTreesByOwnerByRepoByTreeSha ,
3307+ http .HandlerFunc (func (w http.ResponseWriter , _ * http.Request ) {
3308+ w .WriteHeader (http .StatusNotFound )
3309+ _ , _ = w .Write ([]byte (`{"message": "Not Found"}` ))
3310+ }),
3311+ ),
3312+ ),
3313+ requestArgs : map [string ]interface {}{
3314+ "owner" : "owner" ,
3315+ "repo" : "repo" ,
3316+ },
3317+ expectError : true ,
3318+ expectedErrMsg : "failed to get repository tree" ,
3319+ },
3320+ }
3321+
3322+ for _ , tc := range tests {
3323+ t .Run (tc .name , func (t * testing.T ) {
3324+ _ , handler := GetRepositoryTree (stubGetClientFromHTTPFn (tc .mockedClient ), translations .NullTranslationHelper )
3325+
3326+ // Create the tool request
3327+ request := createMCPRequest (tc .requestArgs )
3328+
3329+ result , err := handler (context .Background (), request )
3330+
3331+ if tc .expectError {
3332+ require .NoError (t , err )
3333+ require .True (t , result .IsError )
3334+ errorContent := getErrorResult (t , result )
3335+ assert .Contains (t , errorContent .Text , tc .expectedErrMsg )
3336+ } else {
3337+ require .NoError (t , err )
3338+ require .False (t , result .IsError )
3339+
3340+ // Parse the result and get the text content
3341+ textContent := getTextResult (t , result )
3342+
3343+ // Parse the JSON response
3344+ var treeResponse map [string ]interface {}
3345+ err := json .Unmarshal ([]byte (textContent .Text ), & treeResponse )
3346+ require .NoError (t , err )
3347+
3348+ // Verify response structure
3349+ assert .Equal (t , "owner" , treeResponse ["owner" ])
3350+ assert .Equal (t , "repo" , treeResponse ["repo" ])
3351+ assert .Contains (t , treeResponse , "tree" )
3352+ assert .Contains (t , treeResponse , "count" )
3353+ assert .Contains (t , treeResponse , "sha" )
3354+ assert .Contains (t , treeResponse , "truncated" )
3355+
3356+ // Check filtering if path_filter was provided
3357+ if pathFilter , exists := tc .requestArgs ["path_filter" ]; exists {
3358+ tree := treeResponse ["tree" ].([]interface {})
3359+ for _ , entry := range tree {
3360+ entryMap := entry .(map [string ]interface {})
3361+ path := entryMap ["path" ].(string )
3362+ assert .True (t , strings .HasPrefix (path , pathFilter .(string )),
3363+ "Path %s should start with filter %s" , path , pathFilter )
3364+ }
3365+ }
3366+ }
3367+ })
3368+ }
3369+ }
0 commit comments