Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions tests/unit/quizzes/ai-client.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Unit test coverage for the AI client, requested in #608: request format,
// request-ID propagation, malformed responses, retries/circuit breaker, and
// timeout handling are all covered below.
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";

vi.mock("../../../src/config/index.js", () => ({
Expand Down Expand Up @@ -50,6 +53,30 @@ describe("generateQuizFromAI", () => {
expect(result).toEqual(validBody.questions);
});

it("sends the request as a POST to /generate-quiz with the snake_case body the AI service expects", async () => {
const fetchMock = vi.fn().mockResolvedValue(jsonResponse(200, {
quiz_id: "quiz-1",
questions: [{ prompt: "Q1", options: ["a", "b"], correct_index: 0 }],
}));
vi.stubGlobal("fetch", fetchMock);

const { generateQuizFromAI } = await loadClient();
await generateQuizFromAI(baseParams);

expect(fetchMock).toHaveBeenCalledTimes(1);
const [url, init] = fetchMock.mock.calls[0];
expect(url).toBe("http://ai.test/generate-quiz");
expect(init.method).toBe("POST");
expect(init.headers["Content-Type"]).toBe("application/json");
expect(JSON.parse(init.body)).toEqual({
user_id: baseParams.userId,
course_id: baseParams.courseId,
module_id: baseParams.moduleId,
difficulty: baseParams.difficulty,
num_questions: baseParams.numQuestions,
});
});

it("propagates the current request ID to the AI service", async () => {
const fetchMock = vi.fn().mockResolvedValue(jsonResponse(200, {
quiz_id: "quiz-1",
Expand Down
Loading