test(recipes): add action tests and harden create/update form actions
- Add try-catch around JSON.parse with fail(400) for malformed input - Validate effort against allowed values ['Easy','Medium','Hard'] - Fix NaN risk: Number(serves)||undefined instead of Number(serves) - Add action tests for create/update: validation, JSON.parse crash, success, API error Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,8 @@ import { redirect, fail } from '@sveltejs/kit';
|
||||
import type { PageServerLoad, Actions } from './$types';
|
||||
import { apiClient } from '$lib/server/api';
|
||||
|
||||
const VALID_EFFORTS = ['Easy', 'Medium', 'Hard'];
|
||||
|
||||
export const load: PageServerLoad = async ({ fetch }) => {
|
||||
const api = apiClient(fetch);
|
||||
const { data, error } = await api.GET('/v1/tags', {});
|
||||
@@ -26,30 +28,37 @@ export const actions: Actions = {
|
||||
const tagIds = formData.getAll('tagIds') as string[];
|
||||
|
||||
if (!name?.trim()) return fail(422, { error: 'Name ist erforderlich' });
|
||||
if (!effort) return fail(422, { error: 'Schwierigkeitsgrad ist erforderlich' });
|
||||
if (!effort || !VALID_EFFORTS.includes(effort))
|
||||
return fail(422, { error: 'Ungültiger Schwierigkeitsgrad' });
|
||||
if (!tagIds.length) return fail(422, { error: 'Mindestens eine Kategorie ist erforderlich' });
|
||||
|
||||
const parsedIngredients = JSON.parse(ingredientsJson || '[]');
|
||||
const parsedSteps = JSON.parse(stepsJson || '[]');
|
||||
let parsedIngredients: unknown[];
|
||||
let parsedSteps: unknown[];
|
||||
try {
|
||||
parsedIngredients = JSON.parse(ingredientsJson || '[]');
|
||||
parsedSteps = JSON.parse(stepsJson || '[]');
|
||||
} catch {
|
||||
return fail(400, { error: 'Ungültige Formulardaten' });
|
||||
}
|
||||
|
||||
const api = apiClient(fetch);
|
||||
const { error: apiError } = await api.POST('/v1/recipes', {
|
||||
body: {
|
||||
name: name.trim(),
|
||||
serves: serves ? Number(serves) : undefined,
|
||||
cookTimeMin: cookTimeMin ? Number(cookTimeMin) : undefined,
|
||||
serves: serves ? Number(serves) || undefined : undefined,
|
||||
cookTimeMin: cookTimeMin ? Number(cookTimeMin) || undefined : undefined,
|
||||
effort,
|
||||
ingredients: parsedIngredients
|
||||
.filter((ing: { name: string }) => ing.name?.trim())
|
||||
.map((ing: { name: string; quantity: string; unit: string }, i: number) => ({
|
||||
ingredients: (parsedIngredients as { name: string; quantity: string; unit: string }[])
|
||||
.filter((ing) => ing.name?.trim())
|
||||
.map((ing, i) => ({
|
||||
newIngredientName: ing.name.trim(),
|
||||
quantity: Number(ing.quantity) || 0,
|
||||
unit: ing.unit || '',
|
||||
sortOrder: i
|
||||
})),
|
||||
steps: parsedSteps
|
||||
.filter((s: string) => s?.trim())
|
||||
.map((s: string, i: number) => ({ stepNumber: i + 1, instruction: s.trim() })),
|
||||
steps: (parsedSteps as string[])
|
||||
.filter((s) => s?.trim())
|
||||
.map((s, i) => ({ stepNumber: i + 1, instruction: s.trim() })),
|
||||
tagIds
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user