Files
speckle-server/packages/server/modules/notifications/tests/notifications.spec.ts
T
Kristaps Fabians Geikins bde148f286 chore(server): migrating fully to ESM (#5042)
* wip

* some extra fixes

* stuff kinda works?

* need to figure out mocks

* need to figure out mocks

* fix db listener

* gqlgen fix

* minor gqlgen watch adjustment

* lint fixes

* delete old codegen file

* converting migrations to ESM

* getModuleDIrectory

* vitest sort of works

* added back ts-vitest

* resolve gql double load

* fixing test timeout configs

* TSC lint fix

* fix automate tests

* moar debugging

* debugging

* more debugging

* codegen update

* server works

* yargs migrated

* chore(server): getting rid of global mocks for Server ESM (#5046)

* got rid of email mock

* got rid of comment mocks

* got rid of multi region mocks

* got rid of stripe mock

* admin override mock updated

* removed final mock

* fixing import.meta.resolve calls

* another import.meta.resolve fix

* added requested test

* nyc ESM fix

* removed unneeded deps + linting

* yarn lock forgot to commit

* tryna fix flakyness

* email capture util fix

* sendEmail fix

* fix TSX check

* sender transporter fix + CR comments

* merge main fix

* test fixx

* circleci fix

* gqlgen bigint fix

* error formatter fix

* more error formatting improvements

* esmloader added to Dockerfile

* more dockerfile fixes

* bg jobs fix
2025-07-14 10:26:19 +03:00

133 lines
4.0 KiB
TypeScript

import {
MentionedInCommentData,
NotificationType
} from '@/modules/notifications/helpers/types'
import { publishNotification } from '@/modules/notifications/services/publication'
import {
buildNotificationsStateTracker,
NotificationsStateManager,
purgeNotifications
} from '@/test/notificationsHelper'
import { expect } from 'chai'
import {
InvalidNotificationError,
NotificationValidationError,
UnhandledNotificationError
} from '@/modules/notifications/errors'
import { NotificationJobResultsStatus } from '@/modules/notifications/services/queue'
import { getEventBus } from '@/modules/shared/services/eventBus'
import { NotificationsEvents } from '@/modules/notifications/domain/events'
describe('Notifications', () => {
let notificationsState: NotificationsStateManager
before(async () => {
await purgeNotifications()
notificationsState = await buildNotificationsStateTracker()
})
after(async () => {
notificationsState.destroy()
})
afterEach(() => {
notificationsState.reset()
})
it('can be emitted and routed to proper handler on consumption', async () => {
const targetUserId = '1234555'
const data: MentionedInCommentData = {
threadId: 'aaa',
commentId: 'bbb',
authorId: 'ccc',
streamId: 'ddd'
}
// Enqueue notification
const msgId = await publishNotification(NotificationType.MentionedInComment, {
targetUserId,
data
})
// Wait for ack
await notificationsState.waitForMsgAck(msgId)
const enqueuedMessage = notificationsState.collectedMessages().at(-1)!
expect(enqueuedMessage).to.be.ok
expect(enqueuedMessage?.targetUserId).to.eq(targetUserId)
expect(enqueuedMessage?.type).to.eq(NotificationType.MentionedInComment)
expect(enqueuedMessage?.data).to.deep.equalInAnyOrder(data)
})
it('fail safely when emitted with an unexpected structure', async () => {
// Enqueue notification with invalid structure
const msgId = await publishNotification(NotificationType.MentionedInComment, {
a: 1,
b: 2
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any)
const { err } = await notificationsState.waitForMsgAck(msgId)
expect(err).to.be.ok
expect(err instanceof InvalidNotificationError).to.be.true
expect(err?.message).to.contain('invalid notification')
})
it('fail safely when emitted with an unexpected type', async () => {
// Enqueue notification with invalid structure
const msgId = await publishNotification('booooooooo' as NotificationType, {
targetUserId: '123',
data: {
a: 123
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any
})
const { err } = await notificationsState.waitForMsgAck(msgId)
expect(err).to.be.ok
expect(err instanceof UnhandledNotificationError).to.be.true
})
const validationErrorDataSet = [
{
display: 'successful',
error: new NotificationValidationError('expected validation isue')
},
{ display: 'unsuccessful', error: new Error('ooohhhh') }
]
validationErrorDataSet.forEach(({ display, error }) => {
it(`fail with ${display} ack when handler throws ${error.name}`, async () => {
const data: MentionedInCommentData = {
threadId: 'aaa',
commentId: 'bbb',
authorId: 'ccc',
streamId: 'ddd'
}
getEventBus().listenOnce(NotificationsEvents.Received, () => {
throw error
})
const msgId = await publishNotification(NotificationType.MentionedInComment, {
targetUserId: '123',
data
})
const { err, result } = await notificationsState.waitForMsgAck(msgId)
const isValidationError = error instanceof NotificationValidationError
if (isValidationError) {
expect(err).to.be.not.ok
expect(result?.status).to.eq(NotificationJobResultsStatus.ValidationError)
} else {
expect(err).to.be.ok
expect(err?.name).to.eq(error.name)
expect(err?.message).to.eq(error.message)
expect(result).to.be.not.ok
}
})
})
})