152 lines
5.3 KiB
JavaScript
152 lines
5.3 KiB
JavaScript
const FCodeClient = require('../robot/FCodeClient');
|
|
|
|
const robot = {
|
|
x: 0, y: 300, z: 0,
|
|
phi: Math.PI / 2, theta: -Math.PI / 2, psi: 0, e: 0,
|
|
feedrate: 1000,
|
|
};
|
|
|
|
function mockOk(data) {
|
|
global.fetch = jest.fn().mockResolvedValue({
|
|
ok: true, status: 200, statusText: 'OK',
|
|
json: () => Promise.resolve(data),
|
|
});
|
|
}
|
|
|
|
function mockErr(status, code, message) {
|
|
global.fetch = jest.fn().mockResolvedValue({
|
|
ok: false, status, statusText: 'Error',
|
|
json: () => Promise.resolve({ code, message }),
|
|
});
|
|
}
|
|
|
|
afterEach(() => { delete global.fetch; });
|
|
|
|
/* ---------- isFCode ---------- */
|
|
|
|
describe('isFCode', () => {
|
|
test('erkennt alle bekannten FCodes', () => {
|
|
for (const f of ['FList','FShow','FLoad demo','FSave Name','FClear','FPoint','FPlus','FMinus','FFirst','FLast','FGoto 3','FPlay','FStop']) {
|
|
expect(FCodeClient.isFCode(f)).toBe(true);
|
|
}
|
|
});
|
|
|
|
test('erkennt Nicht-FCodes nicht', () => {
|
|
expect(FCodeClient.isFCode('G1 X100')).toBe(false);
|
|
expect(FCodeClient.isFCode('F1000')).toBe(false);
|
|
expect(FCodeClient.isFCode('M114')).toBe(false);
|
|
expect(FCodeClient.isFCode('Ping')).toBe(false);
|
|
expect(FCodeClient.isFCode('')).toBe(false);
|
|
});
|
|
});
|
|
|
|
/* ---------- handle: Listing / Info ---------- */
|
|
|
|
test('FList → GET /api/programs, type list', async () => {
|
|
mockOk([{ id: 'a', name: 'A' }]);
|
|
const result = await FCodeClient.handle(robot, 'FList');
|
|
expect(result.type).toBe('list');
|
|
expect(global.fetch).toHaveBeenCalledWith(
|
|
expect.stringContaining('/api/programs'),
|
|
expect.objectContaining({ method: 'GET' })
|
|
);
|
|
expect(JSON.parse(result.data)).toEqual([{ id: 'a', name: 'A' }]);
|
|
});
|
|
|
|
test('FShow ohne id → GET /api/active', async () => {
|
|
mockOk({ programId: 'x', cursor: 0 });
|
|
const result = await FCodeClient.handle(robot, 'FShow');
|
|
expect(global.fetch).toHaveBeenCalledWith(expect.stringContaining('/api/active'), expect.anything());
|
|
expect(result.type).toBe('show');
|
|
});
|
|
|
|
test('FShow mit id → GET /api/programs/:id', async () => {
|
|
mockOk({ id: 'demo', name: 'Demo' });
|
|
await FCodeClient.handle(robot, 'FShow demo');
|
|
expect(global.fetch).toHaveBeenCalledWith(expect.stringContaining('/api/programs/demo'), expect.anything());
|
|
});
|
|
|
|
/* ---------- handle: Teaching ---------- */
|
|
|
|
test('FPoint → POST /api/active/points mit Roboterpose (Radian)', async () => {
|
|
mockOk({ index: 0, line: 'G90 G1 x0 y300 z0 a1.5708 b-1.5708 c0 e0 f1000' });
|
|
const result = await FCodeClient.handle(robot, 'FPoint');
|
|
expect(result.type).toBe('point');
|
|
const call = global.fetch.mock.calls[0];
|
|
expect(call[1].method).toBe('POST');
|
|
const body = JSON.parse(call[1].body);
|
|
expect(body.pose.a).toBeCloseTo(Math.PI / 2, 4);
|
|
expect(body.pose.b).toBeCloseTo(-Math.PI / 2, 4);
|
|
expect(body.feedrate).toBe(1000);
|
|
});
|
|
|
|
/* ---------- handle: Program management ---------- */
|
|
|
|
test('FLoad → PUT /api/active mit id', async () => {
|
|
mockOk({ programId: 'mein_prog', cursor: 0, lineCount: 5 });
|
|
const result = await FCodeClient.handle(robot, 'FLoad mein_prog');
|
|
expect(result.type).toBe('ok');
|
|
const body = JSON.parse(global.fetch.mock.calls[0][1].body);
|
|
expect(body).toEqual({ id: 'mein_prog' });
|
|
});
|
|
|
|
test('FSave → POST /api/programs mit name und fromActive:true', async () => {
|
|
mockOk({ id: 'test_prog', name: 'Test Prog' });
|
|
await FCodeClient.handle(robot, 'FSave Test Prog');
|
|
const body = JSON.parse(global.fetch.mock.calls[0][1].body);
|
|
expect(body.name).toBe('Test Prog');
|
|
expect(body.fromActive).toBe(true);
|
|
});
|
|
|
|
test('FClear → POST /api/active/clear', async () => {
|
|
mockOk({ ok: true });
|
|
await FCodeClient.handle(robot, 'FClear');
|
|
expect(global.fetch).toHaveBeenCalledWith(expect.stringContaining('/api/active/clear'), expect.objectContaining({ method: 'POST' }));
|
|
});
|
|
|
|
/* ---------- handle: Stepping → type step ---------- */
|
|
|
|
test('FPlus → POST /api/active/next → type step mit Zeile', async () => {
|
|
mockOk({ cursor: 1, line: 'G90 G1 x10 y300 z0 a1.5708 b-1.5708 c0 e0 f1000' });
|
|
const result = await FCodeClient.handle(robot, 'FPlus');
|
|
expect(result.type).toBe('step');
|
|
expect(result.line).toContain('G1');
|
|
});
|
|
|
|
test('FMinus → POST /api/active/prev', async () => {
|
|
mockOk({ cursor: 0, line: 'G90 G1 x0 y300 z0 a0 b0 c0 e0 f1000' });
|
|
const result = await FCodeClient.handle(robot, 'FMinus');
|
|
expect(result.type).toBe('step');
|
|
});
|
|
|
|
test('FFirst / FLast', async () => {
|
|
mockOk({ cursor: 0, line: 'G90 G1 x0 y0 z0 a0 b0 c0 e0 f1000' });
|
|
const r1 = await FCodeClient.handle(robot, 'FFirst');
|
|
expect(r1.type).toBe('step');
|
|
|
|
mockOk({ cursor: 4, line: 'G90 G1 x5 y0 z0 a0 b0 c0 e0 f1000' });
|
|
const r2 = await FCodeClient.handle(robot, 'FLast');
|
|
expect(r2.type).toBe('step');
|
|
});
|
|
|
|
test('FGoto N → POST /api/active/goto mit index', async () => {
|
|
mockOk({ cursor: 3, line: 'G90 G1 x3 y0 z0 a0 b0 c0 e0 f1000' });
|
|
await FCodeClient.handle(robot, 'FGoto 3');
|
|
const body = JSON.parse(global.fetch.mock.calls[0][1].body);
|
|
expect(body.index).toBe(3);
|
|
});
|
|
|
|
/* ---------- Fehlerbehandlung ---------- */
|
|
|
|
test('Fileservice-Fehler → wirft mit code und status', async () => {
|
|
mockErr(404, 'PROGRAM_NOT_FOUND', 'not found');
|
|
await expect(FCodeClient.handle(robot, 'FLoad nichtda')).rejects.toMatchObject({
|
|
code: 'PROGRAM_NOT_FOUND',
|
|
status: 404,
|
|
});
|
|
});
|
|
|
|
test('Unbekannter FCode → wirft', async () => {
|
|
await expect(FCodeClient.handle(robot, 'FUnbekannt')).rejects.toThrow('Unbekannter FCode');
|
|
});
|