Files
VeillaxandClaude Sonnet 5.5 4afbf2d266
CI / test (push) Successful in 54s
Release / release (push) Successful in 2m31s
Docker / image (push) Successful in 2m52s
Fix the Servers page failing when no servers are configured
An empty server list was sent as null, so the page threw on .length and
showed only the loading placeholder. The API now always returns a list,
the page tolerates null, and tests cover the empty config and the token.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-26 23:58:26 -06:00

73 lines
2.1 KiB
Go

package admin
import (
"io"
"log/slog"
"net/http"
"net/http/httptest"
"os"
"path/filepath"
"strings"
"testing"
"git.veillax.com/Veillax/spinner/internal/config"
"git.veillax.com/Veillax/spinner/internal/health"
"git.veillax.com/Veillax/spinner/internal/proxy"
)
func newAdmin(t *testing.T, cfg string) http.Handler {
t.Helper()
log := slog.New(slog.NewTextHandler(io.Discard, nil))
path := filepath.Join(t.TempDir(), "spinner.json")
if err := os.WriteFile(path, []byte(cfg), 0o600); err != nil {
t.Fatal(err)
}
m, err := config.NewManager(path, log)
if err != nil {
t.Fatal(err)
}
h := health.New(log)
return (&Admin{Cfg: m, Health: h, Proxy: proxy.New(m, h, log), Token: "secret"}).Handler()
}
func get(h http.Handler, path, token string) *httptest.ResponseRecorder {
req := httptest.NewRequest("GET", path, nil)
if token != "" {
req.Header.Set("Authorization", "Bearer "+token)
}
rec := httptest.NewRecorder()
h.ServeHTTP(rec, req)
return rec
}
// The page reads .length on these lists, so an empty config must give [] and never null.
func TestEmptyConfigGivesEmptyLists(t *testing.T) {
for _, cfg := range []string{`{}`, `{"servers":[]}`} {
h := newAdmin(t, cfg)
if body := get(h, "/api/overview", "secret").Body.String(); !strings.Contains(body, `"servers":[]`) {
t.Errorf("%s: overview servers not an empty list: %s", cfg, body)
}
if body := get(h, "/api/config", "secret").Body.String(); !strings.Contains(body, `"servers":[]`) {
t.Errorf("%s: config servers not an empty list: %s", cfg, body)
}
}
}
func TestAuthRequired(t *testing.T) {
h := newAdmin(t, `{}`)
for _, p := range []string{"/api/overview", "/api/config", "/metrics"} {
if c := get(h, p, "").Code; c != http.StatusUnauthorized {
t.Errorf("%s without token: %d", p, c)
}
if c := get(h, p, "wrong").Code; c != http.StatusUnauthorized {
t.Errorf("%s with wrong token: %d", p, c)
}
if c := get(h, p, "secret").Code; c != http.StatusOK {
t.Errorf("%s with token: %d", p, c)
}
}
if c := get(h, "/", "").Code; c != http.StatusOK {
t.Errorf("page should load without a token: %d", c)
}
}