继续实现仿真测试程序
结论:真实浏览器仿真页面新增多测试程序选择和运行能力,覆盖直线、Z 轴轮廓、增量、圆弧和 G81 钻孔,并接入 Node、browser 与 release gate 验证。
This commit is contained in:
@@ -33,44 +33,95 @@
|
||||
throw new Error("real simulation page did not expose ready state");
|
||||
}
|
||||
|
||||
try {
|
||||
const frame = await loadFrame("../../runtime/ui/simulation/index.html");
|
||||
const doc = frame.contentDocument;
|
||||
const state = await waitForState(frame);
|
||||
function assertRenderedState(doc, state) {
|
||||
const polyline = doc.querySelector("[data-toolpath-polyline]");
|
||||
const rows = [...doc.querySelectorAll("[data-motion-row]")];
|
||||
const programRows = [...doc.querySelectorAll("[data-program-line]")];
|
||||
const canonicalOutput = doc.querySelector("[data-canonical-output]")?.textContent ?? "";
|
||||
|
||||
if (doc.body.dataset.simulationReady !== "true") {
|
||||
throw new Error("simulation body readiness flag not true");
|
||||
throw new Error(`simulation body readiness flag not true for ${state.program?.id}`);
|
||||
}
|
||||
if (state.apiName !== "real-browser-simulation-state") {
|
||||
throw new Error("simulation state API name drift");
|
||||
}
|
||||
if (state.summary.motionEventCount < 5) {
|
||||
throw new Error("simulation motion event count too low");
|
||||
if (state.summary.motionEventCount < 2) {
|
||||
throw new Error(`simulation motion event count too low for ${state.program?.id}`);
|
||||
}
|
||||
if (!canonicalOutput.includes("canon_event=")) {
|
||||
throw new Error(`simulation canonical output missing events for ${state.program?.id}`);
|
||||
}
|
||||
if (!polyline?.getAttribute("points")) {
|
||||
throw new Error(`simulation toolpath polyline missing points for ${state.program?.id}`);
|
||||
}
|
||||
if (rows.length !== state.motion.length) {
|
||||
throw new Error(`simulation motion table row count drift for ${state.program?.id}`);
|
||||
}
|
||||
if (programRows.length !== state.summary.programLineCount) {
|
||||
throw new Error(`simulation program row count drift for ${state.program?.id}`);
|
||||
}
|
||||
if (!doc.querySelector("[data-toolpath-svg]")?.getAttribute("viewBox")) {
|
||||
throw new Error(`simulation SVG viewBox missing for ${state.program?.id}`);
|
||||
}
|
||||
if (doc.body.dataset.simulationProgramId !== state.program?.id) {
|
||||
throw new Error(`simulation body program id drift for ${state.program?.id}`);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const frame = await loadFrame("../../runtime/ui/simulation/index.html");
|
||||
const doc = frame.contentDocument;
|
||||
const state = await waitForState(frame);
|
||||
const canonicalOutput = doc.querySelector("[data-canonical-output]")?.textContent ?? "";
|
||||
const api = frame.contentWindow?.linuxCncRealSimulationApi;
|
||||
|
||||
assertRenderedState(doc, state);
|
||||
if (!canonicalOutput.includes("canon_event=STRAIGHT_FEED line=2 x=1 y=0 z=0")) {
|
||||
throw new Error("simulation canonical output missing LinuxCNC feed event");
|
||||
}
|
||||
if (!polyline?.getAttribute("points")?.includes("1,0")) {
|
||||
if (!doc.querySelector("[data-toolpath-polyline]")?.getAttribute("points")?.includes("1,0")) {
|
||||
throw new Error("simulation toolpath polyline missing expected point");
|
||||
}
|
||||
if (rows.length !== state.motion.length) {
|
||||
throw new Error("simulation motion table row count drift");
|
||||
}
|
||||
if (programRows.length < 6) {
|
||||
throw new Error("simulation program rows missing");
|
||||
}
|
||||
if (doc.querySelector('[data-axis="x"]')?.textContent !== "0.000") {
|
||||
throw new Error("simulation final X axis drift");
|
||||
}
|
||||
if (doc.querySelector('[data-axis="y"]')?.textContent !== "0.000") {
|
||||
throw new Error("simulation final Y axis drift");
|
||||
}
|
||||
if (!doc.querySelector("[data-toolpath-svg]")?.getAttribute("viewBox")) {
|
||||
throw new Error("simulation SVG viewBox missing");
|
||||
|
||||
if (!api?.getPrograms || !api?.runProgramById) {
|
||||
throw new Error("simulation API missing program controls");
|
||||
}
|
||||
const programs = api.getPrograms();
|
||||
if (programs.length < 5) {
|
||||
throw new Error("simulation test program inventory too small");
|
||||
}
|
||||
|
||||
for (const program of programs) {
|
||||
const nextState = await api.runProgramById(program.id);
|
||||
assertRenderedState(doc, nextState);
|
||||
if (nextState.program.id !== program.id) {
|
||||
throw new Error(`simulation API returned wrong program id for ${program.id}`);
|
||||
}
|
||||
for (const motionType of program.expectedMotionTypes) {
|
||||
if (!nextState.summary.motionTypes.includes(motionType)) {
|
||||
throw new Error(`simulation program ${program.id} missing motion type ${motionType}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const arcState = await api.runProgramById("arc-g2-g3");
|
||||
const arcPoints = doc.querySelector("[data-toolpath-polyline]")?.getAttribute("points") ?? "";
|
||||
if (!arcState.summary.motionTypes.includes("ARC_FEED")) {
|
||||
throw new Error("arc simulation did not produce ARC_FEED");
|
||||
}
|
||||
if (!arcPoints.includes("1,-1") || !arcPoints.includes("0,0")) {
|
||||
throw new Error(`arc simulation toolpath points did not use canonical arc endpoints: ${arcPoints}`);
|
||||
}
|
||||
|
||||
const drillState = await api.runProgramById("drill-g81");
|
||||
if (drillState.motion.filter(({ type }) => type === "STRAIGHT_FEED").length < 3) {
|
||||
throw new Error("drill simulation did not produce expected feed plunges");
|
||||
}
|
||||
|
||||
status.textContent = "browser_real_simulation_page_smoke=ok";
|
||||
|
||||
Reference in New Issue
Block a user