126 lines
3.7 KiB
TypeScript
126 lines
3.7 KiB
TypeScript
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);
|
|
});
|
|
});
|