Cleanup after initial plan
This commit is contained in:
parent
d2a7e652b3
commit
245520fb50
53 changed files with 6733 additions and 621 deletions
|
|
@ -106,5 +106,129 @@ describe(ShoppingGapService.name, () => {
|
|||
const result = await service.calculateGap('hh1', 'plan2');
|
||||
expect(result.missingItems.length).toBe(0);
|
||||
});
|
||||
|
||||
it('aggregates duplicate ingredients and sorts by product name', async () => {
|
||||
mockMealRepo.findById.mockResolvedValue({
|
||||
_id: 'plan-multi',
|
||||
days: [
|
||||
{
|
||||
meals: [
|
||||
{ recipeId: 'recipeA', servings: 1 },
|
||||
{ recipeId: 'recipeB', servings: 1 },
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
mockRecipesRepo.findById.mockImplementation(async (id) => {
|
||||
if (id === 'recipeA') {
|
||||
return {
|
||||
_id: 'recipeA', servings: 1,
|
||||
ingredients: [{ productId: 'prod1', quantity: 10, isOptional: false }]
|
||||
};
|
||||
}
|
||||
return {
|
||||
_id: 'recipeB', servings: 1,
|
||||
ingredients: [
|
||||
{ productId: 'prod1', quantity: 20, isOptional: false },
|
||||
{ productId: 'prod2', quantity: 5, isOptional: false },
|
||||
]
|
||||
};
|
||||
});
|
||||
|
||||
mockProductsRepo.findByIds.mockResolvedValue([
|
||||
{ _id: 'prod1', name: 'Banana' },
|
||||
{ _id: 'prod2', name: 'Apple' },
|
||||
]);
|
||||
|
||||
mockPantryRepo.findActiveByHousehold.mockResolvedValue([]);
|
||||
|
||||
const result = await service.calculateGap('hh1', 'plan-multi');
|
||||
|
||||
expect(result.missingItems).toHaveLength(2);
|
||||
expect(result.missingItems[0].productName).toBe('Apple');
|
||||
expect(result.missingItems[1].productName).toBe('Banana');
|
||||
expect(result.missingItems[1].requiredQuantity).toBe(30);
|
||||
});
|
||||
|
||||
it('covers fallback paths for missing list, recipe properties and pantry quantities', async () => {
|
||||
mockMealRepo.findById.mockResolvedValue({
|
||||
_id: 'plan-empty',
|
||||
});
|
||||
mockProductsRepo.findByIds.mockResolvedValue([]);
|
||||
mockPantryRepo.findActiveByHousehold.mockResolvedValue([]);
|
||||
|
||||
let res = await service.calculateGap('hh1', 'plan-empty');
|
||||
expect(res.missingItems).toHaveLength(0);
|
||||
|
||||
mockMealRepo.findById.mockResolvedValue({
|
||||
_id: 'plan-missing',
|
||||
days: [
|
||||
{
|
||||
meals: [{ recipeId: 'recipeC', servings: 1 }]
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
mockRecipesRepo.findById.mockResolvedValue({
|
||||
_id: 'recipeC',
|
||||
servings: 1,
|
||||
ingredients: [
|
||||
{ productId: 'prod3', quantity: 10, isOptional: false }
|
||||
]
|
||||
});
|
||||
|
||||
mockProductsRepo.findByIds.mockResolvedValue([
|
||||
{ _id: 'prod3' }
|
||||
]);
|
||||
|
||||
mockPantryRepo.findActiveByHousehold.mockResolvedValue([
|
||||
{ productId: 'prod3' }
|
||||
]);
|
||||
|
||||
res = await service.calculateGap('hh1', 'plan-missing');
|
||||
expect(res.missingItems).toHaveLength(1);
|
||||
const itm = res.missingItems[0]!;
|
||||
expect(itm.unit).toBe('g');
|
||||
expect(itm.productName).toBe('Unknown Ingredient');
|
||||
expect(itm.category).toBe('other');
|
||||
expect(itm.pantryQuantity).toBe(0);
|
||||
});
|
||||
|
||||
it('skips optional ingredients, handles missing recipes and defaults servings to 1', async () => {
|
||||
mockMealRepo.findById.mockResolvedValue({
|
||||
_id: 'plan-edge',
|
||||
days: [
|
||||
{
|
||||
meals: [
|
||||
{ recipeId: 'recipeExist', servings: 2 },
|
||||
{ recipeId: 'recipeNotExist', servings: 1 },
|
||||
]
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
mockRecipesRepo.findById.mockImplementation(async (id) => {
|
||||
if (id === 'recipeExist') {
|
||||
return {
|
||||
_id: 'recipeExist',
|
||||
servings: 0,
|
||||
ingredients: [
|
||||
{ productId: 'prodIng', quantity: 5, isOptional: false },
|
||||
{ productId: 'prodOptional', quantity: 10, isOptional: true },
|
||||
]
|
||||
};
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
mockProductsRepo.findByIds.mockResolvedValue([{ _id: 'prodIng', name: 'Ingredient' }]);
|
||||
mockPantryRepo.findActiveByHousehold.mockResolvedValue([]);
|
||||
|
||||
const result = await service.calculateGap('hh1', 'plan-edge');
|
||||
expect(result.missingItems).toHaveLength(1);
|
||||
expect(result.missingItems[0].productId).toBe('prodIng');
|
||||
expect(result.missingItems[0].requiredQuantity).toBe(10);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue