import { describe, it, expect, vi, beforeEach } from 'vitest'; import { CabinetEventsService } from '../../../src/modules/cabinet-events/cabinet-events.service.js'; describe(CabinetEventsService.name, () => { const mockCabinetEventsRepo = { create: vi.fn(), createMany: vi.fn(), findByHousehold: vi.fn(), findByCabinetItem: vi.fn(), getSpendingSummary: vi.fn(), getAvgUnitPriceByMedicine: vi.fn(), }; let service: CabinetEventsService; const baseEventData = { householdId: 'hh1', userId: 'user-1', cabinetItemId: 'ci-1', medicineId: 'med-1', medicineName: 'Metformin', eventType: 'purchased' as const, quantity: 10, quantityBefore: 0, quantityAfter: 10, sourceType: 'manual' as const, }; beforeEach(() => { vi.clearAllMocks(); service = new CabinetEventsService({ cabinetEventsRepository: mockCabinetEventsRepo as never, }); }); describe('logEvent', () => { it('delegates to repository create', async () => { const created = { _id: 'ev-1', ...baseEventData }; mockCabinetEventsRepo.create.mockResolvedValue(created); const result = await service.logEvent(baseEventData); expect(result).toEqual(created); expect(mockCabinetEventsRepo.create).toHaveBeenCalledWith(baseEventData); }); }); describe('logEvents', () => { it('delegates to repository createMany', async () => { const events = [baseEventData, { ...baseEventData, quantity: 5 }]; const inserted = events.map((e, i) => ({ _id: `ev-${i}`, ...e })); mockCabinetEventsRepo.createMany.mockResolvedValue(inserted); const result = await service.logEvents(events); expect(result).toEqual(inserted); expect(mockCabinetEventsRepo.createMany).toHaveBeenCalledWith(events); }); it('returns empty array for empty input without calling repository', async () => { const result = await service.logEvents([]); expect(result).toEqual([]); expect(mockCabinetEventsRepo.createMany).not.toHaveBeenCalled(); }); }); describe('listEvents', () => { it('delegates to repository findByHousehold', async () => { const expected = { data: [{ _id: 'ev-1' }], pagination: { cursor: null, hasMore: false }, }; mockCabinetEventsRepo.findByHousehold.mockResolvedValue(expected); const query = { limit: 20 }; const result = await service.listEvents('hh1', query); expect(result).toEqual(expected); expect(mockCabinetEventsRepo.findByHousehold).toHaveBeenCalledWith('hh1', query); }); }); describe('getEventsByItem', () => { it('delegates to repository findByCabinetItem', async () => { const expected = { data: [{ _id: 'ev-1', cabinetItemId: 'ci-1' }], pagination: { cursor: null, hasMore: false }, }; mockCabinetEventsRepo.findByCabinetItem.mockResolvedValue(expected); const query = { limit: 20 }; const result = await service.getEventsByItem('hh1', 'ci-1', query); expect(result).toEqual(expected); expect(mockCabinetEventsRepo.findByCabinetItem).toHaveBeenCalledWith('hh1', 'ci-1', query); }); it('passes cursor through to repository', async () => { const expected = { data: [], pagination: { cursor: null, hasMore: false }, }; mockCabinetEventsRepo.findByCabinetItem.mockResolvedValue(expected); const query = { cursor: 'abc123', limit: 10 }; await service.getEventsByItem('hh1', 'ci-1', query); expect(mockCabinetEventsRepo.findByCabinetItem).toHaveBeenCalledWith('hh1', 'ci-1', query); }); }); describe('getSpendingSummary', () => { it('delegates to repository getSpendingSummary', async () => { const expected = { totalSpent: 100, currency: 'USD', byMedicine: [], byPeriod: [], }; mockCabinetEventsRepo.getSpendingSummary.mockResolvedValue(expected); const query = { period: 'month' as const }; const result = await service.getSpendingSummary('hh1', query); expect(result).toEqual(expected); expect(mockCabinetEventsRepo.getSpendingSummary).toHaveBeenCalledWith('hh1', query); }); }); describe('getAvgUnitPrices', () => { it('delegates to repository getAvgUnitPriceByMedicine', async () => { const expected = new Map([['med-1', { avgUnitPrice: 10, currency: 'USD' }]]); mockCabinetEventsRepo.getAvgUnitPriceByMedicine.mockResolvedValue(expected); const result = await service.getAvgUnitPrices('hh1', ['med-1']); expect(result).toEqual(expected); expect(mockCabinetEventsRepo.getAvgUnitPriceByMedicine).toHaveBeenCalledWith('hh1', [ 'med-1', ]); }); }); });