package tools_test import ( "context" "encoding/json" "net/http" "net/http/httptest" "testing" "gitea.d-ma.be/mathias/gitea-mcp/internal/allowlist" "gitea.d-ma.be/mathias/gitea-mcp/internal/gitea" "gitea.d-ma.be/mathias/gitea-mcp/internal/tools" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestIssueListTool(t *testing.T) { tests := []struct { name string input string wantQuery map[string]string respBody string assert func(t *testing.T, out string) }{ { name: "happy path defaults", input: `{"owner":"mathias","name":"infra"}`, wantQuery: map[string]string{"type": "issues", "state": "open", "page": "1", "limit": "30"}, respBody: `[{"number":42,"title":"fix auth","state":"open","html_url":"http://gitea.example/m/infra/issues/42"},{"number":41,"title":"add tests","state":"open"}]`, assert: func(t *testing.T, out string) { assert.Contains(t, out, `"number":42`) assert.Contains(t, out, `"number":41`) }, }, { name: "state filter", input: `{"owner":"mathias","name":"infra","state":"closed"}`, wantQuery: map[string]string{"type": "issues", "state": "closed"}, respBody: `[]`, assert: func(t *testing.T, out string) { assert.Contains(t, out, `"issues":[]`) }, }, { name: "label + since filter", input: `{"owner":"mathias","name":"infra","labels":"bug,critical","since":"2026-05-01T00:00:00Z"}`, wantQuery: map[string]string{"labels": "bug,critical", "since": "2026-05-01T00:00:00Z"}, respBody: `[]`, assert: func(t *testing.T, out string) {}, }, { name: "empty result", input: `{"owner":"mathias","name":"infra"}`, wantQuery: map[string]string{"state": "open"}, respBody: `[]`, assert: func(t *testing.T, out string) { assert.Contains(t, out, `"issues":[]`) assert.NotContains(t, out, `next_page`) }, }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, http.MethodGet, r.Method) assert.Equal(t, "/api/v1/repos/mathias/infra/issues", r.URL.Path) q := r.URL.Query() for k, v := range tc.wantQuery { assert.Equal(t, v, q.Get(k), "query param %q", k) } w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(tc.respBody)) })) defer srv.Close() tool := tools.NewIssueList(gitea.NewClient(srv.URL, "tok"), allowlist.New([]string{"mathias"})) out, err := tool.Call(context.Background(), json.RawMessage(tc.input)) require.NoError(t, err) tc.assert(t, string(out)) }) } } func TestIssueListAllowlistRejects(t *testing.T) { tool := tools.NewIssueList(gitea.NewClient("http://unused", ""), allowlist.New([]string{"mathias"})) _, err := tool.Call(context.Background(), json.RawMessage(`{"owner":"evil","name":"x"}`)) require.Error(t, err) }