Files
TREK/server/tests/unit/nest/notifications/storage-health-notifier.service.test.ts
T

35 lines
1.8 KiB
TypeScript

import { describe, it, expect, vi } from 'vitest';
import { StorageEventsService } from '../../../../src/nest/storage/storage-events.service';
import { StorageHealthNotifierService } from '../../../../src/nest/notifications/storage-health-notifier.service';
import type { NotificationsService } from '../../../../src/nest/notifications/notifications.service';
describe('StorageHealthNotifierService', () => {
it('NOTIF-001 subscribes on bootstrap and sends an admin-scoped replica_failure with params', () => {
const events = new StorageEventsService();
const send = vi.fn().mockResolvedValue(undefined);
const notifier = new StorageHealthNotifierService(events, { send } as unknown as NotificationsService);
notifier.onApplicationBootstrap();
events.emitReplicaFailure({ backend: 's3-bkp', key: 'backups/db.zip', op: 'put', error: 'timeout', at: 1 });
expect(send).toHaveBeenCalledWith({
event: 'replica_failure',
actorId: null,
scope: 'admin',
targetId: 0,
params: { backend: 's3-bkp', key: 'backups/db.zip', op: 'put', error: 'timeout', suppressed: '0' },
});
// Second failure inside the window: suppressed, no second send.
events.emitReplicaFailure({ backend: 's3-bkp', key: 'backups/x.zip', op: 'put', error: 'timeout', at: 2 });
expect(send).toHaveBeenCalledTimes(1);
});
it('NOTIF-002 a rejected send never throws into the emitter (write path stays safe)', () => {
const events = new StorageEventsService();
const send = vi.fn().mockRejectedValue(new Error('smtp down'));
const notifier = new StorageHealthNotifierService(events, { send } as unknown as NotificationsService);
notifier.onApplicationBootstrap();
expect(() =>
events.emitReplicaFailure({ backend: 'b', key: 'k', op: 'delete', error: 'e', at: 3 }),
).not.toThrow();
});
});