6cd5b80adb
- Add new API endpoints for retrieving flyer import sessions: - GET /flyer-import/sessions/latest - Retrieve latest session for user - GET /flyer-import/sessions/:sessionId - Retrieve specific session - Implement session persistence and restoration in Flutter UI - Add toJson() methods to FlyerImportItem and FlyerImportResult for serialization - Add new FlyerImportSession domain model for local session management - Add unit test file for FlyerImportService - Update FlyerImportController with new endpoints and user ID extraction - Update FlyerImportService with session retrieval logic and response mapping - Update API paths in Flutter client - Add session restoration on widget init in FlyerImportTab
87 lines
2.5 KiB
TypeScript
87 lines
2.5 KiB
TypeScript
import { NotFoundException } from '@nestjs/common';
|
|
import { FlyerImportService } from './flyer-import.service';
|
|
|
|
describe('FlyerImportService', () => {
|
|
const prismaMock = {
|
|
flyerSession: {
|
|
findFirst: jest.fn(),
|
|
},
|
|
};
|
|
|
|
const createService = () =>
|
|
new FlyerImportService(
|
|
prismaMock as any,
|
|
{} as any,
|
|
{} as any,
|
|
{} as any,
|
|
);
|
|
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
|
|
describe('getSession', () => {
|
|
it('throws NotFoundException when session is missing', async () => {
|
|
prismaMock.flyerSession.findFirst.mockResolvedValue(null);
|
|
const service = createService();
|
|
|
|
await expect(service.getSession(123, 1)).rejects.toBeInstanceOf(NotFoundException);
|
|
expect(prismaMock.flyerSession.findFirst).toHaveBeenCalledWith({
|
|
where: { id: 123, userId: 1 },
|
|
include: { items: { orderBy: { id: 'asc' } } },
|
|
});
|
|
});
|
|
|
|
it('returns mapped response for owned session', async () => {
|
|
prismaMock.flyerSession.findFirst.mockResolvedValue({
|
|
id: 42,
|
|
items: [
|
|
{
|
|
id: 99,
|
|
rawName: 'Tomat',
|
|
normalizedName: 'tomat',
|
|
categoryHint: 'Gronsaker',
|
|
price: { toNumber: () => 19.9 },
|
|
priceUnit: 'kg',
|
|
comparisonPrice: null,
|
|
comparisonUnit: null,
|
|
offerText: 'Max 2 kop/hushall',
|
|
parseConfidence: 0.9,
|
|
parseReasons: ['ai_parsed'],
|
|
matchedProductId: 5,
|
|
matchedProductName: 'Tomat',
|
|
matchedVia: 'exact',
|
|
matchConfidence: 0.95,
|
|
matchReasons: ['normalized_exact'],
|
|
},
|
|
],
|
|
});
|
|
const service = createService();
|
|
|
|
const result = await service.getSession(42, 1);
|
|
|
|
expect(result.sessionId).toBe(42);
|
|
expect(result.items).toHaveLength(1);
|
|
expect(result.items[0].flyerItemId).toBe(99);
|
|
expect(result.items[0].matchedVia).toBe('exact');
|
|
});
|
|
});
|
|
|
|
describe('getLatestSession', () => {
|
|
it('returns empty response when no sessions exist', async () => {
|
|
prismaMock.flyerSession.findFirst.mockResolvedValue(null);
|
|
const service = createService();
|
|
|
|
const result = await service.getLatestSession(1);
|
|
|
|
expect(result.sessionId).toBeNull();
|
|
expect(result.items).toEqual([]);
|
|
expect(prismaMock.flyerSession.findFirst).toHaveBeenCalledWith({
|
|
where: { userId: 1 },
|
|
orderBy: { createdAt: 'desc' },
|
|
include: { items: { orderBy: { id: 'asc' } } },
|
|
});
|
|
});
|
|
});
|
|
});
|