forgejo-mcp/operation/repo/resources_repo_test.go
Christoph Görn dd9116fbca
fix: 🚨 clear golangci-lint v2 backlog (closes bead forgejo-mcp-hc9)
- errorlint: fmt.Errorf %v→%w across all handlers (errors now wrap the
  underlying SDK/HTTP error for errors.Is/As); errors.Is for
  context.Canceled in cmd
- staticcheck quickfixes: Fprintf over WriteString(Sprintf), tagged
  switches, omit inferred 'any'; QF1001 resolved by hoisting hex checks
  into isHex predicates (normalizeColor, validateSHA)
- govet: reflect.Ptr → reflect.Pointer in pkg/ptr
- errcheck: explicit '_ =' for fs.Parse (ExitOnError) and deferred
  zap Sync
- repair four test assertions the autofix broke (it dropped the
  're.Code != X' half of combined type-assert checks, inverting the
  test); all errors.As sites use 'var re *resource.ResourceError'

golangci-lint: 0 issues. staticcheck, vet, tests: clean.
2026-06-11 00:03:36 +02:00

134 lines
3.7 KiB
Go

package repo
import (
"context"
"encoding/json"
"errors"
"net/http"
"net/http/httptest"
"testing"
"codeberg.org/goern/forgejo-mcp/v2/operation/resource"
"codeberg.org/goern/forgejo-mcp/v2/pkg/forgejo"
forgejo_sdk "codeberg.org/mvdkleijn/forgejo-sdk/forgejo/v3"
"github.com/mark3labs/mcp-go/mcp"
)
func setupRepoMockServer(t *testing.T, statusCode int, body interface{}) *httptest.Server {
t.Helper()
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(statusCode)
if body != nil {
json.NewEncoder(w).Encode(body)
}
}))
client, err := forgejo_sdk.NewClient(srv.URL, forgejo_sdk.SetForgejoVersion("7.0.0"))
if err != nil {
t.Fatalf("creating test client: %v", err)
}
forgejo.SetClientForTesting(client)
return srv
}
func makeRepoResourceRequest(owner, repo string) mcp.ReadResourceRequest {
return mcp.ReadResourceRequest{
Params: mcp.ReadResourceParams{
URI: "forgejo://repo/" + owner + "/" + repo,
},
}
}
func TestRepoResourceHandler_HappyPath(t *testing.T) {
fakeRepo := map[string]interface{}{
"id": 1,
"name": "forgejo-mcp",
"full_name": "goern/forgejo-mcp",
"owner": map[string]interface{}{
"login": "goern",
},
"description": "MCP server for Forgejo",
"html_url": "https://codeberg.org/goern/forgejo-mcp",
"default_branch": "main",
"fork": false,
"archived": false,
"private": false,
"stars_count": 42,
"forks_count": 7,
"watchers_count": 15,
"open_issues_count": 3,
"open_pr_counter": 1,
"size": 512,
"has_issues": true,
"has_wiki": false,
"has_pull_requests": true,
}
srv := setupRepoMockServer(t, http.StatusOK, fakeRepo)
defer srv.Close()
req := makeRepoResourceRequest("goern", "forgejo-mcp")
contents, err := repoResourceHandler(context.Background(), req)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if len(contents) != 1 {
t.Fatalf("expected 1 content block, got %d", len(contents))
}
block, ok := contents[0].(mcp.TextResourceContents)
if !ok {
t.Fatal("content must be TextResourceContents")
}
if block.MIMEType != "application/json" {
t.Errorf("MIME type: got %q, want application/json", block.MIMEType)
}
var payload repoResourcePayload
if err := json.Unmarshal([]byte(block.Text), &payload); err != nil {
t.Fatalf("response is not valid JSON: %v", err)
}
if payload.Name != "forgejo-mcp" {
t.Errorf("expected name=forgejo-mcp, got %q", payload.Name)
}
if payload.StarsCount != 42 {
t.Errorf("expected stars=42, got %d", payload.StarsCount)
}
if payload.HasIssues != true {
t.Error("expected has_issues=true")
}
}
func TestRepoResourceHandler_403(t *testing.T) {
srv := setupRepoMockServer(t, http.StatusForbidden, map[string]string{"message": "Forbidden"})
defer srv.Close()
req := makeRepoResourceRequest("goern", "private-repo")
_, err := repoResourceHandler(context.Background(), req)
if err == nil {
t.Fatal("expected error for 403")
}
var re *resource.ResourceError
if errors.As(err, &re) {
if re.Code != -32002 {
t.Errorf("expected code -32002, got %d", re.Code)
}
}
}
func TestRepoResourceHandler_404(t *testing.T) {
srv := setupRepoMockServer(t, http.StatusNotFound, map[string]string{"message": "Not Found"})
defer srv.Close()
req := makeRepoResourceRequest("goern", "no-such-repo")
_, err := repoResourceHandler(context.Background(), req)
if err == nil {
t.Fatal("expected error for 404")
}
var re *resource.ResourceError
if errors.As(err, &re) {
if re.Code != -32003 {
t.Errorf("expected code -32003, got %d", re.Code)
}
}
}