diff --git a/text12.txt b/text12.txt index 0595f93..bb4b3c2 100644 --- a/text12.txt +++ b/text12.txt @@ -2948,3 +2948,79 @@ host_wasm_opfs_browser_smokes=ok `readIniPanelShellSessionHandoffStatusFromControlPage()`),让外部 shell 在 mount workflow ready 后一次 读取 readonly status、校验 expected status fields,并返回 structured status result;仍保持只读,不新增 控制按钮,不解析 G-code。 + +三十七、2026-06-15 继续执行记录:INI panel shell handoff readonly status workflow helper + +本轮按“第一原则:加快实质性推进”继续推进 SDK/API surface 与 browser/UI workflow,为 shell +handoff 增加 readonly status 聚合 helper,让外部 shell 在 mount workflow ready 后一次读取 +control-page readonly status、校验 expected status fields,并返回 structured status result。 + +完成内容: + +- `ui-shell.js` 新增 `readIniPanelShellSessionHandoffStatusFromControlPage()`; +- 新 helper 支持传入 `readonlyStatus`,也支持从 `controlPageApi.readControlPageStatus()` 读取只读状态; +- 新 helper 返回 `apiName`、`resultVersion`、`phase`、`ready`、`statusLine`、`readStatusMethod`、 + `expectedStatusFields`、`presentStatusFields`、`missingStatusFields`、`readonlyStatus` 与 `readError`; +- control-page API 缺失时返回 structured blocked result,不把缺失方法伪装成 pass; +- control-page API 抛错时把错误写入 `readError`,不把异常直接抛给外部 shell; +- `createIniPanelShellViewModel()` 暴露 `readShellSessionHandoffStatusFromControlPage`; +- `createIniPanelLaunchApiManifest().methods` 新增 `readShellSessionHandoffStatusFromControlPage`, + launch method count 更新为 32; +- `launch.html` 的 `window.linuxCncIniPanelLaunchApi.readShellSessionHandoffStatusFromControlPage()` 暴露 + 真实 browser API,并默认复用 launch 侧 handoff summary 的 expected readonly status fields; +- `ini_panel_shell_integration_workflow_smoke.html` 在真实 browser workflow 中通过 shared status helper + 读取最终 readonly status,并校验 ready、missing fields 与 workflow last action; +- Node smoke 覆盖 readonly status 直传、control-page API 读取、缺失字段与缺失 API blocked 路径; +- 文档同步记录 readonly status workflow 用法; +- 未新增控制按钮; +- 未解析 G-code; +- 未解释 canonical events; +- 未新增 JS CNC 语义; +- 未改变 OPFS/session persistence、LinuxCNC interpreter、tool、parameter、planner 或 + LinuxCNC-owned runtime semantics。 + +验证已通过: + +```bash +git diff --check +wasm-port/tests/ui/node/verify_ini_panel_ui_shell.sh +wasm-port/tests/ui/node/verify_ini_panel_launch_api_manifest.sh +wasm-port/tests/ui/node/verify_ini_panel_shell_integration_manifest.sh +wasm-port/tests/ui/node/verify_ini_panel_entry_docs.sh +wasm-port/tests/ui/node/verify_ui_node_smokes.sh +SKIP_INI_BUILD=1 SKIP_INTERP_BUILD=1 wasm-port/tests/browser/verify_ini_panel_browser.sh +wasm-port/tools/verify_vendor_sync.sh +wasm-port/tools/verify_no_standalone_cnc_semantics.sh +SKIP_INTERP_BUILD=1 wasm-port/tests/wasm/node/verify_interp_wasm.sh +SKIP_INTERP_BUILD=1 wasm-port/tests/wasm/node/verify_sim_configs_inventory_wasm.sh +wasm-port/tests/host/verify_host_smokes.sh +``` + +关键输出: + +```text +ini_panel_ui_shell_node_smoke=ok +ini_panel_launch_api_manifest_node_smoke=ok +ini_panel_shell_integration_manifest_node_smoke=ok +ini_panel_entry_docs_node_smoke=ok +ui_node_smokes=ok +browser_ini_opfs_smoke=ok +browser_ini_control_page_smoke=ok +browser_ini_launch_smoke=ok +browser_ini_shell_integration_workflow_smoke=ok +vendor sync up to date +standalone CNC semantics guard complete +interp_wasm_node_smoke=ok +sim_configs_wasm_node_inventory_executed=28 +sim_configs_wasm_node_inventory_passed=28 +sim_configs_wasm_node_inventory_skipped=131 +sim_configs_wasm_node_inventory_unexpected_fail=0 +host_wasm_opfs_browser_smokes=ok +``` + +下一步建议: + +继续推进 SDK/API surface。下一批建议增加 shell handoff workflow result summary helper(例如 +`createIniPanelShellSessionHandoffWorkflowSummary()`),把 mount workflow、control-page mount workflow +和 readonly status result 合并成一个稳定 summary,方便外部 shell 一次展示 handoff end-to-end 状态; +仍保持只读,不新增控制按钮,不解析 G-code。 diff --git a/wasm-port/docs/panel-entry.md b/wasm-port/docs/panel-entry.md index 49e3a77..cadbec0 100644 --- a/wasm-port/docs/panel-entry.md +++ b/wasm-port/docs/panel-entry.md @@ -246,6 +246,10 @@ mount render-state, renderer result, and any mount error as data. Use outer shell has a control-page API or already-observed session-load state and needs one read-only result containing the derived mount-state, mount display view-model, mount render-state, and DOM mount workflow result. Use +`readIniPanelShellSessionHandoffStatusFromControlPage()` or +`linuxCncIniPanelLaunchApi.readShellSessionHandoffStatusFromControlPage()` +when an outer shell needs to read the control-page readonly status and verify +the expected handoff status fields as a structured ready/blocked result. Use `renderIniPanelShellSessionHandoffMountState()` or `linuxCncIniPanelLaunchApi.renderShellSessionHandoffMountState()` when an outer shell needs the shared read-only DOM renderer for those rows. The launch page @@ -257,7 +261,8 @@ The browser workflow smoke same external shell handoff: read integration manifest, pass readiness gate, open the control page target, mount waiting and ready mount-state into an external shell-owned `[data-external-shell-mount]` DOM region through the shared -mount workflows, then read readonly machine-session status. +mount workflows, then read and validate readonly machine-session status through +the shared status workflow. The control-page refresh workflow lives in `runtime/ui/ini-panel/control-page-refresh-workflow.js`. Use diff --git a/wasm-port/runtime/ui/ini-panel/launch.html b/wasm-port/runtime/ui/ini-panel/launch.html index 165562e..d97e409 100644 --- a/wasm-port/runtime/ui/ini-panel/launch.html +++ b/wasm-port/runtime/ui/ini-panel/launch.html @@ -110,6 +110,7 @@ createIniPanelShellSessionHandoffMountDomReadiness, mountIniPanelShellSessionHandoff, mountIniPanelShellSessionHandoffFromControlPage, + readIniPanelShellSessionHandoffStatusFromControlPage, renderIniPanelShellSessionHandoffMountState, } from "./ui-shell.js"; @@ -207,6 +208,12 @@ ...(options ?? {}), }) ), + readShellSessionHandoffStatusFromControlPage: (options) => ( + readIniPanelShellSessionHandoffStatusFromControlPage({ + handoffSummary: shellViewModel.shellSessionHandoffSummary, + ...(options ?? {}), + }) + ), isSupportedShellSessionHandoffPackage: shellViewModel.isSupportedShellSessionHandoffPackage, getLauncherLinks: () => shellViewModel.launcherLinks, getControlPageApiMethods: () => shellViewModel.controlPage.browserApiMethods, diff --git a/wasm-port/runtime/ui/ini-panel/ui-shell.js b/wasm-port/runtime/ui/ini-panel/ui-shell.js index 72f741d..cce8ffc 100644 --- a/wasm-port/runtime/ui/ini-panel/ui-shell.js +++ b/wasm-port/runtime/ui/ini-panel/ui-shell.js @@ -148,6 +148,7 @@ export function createIniPanelLaunchApiManifest(entries = getVisibleIniPanelEntr "renderShellSessionHandoffMountState", "mountShellSessionHandoff", "mountShellSessionHandoffFromControlPage", + "readShellSessionHandoffStatusFromControlPage", "isSupportedShellSessionHandoffPackage", "getLauncherLinks", "getControlPageApiMethods", @@ -1328,6 +1329,53 @@ export function mountIniPanelShellSessionHandoffFromControlPage({ }; } +export function readIniPanelShellSessionHandoffStatusFromControlPage({ + controlPageApi = null, + readonlyStatus = null, + readStatusMethod = "readControlPageStatus", + handoffSummary = createIniPanelShellSessionHandoffSummary(), + expectedStatusFields = handoffSummary?.readonlyStatusFields ?? [], +} = {}) { + let observedStatus = readonlyStatus; + let readError = null; + if (!observedStatus) { + const readStatus = controlPageApi?.[readStatusMethod]; + if (typeof readStatus === "function") { + try { + observedStatus = readStatus.call(controlPageApi); + } catch (error) { + readError = error?.message ?? String(error); + observedStatus = null; + } + } else { + readError = `Missing ${readStatusMethod}`; + observedStatus = null; + } + } + + const statusObject = observedStatus && typeof observedStatus === "object" ? observedStatus : {}; + const expectedFields = Array.isArray(expectedStatusFields) ? [...expectedStatusFields] : []; + const presentStatusFields = expectedFields.filter((fieldName) => Object.hasOwn(statusObject, fieldName)); + const missingStatusFields = expectedFields.filter((fieldName) => !Object.hasOwn(statusObject, fieldName)); + const ready = !readError && missingStatusFields.length === 0; + + return { + apiName: "ini-panel-shell-session-handoff-readonly-status-result", + resultVersion: 1, + phase: ready ? "ready" : "blocked", + ready, + statusLine: ready + ? "Ready: readonly status fields available" + : `Blocked: ${readError ?? missingStatusFields.join(", ")}`, + readStatusMethod, + expectedStatusFields: expectedFields, + presentStatusFields, + missingStatusFields, + readonlyStatus: observedStatus, + readError, + }; +} + export function createIniPanelShellViewModel(entries = getVisibleIniPanelEntries()) { const shellIntegrationManifest = createIniPanelShellIntegrationManifest(entries); const shellIntegrationReadiness = createIniPanelShellIntegrationReadiness(shellIntegrationManifest); @@ -1447,6 +1495,7 @@ export function createIniPanelShellViewModel(entries = getVisibleIniPanelEntries renderShellSessionHandoffMountState: renderIniPanelShellSessionHandoffMountState, mountShellSessionHandoff: mountIniPanelShellSessionHandoff, mountShellSessionHandoffFromControlPage: mountIniPanelShellSessionHandoffFromControlPage, + readShellSessionHandoffStatusFromControlPage: readIniPanelShellSessionHandoffStatusFromControlPage, isSupportedShellSessionHandoffPackage: isSupportedIniPanelShellSessionHandoffPackage, controlPage: { browserApiSchema: createControlPageBrowserApiSchema(), diff --git a/wasm-port/tests/browser/ini_panel_shell_integration_workflow_smoke.html b/wasm-port/tests/browser/ini_panel_shell_integration_workflow_smoke.html index 47c27b0..8f89e4a 100644 --- a/wasm-port/tests/browser/ini_panel_shell_integration_workflow_smoke.html +++ b/wasm-port/tests/browser/ini_panel_shell_integration_workflow_smoke.html @@ -90,6 +90,7 @@ TOOL_TABLE = browser-shell-tool.tbl !launchApi?.renderShellSessionHandoffMountState || !launchApi?.mountShellSessionHandoff || !launchApi?.mountShellSessionHandoffFromControlPage || + !launchApi?.readShellSessionHandoffStatusFromControlPage || !launchApi?.isSupportedShellSessionHandoffPackage ) { throw new Error("launch API namespace did not expose shell integration helpers"); @@ -353,11 +354,26 @@ TOOL_TABLE = browser-shell-tool.tbl ); const readonlyStatus = controlPageApi[handoffSummary.handoffMethods.readStatus](); + const readonlyStatusResult = launchApi.readShellSessionHandoffStatusFromControlPage({ + controlPageApi, + }); + assertEqual(readonlyStatusResult.phase, "ready", "shell handoff readonly status result phase"); + assertEqual(readonlyStatusResult.ready, true, "shell handoff readonly status result readiness"); + assertEqual( + readonlyStatusResult.missingStatusFields.join(","), + "", + "shell handoff readonly status missing fields", + ); assertEqual( readonlyStatus.workflowStatus.lastAction, "load-session", "shell integration readonly workflow last action", ); + assertEqual( + readonlyStatusResult.readonlyStatus.workflowStatus.lastAction, + readonlyStatus.workflowStatus.lastAction, + "shell handoff readonly status result workflow last action", + ); assertEqual( readonlyStatus.session.parameterFile, "browser-shell-linuxcnc.var", diff --git a/wasm-port/tests/ui/node/verify_ini_panel_entry_docs.mjs b/wasm-port/tests/ui/node/verify_ini_panel_entry_docs.mjs index 3b0c6f9..92ffa77 100644 --- a/wasm-port/tests/ui/node/verify_ini_panel_entry_docs.mjs +++ b/wasm-port/tests/ui/node/verify_ini_panel_entry_docs.mjs @@ -31,6 +31,7 @@ import { createIniPanelShellSessionHandoffMountDomReadiness, mountIniPanelShellSessionHandoff, mountIniPanelShellSessionHandoffFromControlPage, + readIniPanelShellSessionHandoffStatusFromControlPage, renderIniPanelShellSessionHandoffMountState, createIniPanelShellSessionHandoffPackageReport, createIniPanelShellSessionHandoffPackageRenderState, @@ -101,6 +102,7 @@ const requiredShellExports = [ "createIniPanelShellSessionHandoffMountDomReadiness", "mountIniPanelShellSessionHandoff", "mountIniPanelShellSessionHandoffFromControlPage", + "readIniPanelShellSessionHandoffStatusFromControlPage", "renderIniPanelShellSessionHandoffMountState", "createIniPanelShellSessionHandoffPackageReport", "createIniPanelShellSessionHandoffPackageRenderState", @@ -303,6 +305,10 @@ assert.equal( mountIniPanelShellSessionHandoffFromControlPage({ documentRef: null }).mountWorkflow.phase, "blocked", ); +assert.equal( + readIniPanelShellSessionHandoffStatusFromControlPage().phase, + "blocked", +); assert.equal(isSupportedIniPanelShellSessionHandoffPackage(createIniPanelShellViewModel().shellSessionHandoffPackage), true); assert.equal(isSupportedIniPanelShellIntegrationManifest(createIniPanelShellViewModel().shellIntegrationManifest), true); assert.deepEqual(createIniPanelShellViewModel().launchApiSchema, createIniPanelLaunchApiSchema()); @@ -464,6 +470,7 @@ assert.match(docText, /\blinuxCncIniPanelLaunchApi\.getShellSessionHandoffMountD assert.match(docText, /\blinuxCncIniPanelLaunchApi\.getShellSessionHandoffMountDomReadiness\b/); assert.match(docText, /\blinuxCncIniPanelLaunchApi\.mountShellSessionHandoff\b/); assert.match(docText, /\blinuxCncIniPanelLaunchApi\.mountShellSessionHandoffFromControlPage\b/); +assert.match(docText, /\blinuxCncIniPanelLaunchApi\.readShellSessionHandoffStatusFromControlPage\b/); assert.match(docText, /\blinuxCncIniPanelLaunchApi\.getControlPageApiMethods\b/); assert.match(docText, /\bini_panel_shell_integration_workflow_smoke\.html\b/); assert.match(browserIniPanelText, /\bini_panel_shell_integration_workflow_smoke\.html\b/); @@ -484,6 +491,7 @@ assert.match(shellIntegrationWorkflowSmokeText, /\bgetShellSessionHandoffMountDo assert.match(shellIntegrationWorkflowSmokeText, /\bgetShellSessionHandoffMountDomReadiness\b/); assert.match(shellIntegrationWorkflowSmokeText, /\bmountShellSessionHandoff\b/); assert.match(shellIntegrationWorkflowSmokeText, /\bmountShellSessionHandoffFromControlPage\b/); +assert.match(shellIntegrationWorkflowSmokeText, /\breadShellSessionHandoffStatusFromControlPage\b/); assert.match(shellIntegrationWorkflowSmokeText, /\brenderShellSessionHandoffMountState\b/); assert.match(shellIntegrationWorkflowSmokeText, /\bdata-external-shell-mount\b/); assert.match(shellIntegrationWorkflowSmokeText, /\bdata-external-mount-value\b/); diff --git a/wasm-port/tests/ui/node/verify_ini_panel_launch_api_manifest.mjs b/wasm-port/tests/ui/node/verify_ini_panel_launch_api_manifest.mjs index 728c438..a62c663 100644 --- a/wasm-port/tests/ui/node/verify_ini_panel_launch_api_manifest.mjs +++ b/wasm-port/tests/ui/node/verify_ini_panel_launch_api_manifest.mjs @@ -68,6 +68,7 @@ assert.deepEqual(manifest, { "renderShellSessionHandoffMountState", "mountShellSessionHandoff", "mountShellSessionHandoffFromControlPage", + "readShellSessionHandoffStatusFromControlPage", "isSupportedShellSessionHandoffPackage", "getLauncherLinks", "getControlPageApiMethods", @@ -191,6 +192,7 @@ assert.match(launchText, /\bgetShellSessionHandoffMountDomReadiness\b/); assert.match(launchText, /\brenderShellSessionHandoffMountState\b/); assert.match(launchText, /\bmountShellSessionHandoff\b/); assert.match(launchText, /\bmountShellSessionHandoffFromControlPage\b/); +assert.match(launchText, /\breadShellSessionHandoffStatusFromControlPage\b/); assert.match(launchText, /\bisSupportedShellSessionHandoffPackage\b/); assert.match(launchText, /\bdata-handoff-mount\b/); assert.match(launchText, /\bdata-handoff-mount-status\b/); diff --git a/wasm-port/tests/ui/node/verify_ini_panel_shell_integration_manifest.mjs b/wasm-port/tests/ui/node/verify_ini_panel_shell_integration_manifest.mjs index 99ac953..e4e5277 100644 --- a/wasm-port/tests/ui/node/verify_ini_panel_shell_integration_manifest.mjs +++ b/wasm-port/tests/ui/node/verify_ini_panel_shell_integration_manifest.mjs @@ -27,6 +27,7 @@ import { createIniPanelShellSessionHandoffMountDomReadiness, mountIniPanelShellSessionHandoff, mountIniPanelShellSessionHandoffFromControlPage, + readIniPanelShellSessionHandoffStatusFromControlPage, createIniPanelShellSessionHandoffPackageReport, createIniPanelShellSessionHandoffPackageRenderState, createIniPanelShellSessionHandoffPackageSchema, @@ -153,7 +154,7 @@ assert.deepEqual(readiness, { counts: { pages: 2, launcherLinks: 2, - launchMethods: 31, + launchMethods: 32, controlPageMethods: 11, persistenceCapabilities: 3, }, @@ -215,7 +216,7 @@ assert.deepEqual(handoffSummary, { counts: { pages: 2, launcherLinks: 2, - launchMethods: 31, + launchMethods: 32, controlPageMethods: 11, persistenceCapabilities: 3, }, @@ -711,6 +712,10 @@ assert.equal( mountIniPanelShellSessionHandoffFromControlPage({ documentRef: null }).sessionLoadState.phase, "waiting-api", ); +assert.equal( + readIniPanelShellSessionHandoffStatusFromControlPage().readError, + "Missing readControlPageStatus", +); assert.deepEqual( createIniPanelShellSessionHandoffPackageMountState({ handoffPackage, @@ -1122,7 +1127,7 @@ assert.deepEqual(createIniPanelShellIntegrationReadiness(blockedManifest), { counts: { pages: 2, launcherLinks: 2, - launchMethods: 31, + launchMethods: 32, controlPageMethods: 11, persistenceCapabilities: 3, }, @@ -1295,6 +1300,7 @@ assert.match(shellText, /\bexport function createIniPanelShellSessionHandoffMoun assert.match(shellText, /\bexport function createIniPanelShellSessionHandoffMountDomReadiness\b/); assert.match(shellText, /\bexport function mountIniPanelShellSessionHandoff\b/); assert.match(shellText, /\bexport function mountIniPanelShellSessionHandoffFromControlPage\b/); +assert.match(shellText, /\bexport function readIniPanelShellSessionHandoffStatusFromControlPage\b/); assert.match(shellText, /\bexport function createIniPanelShellSessionHandoffPackageReport\b/); assert.match(shellText, /\bexport function createIniPanelShellSessionHandoffPackageRenderState\b/); assert.match(shellText, /\bexport function createIniPanelShellSessionHandoffPackageSchema\b/); @@ -1324,6 +1330,7 @@ assert.match(docText, /\bcreateIniPanelShellSessionHandoffMountDomContract\b/); assert.match(docText, /\bcreateIniPanelShellSessionHandoffMountDomReadiness\b/); assert.match(docText, /\bmountIniPanelShellSessionHandoff\b/); assert.match(docText, /\bmountIniPanelShellSessionHandoffFromControlPage\b/); +assert.match(docText, /\breadIniPanelShellSessionHandoffStatusFromControlPage\b/); assert.match(docText, /\bcreateIniPanelShellSessionHandoffPackageReport\b/); assert.match(docText, /\bcreateIniPanelShellSessionHandoffPackageRenderState\b/); assert.match(docText, /\bcreateIniPanelShellSessionHandoffPackageSchema\b/); diff --git a/wasm-port/tests/ui/node/verify_ini_panel_ui_shell.mjs b/wasm-port/tests/ui/node/verify_ini_panel_ui_shell.mjs index 49664f1..58d3155 100644 --- a/wasm-port/tests/ui/node/verify_ini_panel_ui_shell.mjs +++ b/wasm-port/tests/ui/node/verify_ini_panel_ui_shell.mjs @@ -27,6 +27,7 @@ import { createIniPanelShellSessionHandoffMountDomReadiness, mountIniPanelShellSessionHandoff, mountIniPanelShellSessionHandoffFromControlPage, + readIniPanelShellSessionHandoffStatusFromControlPage, renderIniPanelShellSessionHandoffMountState, createIniPanelShellSessionHandoffPackageReport, createIniPanelShellSessionHandoffPackageRenderState, @@ -102,6 +103,7 @@ assert.equal(typeof createIniPanelShellSessionHandoffMountDomContract, "function assert.equal(typeof createIniPanelShellSessionHandoffMountDomReadiness, "function"); assert.equal(typeof mountIniPanelShellSessionHandoff, "function"); assert.equal(typeof mountIniPanelShellSessionHandoffFromControlPage, "function"); +assert.equal(typeof readIniPanelShellSessionHandoffStatusFromControlPage, "function"); assert.equal(typeof renderIniPanelShellSessionHandoffMountState, "function"); assert.equal(typeof createIniPanelShellSessionHandoffPackageReport, "function"); assert.equal(typeof createIniPanelShellSessionHandoffPackageRenderState, "function"); @@ -708,6 +710,10 @@ assert.equal( shellViewModel.mountShellSessionHandoffFromControlPage, mountIniPanelShellSessionHandoffFromControlPage, ); +assert.equal( + shellViewModel.readShellSessionHandoffStatusFromControlPage, + readIniPanelShellSessionHandoffStatusFromControlPage, +); assert.equal(shellViewModel.createShellSessionHandoffPackageReport, createIniPanelShellSessionHandoffPackageReport); assert.equal(shellViewModel.createShellSessionHandoffPackageSchema, createIniPanelShellSessionHandoffPackageSchema); assert.equal(shellViewModel.isSupportedShellSessionHandoffPackage, isSupportedIniPanelShellSessionHandoffPackage); @@ -883,6 +889,54 @@ const controlPageApiMountWorkflow = mountIniPanelShellSessionHandoffFromControlP }); assert.equal(controlPageApiMountWorkflow.phase, "blocked"); assert.equal(controlPageApiMountWorkflow.sessionLoadState.phase, "waiting-session"); +const readonlyStatusResult = readIniPanelShellSessionHandoffStatusFromControlPage({ + handoffSummary: shellViewModel.shellSessionHandoffSummary, + readonlyStatus: createMachineSessionReadonlyStatus({ + stateBundle: { overview: { phase: "loaded" } }, + workflowStatus: { lastAction: "load-session", run: { status: "not-run" } }, + controlView: { sections: [] }, + }), +}); +assert.equal(readonlyStatusResult.apiName, "ini-panel-shell-session-handoff-readonly-status-result"); +assert.equal(readonlyStatusResult.resultVersion, 1); +assert.equal(readonlyStatusResult.phase, "ready"); +assert.equal(readonlyStatusResult.ready, true); +assert.equal(readonlyStatusResult.readStatusMethod, "readControlPageStatus"); +assert.deepEqual(readonlyStatusResult.expectedStatusFields, shellViewModel.shellSessionHandoffSummary.readonlyStatusFields); +assert.deepEqual(readonlyStatusResult.missingStatusFields, []); +assert.equal(readonlyStatusResult.readonlyStatus.status.lastAction, "load-session"); +assert.equal(readonlyStatusResult.readError, null); +const controlPageApiStatusResult = readIniPanelShellSessionHandoffStatusFromControlPage({ + handoffSummary: shellViewModel.shellSessionHandoffSummary, + controlPageApi: { + readControlPageStatus: () => createMachineSessionReadonlyStatus({ + stateBundle: { overview: { phase: "api-read" } }, + }), + }, +}); +assert.equal(controlPageApiStatusResult.phase, "ready"); +assert.equal(controlPageApiStatusResult.readonlyStatus.overview.phase, "api-read"); +const missingStatusResult = readIniPanelShellSessionHandoffStatusFromControlPage({ + handoffSummary: shellViewModel.shellSessionHandoffSummary, + readonlyStatus: { status: {} }, +}); +assert.equal(missingStatusResult.phase, "blocked"); +assert.deepEqual(missingStatusResult.missingStatusFields, [ + "stateBundle", + "workflowStatus", + "overview", + "controlView", + "report", + "runReadiness", + "run", + "session", +]); +assert.equal( + readIniPanelShellSessionHandoffStatusFromControlPage({ + handoffSummary: shellViewModel.shellSessionHandoffSummary, + }).readError, + "Missing readControlPageStatus", +); assert.deepEqual( mountIniPanelShellSessionHandoff({ documentRef: mountDocument }).renderResult, null,