org_test.go
1 package org 2 3 import ( 4 "context" 5 "encoding/json" 6 "net/http" 7 "net/http/httptest" 8 "testing" 9 10 forgejo_sdk "codeberg.org/mvdkleijn/forgejo-sdk/forgejo/v3" 11 "codeberg.org/goern/forgejo-mcp/v2/pkg/forgejo" 12 "github.com/mark3labs/mcp-go/mcp" 13 ) 14 15 func newCallToolRequest(args map[string]interface{}) mcp.CallToolRequest { 16 return mcp.CallToolRequest{ 17 Params: mcp.CallToolParams{ 18 Arguments: args, 19 }, 20 } 21 } 22 23 func setupOrgMockServer(t *testing.T, handler http.HandlerFunc) *httptest.Server { 24 t.Helper() 25 srv := httptest.NewServer(handler) 26 client, err := forgejo_sdk.NewClient(srv.URL, forgejo_sdk.SetForgejoVersion("7.0.0")) 27 if err != nil { 28 t.Fatalf("creating test client: %v", err) 29 } 30 forgejo.SetClientForTesting(client) 31 return srv 32 } 33 34 func TestCreateOrgFn_Success(t *testing.T) { 35 srv := setupOrgMockServer(t, func(w http.ResponseWriter, r *http.Request) { 36 w.Header().Set("Content-Type", "application/json") 37 w.WriteHeader(http.StatusCreated) 38 json.NewEncoder(w).Encode(map[string]interface{}{ 39 "id": 1, 40 "username": "test-org", 41 }) 42 }) 43 defer srv.Close() 44 45 req := newCallToolRequest(map[string]interface{}{ 46 "name": "test-org", 47 }) 48 result, err := CreateOrgFn(context.Background(), req) 49 if err != nil { 50 t.Fatalf("CreateOrgFn returned error: %v", err) 51 } 52 if result.IsError { 53 t.Fatal("CreateOrgFn returned tool error") 54 } 55 } 56 57 func TestCreateOrgFn_MissingName(t *testing.T) { 58 req := newCallToolRequest(map[string]interface{}{}) 59 _, err := CreateOrgFn(context.Background(), req) 60 if err == nil { 61 t.Fatal("expected error for missing name, got nil") 62 } 63 } 64 65 func TestGetOrgFn_Success(t *testing.T) { 66 srv := setupOrgMockServer(t, func(w http.ResponseWriter, r *http.Request) { 67 w.Header().Set("Content-Type", "application/json") 68 json.NewEncoder(w).Encode(map[string]interface{}{ 69 "id": 1, 70 "username": "test-org", 71 }) 72 }) 73 defer srv.Close() 74 75 req := newCallToolRequest(map[string]interface{}{ 76 "org": "test-org", 77 }) 78 result, err := GetOrgFn(context.Background(), req) 79 if err != nil { 80 t.Fatalf("GetOrgFn returned error: %v", err) 81 } 82 if result.IsError { 83 t.Fatal("GetOrgFn returned tool error") 84 } 85 } 86 87 func TestGetOrgFn_MissingOrg(t *testing.T) { 88 req := newCallToolRequest(map[string]interface{}{}) 89 _, err := GetOrgFn(context.Background(), req) 90 if err == nil { 91 t.Fatal("expected error for missing org, got nil") 92 } 93 } 94 95 func TestListMyOrgsFn_Success(t *testing.T) { 96 srv := setupOrgMockServer(t, func(w http.ResponseWriter, r *http.Request) { 97 w.Header().Set("Content-Type", "application/json") 98 json.NewEncoder(w).Encode([]map[string]interface{}{ 99 {"id": 1, "username": "org1"}, 100 {"id": 2, "username": "org2"}, 101 }) 102 }) 103 defer srv.Close() 104 105 req := newCallToolRequest(map[string]interface{}{ 106 "page": float64(1), 107 "limit": float64(10), 108 }) 109 result, err := ListMyOrgsFn(context.Background(), req) 110 if err != nil { 111 t.Fatalf("ListMyOrgsFn returned error: %v", err) 112 } 113 if result.IsError { 114 t.Fatal("ListMyOrgsFn returned tool error") 115 } 116 } 117 118 func TestListUserOrgsFn_Success(t *testing.T) { 119 srv := setupOrgMockServer(t, func(w http.ResponseWriter, r *http.Request) { 120 w.Header().Set("Content-Type", "application/json") 121 json.NewEncoder(w).Encode([]map[string]interface{}{ 122 {"id": 1, "username": "org1"}, 123 }) 124 }) 125 defer srv.Close() 126 127 req := newCallToolRequest(map[string]interface{}{ 128 "user": "testuser", 129 }) 130 result, err := ListUserOrgsFn(context.Background(), req) 131 if err != nil { 132 t.Fatalf("ListUserOrgsFn returned error: %v", err) 133 } 134 if result.IsError { 135 t.Fatal("ListUserOrgsFn returned tool error") 136 } 137 } 138 139 func TestListUserOrgsFn_MissingUser(t *testing.T) { 140 req := newCallToolRequest(map[string]interface{}{}) 141 _, err := ListUserOrgsFn(context.Background(), req) 142 if err == nil { 143 t.Fatal("expected error for missing user, got nil") 144 } 145 } 146 147 func TestEditOrgFn_Success(t *testing.T) { 148 callCount := 0 149 srv := setupOrgMockServer(t, func(w http.ResponseWriter, r *http.Request) { 150 callCount++ 151 w.Header().Set("Content-Type", "application/json") 152 if r.Method == "PATCH" { 153 w.WriteHeader(http.StatusOK) 154 return 155 } 156 // GET for the follow-up GetOrg 157 json.NewEncoder(w).Encode(map[string]interface{}{ 158 "id": 1, 159 "username": "test-org", 160 "description": "updated", 161 }) 162 }) 163 defer srv.Close() 164 165 req := newCallToolRequest(map[string]interface{}{ 166 "org": "test-org", 167 "description": "updated", 168 }) 169 result, err := EditOrgFn(context.Background(), req) 170 if err != nil { 171 t.Fatalf("EditOrgFn returned error: %v", err) 172 } 173 if result.IsError { 174 t.Fatal("EditOrgFn returned tool error") 175 } 176 } 177 178 func TestEditOrgFn_MissingOrg(t *testing.T) { 179 req := newCallToolRequest(map[string]interface{}{}) 180 _, err := EditOrgFn(context.Background(), req) 181 if err == nil { 182 t.Fatal("expected error for missing org, got nil") 183 } 184 } 185 186 func TestDeleteOrgFn_Success(t *testing.T) { 187 srv := setupOrgMockServer(t, func(w http.ResponseWriter, r *http.Request) { 188 w.WriteHeader(http.StatusNoContent) 189 }) 190 defer srv.Close() 191 192 req := newCallToolRequest(map[string]interface{}{ 193 "org": "test-org", 194 }) 195 result, err := DeleteOrgFn(context.Background(), req) 196 if err != nil { 197 t.Fatalf("DeleteOrgFn returned error: %v", err) 198 } 199 if result.IsError { 200 t.Fatal("DeleteOrgFn returned tool error") 201 } 202 } 203 204 func TestDeleteOrgFn_MissingOrg(t *testing.T) { 205 req := newCallToolRequest(map[string]interface{}{}) 206 _, err := DeleteOrgFn(context.Background(), req) 207 if err == nil { 208 t.Fatal("expected error for missing org, got nil") 209 } 210 }