UNPKG

@ideal-photography/shared

Version:

Shared MongoDB and utility logic for Ideal Photography PWAs: users, products, services, bookings, orders/cart, galleries, reviews, notifications, campaigns, settings, audit logs, minimart items/orders, and push notification subscriptions.

173 lines (140 loc) 5.89 kB
import { jest } from '@jest/globals'; import { emitAlert } from '../index.js'; import AlertBus from '../AlertBus.js'; // Mock NotificationService const mockNotificationService = { createAndSend: jest.fn().mockResolvedValue({ _id: 'notif123', title: 'Welcome to IDEAS MEDIA COMPANY' }) }; // Mock the module before importing jest.unstable_mockModule('../../services/NotificationService.js', () => ({ default: mockNotificationService })); // Mock models const mockModels = { Notification: { create: jest.fn().mockResolvedValue({ _id: 'notif123', title: 'Test Notification', status: 'sent', sentAt: new Date() }) }, User: { find: jest.fn().mockResolvedValue([]) } }; jest.unstable_mockModule('../../mongoDB/index.js', () => ({ models: mockModels })); describe('Alert Flow: emitAlert → handlers → NotificationService', () => { beforeEach(() => { jest.clearAllMocks(); // Clear any existing listeners AlertBus.removeAllListeners('alert'); AlertBus.removeAllListeners('user.registered'); AlertBus.removeAllListeners('booking.created'); }); test('emitAlert enqueues alert to AlertBus', (done) => { const testPayload = { userId: '123', userName: 'Test User' }; AlertBus.once('alert', ({ trigger, payload }) => { expect(trigger).toBe('user.registered'); expect(payload).toEqual(testPayload); done(); }); emitAlert('user.registered', testPayload); }); test('emitAlert throws error for invalid trigger', () => { expect(() => emitAlert('', {})).toThrow('trigger must be non-empty string'); expect(() => emitAlert(null, {})).toThrow('trigger must be non-empty string'); }); test('handler receives payload and generates alertMeta', async () => { const mockUser = { _id: 'user123', name: 'John Doe', email: 'john@example.com' }; // Import and test auth handler directly const { registered } = await import('../../alerts/handlers/auth.js'); const alertMeta = registered({ user: mockUser }); expect(alertMeta).toEqual( expect.objectContaining({ title: expect.stringContaining('Welcome'), recipients: { users: [mockUser._id] }, channels: expect.objectContaining({ email: true }), emailTemplate: 'welcome', emailData: expect.objectContaining({ name: mockUser.name, email: mockUser.email }) }) ); }); test('booking.created handler generates correct alertMeta', async () => { const mockBooking = { _id: 'booking123', shortId: 'BK001', date: new Date('2025-10-15'), time: '14:00' }; const mockUser = { _id: 'user123', name: 'Jane Smith' }; const mockProduct = { name: 'Studio Portrait Session' }; // Import and test booking handler directly const { created } = await import('../../alerts/handlers/bookings.js'); const alertMeta = created({ booking: mockBooking, user: mockUser, product: mockProduct }); expect(alertMeta).toEqual( expect.objectContaining({ title: 'Booking received', message: expect.stringContaining('BK001'), type: 'booking', recipients: { users: [mockUser._id] }, channels: expect.objectContaining({ email: true }), emailTemplate: 'booking-confirmation' }) ); }); test('AlertBus processes queue in order', (done) => { const results = []; AlertBus.on('alert', ({ trigger }) => { results.push(trigger); }); emitAlert('user.registered', {}); emitAlert('booking.created', {}); emitAlert('booking.reminder.6h', {}); setTimeout(() => { expect(results).toEqual(['user.registered', 'booking.created', 'booking.reminder.6h']); done(); }, 100); }); test('channel overrides in opts are applied', async () => { const mockUser = { _id: 'user123', name: 'Test' }; // Test that opts override default channels const { registered } = await import('../../alerts/handlers/auth.js'); const alertMeta = registered({ user: mockUser }); // Default should have email: true expect(alertMeta.channels.email).toBe(true); expect(alertMeta.channels.push).toBe(true); // Test that opts would override these (this is tested in NotificationService) const overriddenChannels = { ...alertMeta.channels, email: false, push: false }; expect(overriddenChannels).toEqual({ inApp: true, email: false, push: false }); }); test('priority override in opts is applied', async () => { const mockUser = { _id: 'user123', name: 'Test' }; // Test that handlers generate default priority const { registered } = await import('../../alerts/handlers/auth.js'); const alertMeta = registered({ user: mockUser }); // Handler doesn't set priority, so it should be undefined (defaults to 'normal' in model) expect(alertMeta.priority).toBeUndefined(); // Test that opts would override this (this is tested in NotificationService) const overriddenPriority = { ...alertMeta, priority: 'urgent' }; expect(overriddenPriority.priority).toBe('urgent'); }); });