import { NotFoundException } from '@nestjs/common'; import { MealPlanService } from './meal-plan.service'; describe('MealPlanService IDOR security', () => { const fromDate = '2026-05-01'; const toDate = '2026-05-07'; const prismaMock = { mealPlanEntry: { findMany: jest.fn(), findUnique: jest.fn(), upsert: jest.fn(), delete: jest.fn(), }, inventoryItem: { findMany: jest.fn(), }, pantryItem: { findMany: jest.fn(), }, recipe: { findUnique: jest.fn(), }, $transaction: jest.fn(), }; const service = new MealPlanService(prismaMock as any); beforeEach(() => { jest.clearAllMocks(); }); const mockEmptyRangeData = () => { prismaMock.mealPlanEntry.findMany.mockResolvedValue([]); prismaMock.inventoryItem.findMany.mockResolvedValue([]); prismaMock.pantryItem.findMany.mockResolvedValue([]); }; it('scopar findByRange till userId', async () => { mockEmptyRangeData(); await service.findByRange(42, fromDate, toDate); expect(prismaMock.mealPlanEntry.findMany).toHaveBeenCalledWith( expect.objectContaining({ where: expect.objectContaining({ userId: 42, date: expect.any(Object), }), }), ); }); it('scopar shoppingList till userId', async () => { mockEmptyRangeData(); await service.shoppingList(42, fromDate, toDate); expect(prismaMock.mealPlanEntry.findMany).toHaveBeenCalledWith( expect.objectContaining({ where: expect.objectContaining({ userId: 42, }), }), ); }); it('scopar inventoryCompare till userId', async () => { mockEmptyRangeData(); await service.inventoryCompare(42, fromDate, toDate); expect(prismaMock.mealPlanEntry.findMany).toHaveBeenCalledWith( expect.objectContaining({ where: expect.objectContaining({ userId: 42, }), }), ); }); it('upsert sätter userId på nya matplansintrag', async () => { prismaMock.mealPlanEntry.upsert.mockResolvedValue({ id: 1, userId: 42, date: new Date(), }); await service.upsert(42, { date: '2026-05-11', recipeId: 1 } as any); expect(prismaMock.mealPlanEntry.upsert).toHaveBeenCalledWith( expect.objectContaining({ where: expect.objectContaining({ userId_date: expect.objectContaining({ userId: 42, }), }), create: expect.objectContaining({ userId: 42, }), }), ); }); it('removeByDate nekar access för annan user', async () => { prismaMock.mealPlanEntry.findUnique.mockResolvedValue(null); await expect(service.removeByDate(42, '2026-05-11')).rejects.toThrow(NotFoundException); expect(prismaMock.mealPlanEntry.findUnique).toHaveBeenCalledWith( expect.objectContaining({ where: expect.objectContaining({ userId_date: expect.objectContaining({ userId: 42, }), }), }), ); }); it('removeByDate verifierar userId innan radering', async () => { const entry = { id: 1, userId: 42, date: new Date() }; prismaMock.mealPlanEntry.findUnique.mockResolvedValue(entry); prismaMock.mealPlanEntry.delete.mockResolvedValue(entry); await service.removeByDate(42, '2026-05-11'); expect(prismaMock.mealPlanEntry.delete).toHaveBeenCalledWith( expect.objectContaining({ where: expect.objectContaining({ id: 1 }), }), ); }); });