package gitea_test import ( "context" "encoding/json" "io" "net/http" "net/http/httptest" "testing" "gitea.d-ma.be/mathias/gitea-mcp/internal/gitea" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) const pullFixture = `{ "number": 7, "title": "Add feature X", "body": "This PR adds feature X", "html_url": "http://example.com/pulls/7", "state": "open", "draft": false, "head": {"ref": "feat/x"}, "base": {"ref": "main"} }` func TestCreatePullRequestSendsPayload(t *testing.T) { var captured []byte srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, "/api/v1/repos/o/r/pulls", r.URL.Path) assert.Equal(t, http.MethodPost, r.Method) var err error captured, err = io.ReadAll(r.Body) require.NoError(t, err) w.WriteHeader(http.StatusCreated) _, _ = w.Write([]byte(pullFixture)) })) defer srv.Close() c := gitea.NewClient(srv.URL, "tok") pr, err := c.CreatePullRequest(context.Background(), "o", "r", gitea.CreatePullRequestArgs{ Title: "Add feature X", Body: "This PR adds feature X", Head: "feat/x", Base: "main", Draft: false, }) require.NoError(t, err) var payload map[string]any require.NoError(t, json.Unmarshal(captured, &payload)) assert.Equal(t, "Add feature X", payload["title"]) assert.Equal(t, "This PR adds feature X", payload["body"]) assert.Equal(t, "feat/x", payload["head"]) assert.Equal(t, "main", payload["base"]) assert.Equal(t, false, payload["draft"]) assert.Equal(t, 7, pr.Number) assert.Equal(t, "Add feature X", pr.Title) assert.Equal(t, "http://example.com/pulls/7", pr.HTMLURL) assert.Equal(t, "feat/x", pr.Head.Ref) assert.Equal(t, "main", pr.Base.Ref) assert.Equal(t, "open", pr.State) assert.False(t, pr.Draft) } func TestGetPullRequest(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, "/api/v1/repos/o/r/pulls/42", r.URL.Path) assert.Equal(t, http.MethodGet, r.Method) w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`{ "number": 42, "title": "Fix bug Y", "body": "Fixes Y", "html_url": "http://example.com/pulls/42", "state": "open", "draft": true, "head": {"ref": "fix/y"}, "base": {"ref": "main"} }`)) })) defer srv.Close() c := gitea.NewClient(srv.URL, "tok") pr, err := c.GetPullRequest(context.Background(), "o", "r", 42) require.NoError(t, err) assert.Equal(t, 42, pr.Number) assert.Equal(t, "Fix bug Y", pr.Title) assert.Equal(t, "http://example.com/pulls/42", pr.HTMLURL) assert.Equal(t, "fix/y", pr.Head.Ref) assert.Equal(t, "main", pr.Base.Ref) assert.Equal(t, "open", pr.State) assert.True(t, pr.Draft) } func TestGetPullRequestFiles(t *testing.T) { filesJSON := `[ {"filename":"main.go","status":"modified","additions":10,"deletions":5}, {"filename":"README.md","status":"added","additions":20,"deletions":0} ]` srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, "/api/v1/repos/o/r/pulls/42/files", r.URL.Path) assert.Equal(t, http.MethodGet, r.Method) w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(filesJSON)) })) defer srv.Close() c := gitea.NewClient(srv.URL, "tok") files, err := c.GetPullRequestFiles(context.Background(), "o", "r", 42) require.NoError(t, err) require.Len(t, files, 2) assert.Equal(t, "main.go", files[0].Filename) assert.Equal(t, "modified", files[0].Status) assert.Equal(t, 10, files[0].Additions) assert.Equal(t, 5, files[0].Deletions) assert.Equal(t, "README.md", files[1].Filename) assert.Equal(t, "added", files[1].Status) assert.Equal(t, 20, files[1].Additions) assert.Equal(t, 0, files[1].Deletions) } func TestGetPullRequestDiff(t *testing.T) { rawDiff := "diff --git a/main.go b/main.go\n--- a/main.go\n+++ b/main.go\n@@ -1,2 +1,3 @@\n+package main\n" srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, "/api/v1/repos/o/r/pulls/42.diff", r.URL.Path) assert.Equal(t, http.MethodGet, r.Method) w.Header().Set("Content-Type", "text/plain") _, _ = w.Write([]byte(rawDiff)) })) defer srv.Close() c := gitea.NewClient(srv.URL, "tok") diff, err := c.GetPullRequestDiff(context.Background(), "o", "r", 42) require.NoError(t, err) assert.Equal(t, []byte(rawDiff), diff) } func TestListPullRequests(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, "/api/v1/repos/o/r/pulls", r.URL.Path) assert.Equal(t, "open", r.URL.Query().Get("state")) assert.Equal(t, "feat/x", r.URL.Query().Get("head")) w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`[` + pullFixture + `]`)) })) defer srv.Close() c := gitea.NewClient(srv.URL, "tok") prs, err := c.ListPullRequests(context.Background(), "o", "r", "open", "feat/x", 0, 0) require.NoError(t, err) require.Len(t, prs, 1) assert.Equal(t, 7, prs[0].Number) assert.Equal(t, "feat/x", prs[0].Head.Ref) } func TestMergePullRequestSuccess(t *testing.T) { var captured []byte srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { assert.Equal(t, "/api/v1/repos/o/r/pulls/7/merge", r.URL.Path) assert.Equal(t, http.MethodPost, r.Method) var err error captured, err = io.ReadAll(r.Body) require.NoError(t, err) w.WriteHeader(http.StatusNoContent) })) defer srv.Close() c := gitea.NewClient(srv.URL, "tok") err := c.MergePullRequest(context.Background(), "o", "r", 7, gitea.MergePRArgs{Do: "squash"}) require.NoError(t, err) var payload map[string]any require.NoError(t, json.Unmarshal(captured, &payload)) assert.Equal(t, "squash", payload["Do"]) } func TestMergePullRequestConflict(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusConflict) _, _ = w.Write([]byte(`{"message":"merge conflict"}`)) })) defer srv.Close() c := gitea.NewClient(srv.URL, "tok") err := c.MergePullRequest(context.Background(), "o", "r", 7, gitea.MergePRArgs{Do: "merge"}) require.Error(t, err) assert.ErrorIs(t, err, gitea.ErrConflict) }