import { describe, it, expect, beforeEach, vi } from 'vitest'; import { openInMemoryForTest } from '../../src/lib/server/db'; const { testDb } = vi.hoisted(() => { // Lazy holder; real DB instantiated in beforeEach. return { testDb: { current: null as ReturnType | null } }; }); vi.mock('$lib/server/db', async () => { const actual = await vi.importActual( '../../src/lib/server/db' ); return { ...actual, getDb: () => { if (!testDb.current) throw new Error('test DB not initialised'); return testDb.current; } }; }); import { POST } from '../../src/routes/api/recipes/+server'; function mkReq(body: unknown) { return { request: new Request('http://test/api/recipes', { method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(body) }) }; } const validBody = { title: 'Aus Foto erstellt', description: 'Abrakadabra — Rezept da.', servings_default: 4, servings_unit: 'Portionen', prep_time_min: 10, cook_time_min: 20, total_time_min: null, ingredients: [ { position: 1, quantity: 1, unit: null, name: 'Apfel', note: null, raw_text: '1 Apfel', section_heading: null } ], steps: [{ position: 1, text: 'Apfel schneiden.' }] }; beforeEach(() => { testDb.current = openInMemoryForTest(); }); describe('POST /api/recipes', () => { it('happy path returns 201 + id', async () => { // eslint-disable-next-line @typescript-eslint/no-explicit-any const res = await POST(mkReq(validBody) as any); expect(res.status).toBe(201); const body = await res.json(); expect(typeof body.id).toBe('number'); expect(body.id).toBeGreaterThan(0); }); it('400 on empty title', async () => { await expect( // eslint-disable-next-line @typescript-eslint/no-explicit-any POST(mkReq({ ...validBody, title: '' }) as any) ).rejects.toMatchObject({ status: 400 }); }); it('400 on missing ingredients array', async () => { const bad = { ...validBody } as Partial; delete bad.ingredients; await expect( // eslint-disable-next-line @typescript-eslint/no-explicit-any POST(mkReq(bad) as any) ).rejects.toMatchObject({ status: 400 }); }); });