build source
This commit is contained in:
commit
ee1fec43ed
4171 changed files with 1351288 additions and 0 deletions
269
internal/forgejo/client_test.go
Normal file
269
internal/forgejo/client_test.go
Normal file
|
|
@ -0,0 +1,269 @@
|
|||
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")
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue