test(security): add and refactor api security/idor coverage
Test Suite / test (24.15.0) (push) Has been cancelled

This commit is contained in:
Nils-Johan Gynther
2026-05-11 16:40:16 +02:00
parent 9b468d9a13
commit 1db30c9b6f
12 changed files with 1025 additions and 23 deletions
@@ -0,0 +1,86 @@
import { BadRequestException } from '@nestjs/common';
import { ReceiptImportController } from './receipt-import.controller';
describe('ReceiptImport controller security', () => {
const receiptImportServiceMock = {
parseReceipt: jest.fn(),
upsertUnitMapping: jest.fn(),
saveReceipt: jest.fn(),
};
const controller = new ReceiptImportController(receiptImportServiceMock as any);
beforeEach(() => {
jest.clearAllMocks();
});
it('parseReceipt nekar när fil saknas', async () => {
await expect(controller.parseReceipt(undefined, { user: { id: 1 } })).rejects.toThrow(BadRequestException);
});
it('parseReceipt nekar otillåten mime-type', async () => {
const file = { buffer: Buffer.from('x'), mimetype: 'text/plain' } as any;
await expect(controller.parseReceipt(file, { user: { id: 1 } })).rejects.toThrow(BadRequestException);
});
it('parseReceipt vidarebefordrar premium/admin och userId', async () => {
const file = { buffer: Buffer.from('x'), mimetype: 'image/jpeg' } as any;
receiptImportServiceMock.parseReceipt.mockResolvedValue([]);
await controller.parseReceipt(file, { user: { id: 42, role: 'admin', isPremium: false } });
expect(receiptImportServiceMock.parseReceipt).toHaveBeenCalledWith(file, true, 42);
});
it('upsertUnitMapping använder req.user.id när tillgänglig', async () => {
receiptImportServiceMock.upsertUnitMapping.mockResolvedValue({ ok: true });
await controller.upsertUnitMapping(
{ productId: 1, originalUnit: 'g', preferredUnit: 'kg' } as any,
{ user: { id: 42 } },
);
expect(receiptImportServiceMock.upsertUnitMapping).toHaveBeenCalledWith(42, 1, 'g', 'kg');
});
it('upsertUnitMapping fallbackar till req.user.userId', async () => {
receiptImportServiceMock.upsertUnitMapping.mockResolvedValue({ ok: true });
await controller.upsertUnitMapping(
{ productId: 1, originalUnit: 'g', preferredUnit: 'kg' } as any,
{ user: { userId: 99 } },
);
expect(receiptImportServiceMock.upsertUnitMapping).toHaveBeenCalledWith(99, 1, 'g', 'kg');
});
it('upsertUnitMapping nekar när användar-id saknas', async () => {
await expect(
controller.upsertUnitMapping({ productId: 1, originalUnit: 'g', preferredUnit: 'kg' } as any, { user: {} }),
).rejects.toThrow(BadRequestException);
});
it('saveReceipt nekar global alias för icke-admin', async () => {
const dto = {
items: [{ learnAliasGlobally: true }],
};
await expect(controller.saveReceipt(dto as any, { user: { id: 42, role: 'user' } })).rejects.toThrow(
BadRequestException,
);
expect(receiptImportServiceMock.saveReceipt).not.toHaveBeenCalled();
});
it('saveReceipt tillåter global alias för admin', async () => {
const dto = {
items: [{ learnAliasGlobally: true }],
};
receiptImportServiceMock.saveReceipt.mockResolvedValue({ success: true });
await controller.saveReceipt(dto as any, { user: { userId: 42, role: 'admin' } });
expect(receiptImportServiceMock.saveReceipt).toHaveBeenCalledWith(42, dto);
});
});