process.env.CALORIE_PROVIDER = 'none'; import { addMeal } from "../meals"; import { getMealGroups, renameMealGroup } from "../mealGroups"; import { getMealTemplates, saveMealTemplate } from "../mealTemplates"; import { addMealPhoto, deleteMealPhoto, getMealPhotos } from "../mealPhotos"; import { resetMemoryStorage } from "../storage/memory"; import { MealType, RecipeFlavor } from "../../../types/gen/types.gen"; const LOGIN = 'tester'; const IMAGE = 'data:image/jpeg;base64,AAAA'; const THUMBNAIL = 'data:image/jpeg;base64,BBBB'; beforeEach(() => resetMemoryStorage()); const rizoto = { name: 'Rizoto', source: 'doma', servings: 2, cookedWeight: 800, ingredients: [{ name: 'Rýže', weight: 200, caloriesPer100g: 350 }, { name: 'Kuře', weight: 300, calories: 400 }], }; describe('recept jídla v seznamu jídel', () => { it('patří ke skupině se stejným názvem a zdrojem a předvyplní z něj porci', async () => { await addMeal(LOGIN, { date: '2025-03-01', mealType: MealType.VECERE, name: 'rizoto', source: 'Doma' }); await saveMealTemplate(LOGIN, rizoto); const [group] = await getMealGroups(LOGIN); // (700 + 400) kcal na 800 g, porce je polovina expect(group).toMatchObject({ count: 1, recipe: { name: 'Rizoto' }, values: { weight: 400, caloriesPer100g: 138 }, }); }); it('recept jídla, které se ještě nejedlo, je v seznamu sám', async () => { await addMeal(LOGIN, { date: '2025-03-01', mealType: MealType.OBED, name: 'Guláš' }); await saveMealTemplate(LOGIN, rizoto); const groups = await getMealGroups(LOGIN); expect(groups.map(group => `${group.name} ${group.count}`)).toEqual(['Guláš 1', 'Rizoto 0']); expect(groups[1].lastDate).toBeUndefined(); }); it('druhý recept téhož jídla nejde založit', async () => { await saveMealTemplate(LOGIN, rizoto); await expect(saveMealTemplate(LOGIN, { ...rizoto, name: 'RIZOTO' })).rejects.toThrow(/už recept má/); }); it('přejmenování vezme recept i fotky s sebou', async () => { await addMeal(LOGIN, { date: '2025-03-01', mealType: MealType.VECERE, ...rizoto }); await saveMealTemplate(LOGIN, rizoto); await addMealPhoto(LOGIN, 'Rizoto', 'doma', IMAGE, THUMBNAIL); await renameMealGroup(LOGIN, 'Rizoto', 'doma', 'Houbové rizoto', undefined); const [recipe] = await getMealTemplates(LOGIN); expect(recipe.name).toBe('Houbové rizoto'); expect(recipe).not.toHaveProperty('source'); expect(await getMealPhotos(LOGIN, 'Houbové rizoto', undefined)).toHaveLength(1); expect(await getMealPhotos(LOGIN, 'Rizoto', 'doma')).toHaveLength(0); }); it('recept je bez zadané chuti slaný a typ i chuť přežijí přejmenování', async () => { const [created] = await saveMealTemplate(LOGIN, rizoto); expect(created).toMatchObject({ flavor: RecipeFlavor.SLANE }); expect(created).not.toHaveProperty('category'); const [saved] = await saveMealTemplate(LOGIN, { ...rizoto, id: created.id, category: ' Pečení ', flavor: RecipeFlavor.SLADKE, }); await renameMealGroup(LOGIN, 'Rizoto', 'doma', 'Sladké rizoto', 'doma'); expect(await getMealTemplates(LOGIN)).toMatchObject([ { id: saved.id, name: 'Sladké rizoto', category: 'Pečení', flavor: RecipeFlavor.SLADKE }, ]); }); it('odmítne neznámou chuť receptu', async () => { await expect(saveMealTemplate(LOGIN, { ...rizoto, flavor: 'KYSELE' })).rejects.toThrow(/chuť/); }); it('dvě jídla s recepty přejmenováním nesloučí', async () => { await saveMealTemplate(LOGIN, rizoto); await saveMealTemplate(LOGIN, { ...rizoto, name: 'Rizoto 2' }); await expect(renameMealGroup(LOGIN, 'Rizoto 2', 'doma', 'Rizoto', 'doma')).rejects.toThrow(/Obě jídla/); }); }); describe('fotky jídla', () => { it('patří jídlu podle názvu a zdroje a skupina nese počet a náhled', async () => { await addMeal(LOGIN, { date: '2025-03-01', mealType: MealType.OBED, name: 'Gyros', source: 'Everest' }); await addMeal(LOGIN, { date: '2025-03-02', mealType: MealType.OBED, name: 'Gyros', source: 'Namaste' }); await addMealPhoto(LOGIN, 'gyros', 'everest', IMAGE, THUMBNAIL); const groups = await getMealGroups(LOGIN); expect(groups.find(group => group.source === 'Everest')).toMatchObject({ photoCount: 1, thumbnail: THUMBNAIL }); expect(groups.find(group => group.source === 'Namaste')).toMatchObject({ photoCount: 0 }); expect(await getMealPhotos(LOGIN, 'Gyros', 'Everest')).toMatchObject([{ image: IMAGE }]); }); it('smazaná fotka zmizí z jídla', async () => { const photo = await addMealPhoto(LOGIN, 'Gyros', undefined, IMAGE, THUMBNAIL); await deleteMealPhoto(LOGIN, photo.id); expect(await getMealPhotos(LOGIN, 'Gyros', undefined)).toEqual([]); await expect(deleteMealPhoto(LOGIN, photo.id)).rejects.toThrow(/nebyla nalezena/); }); it('odmítne něco jiného než obrázek', async () => { await expect(addMealPhoto(LOGIN, 'Gyros', undefined, 'data:text/html;base64,AAAA', THUMBNAIL)) .rejects.toThrow(/obrázek/); }); });