150 lines
4.3 KiB
Go
150 lines
4.3 KiB
Go
package woodpecker
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestNewClientValidation(t *testing.T) {
|
|
if _, err := NewClient("", "tok"); err == nil {
|
|
t.Error("expected error for empty base URL")
|
|
}
|
|
if _, err := NewClient("https://example.com/api", ""); err == nil {
|
|
t.Error("expected error for empty token")
|
|
}
|
|
}
|
|
|
|
func TestNewClientBaseURL(t *testing.T) {
|
|
c, err := NewClient("https://woodpecker.example.com/api/", "tok")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if c.baseURL != "https://woodpecker.example.com/api" {
|
|
t.Errorf("baseURL = %q, want trailing slash trimmed", c.baseURL)
|
|
}
|
|
}
|
|
|
|
func TestGetSuccess(t *testing.T) {
|
|
var gotPath, gotAuth string
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
gotPath = r.URL.Path
|
|
gotAuth = r.Header.Get("Authorization")
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_, _ = w.Write([]byte(`{"id":42,"name":"demo","owner":"me","full_name":"me/demo","private":true,"trusted":false,"active":true,"forge_id":1}`))
|
|
}))
|
|
defer srv.Close()
|
|
|
|
c, err := NewClient(srv.URL+"/api", "secret", WithHTTPClient(srv.Client()))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
var repo Repo
|
|
if err := c.Get(context.Background(), "/repos/42", &repo); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if gotPath != "/api/repos/42" {
|
|
t.Errorf("path = %q", gotPath)
|
|
}
|
|
if gotAuth != "Bearer secret" {
|
|
t.Errorf("auth header = %q", gotAuth)
|
|
}
|
|
if repo.ID != 42 || repo.FullName != "me/demo" || !repo.Private {
|
|
t.Errorf("unexpected repo: %+v", repo)
|
|
}
|
|
}
|
|
|
|
func TestGetEmptyBodySkipsDecode(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
}))
|
|
defer srv.Close()
|
|
|
|
c, _ := NewClient(srv.URL+"/api", "t", WithHTTPClient(srv.Client()))
|
|
var out Repo
|
|
if err := c.Get(context.Background(), "/repos/1", &out); err != nil {
|
|
t.Errorf("empty body should not fail: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestGetErrorStatusAndMessage(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
_, _ = w.Write([]byte(`{"error":"repository not found"}`))
|
|
}))
|
|
defer srv.Close()
|
|
|
|
c, _ := NewClient(srv.URL+"/api", "t", WithHTTPClient(srv.Client()))
|
|
err := c.Get(context.Background(), "/repos/999", &struct{}{})
|
|
apiErr, ok := err.(*APIError)
|
|
if !ok {
|
|
t.Fatalf("expected *APIError, got %T: %v", err, err)
|
|
}
|
|
if apiErr.Status != 404 {
|
|
t.Errorf("status = %d, want 404", apiErr.Status)
|
|
}
|
|
if apiErr.Message != "repository not found" {
|
|
t.Errorf("message = %q", apiErr.Message)
|
|
}
|
|
}
|
|
|
|
func TestGetNetworkErrorBecomes500(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(http.ResponseWriter, *http.Request) {}))
|
|
url := srv.URL
|
|
srv.Close() // connections will fail now
|
|
|
|
c, _ := NewClient(url+"/api", "t", WithHTTPClient(srv.Client()))
|
|
err := c.Get(context.Background(), "/repos/1", &struct{}{})
|
|
apiErr, ok := err.(*APIError)
|
|
if !ok {
|
|
t.Fatalf("expected *APIError, got %T: %v", err, err)
|
|
}
|
|
if apiErr.Status != 500 {
|
|
t.Errorf("status = %d, want 500 for transport error", apiErr.Status)
|
|
}
|
|
if apiErr.Message == "" {
|
|
t.Error("message must carry the transport error detail")
|
|
}
|
|
}
|
|
|
|
func TestGetInvalidJSONBecomes500(t *testing.T) {
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
|
_, _ = w.Write([]byte(`{not json`))
|
|
}))
|
|
defer srv.Close()
|
|
|
|
c, _ := NewClient(srv.URL+"/api", "t", WithHTTPClient(srv.Client()))
|
|
err := c.Get(context.Background(), "/repos/1", &Repo{})
|
|
apiErr, ok := err.(*APIError)
|
|
if !ok {
|
|
t.Fatalf("expected *APIError, got %T: %v", err, err)
|
|
}
|
|
if apiErr.Status != 500 {
|
|
t.Errorf("status = %d, want 500", apiErr.Status)
|
|
}
|
|
}
|
|
|
|
func TestErrorTypeUnmarshalsWithPointers(t *testing.T) {
|
|
var p Pipeline
|
|
payload := `{"id":1,"number":5,"status":"running","event":"push","commit":"abc","branch":"main","ref":"refs/heads/main","created_at":10,"updated_at":11,"started_at":null,"message":null}`
|
|
if err := json.Unmarshal([]byte(payload), &p); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if p.Message != nil {
|
|
t.Error("message should stay nil for explicit null")
|
|
}
|
|
if p.StartedAt != nil {
|
|
t.Error("started_at should stay nil for explicit null")
|
|
}
|
|
if p.Branch != "main" {
|
|
t.Errorf("branch = %q", p.Branch)
|
|
}
|
|
if !strings.HasPrefix(payload, "{") {
|
|
t.Fatal("sanity")
|
|
}
|
|
}
|