85 lines
3.5 KiB
TypeScript
85 lines
3.5 KiB
TypeScript
import { readFileSync } from "node:fs";
|
|
import { dirname, join } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
import { describe, expect, it } from "vitest";
|
|
import { runAbb120Suite } from "../../src/suites/abb120Suite.js";
|
|
import { parseGrl } from "../../src/grl/parser/index.js";
|
|
import { compileSemanticProgram } from "../../src/grl/semantic/index.js";
|
|
import { ABB_IRB120_ZERO_JOINTS } from "../fixtures/abbIrb120.js";
|
|
|
|
const WEB_ROOT = join(dirname(fileURLToPath(import.meta.url)), "../..");
|
|
const PROGRAM_DIR = join(WEB_ROOT, "tests", "fixtures", "abb120", "programs");
|
|
const APP_DIR = join(WEB_ROOT, "app");
|
|
const PROGRAM_NAMES = [
|
|
"A120_00_Smoke.grl",
|
|
"A120_10_JointPickPlace.grl",
|
|
"A120_20_CartesianBlend.grl",
|
|
"A120_30_IOWaitPulse.grl",
|
|
"A120_40_ErrorDiagnostics.grl",
|
|
"A120_50_OperationProcess.grl"
|
|
];
|
|
|
|
function loadPrograms() {
|
|
return PROGRAM_NAMES.map((name) => ({
|
|
name,
|
|
text: readFileSync(join(PROGRAM_DIR, name), "utf8")
|
|
}));
|
|
}
|
|
|
|
describe("ABB120 suite artifacts", () => {
|
|
it("ships six parseable GRL programs with source maps and KDL bridge requests", () => {
|
|
for (const program of loadPrograms()) {
|
|
const ast = parseGrl(program.text);
|
|
const ir = compileSemanticProgram(ast, {
|
|
startJoints: [...ABB_IRB120_ZERO_JOINTS],
|
|
sampleTime: 0.02
|
|
});
|
|
expect(ast.kind).toBe("Program");
|
|
expect(ir.moduleName).toMatch(/^A120/);
|
|
expect(ir.sourceMap.length + ir.kdlBridge.motionRequests.length + ir.kdlBridge.pathRequests.length).toBeGreaterThan(0);
|
|
}
|
|
});
|
|
|
|
it("creates job, post, roundtrip, report, delivery, and screenshot evidence paths", () => {
|
|
const job = runAbb120Suite(loadPrograms(), { now: "2026-06-27T12:00:00.000Z" });
|
|
|
|
expect(job.job_id).toBe("A120-JOB-20260627120000-doc");
|
|
expect(job.robot.robotId).toBe("abb_irb120_3_58");
|
|
expect(job.programs.map((program) => program.name)).toEqual(PROGRAM_NAMES);
|
|
expect(job.post.filenames).toEqual(expect.arrayContaining([
|
|
"A120Smoke.mod",
|
|
"A120Smoke.ls",
|
|
"A120Smoke.src"
|
|
]));
|
|
expect(job.roundtrip.status).toMatch(/pass|warn/);
|
|
expect(job.report_id).toBe("A120-REPORT-20260627120000");
|
|
expect(job.artifacts).toMatchObject({
|
|
jobJson: "A120-JOB-20260627120000-doc/job.json",
|
|
reportHtml: "A120-JOB-20260627120000-doc/reports/A120-REPORT-20260627120000.html",
|
|
deliveryPackageJson: "A120-JOB-20260627120000-doc/delivery/package.json",
|
|
desktopScreenshot: "A120-JOB-20260627120000-doc/screenshots/virtual-controller-desktop.png",
|
|
mobileScreenshot: "A120-JOB-20260627120000-doc/screenshots/virtual-controller-mobile.png"
|
|
});
|
|
});
|
|
|
|
it("has an HTML virtual controller entry with required panels", () => {
|
|
const html = readFileSync(join(APP_DIR, "virtual-controller.html"), "utf8");
|
|
const css = readFileSync(join(APP_DIR, "virtual-controller.css"), "utf8");
|
|
const js = readFileSync(join(APP_DIR, "virtual-controller.js"), "utf8");
|
|
|
|
expect(html).toContain("ABB120 Station");
|
|
expect(html).toContain("Path: pick_place");
|
|
expect(html).toContain("W2-JOB-latest");
|
|
expect(html).toContain("working2-abb120-spec");
|
|
expect(html).toContain("Controller");
|
|
expect(html).toContain("Motion Queue");
|
|
expect(html).toContain("Reports");
|
|
expect(html).toContain('src="./virtual-controller.js"');
|
|
expect(html).not.toContain('src="./virtual-controller.ts"');
|
|
expect(css).toContain(".viewport");
|
|
expect(css).toContain("@media");
|
|
expect(js).toContain("data-command");
|
|
expect(js).toContain("data-tab");
|
|
});
|
|
});
|