const { createRobotFromEnv, loadKinematicsClass, parseParams, DEFAULT_KINEMATICS, } = require('../robot/KinematicsFactory'); const Arm3SegmentLinearX = require('../robot/kinematics/Arm3SegmentLinearX'); const RobotBase = require('../robot/RobotBase'); describe('KinematicsFactory (Roadmap 12, Phase 2)', () => { test('Default-Kinematik ohne Env, mit Fallback-Params', () => { const robot = createRobotFromEnv({}, { l1: 250, l2: 264, l3: 100 }); expect(robot).toBeInstanceOf(Arm3SegmentLinearX); expect(robot).toBeInstanceOf(RobotBase); expect([robot.l1, robot.l2, robot.l3]).toEqual([250, 264, 100]); }); test('ROBOT_KINEMATICS_PARAMS überschreibt die Fallback-Params', () => { const robot = createRobotFromEnv( { ROBOT_KINEMATICS: 'arm3segmentlinearx', ROBOT_KINEMATICS_PARAMS: '{"l1":300,"l2":200,"l3":10}', }, { l1: 250, l2: 264, l3: 100 } ); expect([robot.l1, robot.l2, robot.l3]).toEqual([300, 200, 10]); }); test('Bezeichner ist case-insensitive', () => { expect(loadKinematicsClass('Arm3SegmentLinearX')).toBe(Arm3SegmentLinearX); expect(loadKinematicsClass(DEFAULT_KINEMATICS)).toBe(Arm3SegmentLinearX); }); test('Unbekannte Kinematik → klare Fehlermeldung (kein silent fail)', () => { expect(() => createRobotFromEnv({ ROBOT_KINEMATICS: 'doesNotExist' })) .toThrow(/Unbekannte Kinematik "doesNotExist"/); }); test('Ungültiges JSON in ROBOT_KINEMATICS_PARAMS → klare Fehlermeldung', () => { expect(() => parseParams('{bad json')) .toThrow(/ROBOT_KINEMATICS_PARAMS ist kein gültiges JSON/); }); test('parseParams: leer/undefined → leeres Objekt', () => { expect(parseParams()).toEqual({}); expect(parseParams('')).toEqual({}); }); }); describe('RobotBase ist abstrakt (Roadmap 12, Phase 0)', () => { test('calculateAngles3D() wirft, wenn nicht überschrieben', () => { expect(() => new RobotBase().calculateAngles3D()) .toThrow(/not implemented/); }); test('calculatePositionFromMotorAngles() wirft, wenn nicht überschrieben', () => { expect(() => new RobotBase().calculatePositionFromMotorAngles()) .toThrow(/not implemented/); }); test('Arm3SegmentLinearX überschreibt beide Kinematik-Methoden', () => { const robot = new Arm3SegmentLinearX(250, 264, 100); expect(() => robot.calculateAngles3D()).not.toThrow(); expect(() => robot.calculatePositionFromMotorAngles()).not.toThrow(); }); });