Files
food-tracer/server/src/tests/mealGroupExtras.test.ts
T
Ondřej Anděl 35cbc5a9ca fix: Jen s chybějícímí údaji -> k doplnění
feat: zobrazení aktuálního počtu jídel
feat: chuť a typ receptu
2026-10-16 08:30:18 +02:00

120 lines
5.2 KiB
TypeScript

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/);
});
});