推进 INI 面板 control page controller helper

This commit is contained in:
2026-06-14 23:08:19 +08:00
parent 2844fd25c3
commit 59ffacb64e
7 changed files with 272 additions and 45 deletions

View File

@@ -0,0 +1,105 @@
import assert from "node:assert/strict";
import {
createMachineSessionControlPageController,
} from "../../../runtime/ui/ini-panel/control-page-controller.js";
function createPanelFrame(panelApi = null) {
const listeners = new Map();
return {
contentWindow: panelApi ? { linuxCncIniPanelApi: panelApi } : null,
src: null,
addEventListener(type, listener) {
listeners.set(type, listener);
},
dispatch(type) {
listeners.get(type)?.();
},
};
}
const rendered = [];
const viewNode = { textContent: "" };
const statusNode = { textContent: "" };
const expectedView = {
status: {
lastAction: "run-gcode",
runStatus: "ok",
error: null,
},
sections: [
{
id: "run",
rows: [
{ label: "Canonical events", value: 2 },
],
},
],
};
let intervalCallback = null;
const panelFrame = createPanelFrame();
const controller = createMachineSessionControlPageController({
panelFrame,
statusNode,
viewNode,
pollMs: 250,
setIntervalFn: (callback, ms) => {
intervalCallback = callback;
return `timer:${ms}`;
},
renderControlView: (container, view) => {
rendered.push({ container, view });
return { statusNode: { textContent: "rendered" } };
},
});
assert.equal(controller.getPanelWindow(), null);
assert.equal(controller.getPanelApi(), null);
assert.equal(controller.getControlView(), null);
assert.equal(controller.render(), null);
assert.equal(statusNode.textContent, "waiting for panel");
assert.equal(viewNode.textContent, "");
assert.equal(controller.startPolling(), "timer:250");
assert.equal(controller.startPolling(), "timer:250");
assert.equal(typeof intervalCallback, "function");
const panelApi = {
getMachineSessionControlView: () => expectedView,
};
panelFrame.contentWindow = { linuxCncIniPanelApi: panelApi };
assert.equal(controller.getPanelApi(), panelApi);
assert.equal(controller.getControlView(), expectedView);
const renderResult = controller.render();
assert.deepEqual(renderResult, { statusNode: { textContent: "rendered" } });
assert.equal(statusNode.textContent, "run-gcode | ok | -");
assert.deepEqual(rendered, [{ container: viewNode, view: expectedView }]);
const mountedFrame = createPanelFrame(panelApi);
const mountedStatusNode = { textContent: "" };
const mountedViewNode = { textContent: "" };
let mountedIntervalMs = null;
const mountedController = createMachineSessionControlPageController({
panelFrame: mountedFrame,
statusNode: mountedStatusNode,
viewNode: mountedViewNode,
setIntervalFn: (_callback, ms) => {
mountedIntervalMs = ms;
return "mounted-timer";
},
renderControlView: () => "mounted-render",
});
assert.equal(mountedController.mount({ panelSrc: "./custom-panel.html" }), mountedController);
assert.equal(mountedFrame.src, "./custom-panel.html");
assert.equal(mountedIntervalMs, 200);
mountedFrame.dispatch("load");
assert.equal(mountedStatusNode.textContent, "run-gcode | ok | -");
assert.throws(
() => createMachineSessionControlPageController(),
/panel iframe/,
);
console.log("ini_panel_control_page_controller_node_smoke=ok");

View File

@@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "$0")/../../.." && pwd)"
node "$ROOT_DIR/tests/ui/node/verify_ini_panel_control_page_controller.mjs"

View File

@@ -9,5 +9,6 @@ ROOT_DIR="$(cd "$(dirname "$0")/../../.." && pwd)"
"$ROOT_DIR/tests/ui/node/verify_ini_panel_session_workflow.sh"
"$ROOT_DIR/tests/ui/node/verify_ini_panel_machine_file_summary.sh"
"$ROOT_DIR/tests/ui/node/verify_ini_panel_state_summary.sh"
"$ROOT_DIR/tests/ui/node/verify_ini_panel_control_page_controller.sh"
echo "ui_node_smokes=ok"