推进 text12 接续和 control-page session readiness workflow

This commit is contained in:
2026-06-15 04:57:21 +08:00
parent ed5d03ea1b
commit 98d236250f
13 changed files with 621 additions and 0 deletions

View File

@@ -64,6 +64,7 @@ TOOL_TABLE = browser-tool.tbl
if (
!controlPageApi?.getControlView ||
!controlPageApi?.getPanelApi ||
!controlPageApi?.loadControlPageSessionState ||
!controlPageApi?.refreshControlPage ||
!controlPageApi?.renderControlPage
) {
@@ -88,6 +89,11 @@ TOOL_TABLE = browser-tool.tbl
"rendered",
"control page refresh phase",
);
assertEqual(
controlPageApi.loadControlPageSessionState().phase,
"ready",
"control page session load phase",
);
panelDoc.getElementById("ini-editor").value = iniText;
panelDoc.getElementById("query").click();

View File

@@ -39,6 +39,17 @@ const expectedView = {
},
],
};
const expectedStateBundle = {
report: {
readiness: {
ini: "INI WASM: ready",
},
},
};
const expectedWorkflowStatus = {
lastAction: "run-gcode",
error: null,
};
let intervalCallback = null;
const panelFrame = createPanelFrame();
@@ -69,11 +80,23 @@ assert.equal(typeof intervalCallback, "function");
const panelApi = {
getMachineSessionControlView: () => expectedView,
getMachineSessionStateBundle: () => expectedStateBundle,
getMachineSessionWorkflowStatus: () => expectedWorkflowStatus,
};
panelFrame.contentWindow = { linuxCncIniPanelApi: panelApi };
assert.equal(controller.getPanelApi(), panelApi);
assert.equal(controller.getControlView(), expectedView);
assert.deepEqual(controller.loadSessionState(), {
phase: "ready",
panelReady: true,
apiReady: true,
controlViewReady: true,
stateBundle: expectedStateBundle,
workflowStatus: expectedWorkflowStatus,
controlView: expectedView,
error: null,
});
const renderResult = controller.render();
assert.deepEqual(renderResult, { statusNode: { textContent: "rendered" } });
assert.equal(statusNode.textContent, "run-gcode | ok | -");

View File

@@ -0,0 +1,121 @@
import assert from "node:assert/strict";
import {
createControlPageSessionLoadState,
loadMachineSessionForControlPageWorkflow,
} from "../../../runtime/ui/ini-panel/control-page-session-workflow.js";
const stateBundle = {
report: {
readiness: {
ini: "INI WASM: ready",
interp: "Interpreter WASM: ready",
opfs: "OPFS: ready",
},
},
};
const workflowStatus = {
lastAction: "load-session",
error: null,
};
const controlView = {
status: {
lastAction: "load-session",
runStatus: null,
error: null,
},
sections: [],
};
assert.deepEqual(createControlPageSessionLoadState({ phase: "waiting-panel" }), {
phase: "waiting-panel",
panelReady: false,
apiReady: false,
controlViewReady: false,
stateBundle: null,
workflowStatus: null,
controlView: null,
error: null,
});
assert.deepEqual(
loadMachineSessionForControlPageWorkflow({
getPanelWindow: () => null,
getPanelApi: () => null,
getControlView: () => null,
}),
createControlPageSessionLoadState({ phase: "waiting-panel" }),
);
assert.deepEqual(
loadMachineSessionForControlPageWorkflow({
getPanelWindow: () => ({}),
getPanelApi: () => null,
getControlView: () => null,
}),
createControlPageSessionLoadState({
phase: "waiting-api",
panelReady: true,
}),
);
const panelApiWithoutControlView = {
getMachineSessionStateBundle: () => stateBundle,
getMachineSessionWorkflowStatus: () => workflowStatus,
};
assert.deepEqual(
loadMachineSessionForControlPageWorkflow({
getPanelWindow: () => ({}),
getPanelApi: () => panelApiWithoutControlView,
getControlView: () => null,
}),
createControlPageSessionLoadState({
phase: "waiting-session",
panelReady: true,
apiReady: true,
stateBundle,
workflowStatus,
}),
);
const panelApi = {
...panelApiWithoutControlView,
getMachineSessionControlView: () => controlView,
};
assert.deepEqual(
loadMachineSessionForControlPageWorkflow({
getPanelWindow: () => ({}),
getPanelApi: () => panelApi,
getControlView: () => controlView,
}),
createControlPageSessionLoadState({
phase: "ready",
panelReady: true,
apiReady: true,
controlViewReady: true,
stateBundle,
workflowStatus,
controlView,
}),
);
assert.deepEqual(
loadMachineSessionForControlPageWorkflow({
getPanelWindow: () => {
throw new Error("cross-origin frame");
},
getPanelApi: () => null,
getControlView: () => null,
}),
createControlPageSessionLoadState({
phase: "error",
error: "cross-origin frame",
}),
);
assert.throws(
() => loadMachineSessionForControlPageWorkflow(),
/panel window getter/,
);
console.log("ini_panel_control_page_session_workflow_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_session_workflow.mjs"

View File

@@ -6,8 +6,10 @@ import { dirname, resolve } from "node:path";
import {
INI_PANEL_ENTRIES,
controlPageStatusText,
createControlPageSessionLoadState,
createIniPanelLauncherLinkViewModel,
createIniPanelShellViewModel,
loadMachineSessionForControlPageWorkflow,
refreshMachineSessionControlPage,
getVisibleIniPanelEntries,
} from "../../../runtime/ui/ini-panel/ui-shell.js";
@@ -20,15 +22,21 @@ const refreshWorkflowText = readFileSync(
resolve(root, "runtime/ui/ini-panel/control-page-refresh-workflow.js"),
"utf8",
);
const sessionWorkflowText = readFileSync(
resolve(root, "runtime/ui/ini-panel/control-page-session-workflow.js"),
"utf8",
);
const requiredShellExports = [
"INI_PANEL_ENTRIES",
"controlPageStatusText",
"createControlPageSessionLoadState",
"createIniPanelLauncherLinkViewModel",
"createIniPanelShellViewModel",
"getIniPanelEntryByHref",
"getVisibleIniPanelEntries",
"createMachineSessionControlPageController",
"loadMachineSessionForControlPageWorkflow",
"refreshMachineSessionControlPage",
"renderMachineSessionControlView",
];
@@ -47,6 +55,14 @@ for (const exportName of [
assert.match(docText, new RegExp(`\\b${exportName}\\b`));
}
for (const exportName of [
"createControlPageSessionLoadState",
"loadMachineSessionForControlPageWorkflow",
]) {
assert.match(sessionWorkflowText, new RegExp(`\\bexport function ${exportName}\\b`));
assert.match(docText, new RegExp(`\\b${exportName}\\b`));
}
const requiredPages = [
["Launch", "runtime/ui/ini-panel/launch.html"],
["Edit and run", "runtime/ui/ini-panel/index.html"],
@@ -69,7 +85,18 @@ assert.deepEqual(
assert.deepEqual(createIniPanelShellViewModel().pages, getVisibleIniPanelEntries());
assert.deepEqual(createIniPanelShellViewModel().launcherLinks, createIniPanelLauncherLinkViewModel());
assert.equal(controlPageStatusText({ lastAction: "run-gcode", runStatus: "ok", error: null }), "run-gcode | ok | -");
assert.deepEqual(createControlPageSessionLoadState({ phase: "waiting-panel" }), {
phase: "waiting-panel",
panelReady: false,
apiReady: false,
controlViewReady: false,
stateBundle: null,
workflowStatus: null,
controlView: null,
error: null,
});
assert.equal(typeof createIniPanelShellViewModel().controlPage.createController, "function");
assert.equal(createIniPanelShellViewModel().controlPage.loadSessionState, loadMachineSessionForControlPageWorkflow);
assert.equal(createIniPanelShellViewModel().controlPage.refresh, refreshMachineSessionControlPage);
assert.equal(typeof createIniPanelShellViewModel().controlPage.renderView, "function");

View File

@@ -6,10 +6,12 @@ import {
createIniPanelLauncherLinkViewModel,
createIniPanelShellViewModel,
createControlPageRefreshState,
createControlPageSessionLoadState,
createMachineSessionControlPageController,
getIniPanelEntryByHref,
getIniPanelEntryManifest,
getVisibleIniPanelEntries,
loadMachineSessionForControlPageWorkflow,
refreshMachineSessionControlPage,
renderMachineSessionControlView,
} from "../../../runtime/ui/ini-panel/ui-shell.js";
@@ -24,8 +26,19 @@ assert.deepEqual(createControlPageRefreshState({ phase: "waiting", statusText: "
renderResult: null,
error: null,
});
assert.deepEqual(createControlPageSessionLoadState({ phase: "waiting-panel" }), {
phase: "waiting-panel",
panelReady: false,
apiReady: false,
controlViewReady: false,
stateBundle: null,
workflowStatus: null,
controlView: null,
error: null,
});
assert.equal(getIniPanelEntryByHref("./index.html")?.id, "edit-run");
assert.equal(typeof createMachineSessionControlPageController, "function");
assert.equal(typeof loadMachineSessionForControlPageWorkflow, "function");
assert.equal(typeof refreshMachineSessionControlPage, "function");
assert.equal(typeof renderMachineSessionControlView, "function");
@@ -65,6 +78,7 @@ assert.deepEqual(shellViewModel.pages, [
]);
assert.deepEqual(shellViewModel.launcherLinks, createIniPanelLauncherLinkViewModel());
assert.equal(shellViewModel.controlPage.createController, createMachineSessionControlPageController);
assert.equal(shellViewModel.controlPage.loadSessionState, loadMachineSessionForControlPageWorkflow);
assert.equal(shellViewModel.controlPage.refresh, refreshMachineSessionControlPage);
assert.equal(shellViewModel.controlPage.renderView, renderMachineSessionControlView);
shellViewModel.pages[0].title = "changed";
@@ -102,6 +116,7 @@ const controller = createMachineSessionControlPageController({
assert.deepEqual(controller.render(), { rendered: true });
assert.equal(statusNode.textContent, "run-gcode | ok | -");
assert.equal(renderedView.status.runStatus, "ok");
assert.equal(controller.loadSessionState().phase, "ready");
assert.equal(controller.refresh().phase, "rendered");
console.log("ini_panel_ui_shell_node_smoke=ok");

View File

@@ -11,6 +11,7 @@ ROOT_DIR="$(cd "$(dirname "$0")/../../.." && pwd)"
"$ROOT_DIR/tests/ui/node/verify_ini_panel_state_summary.sh"
"$ROOT_DIR/tests/ui/node/verify_ini_panel_control_page_controller.sh"
"$ROOT_DIR/tests/ui/node/verify_ini_panel_control_page_refresh_workflow.sh"
"$ROOT_DIR/tests/ui/node/verify_ini_panel_control_page_session_workflow.sh"
"$ROOT_DIR/tests/ui/node/verify_ini_panel_entry_manifest.sh"
"$ROOT_DIR/tests/ui/node/verify_ini_panel_ui_shell.sh"
"$ROOT_DIR/tests/ui/node/verify_ini_panel_entry_docs.sh"