Files
Adam Holt 3956a97e7c WIP
2026-01-12 13:11:09 +01:00

101 lines
3.1 KiB
Go

package github
import (
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
"time"
"github.com/github/github-mcp-server/pkg/lockdown"
"github.com/github/github-mcp-server/pkg/raw"
"github.com/github/github-mcp-server/pkg/translations"
"github.com/google/go-github/v79/github"
"github.com/shurcooL/githubv4"
)
// stubDeps is a test helper that implements ToolDependencies with configurable behavior.
// Use this when you need to test error paths or when you need closure-based client creation.
type stubDeps struct {
clientFn func(context.Context) (*github.Client, error)
gqlClientFn func(context.Context) (*githubv4.Client, error)
rawClientFn func(context.Context) (*raw.Client, error)
repoAccessCache *lockdown.RepoAccessCache
t translations.TranslationHelperFunc
flags FeatureFlags
contentWindowSize int
}
func (s stubDeps) GetClient(ctx context.Context) (*github.Client, error) {
if s.clientFn != nil {
return s.clientFn(ctx)
}
return nil, nil
}
func (s stubDeps) GetGQLClient(ctx context.Context) (*githubv4.Client, error) {
if s.gqlClientFn != nil {
return s.gqlClientFn(ctx)
}
return nil, nil
}
func (s stubDeps) GetRawClient(ctx context.Context) (*raw.Client, error) {
if s.rawClientFn != nil {
return s.rawClientFn(ctx)
}
return nil, nil
}
func (s stubDeps) GetRepoAccessCache() *lockdown.RepoAccessCache { return s.repoAccessCache }
func (s stubDeps) GetT() translations.TranslationHelperFunc { return s.t }
func (s stubDeps) GetFlags() FeatureFlags { return s.flags }
func (s stubDeps) GetContentWindowSize() int { return s.contentWindowSize }
// Helper functions to create stub client functions for error testing
func stubClientFnFromHTTP(httpClient *http.Client) func(context.Context) (*github.Client, error) {
return func(_ context.Context) (*github.Client, error) {
return github.NewClient(httpClient), nil
}
}
func stubClientFnErr(errMsg string) func(context.Context) (*github.Client, error) {
return func(_ context.Context) (*github.Client, error) {
return nil, errors.New(errMsg)
}
}
func stubGQLClientFnErr(errMsg string) func(context.Context) (*githubv4.Client, error) {
return func(_ context.Context) (*githubv4.Client, error) {
return nil, errors.New(errMsg)
}
}
func stubRepoAccessCache(client *githubv4.Client, ttl time.Duration) *lockdown.RepoAccessCache {
cacheName := fmt.Sprintf("repo-access-cache-test-%d", time.Now().UnixNano())
return lockdown.GetInstance(client, lockdown.WithTTL(ttl), lockdown.WithCacheName(cacheName))
}
func stubFeatureFlags(enabledFlags map[string]bool) FeatureFlags {
return FeatureFlags{
LockdownMode: enabledFlags["lockdown-mode"],
}
}
func badRequestHandler(msg string) http.HandlerFunc {
return func(w http.ResponseWriter, _ *http.Request) {
structuredErrorResponse := github.ErrorResponse{
Message: msg,
}
b, err := json.Marshal(structuredErrorResponse)
if err != nil {
http.Error(w, "failed to marshal error response", http.StatusInternalServerError)
}
http.Error(w, string(b), http.StatusBadRequest)
}
}