193 lines
5.8 KiB
JavaScript
193 lines
5.8 KiB
JavaScript
const fs = require('fs');
|
|
const https = require('https');
|
|
const createInfoServer = require('../server/InfoServer');
|
|
const GCode = require('../robot/GCode');
|
|
|
|
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 request(url) {
|
|
return new Promise((resolve, reject) => {
|
|
const agent = new https.Agent({ rejectUnauthorized: false });
|
|
https.get(url, { agent }, (res) => {
|
|
let data = '';
|
|
res.on('data', (chunk) => {
|
|
data += chunk.toString();
|
|
});
|
|
res.on('end', () => {
|
|
resolve({ statusCode: res.statusCode, body: data });
|
|
});
|
|
}).on('error', reject);
|
|
});
|
|
}
|
|
|
|
describe('InfoServer', () => {
|
|
let server;
|
|
let port;
|
|
|
|
afterEach(async () => {
|
|
if (server) {
|
|
await new Promise((resolve) => server.close(resolve));
|
|
server = null;
|
|
}
|
|
});
|
|
|
|
test('returns status JSON with sender and shared state information', async () => {
|
|
const key = fs.readFileSync('https/localhost.key');
|
|
const cert = fs.readFileSync('https/localhost.pem');
|
|
const httpsOptions = { key, cert, passphrase: 'abcd' };
|
|
|
|
const sharedState = {
|
|
connectedClients: ['127.0.0.1'],
|
|
lastCommands: ['G1 X10 Y10'],
|
|
lastPings: ['Ping']
|
|
};
|
|
|
|
const robot = {
|
|
x: 1,
|
|
y: 2,
|
|
z: 3,
|
|
phi: 0,
|
|
theta: 0,
|
|
psi: 0
|
|
};
|
|
|
|
const senders = [
|
|
{ name: 'Base', instance: { tSocket: {} } },
|
|
{ name: 'Hand', instance: null }
|
|
];
|
|
|
|
server = createInfoServer(httpsOptions, sharedState, robot, GCode, senders);
|
|
port = await listen(server);
|
|
|
|
const { statusCode, body } = await request(`https://127.0.0.1:${port}/api/status`);
|
|
expect(statusCode).toBe(200);
|
|
|
|
const status = JSON.parse(body);
|
|
expect(status.clients).toEqual(['127.0.0.1']);
|
|
expect(status.lastCommands).toEqual(['G1 X10 Y10']);
|
|
expect(status.lastPings).toEqual(['Ping']);
|
|
|
|
// Machine-readable top-level health summary (one of two senders connected)
|
|
expect(status.health).toEqual({ ok: false, connectedSenders: 1, totalSenders: 2 });
|
|
expect(typeof status.generatedAt).toBe('string');
|
|
expect(Number.isNaN(Date.parse(status.generatedAt))).toBe(false);
|
|
|
|
expect(status.senders).toEqual([
|
|
{
|
|
name: 'Base',
|
|
state: 'connected',
|
|
url: null,
|
|
isTestMode: false,
|
|
error: null,
|
|
reconnectAttempt: 0,
|
|
reconnectTimer: false,
|
|
health: 'ok',
|
|
reason: undefined
|
|
},
|
|
{
|
|
name: 'Hand',
|
|
state: 'disconnected',
|
|
url: null,
|
|
isTestMode: false,
|
|
error: null,
|
|
reconnectAttempt: 0,
|
|
reconnectTimer: false,
|
|
health: 'disconnected',
|
|
reason: 'no active socket connection'
|
|
}
|
|
]);
|
|
});
|
|
|
|
test('returns sender health details from instance.getStatus()', async () => {
|
|
const key = fs.readFileSync('https/localhost.key');
|
|
const cert = fs.readFileSync('https/localhost.pem');
|
|
const httpsOptions = { key, cert, passphrase: 'abcd' };
|
|
|
|
const sharedState = { connectedClients: [], lastCommands: [], lastPings: [] };
|
|
const robot = { x: 0, y: 0, z: 0, phi: 0, theta: 0, psi: 0 };
|
|
const senders = [
|
|
{
|
|
name: 'Reconnect',
|
|
instance: {
|
|
getStatus: () => ({
|
|
state: 'reconnecting',
|
|
url: 'reconnect.test',
|
|
error: 'timeout',
|
|
isTestMode: false,
|
|
reconnectAttempt: 2,
|
|
reconnectTimer: true
|
|
})
|
|
}
|
|
}
|
|
];
|
|
|
|
server = createInfoServer(httpsOptions, sharedState, robot, GCode, senders);
|
|
port = await listen(server);
|
|
|
|
const { statusCode, body } = await request(`https://127.0.0.1:${port}/api/status`);
|
|
expect(statusCode).toBe(200);
|
|
|
|
const status = JSON.parse(body);
|
|
expect(status.senders).toEqual([
|
|
{
|
|
name: 'Reconnect',
|
|
state: 'reconnecting',
|
|
url: 'reconnect.test',
|
|
isTestMode: false,
|
|
error: 'timeout',
|
|
reconnectAttempt: 2,
|
|
reconnectTimer: true,
|
|
health: 'warning',
|
|
reason: undefined
|
|
}
|
|
]);
|
|
});
|
|
|
|
test('returns position JSON from GCode.getM114', async () => {
|
|
const key = fs.readFileSync('https/localhost.key');
|
|
const cert = fs.readFileSync('https/localhost.pem');
|
|
const httpsOptions = { key, cert, passphrase: 'abcd' };
|
|
|
|
const sharedState = { connectedClients: [], lastCommands: [], lastPings: [] };
|
|
const robot = { x: 10, y: 20, z: 30, phi: 0.1, theta: 0.2, psi: 0.3, xMotor: 0, alpha: 0, beta: 0, a: 0, b: 0, c: 0 };
|
|
const senders = [];
|
|
|
|
server = createInfoServer(httpsOptions, sharedState, robot, GCode, senders);
|
|
port = await listen(server);
|
|
|
|
const { statusCode, body } = await request(`https://127.0.0.1:${port}/api/position`);
|
|
expect(statusCode).toBe(200);
|
|
|
|
const json = JSON.parse(body);
|
|
expect(json.position).toEqual({ x: 10, y: 20, z: 30, a: 0.1, b: 0.2, c: 0.3 });
|
|
});
|
|
|
|
test('returns 404 for unknown endpoints', async () => {
|
|
const key = fs.readFileSync('https/localhost.key');
|
|
const cert = fs.readFileSync('https/localhost.pem');
|
|
const httpsOptions = { key, cert, passphrase: 'abcd' };
|
|
|
|
const sharedState = { connectedClients: [], lastCommands: [], lastPings: [] };
|
|
const robot = { x: 0, y: 0, z: 0, phi: 0, theta: 0, psi: 0, xMotor: 0, alpha: 0, beta: 0, a: 0, b: 0, c: 0 };
|
|
const senders = [];
|
|
|
|
server = createInfoServer(httpsOptions, sharedState, robot, GCode, senders);
|
|
port = await listen(server);
|
|
|
|
const { statusCode } = await request(`https://127.0.0.1:${port}/api/unknown`);
|
|
expect(statusCode).toBe(404);
|
|
});
|
|
});
|