141 lines
3.7 KiB
Go
141 lines
3.7 KiB
Go
package questions
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"boostai-backend/internal/http/respond"
|
|
"boostai-backend/internal/questiongen"
|
|
"boostai-backend/internal/sqlc"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
)
|
|
|
|
func TestGenerateQuestionsReturnsGeneratorUnavailable(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
handler := NewHandler(nil, nil)
|
|
status, body := performGenerateRequest(t, handler, map[string]any{
|
|
"topic": "fractions",
|
|
"difficulty": "easy",
|
|
"count": 1,
|
|
}, true)
|
|
|
|
if status != fiber.StatusServiceUnavailable {
|
|
t.Fatalf("expected status %d, got %d", fiber.StatusServiceUnavailable, status)
|
|
}
|
|
if body.Error != "generator_unavailable" {
|
|
t.Fatalf("expected generator_unavailable error, got %#v", body)
|
|
}
|
|
}
|
|
|
|
func TestGenerateQuestionsRequiresTeacherAuthentication(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
handler := NewHandler(nil, questiongen.NewService())
|
|
status, body := performGenerateRequest(t, handler, map[string]any{
|
|
"topic": "fractions",
|
|
"difficulty": "easy",
|
|
"count": 1,
|
|
}, false)
|
|
|
|
if status != fiber.StatusUnauthorized {
|
|
t.Fatalf("expected status %d, got %d", fiber.StatusUnauthorized, status)
|
|
}
|
|
if body.Error != "unauthorized" {
|
|
t.Fatalf("expected unauthorized error, got %#v", body)
|
|
}
|
|
}
|
|
|
|
func TestGenerateQuestionsRejectsZeroCount(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
handler := NewHandler(nil, questiongen.NewService())
|
|
status, body := performGenerateRequest(t, handler, map[string]any{
|
|
"topic": "fractions",
|
|
"difficulty": "easy",
|
|
"count": 0,
|
|
}, true)
|
|
|
|
if status != fiber.StatusBadRequest {
|
|
t.Fatalf("expected status %d, got %d", fiber.StatusBadRequest, status)
|
|
}
|
|
if body.Message != "count must be between 1 and 25" {
|
|
t.Fatalf("expected count validation message, got %#v", body)
|
|
}
|
|
}
|
|
|
|
func TestGenerateQuestionsRejectsInvalidStatus(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
handler := NewHandler(nil, questiongen.NewService())
|
|
status, body := performGenerateRequest(t, handler, map[string]any{
|
|
"topic": "fractions",
|
|
"difficulty": "easy",
|
|
"count": 1,
|
|
"status": "invalid",
|
|
}, true)
|
|
|
|
if status != fiber.StatusBadRequest {
|
|
t.Fatalf("expected status %d, got %d", fiber.StatusBadRequest, status)
|
|
}
|
|
if body.Message != "status must be draft, published, or archived" {
|
|
t.Fatalf("expected invalid status message, got %#v", body)
|
|
}
|
|
}
|
|
|
|
func TestGenerateQuestionsRejectsInvalidTopic(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
handler := NewHandler(nil, questiongen.NewService())
|
|
status, body := performGenerateRequest(t, handler, map[string]any{
|
|
"topic": "not_a_topic",
|
|
"difficulty": "easy",
|
|
"count": 1,
|
|
}, true)
|
|
|
|
if status != fiber.StatusBadRequest {
|
|
t.Fatalf("expected status %d, got %d", fiber.StatusBadRequest, status)
|
|
}
|
|
if body.Error != "invalid_request" {
|
|
t.Fatalf("expected invalid_request error, got %#v", body)
|
|
}
|
|
}
|
|
|
|
func performGenerateRequest(t *testing.T, handler *Handler, payload map[string]any, authenticated bool) (int, respond.ErrorBody) {
|
|
t.Helper()
|
|
|
|
app := fiber.New()
|
|
app.Post("/questions/generate", func(c *fiber.Ctx) error {
|
|
if authenticated {
|
|
c.Locals("auth.user_id", int64(42))
|
|
c.Locals("auth.role", sqlc.UserRoleTeacher)
|
|
}
|
|
return handler.GenerateQuestions(c)
|
|
})
|
|
|
|
bodyBytes, err := json.Marshal(payload)
|
|
if err != nil {
|
|
t.Fatalf("marshal payload: %v", err)
|
|
}
|
|
|
|
req := httptest.NewRequest(http.MethodPost, "/questions/generate", bytes.NewReader(bodyBytes))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
resp, err := app.Test(req)
|
|
if err != nil {
|
|
t.Fatalf("app.Test returned error: %v", err)
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
var errorBody respond.ErrorBody
|
|
if err := json.NewDecoder(resp.Body).Decode(&errorBody); err != nil {
|
|
t.Fatalf("decode error response: %v", err)
|
|
}
|
|
|
|
return resp.StatusCode, errorBody
|
|
}
|