const http = require('http'); const WebSocket = require('ws'); const initInputWS = require('../server/InputWS'); const GCode = require('../robot/GCode'); const createDummyRobot = require('./helpers/createDummyRobot'); function listen(server) { return new Promise((resolve, reject) => { server.listen(0, () => { const address = server.address(); if (address && address.port) { resolve(address.port); } else { reject(new Error('Failed to get server port')); } }); server.on('error', reject); }); } function connectWebSocket(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 waitForMessage(ws) { return new Promise((resolve, reject) => { const timer = setTimeout(() => reject(new Error('Timeout waiting for message')), 2000); ws.on('message', (data) => { clearTimeout(timer); resolve(data.toString()); }); }); } describe('InputWS', () => { let server; let port; let wss; afterEach(async () => { if (server) { await new Promise((resolve) => server.close(resolve)); server = null; } }); test('responds to Ping and updates sharedState', async () => { server = http.createServer(); const sharedState = { connectedClients: [], lastCommands: [], lastPings: [] }; const robot = createDummyRobot(); wss = initInputWS(server, robot, GCode, sharedState); port = await listen(server); const client = await connectWebSocket(port); const messagePromise = waitForMessage(client); client.send('Ping'); const message = await messagePromise; expect(message).toBe('Ping'); expect(sharedState.lastPings.length).toBe(1); expect(sharedState.connectedClients.length).toBe(1); client.close(); }); test('responds to M114 with current robot position JSON', async () => { server = http.createServer(); const sharedState = { connectedClients: [], lastCommands: [], lastPings: [] }; const robot = createDummyRobot(); robot.x = 12; robot.y = 34; robot.z = 56; robot.phi = 1; robot.theta = 2; robot.psi = 3; wss = initInputWS(server, robot, GCode, sharedState); port = await listen(server); const client = await connectWebSocket(port); const messagePromise = waitForMessage(client); client.send('M114'); const message = await messagePromise; const parsed = JSON.parse(message); expect(parsed.position).toEqual({ x: 12, y: 34, z: 56, a: 1, b: 2, c: 3, e: 0 }); expect(parsed.motorCounts).toBeDefined(); client.close(); }); test('receives GCode text and broadcasts updated position', async () => { server = http.createServer(); const sharedState = { connectedClients: [], lastCommands: [], lastPings: [] }; const robot = createDummyRobot(); wss = initInputWS(server, robot, GCode, sharedState); port = await listen(server); const client = await connectWebSocket(port); const messagePromise = waitForMessage(client); client.send('G1 X1 Y2 Z3'); const message = await messagePromise; const parsed = JSON.parse(message); expect(parsed.position).toEqual({ x: 1, y: 2, z: 3, a: 0, b: 0, c: 0, e: 0 }); expect(robot.sendCommand).toHaveBeenCalled(); client.close(); }); });