269 lines
7.9 KiB
Go
269 lines
7.9 KiB
Go
package forgejo
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestCreateForgejoUser_Success(t *testing.T) {
|
|
mux := http.NewServeMux()
|
|
|
|
mux.HandleFunc("POST /api/v1/admin/users", func(w http.ResponseWriter, r *http.Request) {
|
|
user, pass, ok := r.BasicAuth()
|
|
if !ok || user != "admin" || pass != "secret" {
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
var body map[string]interface{}
|
|
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
|
t.Fatalf("decode body: %v", err)
|
|
}
|
|
if body["username"] != "alice" {
|
|
t.Fatalf("expected username 'alice', got %v", body["username"])
|
|
}
|
|
if body["must_change_password"] != false {
|
|
t.Fatal("expected must_change_password false")
|
|
}
|
|
|
|
w.WriteHeader(http.StatusCreated)
|
|
json.NewEncoder(w).Encode(map[string]interface{}{"id": 2, "login": "alice"})
|
|
})
|
|
|
|
mux.HandleFunc("POST /api/v1/users/alice/tokens", func(w http.ResponseWriter, r *http.Request) {
|
|
user, _, ok := r.BasicAuth()
|
|
if !ok || user != "alice" {
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
var body map[string]interface{}
|
|
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
|
t.Fatalf("decode body: %v", err)
|
|
}
|
|
if body["name"] != "dev-pod-access" {
|
|
t.Fatalf("expected token name 'dev-pod-access', got %v", body["name"])
|
|
}
|
|
|
|
w.WriteHeader(http.StatusCreated)
|
|
json.NewEncoder(w).Encode(map[string]interface{}{"sha1": "tok_abc123"})
|
|
})
|
|
|
|
srv := httptest.NewServer(mux)
|
|
defer srv.Close()
|
|
|
|
client := NewClient(srv.URL, "admin", "secret")
|
|
token, err := client.CreateForgejoUser(context.Background(), "alice")
|
|
if err != nil {
|
|
t.Fatalf("CreateForgejoUser: %v", err)
|
|
}
|
|
if token != "tok_abc123" {
|
|
t.Fatalf("expected token 'tok_abc123', got %q", token)
|
|
}
|
|
}
|
|
|
|
func TestCreateForgejoUser_CreateUserFails(t *testing.T) {
|
|
mux := http.NewServeMux()
|
|
mux.HandleFunc("POST /api/v1/admin/users", func(w http.ResponseWriter, _ *http.Request) {
|
|
w.WriteHeader(http.StatusUnprocessableEntity)
|
|
w.Write([]byte(`{"message": "user already exists"}`))
|
|
})
|
|
|
|
srv := httptest.NewServer(mux)
|
|
defer srv.Close()
|
|
|
|
client := NewClient(srv.URL, "admin", "secret")
|
|
_, err := client.CreateForgejoUser(context.Background(), "alice")
|
|
if err == nil {
|
|
t.Fatal("expected error")
|
|
}
|
|
if !strings.Contains(err.Error(), "user already exists") {
|
|
t.Fatalf("expected 'user already exists' in error, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestCreateForgejoUser_TokenCreationFails_CleansUpUser(t *testing.T) {
|
|
var isUserDeleted bool
|
|
|
|
mux := http.NewServeMux()
|
|
mux.HandleFunc("POST /api/v1/admin/users", func(w http.ResponseWriter, _ *http.Request) {
|
|
w.WriteHeader(http.StatusCreated)
|
|
json.NewEncoder(w).Encode(map[string]interface{}{"id": 2, "login": "alice"})
|
|
})
|
|
mux.HandleFunc("POST /api/v1/users/alice/tokens", func(w http.ResponseWriter, _ *http.Request) {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
w.Write([]byte(`{"message": "db error"}`))
|
|
})
|
|
mux.HandleFunc("DELETE /api/v1/admin/users/alice", func(w http.ResponseWriter, _ *http.Request) {
|
|
isUserDeleted = true
|
|
w.WriteHeader(http.StatusNoContent)
|
|
})
|
|
|
|
srv := httptest.NewServer(mux)
|
|
defer srv.Close()
|
|
|
|
client := NewClient(srv.URL, "admin", "secret")
|
|
_, err := client.CreateForgejoUser(context.Background(), "alice")
|
|
if err == nil {
|
|
t.Fatal("expected error on token creation failure")
|
|
}
|
|
if !isUserDeleted {
|
|
t.Fatal("expected user to be cleaned up after token creation failure")
|
|
}
|
|
}
|
|
|
|
func TestDeleteForgejoUser_Success(t *testing.T) {
|
|
mux := http.NewServeMux()
|
|
mux.HandleFunc("DELETE /api/v1/admin/users/alice", func(w http.ResponseWriter, r *http.Request) {
|
|
user, pass, ok := r.BasicAuth()
|
|
if !ok || user != "admin" || pass != "secret" {
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
return
|
|
}
|
|
if r.URL.Query().Get("purge") != "true" {
|
|
t.Fatal("expected purge=true query param")
|
|
}
|
|
w.WriteHeader(http.StatusNoContent)
|
|
})
|
|
|
|
srv := httptest.NewServer(mux)
|
|
defer srv.Close()
|
|
|
|
client := NewClient(srv.URL, "admin", "secret")
|
|
if err := client.DeleteForgejoUser(context.Background(), "alice"); err != nil {
|
|
t.Fatalf("DeleteForgejoUser: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestDeleteForgejoUser_NotFound_NoError(t *testing.T) {
|
|
mux := http.NewServeMux()
|
|
mux.HandleFunc("DELETE /api/v1/admin/users/alice", func(w http.ResponseWriter, _ *http.Request) {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
})
|
|
|
|
srv := httptest.NewServer(mux)
|
|
defer srv.Close()
|
|
|
|
client := NewClient(srv.URL, "admin", "secret")
|
|
if err := client.DeleteForgejoUser(context.Background(), "alice"); err != nil {
|
|
t.Fatalf("expected no error for 404, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestGetRepoFileContent_Success(t *testing.T) {
|
|
mux := http.NewServeMux()
|
|
mux.HandleFunc("GET /api/v1/repos/alice/myrepo/contents/.spinoff.yml", func(w http.ResponseWriter, r *http.Request) {
|
|
user, pass, ok := r.BasicAuth()
|
|
if !ok || user != "admin" || pass != "secret" {
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
return
|
|
}
|
|
if r.URL.Query().Get("ref") != "main" {
|
|
t.Fatalf("expected ref=main, got %s", r.URL.Query().Get("ref"))
|
|
}
|
|
w.WriteHeader(http.StatusOK)
|
|
json.NewEncoder(w).Encode(map[string]interface{}{
|
|
"content": "dG9vbHM6IFtydXN0XQo=",
|
|
"encoding": "base64",
|
|
})
|
|
})
|
|
|
|
srv := httptest.NewServer(mux)
|
|
defer srv.Close()
|
|
|
|
client := NewClient(srv.URL, "admin", "secret")
|
|
content, err := client.GetRepoFileContent(context.Background(), "alice", "myrepo", ".spinoff.yml", "main")
|
|
if err != nil {
|
|
t.Fatalf("GetRepoFileContent: %v", err)
|
|
}
|
|
if string(content) != "tools: [rust]\n" {
|
|
t.Fatalf("expected 'tools: [rust]\\n', got %q", string(content))
|
|
}
|
|
}
|
|
|
|
func TestGetRepoFileContent_NotFound(t *testing.T) {
|
|
mux := http.NewServeMux()
|
|
mux.HandleFunc("GET /api/v1/repos/alice/myrepo/contents/.spinoff.yml", func(w http.ResponseWriter, _ *http.Request) {
|
|
w.WriteHeader(http.StatusNotFound)
|
|
})
|
|
|
|
srv := httptest.NewServer(mux)
|
|
defer srv.Close()
|
|
|
|
client := NewClient(srv.URL, "admin", "secret")
|
|
content, err := client.GetRepoFileContent(context.Background(), "alice", "myrepo", ".spinoff.yml", "main")
|
|
if err != nil {
|
|
t.Fatalf("expected no error for 404, got: %v", err)
|
|
}
|
|
if content != nil {
|
|
t.Fatalf("expected nil content for 404, got %q", string(content))
|
|
}
|
|
}
|
|
|
|
func TestCreateIssueComment_Success(t *testing.T) {
|
|
mux := http.NewServeMux()
|
|
mux.HandleFunc("POST /api/v1/repos/alice/myrepo/issues/42/comments", func(w http.ResponseWriter, r *http.Request) {
|
|
user, pass, ok := r.BasicAuth()
|
|
if !ok || user != "admin" || pass != "secret" {
|
|
w.WriteHeader(http.StatusUnauthorized)
|
|
return
|
|
}
|
|
var body map[string]string
|
|
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
|
t.Fatalf("decode body: %v", err)
|
|
}
|
|
if body["body"] != "Builder pod created" {
|
|
t.Fatalf("expected body 'Builder pod created', got %q", body["body"])
|
|
}
|
|
w.WriteHeader(http.StatusCreated)
|
|
json.NewEncoder(w).Encode(map[string]interface{}{"id": 1})
|
|
})
|
|
|
|
srv := httptest.NewServer(mux)
|
|
defer srv.Close()
|
|
|
|
client := NewClient(srv.URL, "admin", "secret")
|
|
err := client.CreateIssueComment(context.Background(), "alice", "myrepo", 42, "Builder pod created")
|
|
if err != nil {
|
|
t.Fatalf("CreateIssueComment: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestCreateIssueComment_Failure(t *testing.T) {
|
|
mux := http.NewServeMux()
|
|
mux.HandleFunc("POST /api/v1/repos/alice/myrepo/issues/42/comments", func(w http.ResponseWriter, _ *http.Request) {
|
|
w.WriteHeader(http.StatusForbidden)
|
|
w.Write([]byte(`{"message": "forbidden"}`))
|
|
})
|
|
|
|
srv := httptest.NewServer(mux)
|
|
defer srv.Close()
|
|
|
|
client := NewClient(srv.URL, "admin", "secret")
|
|
err := client.CreateIssueComment(context.Background(), "alice", "myrepo", 42, "test")
|
|
if err == nil {
|
|
t.Fatal("expected error")
|
|
}
|
|
if !strings.Contains(err.Error(), "403") {
|
|
t.Fatalf("expected 403 in error, got: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestGeneratePassword(t *testing.T) {
|
|
p1, err := generatePassword(16)
|
|
if err != nil {
|
|
t.Fatalf("generatePassword: %v", err)
|
|
}
|
|
if len(p1) != 32 {
|
|
t.Fatalf("expected 32 hex chars, got %d", len(p1))
|
|
}
|
|
|
|
p2, _ := generatePassword(16)
|
|
if p1 == p2 {
|
|
t.Fatal("expected different passwords")
|
|
}
|
|
}
|