import { NotificationAudience } from '@edr/types'; import { MaintenanceService } from './maintenance.service'; import { FREIGHT_PERMS } from '../../seed/freight-permissions.registry'; /** * The daily due-alert: a SCHEDULED item that crossed its km or date threshold * gets one BACKOFFICE notification, then is stamped so it isn't repeated. */ function makeService(due: Array>) { const update = jest.fn(); const notify = jest.fn(); const service = Object.create(MaintenanceService.prototype) as Record; service.maintenanceRepository = { getUnnotifiedDue: jest.fn().mockResolvedValue(due) }; service.scheduleRepository = { update }; service.inbox = { notify }; service.logger = { error: jest.fn() }; return { service: service as unknown as MaintenanceService, update, notify }; } describe('MaintenanceService.sendDueAlerts', () => { it('reports the km reason when the km threshold was crossed', async () => { const { service, notify, update } = makeService([ { id: 'sched-1', vehicleId: 'v-1', plateNumber: 'ET-9875', maintenanceType: 'PREVENTIVE', description: 'Oil change', nextDueKm: 50000, nextDueDate: null, currentKm: 50200, }, ]); await service.sendDueAlerts(); expect(notify).toHaveBeenCalledWith( expect.objectContaining({ audience: NotificationAudience.BACKOFFICE, // The fleet desk, not every employee in the company. recipients: { permissionKeys: [FREIGHT_PERMS.maintenance.getNotification], }, title: 'Maintenance due — ET-9875', body: expect.stringContaining('driven 50200 km (due at 50000 km)'), }), ); expect(update).toHaveBeenCalledWith('sched-1', { dueNotifiedAt: expect.any(Date) }); }); it('reports the date reason when only the due date has passed', async () => { const { service, notify } = makeService([ { id: 'sched-2', vehicleId: 'v-2', plateNumber: 'AA-8642', maintenanceType: 'INSPECTION', description: 'Annual inspection', nextDueKm: null, nextDueDate: new Date('2026-01-01'), currentKm: 1000, }, ]); await service.sendDueAlerts(); expect(notify).toHaveBeenCalledWith( expect.objectContaining({ body: expect.stringContaining('due 1/1/2026') }), ); }); it('does nothing when nothing is due', async () => { const { service, notify, update } = makeService([]); await service.sendDueAlerts(); expect(notify).not.toHaveBeenCalled(); expect(update).not.toHaveBeenCalled(); }); });