import { NotFoundException } from '@nestjs/common'; import { InspectionsService } from './inspections.service'; import { PrismaService } from '../prisma/prisma.service'; import { WebhooksService } from '../webhooks/webhooks.service'; import { AutomationService } from '../automation/automation.service'; import { AuditLogService } from '../audit/audit-log.service'; import { CalendarSyncService } from '../calendar-sync/calendar-sync.service'; describe('InspectionsService', () => { let service: InspectionsService; let prisma: { inspection: { findMany: jest.Mock; findUnique: jest.Mock; create: jest.Mock; update: jest.Mock; }; task: { create: jest.Mock }; }; let auditLog: { record: jest.Mock }; let calendarSync: { enqueue: jest.Mock; cancel: jest.Mock }; const inspection = { id: 'inspection-1', colonyId: 'colony-1', date: new Date(), }; beforeEach(() => { prisma = { inspection: { findMany: jest.fn(), findUnique: jest.fn(), create: jest.fn(), update: jest.fn(), }, task: { create: jest.fn() }, }; const webhooks = { dispatch: jest.fn().mockResolvedValue(undefined) }; const automation = { evaluateInspection: jest.fn().mockResolvedValue(undefined), }; auditLog = { record: jest.fn().mockResolvedValue(undefined) }; calendarSync = { enqueue: jest.fn(), cancel: jest.fn() }; service = new InspectionsService( prisma as unknown as PrismaService, webhooks as unknown as WebhooksService, automation as unknown as AutomationService, auditLog as unknown as AuditLogService, calendarSync as unknown as CalendarSyncService, ); }); it('findById throws NotFoundException when missing', async () => { prisma.inspection.findUnique.mockResolvedValue(null); await expect(service.findById('missing')).rejects.toBeInstanceOf( NotFoundException, ); }); it('create stores the acting user as the inspector', async () => { prisma.inspection.create.mockResolvedValue(inspection); await service.create( { colonyId: 'colony-1', date: '2026-01-01' }, 'user-1', ); const [[createArg]] = prisma.inspection.create.mock.calls as [ [{ data: { colonyId: string; userId: string } }], ]; expect(createArg.data.colonyId).toBe('colony-1'); expect(createArg.data.userId).toBe('user-1'); }); it('create writes an audit log entry with the created inspection', async () => { prisma.inspection.create.mockResolvedValue(inspection); await service.create( { colonyId: 'colony-1', date: '2026-01-01' }, 'user-1', ); expect(auditLog.record).toHaveBeenCalledWith({ entityType: 'Inspection', entityId: 'inspection-1', action: 'CREATE', userId: 'user-1', afterData: inspection, }); }); it('update writes an audit log entry with before and after data', async () => { prisma.inspection.findUnique.mockResolvedValue(inspection); const updated = { ...inspection, notes: 'geändert' }; prisma.inspection.update.mockResolvedValue(updated); const result = await service.update( 'inspection-1', { notes: 'geändert' }, 'user-1', ); expect(result).toBe(updated); expect(auditLog.record).toHaveBeenCalledWith( expect.objectContaining({ entityType: 'Inspection', entityId: 'inspection-1', action: 'UPDATE', beforeData: inspection, afterData: updated, }), ); }); it('update re-enqueues the calendar sync so a changed date moves the event', async () => { prisma.inspection.findUnique.mockResolvedValue(inspection); prisma.inspection.update.mockResolvedValue(inspection); await service.update('inspection-1', { date: '2026-05-02' }, 'user-1'); expect(calendarSync.enqueue).toHaveBeenCalledWith( 'INSPECTION', 'inspection-1', ); }); it('createTaskFromInspection links the task to the inspection and its colony', async () => { prisma.inspection.findUnique.mockResolvedValue(inspection); prisma.task.create.mockResolvedValue({ id: 'task-1' }); await service.createTaskFromInspection( 'inspection-1', { title: 'Nachschauen' }, 'user-1', ); const [[taskArg]] = prisma.task.create.mock.calls as [ [ { data: { sourceInspectionId: string; relatedType: string; relatedId: string; }; }, ], ]; expect(taskArg.data.sourceInspectionId).toBe('inspection-1'); expect(taskArg.data.relatedType).toBe('COLONY'); expect(taskArg.data.relatedId).toBe('colony-1'); }); });