core tests
This commit is contained in:
@@ -0,0 +1,250 @@
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import { NotificationPreference } from '../entities/NotificationPreference';
|
||||
import { NotificationPreferenceRepository } from './NotificationPreferenceRepository';
|
||||
|
||||
describe('NotificationPreferenceRepository - Interface Contract', () => {
|
||||
it('NotificationPreferenceRepository interface defines findByDriverId method', () => {
|
||||
const mockRepository: NotificationPreferenceRepository = {
|
||||
findByDriverId: vi.fn().mockResolvedValue(null),
|
||||
save: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
getOrCreateDefault: vi.fn().mockResolvedValue({} as NotificationPreference),
|
||||
};
|
||||
|
||||
expect(mockRepository.findByDriverId).toBeDefined();
|
||||
expect(typeof mockRepository.findByDriverId).toBe('function');
|
||||
});
|
||||
|
||||
it('NotificationPreferenceRepository interface defines save method', () => {
|
||||
const mockRepository: NotificationPreferenceRepository = {
|
||||
findByDriverId: vi.fn().mockResolvedValue(null),
|
||||
save: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
getOrCreateDefault: vi.fn().mockResolvedValue({} as NotificationPreference),
|
||||
};
|
||||
|
||||
expect(mockRepository.save).toBeDefined();
|
||||
expect(typeof mockRepository.save).toBe('function');
|
||||
});
|
||||
|
||||
it('NotificationPreferenceRepository interface defines delete method', () => {
|
||||
const mockRepository: NotificationPreferenceRepository = {
|
||||
findByDriverId: vi.fn().mockResolvedValue(null),
|
||||
save: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
getOrCreateDefault: vi.fn().mockResolvedValue({} as NotificationPreference),
|
||||
};
|
||||
|
||||
expect(mockRepository.delete).toBeDefined();
|
||||
expect(typeof mockRepository.delete).toBe('function');
|
||||
});
|
||||
|
||||
it('NotificationPreferenceRepository interface defines getOrCreateDefault method', () => {
|
||||
const mockRepository: NotificationPreferenceRepository = {
|
||||
findByDriverId: vi.fn().mockResolvedValue(null),
|
||||
save: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
getOrCreateDefault: vi.fn().mockResolvedValue({} as NotificationPreference),
|
||||
};
|
||||
|
||||
expect(mockRepository.getOrCreateDefault).toBeDefined();
|
||||
expect(typeof mockRepository.getOrCreateDefault).toBe('function');
|
||||
});
|
||||
});
|
||||
|
||||
describe('NotificationPreferenceRepository - Integration', () => {
|
||||
it('can find preferences by driver ID', async () => {
|
||||
const mockPreference = NotificationPreference.create({
|
||||
id: 'driver-1',
|
||||
driverId: 'driver-1',
|
||||
channels: {
|
||||
in_app: { enabled: true },
|
||||
email: { enabled: true },
|
||||
discord: { enabled: false },
|
||||
push: { enabled: false },
|
||||
},
|
||||
quietHoursStart: 22,
|
||||
quietHoursEnd: 7,
|
||||
});
|
||||
|
||||
const mockRepository: NotificationPreferenceRepository = {
|
||||
findByDriverId: vi.fn().mockResolvedValue(mockPreference),
|
||||
save: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
getOrCreateDefault: vi.fn().mockResolvedValue(mockPreference),
|
||||
};
|
||||
|
||||
const result = await mockRepository.findByDriverId('driver-1');
|
||||
|
||||
expect(result).toBe(mockPreference);
|
||||
expect(mockRepository.findByDriverId).toHaveBeenCalledWith('driver-1');
|
||||
});
|
||||
|
||||
it('returns null when preferences not found', async () => {
|
||||
const mockRepository: NotificationPreferenceRepository = {
|
||||
findByDriverId: vi.fn().mockResolvedValue(null),
|
||||
save: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
getOrCreateDefault: vi.fn().mockResolvedValue({} as NotificationPreference),
|
||||
};
|
||||
|
||||
const result = await mockRepository.findByDriverId('driver-999');
|
||||
|
||||
expect(result).toBeNull();
|
||||
expect(mockRepository.findByDriverId).toHaveBeenCalledWith('driver-999');
|
||||
});
|
||||
|
||||
it('can save preferences', async () => {
|
||||
const mockPreference = NotificationPreference.create({
|
||||
id: 'driver-1',
|
||||
driverId: 'driver-1',
|
||||
channels: {
|
||||
in_app: { enabled: true },
|
||||
email: { enabled: true },
|
||||
discord: { enabled: false },
|
||||
push: { enabled: false },
|
||||
},
|
||||
quietHoursStart: 22,
|
||||
quietHoursEnd: 7,
|
||||
});
|
||||
|
||||
const mockRepository: NotificationPreferenceRepository = {
|
||||
findByDriverId: vi.fn().mockResolvedValue(mockPreference),
|
||||
save: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
getOrCreateDefault: vi.fn().mockResolvedValue(mockPreference),
|
||||
};
|
||||
|
||||
await mockRepository.save(mockPreference);
|
||||
|
||||
expect(mockRepository.save).toHaveBeenCalledWith(mockPreference);
|
||||
});
|
||||
|
||||
it('can delete preferences by driver ID', async () => {
|
||||
const mockRepository: NotificationPreferenceRepository = {
|
||||
findByDriverId: vi.fn().mockResolvedValue(null),
|
||||
save: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
getOrCreateDefault: vi.fn().mockResolvedValue({} as NotificationPreference),
|
||||
};
|
||||
|
||||
await mockRepository.delete('driver-1');
|
||||
|
||||
expect(mockRepository.delete).toHaveBeenCalledWith('driver-1');
|
||||
});
|
||||
|
||||
it('can get or create default preferences', async () => {
|
||||
const defaultPreference = NotificationPreference.createDefault('driver-1');
|
||||
|
||||
const mockRepository: NotificationPreferenceRepository = {
|
||||
findByDriverId: vi.fn().mockResolvedValue(null),
|
||||
save: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
getOrCreateDefault: vi.fn().mockResolvedValue(defaultPreference),
|
||||
};
|
||||
|
||||
const result = await mockRepository.getOrCreateDefault('driver-1');
|
||||
|
||||
expect(result).toBe(defaultPreference);
|
||||
expect(mockRepository.getOrCreateDefault).toHaveBeenCalledWith('driver-1');
|
||||
});
|
||||
|
||||
it('handles workflow: find, update, save', async () => {
|
||||
const existingPreference = NotificationPreference.create({
|
||||
id: 'driver-1',
|
||||
driverId: 'driver-1',
|
||||
channels: {
|
||||
in_app: { enabled: true },
|
||||
email: { enabled: false },
|
||||
discord: { enabled: false },
|
||||
push: { enabled: false },
|
||||
},
|
||||
});
|
||||
|
||||
const updatedPreference = NotificationPreference.create({
|
||||
id: 'driver-1',
|
||||
driverId: 'driver-1',
|
||||
channels: {
|
||||
in_app: { enabled: true },
|
||||
email: { enabled: true },
|
||||
discord: { enabled: true },
|
||||
push: { enabled: false },
|
||||
},
|
||||
});
|
||||
|
||||
const mockRepository: NotificationPreferenceRepository = {
|
||||
findByDriverId: vi.fn()
|
||||
.mockResolvedValueOnce(existingPreference)
|
||||
.mockResolvedValueOnce(updatedPreference),
|
||||
save: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
getOrCreateDefault: vi.fn().mockResolvedValue(existingPreference),
|
||||
};
|
||||
|
||||
// Find existing preferences
|
||||
const found = await mockRepository.findByDriverId('driver-1');
|
||||
expect(found).toBe(existingPreference);
|
||||
|
||||
// Update preferences
|
||||
const updated = found!.updateChannel('email', { enabled: true });
|
||||
const updated2 = updated.updateChannel('discord', { enabled: true });
|
||||
|
||||
// Save updated preferences
|
||||
await mockRepository.save(updated2);
|
||||
expect(mockRepository.save).toHaveBeenCalledWith(updated2);
|
||||
|
||||
// Verify update
|
||||
const updatedFound = await mockRepository.findByDriverId('driver-1');
|
||||
expect(updatedFound).toBe(updatedPreference);
|
||||
});
|
||||
|
||||
it('handles workflow: get or create, then update', async () => {
|
||||
const defaultPreference = NotificationPreference.createDefault('driver-1');
|
||||
|
||||
const updatedPreference = NotificationPreference.create({
|
||||
id: 'driver-1',
|
||||
driverId: 'driver-1',
|
||||
channels: {
|
||||
in_app: { enabled: true },
|
||||
email: { enabled: true },
|
||||
discord: { enabled: false },
|
||||
push: { enabled: false },
|
||||
},
|
||||
});
|
||||
|
||||
const mockRepository: NotificationPreferenceRepository = {
|
||||
findByDriverId: vi.fn().mockResolvedValue(null),
|
||||
save: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
getOrCreateDefault: vi.fn().mockResolvedValue(defaultPreference),
|
||||
};
|
||||
|
||||
// Get or create default preferences
|
||||
const preferences = await mockRepository.getOrCreateDefault('driver-1');
|
||||
expect(preferences).toBe(defaultPreference);
|
||||
|
||||
// Update preferences
|
||||
const updated = preferences.updateChannel('email', { enabled: true });
|
||||
|
||||
// Save updated preferences
|
||||
await mockRepository.save(updated);
|
||||
expect(mockRepository.save).toHaveBeenCalledWith(updated);
|
||||
});
|
||||
|
||||
it('handles workflow: delete preferences', async () => {
|
||||
const mockRepository: NotificationPreferenceRepository = {
|
||||
findByDriverId: vi.fn().mockResolvedValue(null),
|
||||
save: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
getOrCreateDefault: vi.fn().mockResolvedValue({} as NotificationPreference),
|
||||
};
|
||||
|
||||
// Delete preferences
|
||||
await mockRepository.delete('driver-1');
|
||||
expect(mockRepository.delete).toHaveBeenCalledWith('driver-1');
|
||||
|
||||
// Verify deletion
|
||||
const result = await mockRepository.findByDriverId('driver-1');
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,539 @@
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import { Notification } from '../entities/Notification';
|
||||
import { NotificationRepository } from './NotificationRepository';
|
||||
|
||||
describe('NotificationRepository - Interface Contract', () => {
|
||||
it('NotificationRepository interface defines findById method', () => {
|
||||
const mockRepository: NotificationRepository = {
|
||||
findById: vi.fn().mockResolvedValue(null),
|
||||
findByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findUnreadByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findByRecipientIdAndType: vi.fn().mockResolvedValue([]),
|
||||
countUnreadByRecipientId: vi.fn().mockResolvedValue(0),
|
||||
create: vi.fn().mockResolvedValue(undefined),
|
||||
update: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
deleteAllByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
markAllAsReadByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
|
||||
expect(mockRepository.findById).toBeDefined();
|
||||
expect(typeof mockRepository.findById).toBe('function');
|
||||
});
|
||||
|
||||
it('NotificationRepository interface defines findByRecipientId method', () => {
|
||||
const mockRepository: NotificationRepository = {
|
||||
findById: vi.fn().mockResolvedValue(null),
|
||||
findByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findUnreadByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findByRecipientIdAndType: vi.fn().mockResolvedValue([]),
|
||||
countUnreadByRecipientId: vi.fn().mockResolvedValue(0),
|
||||
create: vi.fn().mockResolvedValue(undefined),
|
||||
update: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
deleteAllByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
markAllAsReadByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
|
||||
expect(mockRepository.findByRecipientId).toBeDefined();
|
||||
expect(typeof mockRepository.findByRecipientId).toBe('function');
|
||||
});
|
||||
|
||||
it('NotificationRepository interface defines findUnreadByRecipientId method', () => {
|
||||
const mockRepository: NotificationRepository = {
|
||||
findById: vi.fn().mockResolvedValue(null),
|
||||
findByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findUnreadByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findByRecipientIdAndType: vi.fn().mockResolvedValue([]),
|
||||
countUnreadByRecipientId: vi.fn().mockResolvedValue(0),
|
||||
create: vi.fn().mockResolvedValue(undefined),
|
||||
update: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
deleteAllByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
markAllAsReadByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
|
||||
expect(mockRepository.findUnreadByRecipientId).toBeDefined();
|
||||
expect(typeof mockRepository.findUnreadByRecipientId).toBe('function');
|
||||
});
|
||||
|
||||
it('NotificationRepository interface defines findByRecipientIdAndType method', () => {
|
||||
const mockRepository: NotificationRepository = {
|
||||
findById: vi.fn().mockResolvedValue(null),
|
||||
findByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findUnreadByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findByRecipientIdAndType: vi.fn().mockResolvedValue([]),
|
||||
countUnreadByRecipientId: vi.fn().mockResolvedValue(0),
|
||||
create: vi.fn().mockResolvedValue(undefined),
|
||||
update: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
deleteAllByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
markAllAsReadByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
|
||||
expect(mockRepository.findByRecipientIdAndType).toBeDefined();
|
||||
expect(typeof mockRepository.findByRecipientIdAndType).toBe('function');
|
||||
});
|
||||
|
||||
it('NotificationRepository interface defines countUnreadByRecipientId method', () => {
|
||||
const mockRepository: NotificationRepository = {
|
||||
findById: vi.fn().mockResolvedValue(null),
|
||||
findByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findUnreadByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findByRecipientIdAndType: vi.fn().mockResolvedValue([]),
|
||||
countUnreadByRecipientId: vi.fn().mockResolvedValue(0),
|
||||
create: vi.fn().mockResolvedValue(undefined),
|
||||
update: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
deleteAllByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
markAllAsReadByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
|
||||
expect(mockRepository.countUnreadByRecipientId).toBeDefined();
|
||||
expect(typeof mockRepository.countUnreadByRecipientId).toBe('function');
|
||||
});
|
||||
|
||||
it('NotificationRepository interface defines create method', () => {
|
||||
const mockRepository: NotificationRepository = {
|
||||
findById: vi.fn().mockResolvedValue(null),
|
||||
findByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findUnreadByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findByRecipientIdAndType: vi.fn().mockResolvedValue([]),
|
||||
countUnreadByRecipientId: vi.fn().mockResolvedValue(0),
|
||||
create: vi.fn().mockResolvedValue(undefined),
|
||||
update: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
deleteAllByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
markAllAsReadByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
|
||||
expect(mockRepository.create).toBeDefined();
|
||||
expect(typeof mockRepository.create).toBe('function');
|
||||
});
|
||||
|
||||
it('NotificationRepository interface defines update method', () => {
|
||||
const mockRepository: NotificationRepository = {
|
||||
findById: vi.fn().mockResolvedValue(null),
|
||||
findByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findUnreadByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findByRecipientIdAndType: vi.fn().mockResolvedValue([]),
|
||||
countUnreadByRecipientId: vi.fn().mockResolvedValue(0),
|
||||
create: vi.fn().mockResolvedValue(undefined),
|
||||
update: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
deleteAllByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
markAllAsReadByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
|
||||
expect(mockRepository.update).toBeDefined();
|
||||
expect(typeof mockRepository.update).toBe('function');
|
||||
});
|
||||
|
||||
it('NotificationRepository interface defines delete method', () => {
|
||||
const mockRepository: NotificationRepository = {
|
||||
findById: vi.fn().mockResolvedValue(null),
|
||||
findByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findUnreadByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findByRecipientIdAndType: vi.fn().mockResolvedValue([]),
|
||||
countUnreadByRecipientId: vi.fn().mockResolvedValue(0),
|
||||
create: vi.fn().mockResolvedValue(undefined),
|
||||
update: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
deleteAllByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
markAllAsReadByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
|
||||
expect(mockRepository.delete).toBeDefined();
|
||||
expect(typeof mockRepository.delete).toBe('function');
|
||||
});
|
||||
|
||||
it('NotificationRepository interface defines deleteAllByRecipientId method', () => {
|
||||
const mockRepository: NotificationRepository = {
|
||||
findById: vi.fn().mockResolvedValue(null),
|
||||
findByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findUnreadByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findByRecipientIdAndType: vi.fn().mockResolvedValue([]),
|
||||
countUnreadByRecipientId: vi.fn().mockResolvedValue(0),
|
||||
create: vi.fn().mockResolvedValue(undefined),
|
||||
update: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
deleteAllByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
markAllAsReadByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
|
||||
expect(mockRepository.deleteAllByRecipientId).toBeDefined();
|
||||
expect(typeof mockRepository.deleteAllByRecipientId).toBe('function');
|
||||
});
|
||||
|
||||
it('NotificationRepository interface defines markAllAsReadByRecipientId method', () => {
|
||||
const mockRepository: NotificationRepository = {
|
||||
findById: vi.fn().mockResolvedValue(null),
|
||||
findByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findUnreadByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findByRecipientIdAndType: vi.fn().mockResolvedValue([]),
|
||||
countUnreadByRecipientId: vi.fn().mockResolvedValue(0),
|
||||
create: vi.fn().mockResolvedValue(undefined),
|
||||
update: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
deleteAllByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
markAllAsReadByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
|
||||
expect(mockRepository.markAllAsReadByRecipientId).toBeDefined();
|
||||
expect(typeof mockRepository.markAllAsReadByRecipientId).toBe('function');
|
||||
});
|
||||
});
|
||||
|
||||
describe('NotificationRepository - Integration', () => {
|
||||
it('can find notification by ID', async () => {
|
||||
const notification = Notification.create({
|
||||
id: 'notification-1',
|
||||
recipientId: 'driver-1',
|
||||
type: 'system_announcement',
|
||||
title: 'Test',
|
||||
body: 'Test body',
|
||||
channel: 'in_app',
|
||||
});
|
||||
|
||||
const mockRepository: NotificationRepository = {
|
||||
findById: vi.fn().mockResolvedValue(notification),
|
||||
findByRecipientId: vi.fn().mockResolvedValue([notification]),
|
||||
findUnreadByRecipientId: vi.fn().mockResolvedValue([notification]),
|
||||
findByRecipientIdAndType: vi.fn().mockResolvedValue([notification]),
|
||||
countUnreadByRecipientId: vi.fn().mockResolvedValue(1),
|
||||
create: vi.fn().mockResolvedValue(undefined),
|
||||
update: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
deleteAllByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
markAllAsReadByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
|
||||
const result = await mockRepository.findById('notification-1');
|
||||
|
||||
expect(result).toBe(notification);
|
||||
expect(mockRepository.findById).toHaveBeenCalledWith('notification-1');
|
||||
});
|
||||
|
||||
it('returns null when notification not found by ID', async () => {
|
||||
const mockRepository: NotificationRepository = {
|
||||
findById: vi.fn().mockResolvedValue(null),
|
||||
findByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findUnreadByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findByRecipientIdAndType: vi.fn().mockResolvedValue([]),
|
||||
countUnreadByRecipientId: vi.fn().mockResolvedValue(0),
|
||||
create: vi.fn().mockResolvedValue(undefined),
|
||||
update: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
deleteAllByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
markAllAsReadByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
|
||||
const result = await mockRepository.findById('notification-999');
|
||||
|
||||
expect(result).toBeNull();
|
||||
expect(mockRepository.findById).toHaveBeenCalledWith('notification-999');
|
||||
});
|
||||
|
||||
it('can find all notifications for a recipient', async () => {
|
||||
const notifications = [
|
||||
Notification.create({
|
||||
id: 'notification-1',
|
||||
recipientId: 'driver-1',
|
||||
type: 'system_announcement',
|
||||
title: 'Test 1',
|
||||
body: 'Body 1',
|
||||
channel: 'in_app',
|
||||
}),
|
||||
Notification.create({
|
||||
id: 'notification-2',
|
||||
recipientId: 'driver-1',
|
||||
type: 'race_registration_open',
|
||||
title: 'Test 2',
|
||||
body: 'Body 2',
|
||||
channel: 'email',
|
||||
}),
|
||||
];
|
||||
|
||||
const mockRepository: NotificationRepository = {
|
||||
findById: vi.fn().mockResolvedValue(null),
|
||||
findByRecipientId: vi.fn().mockResolvedValue(notifications),
|
||||
findUnreadByRecipientId: vi.fn().mockResolvedValue(notifications),
|
||||
findByRecipientIdAndType: vi.fn().mockResolvedValue(notifications),
|
||||
countUnreadByRecipientId: vi.fn().mockResolvedValue(2),
|
||||
create: vi.fn().mockResolvedValue(undefined),
|
||||
update: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
deleteAllByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
markAllAsReadByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
|
||||
const result = await mockRepository.findByRecipientId('driver-1');
|
||||
|
||||
expect(result).toBe(notifications);
|
||||
expect(mockRepository.findByRecipientId).toHaveBeenCalledWith('driver-1');
|
||||
});
|
||||
|
||||
it('can find unread notifications for a recipient', async () => {
|
||||
const unreadNotifications = [
|
||||
Notification.create({
|
||||
id: 'notification-1',
|
||||
recipientId: 'driver-1',
|
||||
type: 'system_announcement',
|
||||
title: 'Test 1',
|
||||
body: 'Body 1',
|
||||
channel: 'in_app',
|
||||
}),
|
||||
];
|
||||
|
||||
const mockRepository: NotificationRepository = {
|
||||
findById: vi.fn().mockResolvedValue(null),
|
||||
findByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findUnreadByRecipientId: vi.fn().mockResolvedValue(unreadNotifications),
|
||||
findByRecipientIdAndType: vi.fn().mockResolvedValue(unreadNotifications),
|
||||
countUnreadByRecipientId: vi.fn().mockResolvedValue(1),
|
||||
create: vi.fn().mockResolvedValue(undefined),
|
||||
update: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
deleteAllByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
markAllAsReadByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
|
||||
const result = await mockRepository.findUnreadByRecipientId('driver-1');
|
||||
|
||||
expect(result).toBe(unreadNotifications);
|
||||
expect(mockRepository.findUnreadByRecipientId).toHaveBeenCalledWith('driver-1');
|
||||
});
|
||||
|
||||
it('can find notifications by type for a recipient', async () => {
|
||||
const protestNotifications = [
|
||||
Notification.create({
|
||||
id: 'notification-1',
|
||||
recipientId: 'driver-1',
|
||||
type: 'protest_filed',
|
||||
title: 'Protest Filed',
|
||||
body: 'A protest has been filed',
|
||||
channel: 'in_app',
|
||||
}),
|
||||
];
|
||||
|
||||
const mockRepository: NotificationRepository = {
|
||||
findById: vi.fn().mockResolvedValue(null),
|
||||
findByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findUnreadByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findByRecipientIdAndType: vi.fn().mockResolvedValue(protestNotifications),
|
||||
countUnreadByRecipientId: vi.fn().mockResolvedValue(0),
|
||||
create: vi.fn().mockResolvedValue(undefined),
|
||||
update: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
deleteAllByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
markAllAsReadByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
|
||||
const result = await mockRepository.findByRecipientIdAndType('driver-1', 'protest_filed');
|
||||
|
||||
expect(result).toBe(protestNotifications);
|
||||
expect(mockRepository.findByRecipientIdAndType).toHaveBeenCalledWith('driver-1', 'protest_filed');
|
||||
});
|
||||
|
||||
it('can count unread notifications for a recipient', async () => {
|
||||
const mockRepository: NotificationRepository = {
|
||||
findById: vi.fn().mockResolvedValue(null),
|
||||
findByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findUnreadByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findByRecipientIdAndType: vi.fn().mockResolvedValue([]),
|
||||
countUnreadByRecipientId: vi.fn().mockResolvedValue(3),
|
||||
create: vi.fn().mockResolvedValue(undefined),
|
||||
update: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
deleteAllByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
markAllAsReadByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
|
||||
const count = await mockRepository.countUnreadByRecipientId('driver-1');
|
||||
|
||||
expect(count).toBe(3);
|
||||
expect(mockRepository.countUnreadByRecipientId).toHaveBeenCalledWith('driver-1');
|
||||
});
|
||||
|
||||
it('can create a new notification', async () => {
|
||||
const notification = Notification.create({
|
||||
id: 'notification-1',
|
||||
recipientId: 'driver-1',
|
||||
type: 'system_announcement',
|
||||
title: 'Test',
|
||||
body: 'Test body',
|
||||
channel: 'in_app',
|
||||
});
|
||||
|
||||
const mockRepository: NotificationRepository = {
|
||||
findById: vi.fn().mockResolvedValue(null),
|
||||
findByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findUnreadByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findByRecipientIdAndType: vi.fn().mockResolvedValue([]),
|
||||
countUnreadByRecipientId: vi.fn().mockResolvedValue(0),
|
||||
create: vi.fn().mockResolvedValue(undefined),
|
||||
update: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
deleteAllByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
markAllAsReadByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
|
||||
await mockRepository.create(notification);
|
||||
|
||||
expect(mockRepository.create).toHaveBeenCalledWith(notification);
|
||||
});
|
||||
|
||||
it('can update an existing notification', async () => {
|
||||
const notification = Notification.create({
|
||||
id: 'notification-1',
|
||||
recipientId: 'driver-1',
|
||||
type: 'system_announcement',
|
||||
title: 'Test',
|
||||
body: 'Test body',
|
||||
channel: 'in_app',
|
||||
});
|
||||
|
||||
const mockRepository: NotificationRepository = {
|
||||
findById: vi.fn().mockResolvedValue(notification),
|
||||
findByRecipientId: vi.fn().mockResolvedValue([notification]),
|
||||
findUnreadByRecipientId: vi.fn().mockResolvedValue([notification]),
|
||||
findByRecipientIdAndType: vi.fn().mockResolvedValue([notification]),
|
||||
countUnreadByRecipientId: vi.fn().mockResolvedValue(1),
|
||||
create: vi.fn().mockResolvedValue(undefined),
|
||||
update: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
deleteAllByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
markAllAsReadByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
|
||||
await mockRepository.update(notification);
|
||||
|
||||
expect(mockRepository.update).toHaveBeenCalledWith(notification);
|
||||
});
|
||||
|
||||
it('can delete a notification by ID', async () => {
|
||||
const mockRepository: NotificationRepository = {
|
||||
findById: vi.fn().mockResolvedValue(null),
|
||||
findByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findUnreadByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findByRecipientIdAndType: vi.fn().mockResolvedValue([]),
|
||||
countUnreadByRecipientId: vi.fn().mockResolvedValue(0),
|
||||
create: vi.fn().mockResolvedValue(undefined),
|
||||
update: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
deleteAllByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
markAllAsReadByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
|
||||
await mockRepository.delete('notification-1');
|
||||
|
||||
expect(mockRepository.delete).toHaveBeenCalledWith('notification-1');
|
||||
});
|
||||
|
||||
it('can delete all notifications for a recipient', async () => {
|
||||
const mockRepository: NotificationRepository = {
|
||||
findById: vi.fn().mockResolvedValue(null),
|
||||
findByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findUnreadByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findByRecipientIdAndType: vi.fn().mockResolvedValue([]),
|
||||
countUnreadByRecipientId: vi.fn().mockResolvedValue(0),
|
||||
create: vi.fn().mockResolvedValue(undefined),
|
||||
update: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
deleteAllByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
markAllAsReadByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
|
||||
await mockRepository.deleteAllByRecipientId('driver-1');
|
||||
|
||||
expect(mockRepository.deleteAllByRecipientId).toHaveBeenCalledWith('driver-1');
|
||||
});
|
||||
|
||||
it('can mark all notifications as read for a recipient', async () => {
|
||||
const mockRepository: NotificationRepository = {
|
||||
findById: vi.fn().mockResolvedValue(null),
|
||||
findByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findUnreadByRecipientId: vi.fn().mockResolvedValue([]),
|
||||
findByRecipientIdAndType: vi.fn().mockResolvedValue([]),
|
||||
countUnreadByRecipientId: vi.fn().mockResolvedValue(0),
|
||||
create: vi.fn().mockResolvedValue(undefined),
|
||||
update: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
deleteAllByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
markAllAsReadByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
|
||||
await mockRepository.markAllAsReadByRecipientId('driver-1');
|
||||
|
||||
expect(mockRepository.markAllAsReadByRecipientId).toHaveBeenCalledWith('driver-1');
|
||||
});
|
||||
|
||||
it('handles workflow: create, find, update, delete', async () => {
|
||||
const notification = Notification.create({
|
||||
id: 'notification-1',
|
||||
recipientId: 'driver-1',
|
||||
type: 'system_announcement',
|
||||
title: 'Test',
|
||||
body: 'Test body',
|
||||
channel: 'in_app',
|
||||
});
|
||||
|
||||
const updatedNotification = Notification.create({
|
||||
id: 'notification-1',
|
||||
recipientId: 'driver-1',
|
||||
type: 'system_announcement',
|
||||
title: 'Updated Test',
|
||||
body: 'Updated body',
|
||||
channel: 'in_app',
|
||||
});
|
||||
|
||||
const mockRepository: NotificationRepository = {
|
||||
findById: vi.fn()
|
||||
.mockResolvedValueOnce(notification)
|
||||
.mockResolvedValueOnce(updatedNotification)
|
||||
.mockResolvedValueOnce(null),
|
||||
findByRecipientId: vi.fn()
|
||||
.mockResolvedValueOnce([notification])
|
||||
.mockResolvedValueOnce([updatedNotification])
|
||||
.mockResolvedValueOnce([]),
|
||||
findUnreadByRecipientId: vi.fn()
|
||||
.mockResolvedValueOnce([notification])
|
||||
.mockResolvedValueOnce([updatedNotification])
|
||||
.mockResolvedValueOnce([]),
|
||||
findByRecipientIdAndType: vi.fn().mockResolvedValue([]),
|
||||
countUnreadByRecipientId: vi.fn()
|
||||
.mockResolvedValueOnce(1)
|
||||
.mockResolvedValueOnce(1)
|
||||
.mockResolvedValueOnce(0),
|
||||
create: vi.fn().mockResolvedValue(undefined),
|
||||
update: vi.fn().mockResolvedValue(undefined),
|
||||
delete: vi.fn().mockResolvedValue(undefined),
|
||||
deleteAllByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
markAllAsReadByRecipientId: vi.fn().mockResolvedValue(undefined),
|
||||
};
|
||||
|
||||
// Create notification
|
||||
await mockRepository.create(notification);
|
||||
expect(mockRepository.create).toHaveBeenCalledWith(notification);
|
||||
|
||||
// Find notification
|
||||
const found = await mockRepository.findById('notification-1');
|
||||
expect(found).toBe(notification);
|
||||
|
||||
// Update notification
|
||||
await mockRepository.update(updatedNotification);
|
||||
expect(mockRepository.update).toHaveBeenCalledWith(updatedNotification);
|
||||
|
||||
// Verify update
|
||||
const updatedFound = await mockRepository.findById('notification-1');
|
||||
expect(updatedFound).toBe(updatedNotification);
|
||||
|
||||
// Delete notification
|
||||
await mockRepository.delete('notification-1');
|
||||
expect(mockRepository.delete).toHaveBeenCalledWith('notification-1');
|
||||
|
||||
// Verify deletion
|
||||
const deletedFound = await mockRepository.findById('notification-1');
|
||||
expect(deletedFound).toBeNull();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user