feat: add ownership check to evaluateAnswer, AuthenticatedRequest type
This commit is contained in:
parent
fdeb769640
commit
1e30f04e81
8 changed files with 189 additions and 39 deletions
|
|
@ -36,7 +36,6 @@ beforeEach(() => {
|
|||
});
|
||||
|
||||
describe("createGameSession", () => {
|
||||
|
||||
let store: InMemoryGameSessionStore;
|
||||
|
||||
beforeEach(() => {
|
||||
|
|
@ -44,14 +43,14 @@ describe("createGameSession", () => {
|
|||
});
|
||||
|
||||
it("returns a session with the correct number of questions", async () => {
|
||||
const session = await createGameSession(validRequest, store);
|
||||
const session = await createGameSession(validRequest, store, "user-1");
|
||||
|
||||
expect(session.sessionId).toBeDefined();
|
||||
expect(session.questions).toHaveLength(3);
|
||||
});
|
||||
|
||||
it("each question has exactly 4 options", async () => {
|
||||
const session = await createGameSession(validRequest, store);
|
||||
const session = await createGameSession(validRequest, store, "user-1");
|
||||
|
||||
for (const question of session.questions) {
|
||||
expect(question.options).toHaveLength(4);
|
||||
|
|
@ -59,14 +58,14 @@ describe("createGameSession", () => {
|
|||
});
|
||||
|
||||
it("each question has a unique questionId", async () => {
|
||||
const session = await createGameSession(validRequest, store);
|
||||
const session = await createGameSession(validRequest, store, "user-1");
|
||||
const ids = session.questions.map((q) => q.questionId);
|
||||
|
||||
expect(new Set(ids).size).toBe(ids.length);
|
||||
});
|
||||
|
||||
it("options have sequential optionIds 0-3", async () => {
|
||||
const session = await createGameSession(validRequest, store);
|
||||
const session = await createGameSession(validRequest, store, "user-1");
|
||||
|
||||
for (const question of session.questions) {
|
||||
const optionIds = question.options.map((o) => o.optionId);
|
||||
|
|
@ -75,7 +74,7 @@ describe("createGameSession", () => {
|
|||
});
|
||||
|
||||
it("the correct answer is always among the options", async () => {
|
||||
const session = await createGameSession(validRequest, store);
|
||||
const session = await createGameSession(validRequest, store, "user-1");
|
||||
|
||||
for (let i = 0; i < session.questions.length; i++) {
|
||||
const question = session.questions[i]!;
|
||||
|
|
@ -87,7 +86,7 @@ describe("createGameSession", () => {
|
|||
});
|
||||
|
||||
it("distractors are never the correct answer", async () => {
|
||||
const session = await createGameSession(validRequest, store);
|
||||
const session = await createGameSession(validRequest, store, "user-1");
|
||||
|
||||
for (let i = 0; i < session.questions.length; i++) {
|
||||
const question = session.questions[i]!;
|
||||
|
|
@ -103,7 +102,7 @@ describe("createGameSession", () => {
|
|||
});
|
||||
|
||||
it("sets the prompt from the source text", async () => {
|
||||
const session = await createGameSession(validRequest, store);
|
||||
const session = await createGameSession(validRequest, store, "user-1");
|
||||
|
||||
expect(session.questions[0]!.prompt).toBe("dog");
|
||||
expect(session.questions[1]!.prompt).toBe("cat");
|
||||
|
|
@ -111,14 +110,14 @@ describe("createGameSession", () => {
|
|||
});
|
||||
|
||||
it("passes gloss through (null or string)", async () => {
|
||||
const session = await createGameSession(validRequest, store);
|
||||
const session = await createGameSession(validRequest, store, "user-1");
|
||||
|
||||
expect(session.questions[0]!.gloss).toBeNull();
|
||||
expect(session.questions[2]!.gloss).toBe("a building for living in");
|
||||
});
|
||||
|
||||
it("calls getGameTerms with the correct arguments", async () => {
|
||||
await createGameSession(validRequest, store);
|
||||
await createGameSession(validRequest, store, "user-1");
|
||||
|
||||
expect(mockGetGameTerms).toHaveBeenCalledWith(
|
||||
"en",
|
||||
|
|
@ -130,7 +129,7 @@ describe("createGameSession", () => {
|
|||
});
|
||||
|
||||
it("calls getDistractors once per question", async () => {
|
||||
await createGameSession(validRequest, store);
|
||||
await createGameSession(validRequest, store, "user-1");
|
||||
|
||||
expect(mockGetDistractors).toHaveBeenCalledTimes(3);
|
||||
});
|
||||
|
|
@ -138,23 +137,21 @@ describe("createGameSession", () => {
|
|||
it("propagates unexpected errors from getGameTerms", async () => {
|
||||
mockGetGameTerms.mockRejectedValue(new Error("connection refused"));
|
||||
|
||||
await expect(createGameSession(validRequest, store)).rejects.toThrow(
|
||||
"connection refused",
|
||||
);
|
||||
await expect(
|
||||
createGameSession(validRequest, store, "user-1"),
|
||||
).rejects.toThrow("connection refused");
|
||||
});
|
||||
});
|
||||
|
||||
describe("evaluateAnswer", () => {
|
||||
|
||||
let store: InMemoryGameSessionStore;
|
||||
|
||||
beforeEach(() => {
|
||||
store = new InMemoryGameSessionStore();
|
||||
});
|
||||
|
||||
|
||||
it("returns isCorrect: true when the correct option is selected", async () => {
|
||||
const session = await createGameSession(validRequest, store);
|
||||
const session = await createGameSession(validRequest, store, "user-1");
|
||||
const question = session.questions[0]!;
|
||||
const correctText = fakeTerms[0]!.targetText;
|
||||
const correctOption = question.options.find((o) => o.text === correctText)!;
|
||||
|
|
@ -166,6 +163,7 @@ describe("evaluateAnswer", () => {
|
|||
selectedOptionId: correctOption.optionId,
|
||||
},
|
||||
store,
|
||||
"user-1",
|
||||
);
|
||||
|
||||
expect(result.isCorrect).toBe(true);
|
||||
|
|
@ -174,7 +172,7 @@ describe("evaluateAnswer", () => {
|
|||
});
|
||||
|
||||
it("returns isCorrect: false when a wrong option is selected", async () => {
|
||||
const session = await createGameSession(validRequest, store);
|
||||
const session = await createGameSession(validRequest, store, "user-1");
|
||||
const question = session.questions[0]!;
|
||||
const correctText = fakeTerms[0]!.targetText;
|
||||
const correctOption = question.options.find((o) => o.text === correctText)!;
|
||||
|
|
@ -187,6 +185,7 @@ describe("evaluateAnswer", () => {
|
|||
selectedOptionId: wrongOption.optionId,
|
||||
},
|
||||
store,
|
||||
"user-1",
|
||||
);
|
||||
|
||||
expect(result.isCorrect).toBe(false);
|
||||
|
|
@ -201,13 +200,13 @@ describe("evaluateAnswer", () => {
|
|||
selectedOptionId: 0,
|
||||
};
|
||||
|
||||
await expect(evaluateAnswer(submission, store)).rejects.toThrow(
|
||||
await expect(evaluateAnswer(submission, store, "user-1")).rejects.toThrow(
|
||||
"Game session not found",
|
||||
);
|
||||
});
|
||||
|
||||
it("throws NotFoundError for a non-existent question", async () => {
|
||||
const session = await createGameSession(validRequest, store);
|
||||
const session = await createGameSession(validRequest, store, "user-1");
|
||||
|
||||
const submission: AnswerSubmission = {
|
||||
sessionId: session.sessionId,
|
||||
|
|
@ -215,13 +214,13 @@ describe("evaluateAnswer", () => {
|
|||
selectedOptionId: 0,
|
||||
};
|
||||
|
||||
await expect(evaluateAnswer(submission, store)).rejects.toThrow(
|
||||
await expect(evaluateAnswer(submission, store, "user-1")).rejects.toThrow(
|
||||
"Question not found",
|
||||
);
|
||||
});
|
||||
|
||||
it("throws NotFoundError when the same question is submitted twice", async () => {
|
||||
const session = await createGameSession(validRequest, store);
|
||||
const session = await createGameSession(validRequest, store, "user-1");
|
||||
const question = session.questions[0]!;
|
||||
|
||||
await evaluateAnswer(
|
||||
|
|
@ -231,6 +230,7 @@ describe("evaluateAnswer", () => {
|
|||
selectedOptionId: 0,
|
||||
},
|
||||
store,
|
||||
"user-1",
|
||||
);
|
||||
|
||||
await expect(
|
||||
|
|
@ -241,12 +241,13 @@ describe("evaluateAnswer", () => {
|
|||
selectedOptionId: 0,
|
||||
},
|
||||
store,
|
||||
"user-1",
|
||||
),
|
||||
).rejects.toThrow("Question not found");
|
||||
});
|
||||
|
||||
it("deletes the session after the last question is answered", async () => {
|
||||
const session = await createGameSession(validRequest, store);
|
||||
const session = await createGameSession(validRequest, store, "user-1");
|
||||
|
||||
for (const question of session.questions) {
|
||||
await evaluateAnswer(
|
||||
|
|
@ -256,6 +257,7 @@ describe("evaluateAnswer", () => {
|
|||
selectedOptionId: 0,
|
||||
},
|
||||
store,
|
||||
"user-1",
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -267,6 +269,7 @@ describe("evaluateAnswer", () => {
|
|||
selectedOptionId: 0,
|
||||
},
|
||||
store,
|
||||
"user-1",
|
||||
),
|
||||
).rejects.toThrow("Game session not found");
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue