import { describe, expect, it } from "vitest"; import { postProcessAllBrands } from "../../src/grl/post/index.js"; import { parseGrl } from "../../src/grl/parser/index.js"; import { compileSemanticProgram } from "../../src/grl/semantic/index.js"; import { applyPatch, pathOperationToGrl, sampleOlpProject, validateOlpProject, type OlpProjectModel } from "../../src/olp/index.js"; describe("OLP project model", () => { it("creates a serializable station/resource/path/operation sample", () => { const project = sampleOlpProject(); const restored = JSON.parse(JSON.stringify(project)) as OlpProjectModel; const report = validateOlpProject(restored); expect(restored.schemaVersion).toBe("olp/0.1"); expect(report).toEqual({ ok: true, issues: [] }); expect(restored.resources.robots[0]).toMatchObject({ id: "robot_1", kind: "robot", brand: "abb" }); expect(restored.externalAxes[0]).toMatchObject({ id: "track_1", axisKind: "linear" }); expect(restored.motionGroups[0]).toMatchObject({ robotIds: ["robot_1"], externalAxisIds: ["track_1"], coordination: "synchronized" }); }); it("applies brand import style object patches and validates references", () => { const patched = applyPatch(sampleOlpProject(), [ { op: "add", path: "/targets/-", value: { id: "inspect", name: "inspect", kind: "pose", robotId: "robot_1", pose: [650, 25, 0, 0, 0, 0], toolId: "tool_gripper", frameId: "frame_fixture" } }, { op: "add", path: "/paths/0/points/-", value: { id: "p03", name: "p03", motion: "movel", targetId: "inspect", speedId: "v_linear", zoneId: "z10" } } ]); expect(validateOlpProject(patched).ok).toBe(true); expect(patched.paths[0]?.points.map((point) => point.name)).toEqual(["p00", "p01", "p02", "p03"]); }); it("generates stable parseable GRL from Path and Operation", () => { const result = pathOperationToGrl(sampleOlpProject(), "pick_op", { moduleName: "DemoCell", style: "expanded" }); const ast = parseGrl(result.text); const ir = compileSemanticProgram(ast, { startJoints: [0, 0, 0, 0, 0, 0], sampleTime: 0.004 }); const post = postProcessAllBrands(ir); expect(result.stableIds).toEqual({ targets: ["home", "pick", "place"], points: ["p00", "p01", "p02"], path: "pick_path", operation: "pick_op" }); expect(result.text).toContain("path pick_path"); expect(result.text).toContain("operation pick_op"); expect(result.program).toMatchObject({ id: "pick_op_grl", language: "grl", entryOperationIds: ["pick_op"] }); expect(ir.operations[0]).toMatchObject({ operationId: "pick_op", kind: "handling", pathId: "pick_path" }); expect(post.outputs.abb.text).toContain("MODULE DemoCell"); expect(post.outputs.fanuc.text).toContain("/PROG MAIN"); expect(post.outputs.kuka.text).toContain("DEF Main()"); }); it("reports broken schema references with stable issue codes", () => { const project = sampleOlpProject(); project.operations[0]!.pathId = "missing_path"; expect(validateOlpProject(project)).toMatchObject({ ok: false, issues: [expect.objectContaining({ code: "OLP_REF_PATH_MISSING" })] }); }); });