farmcontrol-api/src/events/__tests__/eventmanager.test.js
Tom Butcher 97c44565a8
Some checks failed
farmcontrol/farmcontrol-api/pipeline/head There was a failure building this commit
Implement EventManager for handling object events and enhance document template management
This commit introduces the `EventManager` class, which facilitates tracking and broadcasting object events using NATS and websockets. The `documenttemplate.schema.js` file is updated to change the `testObject` field type to `ObjectId` with a reference path, improving data integrity. Additionally, the document template service is enhanced with new functionalities for asynchronous rendering and progress reporting, utilizing Redis for storing render requests. Corresponding tests are added to ensure the correct functionality of the new event handling and document management features.
2026-08-22 12:56:05 +01:00

135 lines
3.7 KiB
JavaScript

import { jest } from '@jest/globals';
jest.unstable_mockModule('../../database/nats.js', () => ({
natsServer: {
publish: jest.fn().mockResolvedValue({ success: true }),
subscribe: jest.fn().mockResolvedValue({ success: true }),
removeSubscription: jest.fn().mockResolvedValue({ success: true })
}
}));
jest.unstable_mockModule('log4js', () => ({
default: {
getLogger: () => ({
level: 'info',
debug: jest.fn(),
error: jest.fn(),
warn: jest.fn(),
trace: jest.fn(),
info: jest.fn()
})
}
}));
jest.unstable_mockModule('../../config.js', () => ({
default: {
server: {
logLevel: 'info'
}
}
}));
const { EventManager } = await import('../eventmanager.js');
const { natsServer } = await import('../../database/nats.js');
describe('EventManager', () => {
let mockSocketClient;
let eventManager;
beforeEach(() => {
jest.clearAllMocks();
mockSocketClient = {
socketId: 'test-socket-id',
socket: {
emit: jest.fn()
}
};
eventManager = new EventManager(mockSocketClient);
});
describe('subscribeToObjectEvent', () => {
it('should subscribe to object events and emit when received', async () => {
const id = 'obj-123';
const objectType = 'printer';
const eventType = 'status';
await eventManager.subscribeToObjectEvent(id, objectType, eventType);
expect(natsServer.subscribe).toHaveBeenCalledWith(
'printers.obj-123.events.status',
'test-socket-id',
expect.any(Function)
);
// Simulate NATS message
const natsCallback = natsServer.subscribe.mock.calls[0][2];
const eventData = { status: 'online' };
natsCallback('printers.obj-123.events.status', eventData);
expect(mockSocketClient.socket.emit).toHaveBeenCalledWith('objectEvent', {
_id: id,
objectType: objectType,
event: eventData
});
});
});
describe('removeObjectEventsListener', () => {
it('should remove specific subscription', async () => {
const id = 'obj-123';
const objectType = 'printer';
const eventType = 'status';
await eventManager.subscribeToObjectEvent(id, objectType, eventType);
await eventManager.removeObjectEventsListener(id, objectType, eventType);
expect(natsServer.removeSubscription).toHaveBeenCalledWith(
'printers.obj-123.events.status',
'test-socket-id'
);
expect(eventManager.subscriptions.size).toBe(0);
});
});
describe('sendObjectEvent', () => {
it('should publish event to NATS', async () => {
const id = 'obj-123';
const objectType = 'printer';
const event = { type: 'alert', message: 'low filament' };
const result = await eventManager.sendObjectEvent(id, objectType, event);
expect(result).toEqual({ success: true });
expect(natsServer.publish).toHaveBeenCalledWith(
'printers.obj-123.events.alert',
event
);
});
it('should handle errors when publishing fails', async () => {
natsServer.publish.mockRejectedValueOnce(new Error('NATS error'));
const result = await eventManager.sendObjectEvent('id', 'type', {
type: 't'
});
expect(result).toHaveProperty('error', 'NATS error');
});
});
describe('removeAllListeners', () => {
it('should remove all subscriptions', async () => {
await eventManager.subscribeToObjectEvent('1', 'printer', 'e1');
await eventManager.subscribeToObjectEvent('2', 'printer', 'e2');
await eventManager.removeAllListeners();
expect(natsServer.removeSubscription).toHaveBeenCalledTimes(2);
expect(eventManager.subscriptions.size).toBe(0);
});
});
});