refactor: update result schemas and tests for improved state management and feedback modes
Test / backend (push) Successful in 13s
Test / frontend (push) Successful in 24s
Release Pipeline / build-and-release (push) Failing after 6s

This commit is contained in:
LaurensBartelds committed 2026-04-26 23:54:56 +02:00
1 parent ae8a01bc54
commit 95603f93a0
4 files changed
+47 -46

No files matched your search

+43 -20
View File
@@ -11,12 +11,12 @@ describe('submitResultSchema', () => {
graded_count: 10,
elapsed_ms: 120000,
state: {
currentIdx: 0,
answers: { q1: 'a' },
gradedAnswers: { q1: { correct: true, points: 1 } },
answeredCount: 10,
score: 80,
correctCount: 8,
gradedCount: 10,
flags: { q1: false },
notes: '',
startedAt: Date.now(),
feedbackMode: 'end',
},
exam: {
title: 'My Exam',
@@ -34,12 +34,12 @@ describe('submitResultSchema', () => {
graded_count: 10,
elapsed_ms: 120000,
state: {
currentIdx: 0,
answers: {},
gradedAnswers: {},
answeredCount: 0,
score: 0,
correctCount: 0,
gradedCount: 0,
flags: {},
notes: '',
startedAt: Date.now(),
feedbackMode: 'end',
},
exam: { title: 'My Exam', questions: [] },
})
@@ -56,12 +56,12 @@ describe('submitResultSchema', () => {
graded_count: 10,
elapsed_ms: 120000,
state: {
currentIdx: 0,
answers: {},
gradedAnswers: {},
answeredCount: 0,
score: 0,
correctCount: 0,
gradedCount: 0,
flags: {},
notes: '',
startedAt: Date.now(),
feedbackMode: 'end',
},
exam: { title: 'My Exam', questions: [] },
})
@@ -77,12 +77,35 @@ describe('submitResultSchema', () => {
graded_count: 10,
elapsed_ms: 120000,
state: {
currentIdx: 0,
answers: {},
gradedAnswers: {},
answeredCount: 0,
score: 0,
correctCount: 0,
gradedCount: 0,
flags: {},
notes: '',
startedAt: Date.now(),
feedbackMode: 'end',
},
exam: { title: 'My Exam', questions: [] },
})
expect(result.success).toBe(true)
})
it('accepts immediate feedback mode', () => {
const result = submitResultSchema.safeParse({
title: 'My Exam',
score_points: 8,
total_points: 10,
correct_count: 8,
graded_count: 10,
elapsed_ms: 120000,
state: {
currentIdx: 2,
answers: { q1: 'a', q2: 'b' },
flags: { q1: true },
notes: 'some notes',
revealed: { q1: true },
startedAt: Date.now(),
completedAt: Date.now(),
feedbackMode: 'immediate',
},
exam: { title: 'My Exam', questions: [] },
})
+2 -24
View File
@@ -1,7 +1,5 @@
import { z } from 'zod'
const answerValueSchema = z.union([z.string(), z.array(z.string()), z.record(z.string(), z.string())])
export const submitResultSchema = z.object({
exam_id: z.number().nullable().optional(),
title: z.string().min(1),
@@ -11,28 +9,8 @@ export const submitResultSchema = z.object({
graded_count: z.number(),
passing_score: z.number().optional(),
elapsed_ms: z.number(),
state: z.object({
answers: z.record(z.string(), answerValueSchema),
gradedAnswers: z.record(z.string(), z.object({
correct: z.boolean(),
points: z.number(),
explanation: z.string().optional(),
})),
answeredCount: z.number(),
score: z.number(),
correctCount: z.number(),
gradedCount: z.number(),
timeExpired: z.boolean().optional(),
}),
exam: z.object({
id: z.string().optional(),
title: z.string(),
subtitle: z.string().optional(),
questions: z.array(z.any()),
timeLimitMinutes: z.number().nullable().optional(),
passingScore: z.number().optional(),
feedbackMode: z.enum(['end', 'immediate']).optional(),
}).passthrough(),
state: z.record(z.unknown()),
exam: z.record(z.unknown()),
})
export const resultIdParamSchema = z.object({
+1 -1
View File
@@ -61,7 +61,7 @@ function AppInner() {
const apiHistory: HistoryEntry[] = data.results.map((r) => ({
id: String(r.id),
title: r.title,
completedAt: r.completed_at * 1000,
completedAt: r.completed_at,
elapsedMs: r.elapsed_ms,
gradedCount: r.graded_count,
correctCount: r.correct_count,
@@ -1 +1 @@
{"version":"4.1.5","results":[[":frontend/src/utils/grading.test.ts",{"duration":13.527699999999982,"failed":false}],[":frontend/src/utils/latex.test.ts",{"duration":19.335300000000075,"failed":false}],[":backend/src/validators/authSchemas.test.ts",{"duration":18.226099999999974,"failed":false}],[":frontend/src/utils/validation.test.ts",{"duration":8.861599999999953,"failed":false}],[":frontend/src/utils/storage.test.ts",{"duration":13.730599999999981,"failed":false}],[":backend/src/validators/examSchemas.test.ts",{"duration":14.561199999999985,"failed":false}],[":backend/src/validators/adminSchemas.test.ts",{"duration":10.744000000000028,"failed":false}],[":backend/src/middleware/error.test.ts",{"duration":3.961199999999991,"failed":false}],[":frontend/src/utils/slug.test.ts",{"duration":7.912199999999984,"failed":false}],[":frontend/src/utils/formatting.test.ts",{"duration":8.322499999999991,"failed":false}],[":backend/src/config.test.ts",{"duration":5.9365999999999985,"failed":false}],[":backend/src/validators/resultSchemas.test.ts",{"duration":10.511600000000044,"failed":false}],[":backend/src/utils/tokens.test.ts",{"duration":197.5005,"failed":false}],[":backend/src/validators/setupSchemas.test.ts",{"duration":12.653300000000058,"failed":false}],[":backend/src/utils/asyncHandler.test.ts",{"duration":8.633299999999963,"failed":false}],[":frontend/src/utils/api.test.ts",{"duration":5.6884000000000015,"failed":false}]]}
{"version":"4.1.5","results":[[":frontend/src/utils/grading.test.ts",{"duration":7.161699999999996,"failed":false}],[":frontend/src/utils/latex.test.ts",{"duration":9.518499999999989,"failed":false}],[":backend/src/validators/authSchemas.test.ts",{"duration":7.022400000000005,"failed":false}],[":frontend/src/utils/validation.test.ts",{"duration":4.217900000000014,"failed":false}],[":frontend/src/utils/storage.test.ts",{"duration":4.687600000000003,"failed":false}],[":backend/src/validators/examSchemas.test.ts",{"duration":6.788000000000011,"failed":false}],[":backend/src/validators/adminSchemas.test.ts",{"duration":7.534500000000008,"failed":false}],[":backend/src/middleware/error.test.ts",{"duration":2.5043000000000006,"failed":false}],[":frontend/src/utils/slug.test.ts",{"duration":4.5700999999999965,"failed":false}],[":frontend/src/utils/formatting.test.ts",{"duration":4.011300000000006,"failed":false}],[":backend/src/config.test.ts",{"duration":4.423100000000005,"failed":false}],[":backend/src/validators/resultSchemas.test.ts",{"duration":5.812899999999985,"failed":false}],[":backend/src/utils/tokens.test.ts",{"duration":73.72379999999998,"failed":false}],[":backend/src/validators/setupSchemas.test.ts",{"duration":5.070899999999995,"failed":false}],[":backend/src/utils/asyncHandler.test.ts",{"duration":4.5079000000000065,"failed":false}],[":frontend/src/utils/api.test.ts",{"duration":3.4222000000000037,"failed":false}]]}