feat(timetable): validate API responses against Zod schemas at runtime
Per Phase A finding A5 — Zod schemas in @/schemas/timetable.ts were
types-only; nothing parsed actual server responses. Backend → frontend
contract drift would only surface as TypeError deep in components.
useTimetable.ts queries now parse:
- useStages → stageArraySchema.parse()
- usePerformances → performanceArraySchema.parse()
- useWachtrij → performanceArraySchema.parse()
- useEngagement → artistEngagementSchema.parse()
useTimetableMutations.ts mutations now parse:
- move success → moveTimetableSuccessSchema.parse()
- move 409 errors → moveTimetableConflictSchema.parse() (the .errors
sub-object — see backend canon at TimetableMoveController:64)
- create / updateNotes → performanceSchema.parse()
- createStage / updateStage → stageSchema.parse()
The move() success parse runs OUTSIDE the try/catch so a Zod failure on
a 200 response surfaces as a true error rather than being misclassified
as a 409. Per Phase A finding A8 the conflict shape already matches
backend field-for-field; no schema correction needed, but the parse()
locks future drift in.
Regression test (tests/unit/composables/api/zodParseFailure.test.ts):
- move() success with missing fields → rejects with ZodError
- move() 409 with malformed errors payload → rejects with ZodError
- createStage() with missing fields → rejects with ZodError
Existing test fixture for createStage was missing created_at/updated_at;
fixed in same commit (real backend responses always include them).
Test count: 321 → 324.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -188,7 +188,19 @@ describe('useTimetableMutations', () => {
|
||||
describe('createStage', () => {
|
||||
it('hits POST /stages', async () => {
|
||||
mocked.post.mockResolvedValueOnce({
|
||||
data: { success: true, data: { id: 's2', name: 'New Stage', color: '#aabbcc', capacity: 1000, sort_order: 1, event_id: 'ev_1' } },
|
||||
data: {
|
||||
success: true,
|
||||
data: {
|
||||
id: 's2',
|
||||
name: 'New Stage',
|
||||
color: '#aabbcc',
|
||||
capacity: 1000,
|
||||
sort_order: 1,
|
||||
event_id: 'ev_1',
|
||||
created_at: '2026-07-10T18:00:00.000Z',
|
||||
updated_at: '2026-07-10T18:00:00.000Z',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const { api } = mountWithMutations()
|
||||
|
||||
Reference in New Issue
Block a user