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 }