fix notifications
Build & Push / Pipeline Tests (push) Failing after 1m8s
Build & Push / Build & Push Docker Image (push) Has been skipped
Test / Type Check (all packages) (push) Successful in 53s
Test / API Unit Tests (push) Failing after 52s
Test / Homepage Unit Tests (push) Successful in 46s
Test / Carplace Unit Tests (push) Successful in 43s
Test / Admin Unit Tests (push) Successful in 43s
Test / Dashboard Unit Tests (push) Successful in 46s
Test / API Integration Tests (push) Successful in 1m7s
Build & Push / Pipeline Tests (push) Failing after 1m8s
Build & Push / Build & Push Docker Image (push) Has been skipped
Test / Type Check (all packages) (push) Successful in 53s
Test / API Unit Tests (push) Failing after 52s
Test / Homepage Unit Tests (push) Successful in 46s
Test / Carplace Unit Tests (push) Successful in 43s
Test / Admin Unit Tests (push) Successful in 43s
Test / Dashboard Unit Tests (push) Successful in 46s
Test / API Integration Tests (push) Successful in 1m7s
This commit is contained in:
@@ -119,12 +119,12 @@ describe('operations validation API contracts', () => {
|
||||
|
||||
it('accepts valid company notification preferences and passes employee identity', async () => {
|
||||
const res = await request(app).patch('/api/v1/notifications/company/preferences').send([
|
||||
{ notificationType: 'BOOKING_CREATED', channel: 'EMAIL', enabled: true },
|
||||
{ notificationType: 'NEW_BOOKING', channel: 'EMAIL', enabled: true },
|
||||
])
|
||||
|
||||
expect(res.status).toBe(200)
|
||||
expect(notificationService.setPreferences).toHaveBeenCalledWith('employee_1', [
|
||||
{ notificationType: 'BOOKING_CREATED', channel: 'EMAIL', enabled: true },
|
||||
{ notificationType: 'NEW_BOOKING', channel: 'EMAIL', enabled: true },
|
||||
])
|
||||
})
|
||||
|
||||
|
||||
@@ -146,6 +146,7 @@ describe('operations API contracts', () => {
|
||||
|
||||
expect(res.status).toBe(200)
|
||||
expect(res.body).toEqual({ data: { unread: 7 } })
|
||||
expect(notificationService.countUnread).toHaveBeenCalledWith('employee_1')
|
||||
})
|
||||
|
||||
it('GET /api/v1/notifications/history coerces limit and passes history filters to the service', async () => {
|
||||
|
||||
@@ -182,35 +182,78 @@ export async function createCompanyNotification(
|
||||
employeeId?: string,
|
||||
overrides: Record<string, unknown> = {},
|
||||
) {
|
||||
return prisma.notification.create({
|
||||
const notificationEvent = await prisma.notificationEvent.create({
|
||||
data: {
|
||||
companyId,
|
||||
employeeId,
|
||||
type: 'PAYMENT_RECEIVED',
|
||||
title: 'Payment received',
|
||||
body: 'A payment was recorded.',
|
||||
channel: 'IN_APP',
|
||||
status: 'PENDING',
|
||||
...overrides,
|
||||
type: (overrides.type ?? 'PAYMENT_RECEIVED') as any,
|
||||
title: (overrides.title ?? 'Payment received') as string,
|
||||
body: (overrides.body ?? 'A payment was recorded.') as string,
|
||||
data: (overrides.data ?? {}) as any,
|
||||
sourceType: (overrides.sourceType ?? 'test') as string,
|
||||
sourceId: (overrides.sourceId ?? `source-${uid()}`) as string,
|
||||
idempotencyKey: (overrides.idempotencyKey ?? `test-${uid()}`) as string,
|
||||
} as any,
|
||||
})
|
||||
|
||||
const recipient = await prisma.notificationRecipient.create({
|
||||
data: {
|
||||
notificationEventId: notificationEvent.id,
|
||||
recipientType: 'EMPLOYEE',
|
||||
employeeId,
|
||||
readAt: (overrides.readAt ?? null) as Date | null,
|
||||
} as any,
|
||||
})
|
||||
|
||||
await prisma.notificationDelivery.create({
|
||||
data: {
|
||||
notificationRecipientId: recipient.id,
|
||||
channel: (overrides.channel ?? 'IN_APP') as any,
|
||||
status: (overrides.status ?? 'DELIVERED') === 'READ' ? 'DELIVERED' : (overrides.status ?? 'DELIVERED') as any,
|
||||
deliveredAt: overrides.sentAt ? (overrides.sentAt as Date) : new Date(),
|
||||
} as any,
|
||||
})
|
||||
|
||||
return recipient
|
||||
}
|
||||
|
||||
export async function createRenterNotification(
|
||||
renterId: string,
|
||||
overrides: Record<string, unknown> = {},
|
||||
) {
|
||||
return prisma.notification.create({
|
||||
const companyId = (overrides.companyId as string | undefined)
|
||||
?? (await prisma.company.findFirstOrThrow({ select: { id: true } })).id
|
||||
const notificationEvent = await prisma.notificationEvent.create({
|
||||
data: {
|
||||
renterId,
|
||||
type: 'BOOKING_CONFIRMED',
|
||||
title: 'Booking confirmed',
|
||||
body: 'Your booking is confirmed.',
|
||||
channel: 'IN_APP',
|
||||
status: 'PENDING',
|
||||
...overrides,
|
||||
companyId,
|
||||
type: (overrides.type ?? 'BOOKING_CONFIRMED') as any,
|
||||
title: (overrides.title ?? 'Booking confirmed') as string,
|
||||
body: (overrides.body ?? 'Your booking is confirmed.') as string,
|
||||
data: (overrides.data ?? {}) as any,
|
||||
sourceType: (overrides.sourceType ?? 'test') as string,
|
||||
sourceId: (overrides.sourceId ?? `source-${uid()}`) as string,
|
||||
idempotencyKey: (overrides.idempotencyKey ?? `test-${uid()}`) as string,
|
||||
} as any,
|
||||
})
|
||||
|
||||
const recipient = await prisma.notificationRecipient.create({
|
||||
data: {
|
||||
notificationEventId: notificationEvent.id,
|
||||
recipientType: 'RENTER',
|
||||
renterId,
|
||||
readAt: (overrides.readAt ?? null) as Date | null,
|
||||
} as any,
|
||||
})
|
||||
|
||||
await prisma.notificationDelivery.create({
|
||||
data: {
|
||||
notificationRecipientId: recipient.id,
|
||||
channel: (overrides.channel ?? 'IN_APP') as any,
|
||||
status: (overrides.status ?? 'DELIVERED') === 'READ' ? 'DELIVERED' : (overrides.status ?? 'DELIVERED') as any,
|
||||
deliveredAt: overrides.sentAt ? (overrides.sentAt as Date) : new Date(),
|
||||
} as any,
|
||||
})
|
||||
|
||||
return recipient
|
||||
}
|
||||
|
||||
export function signEmployeeToken(employeeId: string, _companyId: string, _role: string = 'OWNER') {
|
||||
|
||||
@@ -115,7 +115,7 @@ describe('Notifications API', () => {
|
||||
|
||||
it('updates renter notification preferences', async () => {
|
||||
const payload = [
|
||||
{ notificationType: 'BOOKING_CONFIRMED', channel: 'PUSH', enabled: true },
|
||||
{ notificationType: 'BOOKING_CONFIRMED', channel: 'EMAIL', enabled: true },
|
||||
]
|
||||
|
||||
const patchRes = await request(app)
|
||||
@@ -136,7 +136,7 @@ describe('Notifications API', () => {
|
||||
expect.objectContaining({
|
||||
renterId,
|
||||
notificationType: 'BOOKING_CONFIRMED',
|
||||
channel: 'PUSH',
|
||||
channel: 'EMAIL',
|
||||
enabled: true,
|
||||
}),
|
||||
]),
|
||||
|
||||
@@ -82,7 +82,7 @@ describe('Operations API integration', () => {
|
||||
expect(marked.status).toBe(200)
|
||||
expect(marked.body.data).toEqual({ success: true })
|
||||
|
||||
const stored = await prisma.notification.findUniqueOrThrow({ where: { id: notification.id } })
|
||||
const stored = await prisma.notificationRecipient.findUniqueOrThrow({ where: { id: notification.id } })
|
||||
expect(stored.readAt).toBeInstanceOf(Date)
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user