Files
appRobotFileservice/test/activeState.test.js
chk b68bdfa9b4 Initiales Projekt-Skelett appRobotFileservice
Ausgelagertes Programm-/File-Handling (vormals GCode.receiveFC im appRobotDriver,
ToDo_4 / ToDo_6b). Express-Service mit .gcode + .json-Storage, aktivem Programm +
Cursor, Teaching (FPoint) und Playback. Speicherung in Grad, driver-nativ (Radian)
zum Driver. Konzept/API unter doc/draft_filehandeling*.md. Tests: jest (13 gruen).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-14 10:12:41 +02:00

81 lines
2.7 KiB
JavaScript

const os = require('os');
const path = require('path');
const fsp = require('fs/promises');
const cfg = require('../src/config');
const store = require('../src/store/fileStore');
const units = require('../src/gcode/units');
const { ActiveState } = require('../src/active/activeState');
let tmp;
beforeEach(async () => {
tmp = await fsp.mkdtemp(path.join(os.tmpdir(), 'fsvc-act-'));
cfg.storageDir = tmp;
});
afterEach(async () => {
await fsp.rm(tmp, { recursive: true, force: true });
});
test('Teaching: load(leer) → appendPoint → reload findet Zeile + Cursor', async () => {
const a = new ActiveState();
await a.load('teach_1'); // existiert nicht → leer angelegt
expect(a.getState().lineCount).toBe(0);
const pose = { x: 0, y: 300, z: 0, a: Math.PI / 2, b: -Math.PI / 2, c: 0, e: 0 };
const r = await a.appendPoint(pose, 1000);
expect(r.index).toBe(0);
expect(r.line).toContain('a90.00'); // in Grad gespeichert
const b = new ActiveState();
await b.load('teach_1');
expect(b.getState().lineCount).toBe(1);
expect(b.getState().cursor).toBe(0);
});
test('Playback: stepping liefert driver-native (Radian) Zeilen, Grenzen werfen', async () => {
await store.write('play_1', {
name: 'Play 1',
lines: [
'G90 G1 x0 y300 z0 a90.00 b-90.00 c0.00 e0.00 f1000 ;1',
'G90 G1 x10 y300 z0 a0.00 b-90.00 c0.00 e0.00 f1000 ;2',
],
});
const a = new ActiveState();
await a.load('play_1');
const first = a.first();
expect(first.cursor).toBe(0);
expect(first.line).not.toMatch(/;/);
const aVal = Number(first.line.split(/\s+/).find((t) => t.startsWith('a')).slice(1));
expect(aVal).toBeCloseTo(Math.PI / 2, 4);
expect(a.next().cursor).toBe(1);
expect(() => a.next()).toThrow(); // über das Ende → CURSOR_OUT_OF_RANGE
});
test('Cursor wird beim Speichern als !-Kommentar abgelegt (genau eine Zeile)', async () => {
await store.write('cur_1', {
name: 'Cur',
lines: [
'G90 G1 x0 y0 z0 a0 b0 c0 e0 f1000 ;1',
'G90 G1 x1 y0 z0 a0 b0 c0 e0 f1000 ;2',
],
});
const a = new ActiveState();
await a.load('cur_1');
a.next(); // cursor → 1 (kein Persist)
await a.appendLine('G4 P0.1'); // persistiert, cursor → 2
const prog = await store.read('cur_1');
const marked = prog.lines.filter(units.hasCursorMarker);
expect(marked).toHaveLength(1);
expect(units.splitComment(marked[0]).code).toBe('G4 P0.1');
});
test('Aktion ohne aktives Programm → NO_ACTIVE_PROGRAM', async () => {
const a = new ActiveState();
expect(() => a.next()).toThrow(); // NO_ACTIVE_PROGRAM
await expect(a.appendPoint({ x: 0, y: 0, z: 0, a: 0, b: 0, c: 0, e: 0 })).rejects.toMatchObject({
code: 'NO_ACTIVE_PROGRAM',
});
});