Files
BoostAI/Backend/internal/handlers/web/reseed/reseed_test.go
2026-05-26 13:43:09 +01:00

138 lines
4.2 KiB
Go

package reseed
import (
"context"
"errors"
"io"
"net/http"
"net/http/httptest"
"strings"
"testing"
"boostai-backend/internal/config"
"boostai-backend/internal/seeddata"
"github.com/gofiber/fiber/v2"
)
func TestPageRequiresEnableFlag(t *testing.T) {
t.Parallel()
h := &Handler{cfg: &config.Config{Environment: "production"}}
status, _ := performRequest(t, h, http.MethodGet, "/reseed", "", "")
if status != fiber.StatusNotFound {
t.Fatalf("expected 404, got %d", status)
}
}
func TestLoginSetsCookieAndRedirects(t *testing.T) {
t.Parallel()
h := newTestHandler(func(ctx context.Context, mockDataDir string) (seeddata.Summary, error) {
return seeddata.Summary{}, nil
})
status, resp := performRequest(t, h, http.MethodPost, "/reseed/login", "password=1588", "")
if status != fiber.StatusSeeOther {
t.Fatalf("expected 303, got %d", status)
}
if location := resp.Header.Get("Location"); location != "/reseed" {
t.Fatalf("expected redirect to /reseed, got %q", location)
}
if cookie := resp.Header.Get("Set-Cookie"); !strings.Contains(cookie, reseedCookieName+"=") {
t.Fatalf("expected auth cookie, got %q", cookie)
}
}
func TestRunRequiresAuthCookie(t *testing.T) {
t.Parallel()
h := newTestHandler(func(ctx context.Context, mockDataDir string) (seeddata.Summary, error) {
return seeddata.Summary{}, nil
})
status, body := performRequestBody(t, h, http.MethodPost, "/reseed/run", "", "")
if status != fiber.StatusUnauthorized {
t.Fatalf("expected 401, got %d", status)
}
if !strings.Contains(body, "Please unlock the reseed page first") {
t.Fatalf("expected unlock message, got %q", body)
}
}
func TestRunExecutesReseed(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, MockDataDir: mockDataDir}, nil
})
status, body := performRequestBody(t, h, http.MethodPost, "/reseed/run", "", reseedCookieName+"="+h.authCookieValue())
if status != fiber.StatusOK {
t.Fatalf("expected 200, got %d", status)
}
if !strings.Contains(body, "Reseed completed") || !strings.Contains(body, "student_answers: 588") {
t.Fatalf("expected success summary, got %q", body)
}
}
func TestRunSurfacesRunnerError(t *testing.T) {
t.Parallel()
h := newTestHandler(func(ctx context.Context, mockDataDir string) (seeddata.Summary, error) {
return seeddata.Summary{}, errors.New("boom")
})
status, body := performRequestBody(t, h, http.MethodPost, "/reseed/run", "", reseedCookieName+"="+h.authCookieValue())
if status != fiber.StatusInternalServerError {
t.Fatalf("expected 500, got %d", status)
}
if !strings.Contains(body, "boom") {
t.Fatalf("expected error body, got %q", body)
}
}
func newTestHandler(fn func(context.Context, string) (seeddata.Summary, error)) *Handler {
return &Handler{
cfg: &config.Config{
Environment: "production",
AdminReseedEnabled: true,
MockDataDir: "/app/Mock-Data",
JWTSecret: "jwt-secret",
ReseedPagePassword: "1588",
},
runner: fn,
}
}
func performRequest(t *testing.T, handler *Handler, method, path, formBody, cookieHeader string) (int, *http.Response) {
t.Helper()
app := testApp(handler)
req := httptest.NewRequest(method, path, strings.NewReader(formBody))
if formBody != "" {
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
}
if cookieHeader != "" {
req.Header.Set("Cookie", cookieHeader)
}
resp, err := app.Test(req)
if err != nil {
t.Fatalf("app.Test: %v", err)
}
return resp.StatusCode, resp
}
func performRequestBody(t *testing.T, handler *Handler, method, path, formBody, cookieHeader string) (int, string) {
t.Helper()
status, resp := performRequest(t, handler, method, path, formBody, cookieHeader)
defer resp.Body.Close()
bodyBytes, err := io.ReadAll(resp.Body)
if err != nil {
t.Fatalf("ReadAll: %v", err)
}
return status, string(bodyBytes)
}
func testApp(handler *Handler) *fiber.App {
app := fiber.New()
app.Get("/reseed", handler.Page)
app.Post("/reseed/login", handler.Login)
app.Post("/reseed/run", handler.Run)
app.Post("/reseed/logout", handler.Logout)
return app
}