daemon: golang WS hub, REST, gitlab, docker spawner, sqlite (18/18 tests)
This commit is contained in:
@@ -0,0 +1,123 @@
|
||||
package main
|
||||
|
||||
// gitlab_test.go — PAT connect + project mapping against httptest upstream.
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func newGitLabUpstream(t *testing.T) (*httptest.Server, *GitLab) {
|
||||
t.Helper()
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/api/v4/user", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Header.Get("Private-Token") != "pat-good" {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"username":"alice"}`))
|
||||
})
|
||||
mux.HandleFunc("/api/v4/projects", func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Header.Get("Private-Token") != "pat-good" {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
q := r.URL.Query()
|
||||
if q.Get("membership") != "true" || q.Get("order_by") != "last_activity_at" {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`[
|
||||
{"path_with_namespace":"team/b","name":"B","namespace":{"path":"team"},
|
||||
"last_activity_at":"2024-02-02T00:00:00Z","web_url":"https://gl/team/b","default_branch":"main"},
|
||||
{"path_with_namespace":"team/a","name":"A","namespace":{"path":"team"},
|
||||
"last_activity_at":"2024-03-03T00:00:00Z","web_url":"https://gl/team/a","default_branch":"trunk"}
|
||||
]`))
|
||||
})
|
||||
ts := httptest.NewServer(mux)
|
||||
t.Cleanup(ts.Close)
|
||||
store := openTestStore(t)
|
||||
return ts, NewGitLab(store, ts.URL)
|
||||
}
|
||||
|
||||
func TestGitLabConnectValidatesAndStores(t *testing.T) {
|
||||
_, gl := newGitLabUpstream(t)
|
||||
|
||||
if status := gl.Status(); status["connected"] != false {
|
||||
t.Fatalf("status before connect = %v", status)
|
||||
}
|
||||
|
||||
if _, err := gl.Connect(context.Background(), "pat-bad"); err == nil {
|
||||
t.Fatal("bad PAT should fail validation")
|
||||
}
|
||||
|
||||
username, err := gl.Connect(context.Background(), "pat-good")
|
||||
if err != nil {
|
||||
t.Fatalf("connect: %v", err)
|
||||
}
|
||||
if username != "alice" {
|
||||
t.Fatalf("username = %q", username)
|
||||
}
|
||||
|
||||
status := gl.Status()
|
||||
if status["connected"] != true || status["username"] != "alice" {
|
||||
t.Fatalf("status after connect = %v", status)
|
||||
}
|
||||
if strings.Contains(mustJSON(t, status), "pat-good") {
|
||||
t.Fatal("status must never expose the PAT")
|
||||
}
|
||||
|
||||
if err := gl.Disconnect(); err != nil {
|
||||
t.Fatalf("disconnect: %v", err)
|
||||
}
|
||||
if status := gl.Status(); status["connected"] != false {
|
||||
t.Fatalf("status after disconnect = %v", status)
|
||||
}
|
||||
}
|
||||
|
||||
func mustJSON(t *testing.T, v any) string {
|
||||
t.Helper()
|
||||
b, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
t.Fatalf("marshal: %v", err)
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func TestGitLabReposMappingAndSorting(t *testing.T) {
|
||||
_, gl := newGitLabUpstream(t)
|
||||
|
||||
if _, err := gl.Repos(context.Background()); err == nil || !strings.Contains(err.Error(), "not connected") {
|
||||
t.Fatalf("repos without connect = %v, want not-connected error", err)
|
||||
}
|
||||
|
||||
if _, err := gl.Connect(context.Background(), "pat-good"); err != nil {
|
||||
t.Fatalf("connect: %v", err)
|
||||
}
|
||||
repos, err := gl.Repos(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("repos: %v", err)
|
||||
}
|
||||
if len(repos) != 2 {
|
||||
t.Fatalf("repos = %d, want 2", len(repos))
|
||||
}
|
||||
want := GitLabRepo{
|
||||
Path: "team/a", Name: "A", Namespace: "team",
|
||||
LastActivityAt: "2024-03-03T00:00:00Z", WebURL: "https://gl/team/a", DefaultBranch: "trunk",
|
||||
}
|
||||
if repos[0] != want {
|
||||
t.Fatalf("first repo = %+v, want %+v (sorted by activity desc)", repos[0], want)
|
||||
}
|
||||
encoded := mustJSON(t, repos[0])
|
||||
for _, key := range []string{`"path":"team/a"`, `"namespace":"team"`, `"webUrl":"https://gl/team/a"`, `"defaultBranch":"trunk"`} {
|
||||
if !strings.Contains(encoded, key) {
|
||||
t.Fatalf("repo JSON %s missing %s", encoded, key)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user