chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,177 @@
|
||||
package github
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/github/github-mcp-server/internal/toolsnaps"
|
||||
"github.com/github/github-mcp-server/pkg/translations"
|
||||
"github.com/google/go-github/v89/github"
|
||||
"github.com/google/jsonschema-go/jsonschema"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_GetRepositoryTree(t *testing.T) {
|
||||
// Verify tool definition once
|
||||
toolDef := GetRepositoryTree(translations.NullTranslationHelper)
|
||||
require.NoError(t, toolsnaps.Test(toolDef.Tool.Name, toolDef.Tool))
|
||||
|
||||
assert.Equal(t, "get_repository_tree", toolDef.Tool.Name)
|
||||
assert.NotEmpty(t, toolDef.Tool.Description)
|
||||
|
||||
// Type assert the InputSchema to access its properties
|
||||
inputSchema, ok := toolDef.Tool.InputSchema.(*jsonschema.Schema)
|
||||
require.True(t, ok, "expected InputSchema to be *jsonschema.Schema")
|
||||
assert.Contains(t, inputSchema.Properties, "owner")
|
||||
assert.Contains(t, inputSchema.Properties, "repo")
|
||||
assert.Contains(t, inputSchema.Properties, "tree_sha")
|
||||
assert.Contains(t, inputSchema.Properties, "recursive")
|
||||
assert.Contains(t, inputSchema.Properties, "path_filter")
|
||||
assert.ElementsMatch(t, inputSchema.Required, []string{"owner", "repo"})
|
||||
|
||||
// Setup mock data
|
||||
mockRepo := &github.Repository{
|
||||
DefaultBranch: github.Ptr("main"),
|
||||
}
|
||||
mockTree := &github.Tree{
|
||||
SHA: github.Ptr("abc123"),
|
||||
Truncated: github.Ptr(false),
|
||||
Entries: []*github.TreeEntry{
|
||||
{
|
||||
Path: github.Ptr("README.md"),
|
||||
Mode: github.Ptr("100644"),
|
||||
Type: github.Ptr("blob"),
|
||||
SHA: github.Ptr("file1sha"),
|
||||
Size: github.Ptr(123),
|
||||
URL: github.Ptr("https://api.github.com/repos/owner/repo/git/blobs/file1sha"),
|
||||
},
|
||||
{
|
||||
Path: github.Ptr("src/main.go"),
|
||||
Mode: github.Ptr("100644"),
|
||||
Type: github.Ptr("blob"),
|
||||
SHA: github.Ptr("file2sha"),
|
||||
Size: github.Ptr(456),
|
||||
URL: github.Ptr("https://api.github.com/repos/owner/repo/git/blobs/file2sha"),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
mockedClient *http.Client
|
||||
requestArgs map[string]any
|
||||
expectError bool
|
||||
expectedErrMsg string
|
||||
}{
|
||||
{
|
||||
name: "successfully get repository tree",
|
||||
mockedClient: MockHTTPClientWithHandlers(map[string]http.HandlerFunc{
|
||||
GetReposByOwnerByRepo: mockResponse(t, http.StatusOK, mockRepo),
|
||||
GetReposGitTreesByOwnerByRepoByTree: mockResponse(t, http.StatusOK, mockTree),
|
||||
}),
|
||||
requestArgs: map[string]any{
|
||||
"owner": "owner",
|
||||
"repo": "repo",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "successfully get repository tree with path filter",
|
||||
mockedClient: MockHTTPClientWithHandlers(map[string]http.HandlerFunc{
|
||||
GetReposByOwnerByRepo: mockResponse(t, http.StatusOK, mockRepo),
|
||||
GetReposGitTreesByOwnerByRepoByTree: mockResponse(t, http.StatusOK, mockTree),
|
||||
}),
|
||||
requestArgs: map[string]any{
|
||||
"owner": "owner",
|
||||
"repo": "repo",
|
||||
"path_filter": "src/",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "repository not found",
|
||||
mockedClient: MockHTTPClientWithHandlers(map[string]http.HandlerFunc{
|
||||
GetReposByOwnerByRepo: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
_, _ = w.Write([]byte(`{"message": "Not Found"}`))
|
||||
}),
|
||||
}),
|
||||
requestArgs: map[string]any{
|
||||
"owner": "owner",
|
||||
"repo": "nonexistent",
|
||||
},
|
||||
expectError: true,
|
||||
expectedErrMsg: "failed to get repository info",
|
||||
},
|
||||
{
|
||||
name: "tree not found",
|
||||
mockedClient: MockHTTPClientWithHandlers(map[string]http.HandlerFunc{
|
||||
GetReposByOwnerByRepo: mockResponse(t, http.StatusOK, mockRepo),
|
||||
GetReposGitTreesByOwnerByRepoByTree: http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
_, _ = w.Write([]byte(`{"message": "Not Found"}`))
|
||||
}),
|
||||
}),
|
||||
requestArgs: map[string]any{
|
||||
"owner": "owner",
|
||||
"repo": "repo",
|
||||
},
|
||||
expectError: true,
|
||||
expectedErrMsg: "failed to get repository tree",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
client := mustNewGHClient(t, tc.mockedClient)
|
||||
deps := BaseDeps{
|
||||
Client: client,
|
||||
}
|
||||
handler := toolDef.Handler(deps)
|
||||
|
||||
// Create the tool request
|
||||
request := createMCPRequest(tc.requestArgs)
|
||||
|
||||
result, err := handler(ContextWithDeps(context.Background(), deps), &request)
|
||||
|
||||
if tc.expectError {
|
||||
require.NoError(t, err)
|
||||
require.True(t, result.IsError)
|
||||
errorContent := getErrorResult(t, result)
|
||||
assert.Contains(t, errorContent.Text, tc.expectedErrMsg)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
require.False(t, result.IsError)
|
||||
|
||||
// Parse the result and get the text content
|
||||
textContent := getTextResult(t, result)
|
||||
|
||||
// Parse the JSON response
|
||||
var treeResponse map[string]any
|
||||
err := json.Unmarshal([]byte(textContent.Text), &treeResponse)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Verify response structure
|
||||
assert.Equal(t, "owner", treeResponse["owner"])
|
||||
assert.Equal(t, "repo", treeResponse["repo"])
|
||||
assert.Contains(t, treeResponse, "tree")
|
||||
assert.Contains(t, treeResponse, "count")
|
||||
assert.Contains(t, treeResponse, "sha")
|
||||
assert.Contains(t, treeResponse, "truncated")
|
||||
|
||||
// Check filtering if path_filter was provided
|
||||
if pathFilter, exists := tc.requestArgs["path_filter"]; exists {
|
||||
tree := treeResponse["tree"].([]any)
|
||||
for _, entry := range tree {
|
||||
entryMap := entry.(map[string]any)
|
||||
path := entryMap["path"].(string)
|
||||
assert.True(t, strings.HasPrefix(path, pathFilter.(string)),
|
||||
"Path %s should start with filter %s", path, pathFilter)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user