feat(api): POST /api/recipes fuer Scratch-Insert aus Foto-Import
This commit is contained in:
86
tests/integration/recipes-post.test.ts
Normal file
86
tests/integration/recipes-post.test.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
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<typeof openInMemoryForTest> | null } };
|
||||
});
|
||||
|
||||
vi.mock('$lib/server/db', async () => {
|
||||
const actual =
|
||||
await vi.importActual<typeof import('../../src/lib/server/db')>(
|
||||
'../../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<typeof validBody>;
|
||||
delete bad.ingredients;
|
||||
await expect(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
POST(mkReq(bad) as any)
|
||||
).rejects.toMatchObject({ status: 400 });
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user