109 lines
3.3 KiB
Go
109 lines
3.3 KiB
Go
package admin
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"boostai-backend/internal/config"
|
|
"boostai-backend/internal/seeddata"
|
|
"boostai-backend/internal/sqlc"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
)
|
|
|
|
func TestReseedDatabaseRequiresEnableFlag(t *testing.T) {
|
|
t.Parallel()
|
|
h := &Handler{cfg: &config.Config{Environment: "production"}}
|
|
status := performReseedRequest(t, h, map[string]any{"confirm": "RESEED"}, "secret", true)
|
|
if status != fiber.StatusNotFound {
|
|
t.Fatalf("expected 404, got %d", status)
|
|
}
|
|
}
|
|
|
|
func TestReseedDatabaseRequiresSecret(t *testing.T) {
|
|
t.Parallel()
|
|
h := newTestHandler(func(ctx context.Context, mockDataDir string) (seeddata.Summary, error) {
|
|
return seeddata.Summary{}, nil
|
|
})
|
|
status := performReseedRequest(t, h, map[string]any{"confirm": "RESEED"}, "wrong", true)
|
|
if status != fiber.StatusForbidden {
|
|
t.Fatalf("expected 403, got %d", status)
|
|
}
|
|
}
|
|
|
|
func TestReseedDatabaseRequiresConfirm(t *testing.T) {
|
|
t.Parallel()
|
|
h := newTestHandler(func(ctx context.Context, mockDataDir string) (seeddata.Summary, error) {
|
|
return seeddata.Summary{}, nil
|
|
})
|
|
status := performReseedRequest(t, h, map[string]any{"confirm": "nope"}, "secret", true)
|
|
if status != fiber.StatusBadRequest {
|
|
t.Fatalf("expected 400, got %d", status)
|
|
}
|
|
}
|
|
|
|
func TestReseedDatabaseReturnsSummary(t *testing.T) {
|
|
t.Parallel()
|
|
h := newTestHandler(func(ctx context.Context, mockDataDir string) (seeddata.Summary, error) {
|
|
if mockDataDir != "/app/Mock-Data" {
|
|
t.Fatalf("expected mock data dir /app/Mock-Data, got %q", mockDataDir)
|
|
}
|
|
return seeddata.Summary{Users: 13, Assignments: 8, StudentAnswers: 588}, nil
|
|
})
|
|
status := performReseedRequest(t, h, map[string]any{"confirm": "RESEED"}, "secret", true)
|
|
if status != fiber.StatusOK {
|
|
t.Fatalf("expected 200, got %d", status)
|
|
}
|
|
}
|
|
|
|
func TestReseedDatabaseSurfacesRunnerError(t *testing.T) {
|
|
t.Parallel()
|
|
h := newTestHandler(func(ctx context.Context, mockDataDir string) (seeddata.Summary, error) {
|
|
return seeddata.Summary{}, errors.New("boom")
|
|
})
|
|
status := performReseedRequest(t, h, map[string]any{"confirm": "RESEED"}, "secret", true)
|
|
if status != fiber.StatusInternalServerError {
|
|
t.Fatalf("expected 500, got %d", status)
|
|
}
|
|
}
|
|
|
|
func newTestHandler(fn func(context.Context, string) (seeddata.Summary, error)) *Handler {
|
|
return &Handler{
|
|
cfg: &config.Config{Environment: "production", AdminReseedEnabled: true, AdminReseedSecret: "secret", MockDataDir: "/app/Mock-Data"},
|
|
runner: fn,
|
|
}
|
|
}
|
|
|
|
func performReseedRequest(t *testing.T, handler *Handler, payload map[string]any, secret string, authenticated bool) int {
|
|
t.Helper()
|
|
app := fiber.New()
|
|
app.Post("/internal/admin/reseed", func(c *fiber.Ctx) error {
|
|
if authenticated {
|
|
c.Locals("auth.user_id", int64(42))
|
|
c.Locals("auth.role", sqlc.UserRoleTeacher)
|
|
c.Locals("auth.email", "teacher@example.com")
|
|
}
|
|
return handler.ReseedDatabase(c)
|
|
})
|
|
bodyBytes, err := json.Marshal(payload)
|
|
if err != nil {
|
|
t.Fatalf("marshal: %v", err)
|
|
}
|
|
req := httptest.NewRequest(http.MethodPost, "/internal/admin/reseed", bytes.NewReader(bodyBytes))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
if secret != "" {
|
|
req.Header.Set(ReseedHeaderName, secret)
|
|
}
|
|
resp, err := app.Test(req)
|
|
if err != nil {
|
|
t.Fatalf("app.Test: %v", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
return resp.StatusCode
|
|
}
|