package gitea import ( "encoding/json" "fmt" "net/http" "net/http/httptest" "testing" ) func TestGetPullRequest(t *testing.T) { pr := PullRequest{ Title: "Add feature X", Body: "This adds feature X.", } pr.Head.Sha = "abc123" server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/api/v1/repos/owner/repo/pulls/1" { t.Errorf("unexpected path: %s", r.URL.Path) } if r.Header.Get("Authorization") != "token test-token" { t.Errorf("unexpected auth header: %s", r.Header.Get("Authorization")) } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(pr) })) defer server.Close() client := NewClient(server.URL, "test-token") got, err := client.GetPullRequest("owner", "repo", 1) if err != nil { t.Fatalf("unexpected error: %v", err) } if got.Title != "Add feature X" { t.Errorf("expected title %q, got %q", "Add feature X", got.Title) } if got.Body != "This adds feature X." { t.Errorf("expected body %q, got %q", "This adds feature X.", got.Body) } if got.Head.Sha != "abc123" { t.Errorf("expected sha %q, got %q", "abc123", got.Head.Sha) } } func TestGetPullRequestDiff(t *testing.T) { expectedDiff := "diff --git a/file.go b/file.go\n--- a/file.go\n+++ b/file.go\n@@ -1 +1 @@\n-old\n+new\n" server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/api/v1/repos/owner/repo/pulls/5.diff" { t.Errorf("unexpected path: %s", r.URL.Path) } w.Write([]byte(expectedDiff)) })) defer server.Close() client := NewClient(server.URL, "test-token") got, err := client.GetPullRequestDiff("owner", "repo", 5) if err != nil { t.Fatalf("unexpected error: %v", err) } if got != expectedDiff { t.Errorf("expected diff %q, got %q", expectedDiff, got) } } func TestGetCommitStatuses(t *testing.T) { statuses := []CommitStatus{ {Status: "success", Context: "ci/test", Description: "All tests passed"}, {Status: "failure", Context: "ci/lint", Description: "Lint failed"}, } server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/api/v1/repos/owner/repo/commits/abc123/statuses" { t.Errorf("unexpected path: %s", r.URL.Path) } w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(statuses) })) defer server.Close() client := NewClient(server.URL, "test-token") got, err := client.GetCommitStatuses("owner", "repo", "abc123") if err != nil { t.Fatalf("unexpected error: %v", err) } if len(got) != 2 { t.Fatalf("expected 2 statuses, got %d", len(got)) } if got[0].Status != "success" { t.Errorf("expected first status %q, got %q", "success", got[0].Status) } if got[1].Status != "failure" { t.Errorf("expected second status %q, got %q", "failure", got[1].Status) } } func TestPostReview(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" { t.Errorf("expected POST, got %s", r.Method) } if r.URL.Path != "/api/v1/repos/owner/repo/pulls/3/reviews" { t.Errorf("unexpected path: %s", r.URL.Path) } if r.Header.Get("Content-Type") != "application/json" { t.Errorf("unexpected content type: %s", r.Header.Get("Content-Type")) } var payload struct { Body string `json:"body"` Event string `json:"event"` } if err := json.NewDecoder(r.Body).Decode(&payload); err != nil { t.Fatalf("failed to decode payload: %v", err) } if payload.Body != "LGTM" { t.Errorf("expected body %q, got %q", "LGTM", payload.Body) } if payload.Event != "APPROVED" { t.Errorf("expected event %q, got %q", "APPROVED", payload.Event) } w.WriteHeader(http.StatusOK) w.Write([]byte(`{}`)) })) defer server.Close() client := NewClient(server.URL, "test-token") err := client.PostReview("owner", "repo", 3, "APPROVED", "LGTM") if err != nil { t.Fatalf("unexpected error: %v", err) } } func TestGetPullRequest_Non200(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusNotFound) w.Write([]byte(`{"message":"not found"}`)) })) defer server.Close() client := NewClient(server.URL, "test-token") _, err := client.GetPullRequest("owner", "repo", 999) if err == nil { t.Fatal("expected error for 404, got nil") } } func TestGetPullRequest_BadJSON(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`not json`)) })) defer server.Close() client := NewClient(server.URL, "test-token") _, err := client.GetPullRequest("owner", "repo", 1) if err == nil { t.Fatal("expected error for bad JSON, got nil") } } func TestPostReview_Non200(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusForbidden) w.Write([]byte(`{"message":"forbidden"}`)) })) defer server.Close() client := NewClient(server.URL, "test-token") err := client.PostReview("owner", "repo", 1, "APPROVED", "test") if err == nil { t.Fatal("expected error for 403, got nil") } } func TestGetFileContent(t *testing.T) { expected := "# Conventions\n- Be nice\n" server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/api/v1/repos/owner/repo/raw/CONVENTIONS.md" { t.Errorf("unexpected path: %s", r.URL.Path) } w.Write([]byte(expected)) })) defer server.Close() client := NewClient(server.URL, "test-token") got, err := client.GetFileContent("owner", "repo", "CONVENTIONS.md") if err != nil { t.Fatalf("unexpected error: %v", err) } if got != expected { t.Errorf("expected %q, got %q", expected, got) } } func TestGetPullRequestFiles(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/api/v1/repos/owner/repo/pulls/1/files" { t.Errorf("unexpected path: %s", r.URL.Path) } w.Header().Set("Content-Type", "application/json") w.Write([]byte(`[{"filename":"main.go","status":"modified"},{"filename":"old.go","status":"removed"}]`)) })) defer server.Close() client := NewClient(server.URL, "test-token") files, err := client.GetPullRequestFiles("owner", "repo", 1) if err != nil { t.Fatalf("unexpected error: %v", err) } if len(files) != 2 { t.Fatalf("expected 2 files, got %d", len(files)) } if files[0].Filename != "main.go" || files[0].Status != "modified" { t.Errorf("unexpected first file: %+v", files[0]) } } func TestGetFileContentRef(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/api/v1/repos/owner/repo/raw/main.go" { t.Errorf("unexpected path: %s", r.URL.Path) } if r.URL.Query().Get("ref") != "feature-branch" { t.Errorf("unexpected ref: %s", r.URL.Query().Get("ref")) } w.Write([]byte("package main\n")) })) defer server.Close() client := NewClient(server.URL, "test-token") content, err := client.GetFileContentRef("owner", "repo", "main.go", "feature-branch") if err != nil { t.Fatalf("unexpected error: %v", err) } if content != "package main\n" { t.Errorf("unexpected content: %q", content) } } func TestListContents(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/api/v1/repos/owner/repo/contents/docs" { t.Errorf("unexpected path: %s", r.URL.Path) } w.Header().Set("Content-Type", "application/json") fmt.Fprintf(w, `[{"name":"guide.md","path":"docs/guide.md","type":"file"},{"name":"sub","path":"docs/sub","type":"dir"}]`) })) defer server.Close() client := NewClient(server.URL, "test-token") entries, err := client.ListContents("owner", "repo", "docs") if err != nil { t.Fatalf("unexpected error: %v", err) } if len(entries) != 2 { t.Fatalf("expected 2 entries, got %d", len(entries)) } if entries[0].Type != "file" || entries[0].Path != "docs/guide.md" { t.Errorf("unexpected first entry: %+v", entries[0]) } if entries[1].Type != "dir" { t.Errorf("expected dir type, got %s", entries[1].Type) } } func TestGetAllFilesInPath_File(t *testing.T) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/api/v1/repos/owner/repo/contents/README.md" { // Gitea returns 404 for contents API on files (it's not a dir) http.NotFound(w, r) return } if r.URL.Path == "/api/v1/repos/owner/repo/raw/README.md" { fmt.Fprintf(w, "# Hello") return } http.NotFound(w, r) })) defer server.Close() client := NewClient(server.URL, "test-token") files, err := client.GetAllFilesInPath("owner", "repo", "README.md") if err != nil { t.Fatalf("unexpected error: %v", err) } if len(files) != 1 { t.Fatalf("expected 1 file, got %d", len(files)) } if files["README.md"] != "# Hello" { t.Errorf("unexpected content: %q", files["README.md"]) } }