create-notification.test.ts
1 import assert from 'node:assert/strict' 2 import { describe, it } from 'node:test' 3 4 import type { AppNotification } from '@/types' 5 import { createNotification } from './create-notification' 6 7 describe('createNotification', () => { 8 it('coalesces repeated dedupKey events into one notification record', () => { 9 const store = new Map<string, AppNotification>() 10 const notifyTopics: string[] = [] 11 const dispatched: string[] = [] 12 13 const deps = { 14 now: (() => { 15 let current = 1_700_000_000_000 16 return () => { 17 current += 1_000 18 return current 19 } 20 })(), 21 save: (id: string, data: AppNotification) => { 22 store.set(id, data) 23 }, 24 notifyTopic: (topic: string) => { 25 notifyTopics.push(topic) 26 }, 27 dispatch: async (notification: AppNotification) => { 28 dispatched.push(notification.id) 29 }, 30 findByDedupKey: (dedupKey: string) => { 31 for (const notification of store.values()) { 32 if (notification.dedupKey === dedupKey) return notification 33 } 34 return null 35 }, 36 createId: (() => { 37 let seq = 0 38 return () => `notif_${++seq}` 39 })(), 40 } 41 42 const first = createNotification({ 43 type: 'warning', 44 title: 'Provider unreachable', 45 message: 'Timeout', 46 dedupKey: 'provider-down:test', 47 }, deps) 48 49 const second = createNotification({ 50 type: 'warning', 51 title: 'Provider unreachable', 52 message: 'Still timing out', 53 dedupKey: 'provider-down:test', 54 }, deps) 55 56 assert.equal(first.created, true) 57 assert.equal(second.created, false) 58 assert.equal(store.size, 1) 59 assert.equal(second.notification.id, first.notification.id) 60 assert.equal(second.notification.message, 'Still timing out') 61 assert.equal(second.notification.occurrenceCount, 2) 62 assert.equal(second.notification.read, false) 63 assert.deepEqual(notifyTopics, ['notifications', 'notifications']) 64 assert.deepEqual(dispatched, [first.notification.id]) 65 }) 66 67 it('can keep a notification in-app only without external dispatch', () => { 68 const store = new Map<string, AppNotification>() 69 const dispatched: string[] = [] 70 71 const result = createNotification({ 72 type: 'warning', 73 title: 'SwarmClaw health alert', 74 message: 'Connector recovered.', 75 dedupKey: 'health-alert:connector-recovered', 76 dispatchExternally: false, 77 }, { 78 now: () => 1_700_000_000_000, 79 save: (id: string, data: AppNotification) => { 80 store.set(id, data) 81 }, 82 notifyTopic: () => {}, 83 dispatch: async (notification: AppNotification) => { 84 dispatched.push(notification.id) 85 }, 86 findByDedupKey: () => null, 87 createId: () => 'notif_health', 88 }) 89 90 assert.equal(result.created, true) 91 assert.equal(store.get('notif_health')?.title, 'SwarmClaw health alert') 92 assert.deepEqual(dispatched, []) 93 }) 94 })