This repository has been archived on 2026-04-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
core/server/handlers/test_helpers_test.go
Jeffrey Smith f0dd43144e rebrand: Switchboard Core → Armature
- Rename Go module switchboard-core → armature (155+ files)
- Rename Docker image → gobha/armature
- Rename K8s resources, secrets, deployments
- Rename Prometheus metrics switchboard_* → armature_*
- Rename env vars SWITCHBOARD_ADMIN_* → ARMATURE_ADMIN_*
- Rename DB names switchboard_core* → armature*
- Update all frontend branding, notification templates, docs
- Update CI scripts, e2e tests, Keycloak realm, nginx conf
- Rename scripts/switchboard-ca.sh → scripts/armature-ca.sh
- Rename k8s/switchboard.yaml → k8s/armature.yaml
- Rename chart alerting/dashboard files
- Fix: DockerHub push uses env: binding for secret injection
- Helm chart updated (name, labels, template functions, dashboard, alerting)
- Replace favicon/icon assets with Armature brand

No functional changes. Pure mechanical rename + CI fix.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 21:39:58 +00:00

140 lines
3.5 KiB
Go

package handlers
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"strings"
"testing"
"time"
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v5"
"github.com/google/uuid"
"armature/database"
)
const testJWTSecret = "test-secret-key-for-handler-tests"
type testHarness struct {
router *gin.Engine
t *testing.T
}
func (h *testHarness) request(method, path, token string, body interface{}) *httptest.ResponseRecorder {
var bodyReader *bytes.Reader
if body != nil {
b, _ := json.Marshal(body)
bodyReader = bytes.NewReader(b)
} else {
bodyReader = bytes.NewReader(nil)
}
req := httptest.NewRequest(method, path, bodyReader)
req.Header.Set("Content-Type", "application/json")
if token != "" {
req.Header.Set("Authorization", "Bearer "+token)
}
w := httptest.NewRecorder()
h.router.ServeHTTP(w, req)
return w
}
func makeToken(userID, email, _ string) string {
claims := Claims{
UserID: userID,
Email: email,
RegisteredClaims: jwt.RegisteredClaims{
IssuedAt: jwt.NewNumericDate(time.Now()),
ExpiresAt: jwt.NewNumericDate(time.Now().Add(15 * time.Minute)),
Issuer: "armature",
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
s, _ := token.SignedString([]byte(testJWTSecret))
return s
}
// seedInsertReturningID inserts a row, pre-generating an id for SQLite.
// Expects query like: INSERT INTO users (col1, col2, ...) VALUES ($1, $2, ...) RETURNING id
func seedInsertReturningID(t *testing.T, query string, args ...interface{}) string {
t.Helper()
id := uuid.New().String()
// Inject id column and value into the query
// "INSERT INTO users (username, ..." → "INSERT INTO users (id, username, ..."
q := strings.Replace(query, "(username,", "(id, username,", 1)
// Strip RETURNING clause
if idx := strings.Index(q, " RETURNING "); idx > 0 {
q = q[:idx]
}
if database.IsSQLite() {
// Convert $N → ?
for i := len(args) + 1; i >= 1; i-- {
q = strings.ReplaceAll(q, "$"+itoa(i), "?")
}
// Add ? for the injected id column
q = strings.Replace(q, "VALUES (", "VALUES (?, ", 1)
newArgs := append([]interface{}{id}, args...)
_, err := database.TestDB.Exec(q, newArgs...)
if err != nil {
t.Fatalf("seedInsertReturningID (sqlite): %v\nquery: %s", err, q)
}
return id
}
// Postgres: renumber $N → $N+1, insert $1 for id
for i := len(args); i >= 1; i-- {
q = strings.ReplaceAll(q, "$"+itoa(i), "$"+itoa(i+1))
}
q = strings.Replace(q, "(id,", "(id,", 1)
// Add id as first value placeholder
q = strings.Replace(q, "VALUES (", "VALUES ($1, ", 1)
newArgs := append([]interface{}{id}, args...)
_, err := database.TestDB.Exec(q, newArgs...)
if err != nil {
t.Fatalf("seedInsertReturningID (pg): %v\nquery: %s", err, q)
}
return id
}
func itoa(i int) string {
if i < 10 {
return string(rune('0' + i))
}
return string(rune('0'+i/10)) + string(rune('0'+i%10))
}
func decode(args ...interface{}) {
switch len(args) {
case 2:
w := args[0].(*httptest.ResponseRecorder)
json.NewDecoder(w.Body).Decode(args[1])
case 3:
t := args[0].(*testing.T)
t.Helper()
w := args[1].(*httptest.ResponseRecorder)
if err := json.NewDecoder(w.Body).Decode(args[2]); err != nil {
t.Fatalf("decode response: %v", err)
}
}
}
// dialectSQL returns query as-is. Placeholder conversion happens in seedInsertReturningID.
func dialectSQL(query string) string {
if database.IsSQLite() {
q := query
for i := 20; i >= 1; i-- {
q = strings.ReplaceAll(q, "$"+itoa(i), "?")
}
return q
}
return query
}
func init() {
_ = http.StatusOK
}