Files
appRobotDriver/test/SenderInterface.test.js
2026-06-12 17:03:38 +02:00

107 lines
3.3 KiB
JavaScript

const EventEmitter = require('events');
const SenderInterface = require('../robot/SenderInterface');
const TelnetSender = require('../robot/TelnetSenderGRBL');
describe('Sender Interface and TelnetSenderGRBL implementation', () => {
test('TelnetSenderGRBL implements the required sender interface methods', () => {
const sender = new TelnetSender('test.test', 2300, 'x', 'y', 'z');
expect(sender).toBeInstanceOf(SenderInterface);
expect(typeof sender.connect).toBe('function');
expect(typeof sender.send).toBe('function');
expect(typeof sender.getStatus).toBe('function');
expect(typeof sender.disconnect).toBe('function');
});
test('test mode sender rejects invalid send payloads and supports idempotent disconnect', () => {
const sender = new TelnetSender('test.test', 2300, 'x', 'y', 'z');
expect(sender.getStatus()).toMatchObject({ state: 'connected' });
sender.tSocket = null;
expect(sender.send('HELLO')).toBe(false);
expect(sender.send('')).toBe(false);
sender.disconnect();
expect(sender.getStatus()).toMatchObject({ state: 'disconnected' });
sender.disconnect();
expect(sender.getStatus()).toMatchObject({ state: 'disconnected' });
});
test('sender reconnects on connection failure and eventually connects', async () => {
let connectAttempts = 0;
const netMock = {
createConnection: () => {
const socket = new EventEmitter();
socket.end = jest.fn();
socket.setKeepAlive = jest.fn(); // benötigt für TCP-Keepalive im connect-Handler
process.nextTick(() => {
connectAttempts += 1;
if (connectAttempts === 1) {
socket.emit('error', new Error('connection failed'));
} else {
socket.emit('connect');
}
});
return socket;
}
};
class DummyTelnetSocket {
constructor(connection) {
this.connection = connection;
}
on(event, listener) {
this.connection.on(event, listener);
return this;
}
write(txt) {
this.connection.written = txt;
}
}
const sender = new TelnetSender('localhost', 2300, 'x', 'y', 'z', null, null, null, null, {
netModule: netMock,
TelnetSocketClass: DummyTelnetSocket,
setTimeoutFn: (fn) => fn(),
setIntervalFn: jest.fn(() => 1), // Heartbeat-Timer: kein echter Intervall
clearIntervalFn: jest.fn(),
autoConnect: false,
reconnectDelay: 1,
maxReconnectDelay: 2
});
const result = await sender.connect();
expect(connectAttempts).toBe(2);
expect(result.getStatus()).toMatchObject({
state: 'connected',
url: 'localhost'
});
expect(result.getStatus().reconnectTimer).toBe(false);
});
test('test mode sender has connected status and can send/disconnect', async () => {
const sender = new TelnetSender('test.test', 2300, 'x', 'y', 'z');
expect(sender.getStatus()).toMatchObject({
state: 'connected',
url: 'test.test',
isTestMode: true
});
expect(sender.send('HELLO')).toBe(true);
expect(sender.tSocket.written).toBe('HELLO\r\n');
sender.disconnect();
expect(sender.getStatus()).toMatchObject({ state: 'disconnected' });
await expect(sender.connect()).resolves.toBe(sender);
expect(sender.getStatus()).toMatchObject({ state: 'connected' });
});
});