fix: improve error semantics, clarify answer key type
This commit is contained in:
parent
6eaf282651
commit
648c5d2979
6 changed files with 62 additions and 34 deletions
|
|
@ -255,7 +255,7 @@ describe("evaluateAnswer", () => {
|
|||
);
|
||||
});
|
||||
|
||||
it("throws NotFoundError for a non-existent question", async () => {
|
||||
it("throws ConflictError for a non-existent question", async () => {
|
||||
const session = await createGameSession(validRequest, store, "user-1");
|
||||
|
||||
const submission: AnswerSubmission = {
|
||||
|
|
@ -264,12 +264,12 @@ describe("evaluateAnswer", () => {
|
|||
selectedOptionId: 0,
|
||||
};
|
||||
|
||||
await expect(evaluateAnswer(submission, store, "user-1")).rejects.toThrow(
|
||||
"Question not found",
|
||||
);
|
||||
await expect(
|
||||
evaluateAnswer(submission, store, "user-1"),
|
||||
).rejects.toMatchObject({ statusCode: 409 });
|
||||
});
|
||||
|
||||
it("throws NotFoundError when the same question is submitted twice", async () => {
|
||||
it("throws ConflictError when the same question is submitted twice", async () => {
|
||||
const session = await createGameSession(validRequest, store, "user-1");
|
||||
const question = session.questions[0]!;
|
||||
|
||||
|
|
@ -293,7 +293,7 @@ describe("evaluateAnswer", () => {
|
|||
store,
|
||||
"user-1",
|
||||
),
|
||||
).rejects.toThrow("Question not found");
|
||||
).rejects.toMatchObject({ statusCode: 409 });
|
||||
});
|
||||
|
||||
it("deletes the session after the last question is answered", async () => {
|
||||
|
|
@ -324,11 +324,11 @@ describe("evaluateAnswer", () => {
|
|||
).rejects.toThrow("Game session not found");
|
||||
});
|
||||
|
||||
it("throws NotFoundError when getGameTerms returns no terms", async () => {
|
||||
it("throws UnprocessableEntityError when getGameTerms returns no terms", async () => {
|
||||
mockGetGameTerms.mockResolvedValue([]);
|
||||
|
||||
await expect(
|
||||
createGameSession(validRequest, store, "user-1"),
|
||||
).rejects.toThrow("No terms found");
|
||||
).rejects.toMatchObject({ statusCode: 422 });
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -9,7 +9,11 @@ import type {
|
|||
AnswerResult,
|
||||
} from "@lila/shared";
|
||||
import type { GameSessionStore } from "../gameSessionStore/index.js";
|
||||
import { NotFoundError } from "../errors/AppError.js";
|
||||
import {
|
||||
NotFoundError,
|
||||
ConflictError,
|
||||
UnprocessableEntityError,
|
||||
} from "../errors/AppError.js";
|
||||
import { shuffleArray } from "../lib/utils.js";
|
||||
|
||||
export const createGameSession = async (
|
||||
|
|
@ -26,10 +30,10 @@ export const createGameSession = async (
|
|||
);
|
||||
|
||||
if (terms.length === 0) {
|
||||
throw new NotFoundError("No terms found for the given filters");
|
||||
throw new UnprocessableEntityError("No terms found for the given filters");
|
||||
}
|
||||
|
||||
const answerKey = new Map<string, number>();
|
||||
const answerKey = new Map<string, { correctOptionId: number }>();
|
||||
|
||||
const questions: GameQuestion[] = await Promise.all(
|
||||
terms.map(async (term) => {
|
||||
|
|
@ -62,7 +66,7 @@ export const createGameSession = async (
|
|||
}));
|
||||
|
||||
const questionId = randomUUID();
|
||||
answerKey.set(questionId, correctOptionId);
|
||||
answerKey.set(questionId, { correctOptionId });
|
||||
|
||||
return {
|
||||
questionId,
|
||||
|
|
@ -90,10 +94,12 @@ export const evaluateAnswer = async (
|
|||
throw new NotFoundError(`Game session not found: ${submission.sessionId}`);
|
||||
}
|
||||
|
||||
const correctOptionId = session.answers.get(submission.questionId);
|
||||
const answer = session.answers.get(submission.questionId);
|
||||
|
||||
if (correctOptionId === undefined) {
|
||||
throw new NotFoundError(`Question not found: ${submission.questionId}`);
|
||||
if (answer === undefined) {
|
||||
throw new ConflictError(
|
||||
`Question already answered: ${submission.questionId}`,
|
||||
);
|
||||
}
|
||||
|
||||
const updatedAnswers = new Map(session.answers);
|
||||
|
|
@ -110,8 +116,8 @@ export const evaluateAnswer = async (
|
|||
|
||||
return {
|
||||
questionId: submission.questionId,
|
||||
isCorrect: submission.selectedOptionId === correctOptionId,
|
||||
correctOptionId,
|
||||
isCorrect: submission.selectedOptionId === answer.correctOptionId,
|
||||
correctOptionId: answer.correctOptionId,
|
||||
selectedOptionId: submission.selectedOptionId,
|
||||
};
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue