Files
recipe-app/backend/src/meal-plan/meal-plan.idor.spec.ts
T
Nils-Johan Gynther 1db30c9b6f
Test Suite / test (24.15.0) (push) Has been cancelled
test(security): add and refactor api security/idor coverage
2026-05-11 16:40:16 +02:00

135 lines
3.6 KiB
TypeScript

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