96 lines
3.0 KiB
JavaScript
96 lines
3.0 KiB
JavaScript
// Testet das FCode-Routing in InputWS (FCodeClient wird gemockt).
|
|
jest.mock('../robot/FCodeClient', () => ({
|
|
isFCode: jest.fn((msg) => /^F[A-Z][a-z]+/.test(String(msg).trim())),
|
|
handle: jest.fn(),
|
|
}));
|
|
|
|
const http = require('http');
|
|
const WebSocket = require('ws');
|
|
const FCodeClient = require('../robot/FCodeClient');
|
|
const initInputWS = require('../server/InputWS');
|
|
const GCode = require('../robot/GCode');
|
|
const createDummyRobot = require('./helpers/createDummyRobot');
|
|
|
|
/* ---------- helpers ---------- */
|
|
|
|
function listen(server) {
|
|
return new Promise((resolve, reject) => {
|
|
server.listen(0, () => {
|
|
const { port } = server.address();
|
|
port ? resolve(port) : reject(new Error('no port'));
|
|
});
|
|
server.on('error', reject);
|
|
});
|
|
}
|
|
|
|
function connect(port) {
|
|
return new Promise((resolve, reject) => {
|
|
const ws = new WebSocket(`ws://127.0.0.1:${port}`);
|
|
ws.on('open', () => resolve(ws));
|
|
ws.on('error', reject);
|
|
});
|
|
}
|
|
|
|
function nextMessage(ws, timeoutMs = 2000) {
|
|
return new Promise((resolve, reject) => {
|
|
const t = setTimeout(() => reject(new Error('Timeout')), timeoutMs);
|
|
ws.once('message', (d) => { clearTimeout(t); resolve(d.toString()); });
|
|
});
|
|
}
|
|
|
|
/* ---------- suite ---------- */
|
|
|
|
describe('InputWS FCode-Routing', () => {
|
|
let server, ws;
|
|
|
|
beforeEach(() => {
|
|
FCodeClient.handle.mockReset();
|
|
FCodeClient.isFCode.mockClear();
|
|
});
|
|
|
|
afterEach(async () => {
|
|
if (ws) { ws.close(); ws = null; }
|
|
if (server) { await new Promise(r => server.close(r)); server = null; }
|
|
});
|
|
|
|
async function setup(robot) {
|
|
server = http.createServer();
|
|
initInputWS(server, robot || createDummyRobot(), GCode, { connectedClients: [], lastCommands: [], lastPings: [] });
|
|
const port = await listen(server);
|
|
ws = await connect(port);
|
|
return ws;
|
|
}
|
|
|
|
test('FList → broadcastet die Antwortdaten vom Fileservice', async () => {
|
|
FCodeClient.handle.mockResolvedValue({ type: 'list', data: JSON.stringify([{ id: 'a' }]) });
|
|
await setup();
|
|
const replyP = nextMessage(ws);
|
|
ws.send('FList');
|
|
expect(JSON.parse(await replyP)).toEqual([{ id: 'a' }]);
|
|
});
|
|
|
|
test('FPlus (step) → GCode-Zeile ausführen + M114 broadcasten', async () => {
|
|
const line = 'G90 G1 x10 y300 z0 a1.5708 b-1.5708 c0 e0 f1000';
|
|
FCodeClient.handle.mockResolvedValue({ type: 'step', line });
|
|
const robot = createDummyRobot();
|
|
await setup(robot);
|
|
const replyP = nextMessage(ws);
|
|
ws.send('FPlus');
|
|
const msg = JSON.parse(await replyP);
|
|
expect(msg.position).toBeDefined();
|
|
expect(robot.sendCommand).toHaveBeenCalled();
|
|
});
|
|
|
|
test('Fileservice-Fehler → machine-readable FILE_ERROR an Sender', async () => {
|
|
const err = Object.assign(new Error('not found'), { code: 'PROGRAM_NOT_FOUND' });
|
|
FCodeClient.handle.mockRejectedValue(err);
|
|
await setup();
|
|
const replyP = nextMessage(ws);
|
|
ws.send('FLoad nichtda');
|
|
const msg = JSON.parse(await replyP);
|
|
expect(msg.type).toBe('error');
|
|
expect(msg.code).toBe('FILE_ERROR');
|
|
expect(msg.input).toBe('FLoad nichtda');
|
|
});
|
|
});
|