import { NotFoundException } from '@nestjs/common'; import { PantryService } from './pantry.service'; describe('PantryService IDOR security', () => { const makeCreatePantryDto = (overrides: Partial<{ productId: number; userId: number }> = {}) => ({ productId: 1, ...overrides, }); const prismaMock = { pantryItem: { findMany: jest.fn(), findUnique: jest.fn(), findFirst: jest.fn(), create: jest.fn(), update: jest.fn(), delete: jest.fn(), }, product: { findUnique: jest.fn(), }, user: { findUnique: jest.fn(), }, inventoryItem: { create: jest.fn(), }, $transaction: jest.fn(), }; const service = new PantryService(prismaMock as any); beforeEach(() => { jest.clearAllMocks(); }); const mockPantryFindManyEmpty = () => { prismaMock.pantryItem.findMany.mockResolvedValue([]); }; it('scopar findAll till userId', async () => { mockPantryFindManyEmpty(); await service.findAll(42); expect(prismaMock.pantryItem.findMany).toHaveBeenCalledWith( expect.objectContaining({ where: expect.objectContaining({ userId: 42 }), }), ); }); it('findAllAdmin kan filtrera per userId', async () => { mockPantryFindManyEmpty(); await service.findAllAdmin({ userId: 99 }); expect(prismaMock.pantryItem.findMany).toHaveBeenCalledWith( expect.objectContaining({ where: expect.objectContaining({ userId: 99 }), }), ); }); it('findAllAdmin returnerar alla items om userId inte specificeras', async () => { mockPantryFindManyEmpty(); await service.findAllAdmin({}); expect(prismaMock.pantryItem.findMany).toHaveBeenCalledWith( expect.objectContaining({ where: {}, }), ); }); it('create sätter userId på nya pantry-items', async () => { prismaMock.product.findUnique.mockResolvedValue({ id: 1 }); prismaMock.pantryItem.create.mockResolvedValue({ id: 1, userId: 42 }); await service.create(42, makeCreatePantryDto() as any); expect(prismaMock.pantryItem.create).toHaveBeenCalledWith( expect.objectContaining({ data: expect.objectContaining({ userId: 42, productId: 1 }), }), ); }); it('createAdmin kan skapa pantry-item för explicit userId', async () => { prismaMock.user.findUnique.mockResolvedValue({ id: 99 }); prismaMock.product.findUnique.mockResolvedValue({ id: 1 }); prismaMock.pantryItem.create.mockResolvedValue({ id: 1, userId: 99 }); await service.createAdmin(1, makeCreatePantryDto({ userId: 99 }) as any, 99); expect(prismaMock.pantryItem.create).toHaveBeenCalledWith( expect.objectContaining({ data: expect.objectContaining({ userId: 99, productId: 1 }), }), ); }); it('createAdmin throws NotFoundException om target user saknas', async () => { prismaMock.user.findUnique.mockResolvedValue(null); await expect(service.createAdmin(1, makeCreatePantryDto({ userId: 999 }) as any, 999)).rejects.toThrow( NotFoundException, ); }); it('remove nekar icke-owner', async () => { // Simulera att item inte hittas (userId matchar inte) prismaMock.pantryItem.findFirst.mockResolvedValue(null); await expect(service.remove(42, 1)).rejects.toThrow(NotFoundException); }); it('moveToInventory nekar icke-owner', async () => { // Simulera att item inte hittas (userId matchar inte) prismaMock.pantryItem.findFirst.mockResolvedValue(null); await expect(service.moveToInventory(42, 1, {} as any)).rejects.toThrow(NotFoundException); }); });