Pulse/internal/api/hosted_org_admin_handlers_test.go
2026-03-18 16:06:30 +00:00

111 lines
3.2 KiB
Go

package api
import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/rcourtman/pulse-go-rewrite/internal/config"
"github.com/rcourtman/pulse-go-rewrite/internal/models"
internalauth "github.com/rcourtman/pulse-go-rewrite/pkg/auth"
)
func TestHostedOrganizationsList_HostedModeGate(t *testing.T) {
hashed, err := internalauth.HashPassword("Password!1")
if err != nil {
t.Fatalf("HashPassword: %v", err)
}
router := &Router{
mux: http.NewServeMux(),
config: &config.Config{DataPath: t.TempDir(), AuthUser: "admin", AuthPass: hashed},
multiTenant: config.NewMultiTenantPersistence(t.TempDir()),
hostedMode: false,
}
router.registerHostedRoutes(nil, nil, nil)
rec := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/api/hosted/organizations", nil)
req.SetBasicAuth("admin", "Password!1")
router.mux.ServeHTTP(rec, req)
if rec.Code != http.StatusNotFound {
t.Fatalf("expected 404 when hosted mode disabled, got %d: %s", rec.Code, rec.Body.String())
}
}
func TestHostedOrganizationsList_ReturnsSummaries(t *testing.T) {
baseDir := t.TempDir()
mtp := config.NewMultiTenantPersistence(baseDir)
hashed, err := internalauth.HashPassword("Password!1")
if err != nil {
t.Fatalf("HashPassword: %v", err)
}
createdAt := time.Date(2026, 2, 10, 12, 0, 0, 0, time.UTC)
org := &models.Organization{
ID: "acme",
DisplayName: "Acme Co",
OwnerUserID: "owner@example.com",
CreatedAt: createdAt,
Status: models.OrgStatusSuspended,
}
if err := mtp.SaveOrganization(org); err != nil {
t.Fatalf("SaveOrganization: %v", err)
}
router := &Router{
mux: http.NewServeMux(),
config: &config.Config{DataPath: baseDir, AuthUser: "admin", AuthPass: hashed},
multiTenant: mtp,
hostedMode: true,
}
router.registerHostedRoutes(nil, nil, nil)
rec := httptest.NewRecorder()
req := httptest.NewRequest(http.MethodGet, "/api/hosted/organizations", nil)
req.SetBasicAuth("admin", "Password!1")
router.mux.ServeHTTP(rec, req)
if rec.Code != http.StatusOK {
t.Fatalf("expected 200, got %d: %s", rec.Code, rec.Body.String())
}
var payload []struct {
OrgID string `json:"org_id"`
DisplayName string `json:"display_name"`
OwnerUserID string `json:"owner_user_id"`
CreatedAt time.Time `json:"created_at"`
Suspended bool `json:"suspended"`
SoftDeleted bool `json:"soft_deleted"`
}
if err := json.NewDecoder(rec.Body).Decode(&payload); err != nil {
t.Fatalf("decode response: %v", err)
}
var foundAcme bool
for _, row := range payload {
if row.OrgID != "acme" {
continue
}
foundAcme = true
if row.DisplayName != "Acme Co" {
t.Fatalf("display_name=%q, want %q", row.DisplayName, "Acme Co")
}
if row.OwnerUserID != "owner@example.com" {
t.Fatalf("owner_user_id=%q, want %q", row.OwnerUserID, "owner@example.com")
}
if !row.CreatedAt.Equal(createdAt) {
t.Fatalf("created_at=%s, want %s", row.CreatedAt.Format(time.RFC3339), createdAt.Format(time.RFC3339))
}
if !row.Suspended {
t.Fatalf("expected suspended=true for acme")
}
if row.SoftDeleted {
t.Fatalf("expected soft_deleted=false for acme")
}
}
if !foundAcme {
t.Fatalf("expected payload to include org acme, got %+v", payload)
}
}