feat(shopping): addRecipeToCart (idempotent via ON CONFLICT)
All checks were successful
Build & Publish Docker Image / build-and-push (push) Successful in 2m20s
All checks were successful
Build & Publish Docker Image / build-and-push (push) Successful in 2m20s
This commit is contained in:
65
tests/integration/shopping-repository.test.ts
Normal file
65
tests/integration/shopping-repository.test.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { openInMemoryForTest } from '../../src/lib/server/db';
|
||||
import { insertRecipe } from '../../src/lib/server/recipes/repository';
|
||||
import {
|
||||
addRecipeToCart,
|
||||
listShoppingList
|
||||
} from '../../src/lib/server/shopping/repository';
|
||||
import type { Recipe } from '../../src/lib/types';
|
||||
|
||||
function recipe(overrides: Partial<Recipe> = {}): Recipe {
|
||||
return {
|
||||
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: [],
|
||||
...overrides
|
||||
};
|
||||
}
|
||||
|
||||
describe('addRecipeToCart', () => {
|
||||
it('inserts recipe with default servings from recipe.servings_default', () => {
|
||||
const db = openInMemoryForTest();
|
||||
const id = insertRecipe(db, recipe({ title: 'Pasta', servings_default: 4 }));
|
||||
addRecipeToCart(db, id, null);
|
||||
const snap = listShoppingList(db);
|
||||
expect(snap.recipes).toHaveLength(1);
|
||||
expect(snap.recipes[0].servings).toBe(4);
|
||||
});
|
||||
|
||||
it('respects explicit servings override', () => {
|
||||
const db = openInMemoryForTest();
|
||||
const id = insertRecipe(db, recipe({ servings_default: 4 }));
|
||||
addRecipeToCart(db, id, null, 2);
|
||||
expect(listShoppingList(db).recipes[0].servings).toBe(2);
|
||||
});
|
||||
|
||||
it('is idempotent: second insert updates servings, not fails', () => {
|
||||
const db = openInMemoryForTest();
|
||||
const id = insertRecipe(db, recipe({ servings_default: 4 }));
|
||||
addRecipeToCart(db, id, null, 2);
|
||||
addRecipeToCart(db, id, null, 6);
|
||||
const snap = listShoppingList(db);
|
||||
expect(snap.recipes).toHaveLength(1);
|
||||
expect(snap.recipes[0].servings).toBe(6);
|
||||
});
|
||||
|
||||
it('falls back to servings=4 when recipe has no default', () => {
|
||||
const db = openInMemoryForTest();
|
||||
const id = insertRecipe(db, recipe({ servings_default: null }));
|
||||
addRecipeToCart(db, id, null);
|
||||
expect(listShoppingList(db).recipes[0].servings).toBe(4);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user