import { BookingNotifierService } from './booking-notifier.service'; /** * Message wording for the schedule-related customer notices: every one must * quote the SCHEDULE's train + voyage numbers, and reschedules must carry the * staff-entered reason instead of a hard-coded "for maintenance". */ describe('BookingNotifierService messages', () => { const schedule = { trainNumber: '8001', voyageNumber: 'V-117' }; const booking = { id: 'b1', reference: 'BK-2026-000928', companyId: 'c1' } as never; const departure = new Date('2026-09-01T05:00:00.000Z'); let sent: string[]; let inbox: string[]; let service: BookingNotifierService; beforeEach(() => { sent = []; inbox = []; const notifications = { directSend: jest.fn(async (_m: string, _to: string, msg: string) => { sent.push(msg); }), }; const inboxSvc = { notify: jest.fn(async (input: { body: string }) => { inbox.push(input.body); }), }; const trainSchedules = { findByIdWithStations: jest.fn(async () => ({ ...schedule, reference: 'S-2026-00012' })), }; // Company contact lookup goes through raw SQL; return one phone + email. const dataSource = { query: jest.fn(async () => [{ phone: '+251900000000', email: 'ops@example.com' }]), }; service = new BookingNotifierService( notifications as never, inboxSvc as never, trainSchedules as never, dataSource as never, ); }); const flush = () => new Promise((r) => setImmediate(r)); it('maintenance reschedule quotes train, voyage and the staff reason', async () => { service.maintenanceMoved(booking, departure, schedule, 'Locomotive maintenance.'); await flush(); expect(inbox[0]).toBe( 'Train 8001 (voyage V-117) for booking BK-2026-000928 was rescheduled — reason: Locomotive maintenance. ' + 'New departure date: 01/09/2026.', ); }); it('maintenance reschedule falls back to "for maintenance" without a reason', async () => { service.maintenanceMoved(booking, departure, schedule, ' '); await flush(); expect(inbox[0]).toContain('was rescheduled for maintenance. New departure date'); }); it('plain reschedule carries the reason and the run label', async () => { service.rescheduled(booking, departure, schedule, 'Crew change'); await flush(); expect(inbox[0]).toBe( 'Booking BK-2026-000928 on train 8001 (voyage V-117) has been rescheduled — reason: Crew change. ' + 'New departure date: 01/09/2026.', ); }); it('resolves the run label from a schedule id when only the id is known', async () => { service.scheduleCancelled(booking, 'sched-1'); await flush(); expect(inbox[0]).toMatch(/^Train 8001 \(voyage V-117\) for booking BK-2026-000928 has been cancelled/); }); });