import { describe, it, expect } from 'vitest'; import { openInMemoryForTest } from '../../src/lib/server/db'; import { runMigrations } from '../../src/lib/server/db/migrate'; describe('db migrations', () => { it('creates all expected tables', () => { const db = openInMemoryForTest(); const tables = ( db.prepare("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name").all() as { name: string; }[] ).map((r) => r.name); for (const t of [ 'profile', 'recipe', 'ingredient', 'step', 'tag', 'recipe_tag', 'rating', 'comment', 'favorite', 'cooking_log', 'allowed_domain', 'schema_migration' ]) { expect(tables).toContain(t); } }); it('is idempotent', () => { const db = openInMemoryForTest(); const countBefore = ( db.prepare('SELECT COUNT(*) AS c FROM schema_migration').get() as { c: number } ).c; runMigrations(db); const countAfter = ( db.prepare('SELECT COUNT(*) AS c FROM schema_migration').get() as { c: number } ).c; expect(countAfter).toBe(countBefore); }); it('cascades recipe delete to ingredients and steps', () => { const db = openInMemoryForTest(); const row = db .prepare('INSERT INTO recipe(title) VALUES (?) RETURNING id') .get('Test') as { id: number }; db.prepare('INSERT INTO ingredient(recipe_id, position, name) VALUES (?, ?, ?)').run( row.id, 1, 'Salz' ); db.prepare('INSERT INTO step(recipe_id, position, text) VALUES (?, ?, ?)').run( row.id, 1, 'Kochen' ); db.prepare('DELETE FROM recipe WHERE id = ?').run(row.id); const ings = db.prepare('SELECT COUNT(*) AS c FROM ingredient').get() as { c: number }; const steps = db.prepare('SELECT COUNT(*) AS c FROM step').get() as { c: number }; expect(ings.c).toBe(0); expect(steps.c).toBe(0); }); it('FTS5 index finds recipes by title', () => { const db = openInMemoryForTest(); db.prepare('INSERT INTO recipe(title, description) VALUES (?, ?)').run( 'Spaghetti Carbonara', 'Italienisches Pasta-Klassiker' ); const hits = db .prepare("SELECT rowid FROM recipe_fts WHERE recipe_fts MATCH 'carbonara'") .all(); expect(hits.length).toBe(1); }); it('enforces rating stars 1..5', () => { const db = openInMemoryForTest(); db.prepare('INSERT INTO profile(name) VALUES (?)').run('Hendrik'); const r = db .prepare('INSERT INTO recipe(title) VALUES (?) RETURNING id') .get('Test') as { id: number }; db.prepare('INSERT INTO rating(recipe_id, profile_id, stars) VALUES (?, 1, 5)').run(r.id); expect(() => db.prepare('INSERT INTO rating(recipe_id, profile_id, stars) VALUES (?, 1, 6)').run(r.id) ).toThrow(); }); });