import { describe, it, expect, beforeEach } from 'vitest'; import { openInMemoryForTest } from '../../src/lib/server/db'; import { createProfile } from '../../src/lib/server/profiles/repository'; import { insertRecipe, getRecipeById } from '../../src/lib/server/recipes/repository'; import { setRating, clearRating, listRatings, addFavorite, removeFavorite, isFavorite, logCooked, listCookingLog, addComment, listComments, deleteComment, renameRecipe } from '../../src/lib/server/recipes/actions'; import type Database from 'better-sqlite3'; let db: Database.Database; let profileId: number; let recipeId: number; beforeEach(() => { db = openInMemoryForTest(); profileId = createProfile(db, 'Hendrik').id; recipeId = insertRecipe(db, { id: null, title: 'Test', description: null, source_url: null, source_domain: null, image_path: null, servings_default: 4, servings_unit: null, prep_time_min: null, cook_time_min: null, total_time_min: null, cuisine: null, category: null, ingredients: [], steps: [], tags: [] }); }); describe('rating', () => { it('upserts a rating', () => { setRating(db, recipeId, profileId, 4); expect(listRatings(db, recipeId)).toEqual([{ profile_id: profileId, stars: 4 }]); setRating(db, recipeId, profileId, 5); expect(listRatings(db, recipeId)[0].stars).toBe(5); }); it('rejects invalid stars', () => { expect(() => setRating(db, recipeId, profileId, 0)).toThrow(); expect(() => setRating(db, recipeId, profileId, 6)).toThrow(); }); it('clears rating', () => { setRating(db, recipeId, profileId, 3); clearRating(db, recipeId, profileId); expect(listRatings(db, recipeId)).toEqual([]); }); }); describe('favorite', () => { it('adds, checks, removes (idempotent add)', () => { expect(isFavorite(db, recipeId, profileId)).toBe(false); addFavorite(db, recipeId, profileId); addFavorite(db, recipeId, profileId); // no-op expect(isFavorite(db, recipeId, profileId)).toBe(true); removeFavorite(db, recipeId, profileId); expect(isFavorite(db, recipeId, profileId)).toBe(false); }); }); describe('cooking log', () => { it('logs cooked and lists', () => { logCooked(db, recipeId, profileId); logCooked(db, recipeId, profileId); expect(listCookingLog(db, recipeId).length).toBe(2); }); }); describe('comments', () => { it('adds, lists with author name, deletes', () => { const id = addComment(db, recipeId, profileId, 'Salz durch Zucker ersetzen'); const list = listComments(db, recipeId); expect(list.length).toBe(1); expect(list[0].text).toBe('Salz durch Zucker ersetzen'); expect(list[0].author).toBe('Hendrik'); deleteComment(db, id); expect(listComments(db, recipeId).length).toBe(0); }); it('rejects empty', () => { expect(() => addComment(db, recipeId, profileId, ' ')).toThrow(); }); }); describe('rename', () => { it('updates title', () => { renameRecipe(db, recipeId, 'Neuer Titel'); const r = getRecipeById(db, recipeId); expect(r!.title).toBe('Neuer Titel'); }); it('rejects empty title', () => { expect(() => renameRecipe(db, recipeId, '')).toThrow(); }); });