推进 INI 面板 shell integration workflow plan

This commit is contained in:
2026-06-15 07:59:51 +08:00
parent a663c8dbca
commit ee665c47be
6 changed files with 244 additions and 1 deletions

View File

@@ -1840,3 +1840,89 @@ host_wasm_opfs_browser_smokes=ok
helper例如 `createIniPanelShellIntegrationWorkflowPlan()`),让外部 shell 在不开 browser 的情况下 helper例如 `createIniPanelShellIntegrationWorkflowPlan()`),让外部 shell 在不开 browser 的情况下
获得 target page、readiness、required methods 与 readonly status handoff plan仍保持只读不新增 获得 target page、readiness、required methods 与 readonly status handoff plan仍保持只读不新增
控制按钮,不解析 G-code。 控制按钮,不解析 G-code。
二十三、2026-06-15 继续执行记录INI panel shell integration workflow plan helper
本轮按“第一原则:加快实质性推进”继续推进 SDK/API surface把 shell integration browser workflow
的只读 handoff 抽成 Node 可测 helper让外部 shell 在不开 browser 的情况下获得 control-page target、
readiness、required methods 与 readonly status handoff plan。
完成内容:
- `wasm-port/runtime/ui/ini-panel/ui-shell.js` 新增
`createIniPanelShellIntegrationWorkflowPlan()`
- workflow plan 从 integration manifest 与 readiness 派生:
- `phase: "ready" | "blocked"`
- `ready`
- `controlEntryId`
- `targetPage`
- `readiness`
- `requiredLaunchApiMethods`
- `requiredControlPageApiMethods`
- `missingLaunchApiMethods`
- `missingControlPageApiMethods`
- `missing`
- `readonlyStatusHandoff.loadSessionStateMethod`
- `readonlyStatusHandoff.readStatusMethod`
- `readonlyStatusHandoff.expectedStatusFields`
- `createIniPanelShellViewModel()` 新增:
- `shellIntegrationWorkflowPlan`
- `createShellIntegrationWorkflowPlan`
- `verify_ini_panel_shell_integration_manifest.mjs` 覆盖:
- ready workflow plan 完整 shape
- blocked readiness 传递到 plan missing
- control target 缺失;
- control-page required method 缺失;
- readonly status handoff fields
- `verify_ini_panel_ui_shell.mjs` 覆盖 shell view-model 的 workflow plan
- `verify_ini_panel_entry_docs.mjs` 与 `docs/panel-entry.md` 记录并校验 workflow plan helper
- 未新增控制按钮;
- 未解析 G-code
- 未解释 canonical events
- 未访问 OPFS 或启动 browser/frame
- 未改变 OPFS/session persistence、LinuxCNC interpreter、tool、parameter、planner 或
LinuxCNC-owned runtime semantics。
验证已通过:
```bash
git diff --check
wasm-port/tests/ui/node/verify_ini_panel_shell_integration_manifest.sh
wasm-port/tests/ui/node/verify_ini_panel_ui_shell.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_shell_integration_manifest_node_smoke=ok
ini_panel_ui_shell_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
```
下一步建议:
继续推进 OPFS/session persistence。下一批建议把 workflow plan 扩展为包含 session handoff summary
helper例如 `createIniPanelShellSessionHandoffSummary()`),把 readiness、target page、readonly
status fields 与 persistence capabilities 压成外部 shell 可直接显示的一页摘要;仍保持只读,不新增
控制按钮,不解析 G-code。

View File

@@ -20,6 +20,7 @@ import {
createIniPanelShellIntegrationManifest, createIniPanelShellIntegrationManifest,
createIniPanelShellIntegrationReadiness, createIniPanelShellIntegrationReadiness,
createIniPanelShellIntegrationSchema, createIniPanelShellIntegrationSchema,
createIniPanelShellIntegrationWorkflowPlan,
createIniPanelShellViewModel, createIniPanelShellViewModel,
getIniPanelEntryByHref, getIniPanelEntryByHref,
getVisibleIniPanelEntries, getVisibleIniPanelEntries,
@@ -124,6 +125,10 @@ Use `createIniPanelShellIntegrationReadiness()` or
needs a read-only `ready`/`blocked` status, failed check names, API names, and needs a read-only `ready`/`blocked` status, failed check names, API names, and
counts for pages, methods, and persistence capabilities before mounting any counts for pages, methods, and persistence capabilities before mounting any
embedded control page. embedded control page.
Use `createIniPanelShellIntegrationWorkflowPlan()` when the outer shell needs a
Node-testable read-only plan for the control-page target, required launch and
control-page API methods, readiness gate, and readonly status handoff fields
before opening a browser frame.
The browser workflow smoke The browser workflow smoke
`tests/browser/ini_panel_shell_integration_workflow_smoke.html` verifies the `tests/browser/ini_panel_shell_integration_workflow_smoke.html` verifies the
same external shell handoff: read integration manifest, pass readiness gate, same external shell handoff: read integration manifest, pass readiness gate,

View File

@@ -324,8 +324,65 @@ export function createIniPanelShellIntegrationReadiness(
}; };
} }
export function createIniPanelShellIntegrationWorkflowPlan({
manifest = createIniPanelShellIntegrationManifest(),
readiness = createIniPanelShellIntegrationReadiness(manifest),
controlEntryId = "control-view",
} = {}) {
const targetPage = manifest?.launchApiManifest?.targetPages?.find(
(page) => page.entryId === controlEntryId,
) ?? null;
const requiredLaunchApiMethods = [
"getShellIntegrationManifest",
"getShellIntegrationReadiness",
];
const requiredControlPageApiMethods = [
"getControlPageApiManifest",
"loadControlPageSessionState",
"readControlPageStatus",
];
const launchMethods = Array.isArray(manifest?.launchApiManifest?.methods)
? manifest.launchApiManifest.methods
: [];
const controlPageMethods = Array.isArray(manifest?.controlPageApiManifest?.methods)
? manifest.controlPageApiManifest.methods
: [];
const missingLaunchApiMethods = requiredLaunchApiMethods.filter(
(methodName) => !launchMethods.includes(methodName),
);
const missingControlPageApiMethods = requiredControlPageApiMethods.filter(
(methodName) => !controlPageMethods.includes(methodName),
);
const missing = [
...readiness.missing,
...(targetPage ? [] : ["controlTargetPage"]),
...missingLaunchApiMethods.map((methodName) => `launchApi.${methodName}`),
...missingControlPageApiMethods.map((methodName) => `controlPageApi.${methodName}`),
];
const ready = readiness.ready && missing.length === 0;
return {
phase: ready ? "ready" : "blocked",
ready,
controlEntryId,
targetPage,
readiness,
requiredLaunchApiMethods,
requiredControlPageApiMethods,
missingLaunchApiMethods,
missingControlPageApiMethods,
missing,
readonlyStatusHandoff: {
loadSessionStateMethod: "loadControlPageSessionState",
readStatusMethod: "readControlPageStatus",
expectedStatusFields: manifest?.controlPageApiManifest?.readonlyStatusApiManifest?.statusFields ?? [],
},
};
}
export function createIniPanelShellViewModel(entries = getVisibleIniPanelEntries()) { export function createIniPanelShellViewModel(entries = getVisibleIniPanelEntries()) {
const shellIntegrationManifest = createIniPanelShellIntegrationManifest(entries); const shellIntegrationManifest = createIniPanelShellIntegrationManifest(entries);
const shellIntegrationReadiness = createIniPanelShellIntegrationReadiness(shellIntegrationManifest);
return { return {
pages: entries.map(({ id, href, title }) => ({ pages: entries.map(({ id, href, title }) => ({
id, id,
@@ -335,11 +392,16 @@ export function createIniPanelShellViewModel(entries = getVisibleIniPanelEntries
launcherLinks: createIniPanelLauncherLinkViewModel(entries), launcherLinks: createIniPanelLauncherLinkViewModel(entries),
shellIntegrationSchema: createIniPanelShellIntegrationSchema(), shellIntegrationSchema: createIniPanelShellIntegrationSchema(),
shellIntegrationManifest, shellIntegrationManifest,
shellIntegrationReadiness: createIniPanelShellIntegrationReadiness(shellIntegrationManifest), shellIntegrationReadiness,
shellIntegrationWorkflowPlan: createIniPanelShellIntegrationWorkflowPlan({
manifest: shellIntegrationManifest,
readiness: shellIntegrationReadiness,
}),
launchApiSchema: createIniPanelLaunchApiSchema(), launchApiSchema: createIniPanelLaunchApiSchema(),
launchApiManifest: createIniPanelLaunchApiManifest(entries), launchApiManifest: createIniPanelLaunchApiManifest(entries),
isSupportedShellIntegrationManifest: isSupportedIniPanelShellIntegrationManifest, isSupportedShellIntegrationManifest: isSupportedIniPanelShellIntegrationManifest,
createShellIntegrationReadiness: createIniPanelShellIntegrationReadiness, createShellIntegrationReadiness: createIniPanelShellIntegrationReadiness,
createShellIntegrationWorkflowPlan: createIniPanelShellIntegrationWorkflowPlan,
controlPage: { controlPage: {
browserApiSchema: createControlPageBrowserApiSchema(), browserApiSchema: createControlPageBrowserApiSchema(),
browserApiManifest: createControlPageBrowserApiManifest(), browserApiManifest: createControlPageBrowserApiManifest(),

View File

@@ -17,6 +17,7 @@ import {
createIniPanelShellIntegrationManifest, createIniPanelShellIntegrationManifest,
createIniPanelShellIntegrationReadiness, createIniPanelShellIntegrationReadiness,
createIniPanelShellIntegrationSchema, createIniPanelShellIntegrationSchema,
createIniPanelShellIntegrationWorkflowPlan,
createIniPanelShellViewModel, createIniPanelShellViewModel,
createMachineSessionReadonlyStatus, createMachineSessionReadonlyStatus,
createMachineSessionReadonlyStatusApiManifest, createMachineSessionReadonlyStatusApiManifest,
@@ -63,6 +64,7 @@ const requiredShellExports = [
"createIniPanelShellIntegrationManifest", "createIniPanelShellIntegrationManifest",
"createIniPanelShellIntegrationReadiness", "createIniPanelShellIntegrationReadiness",
"createIniPanelShellIntegrationSchema", "createIniPanelShellIntegrationSchema",
"createIniPanelShellIntegrationWorkflowPlan",
"createIniPanelShellViewModel", "createIniPanelShellViewModel",
"getIniPanelEntryByHref", "getIniPanelEntryByHref",
"getVisibleIniPanelEntries", "getVisibleIniPanelEntries",
@@ -133,6 +135,13 @@ assert.deepEqual(
createIniPanelShellViewModel().shellIntegrationReadiness, createIniPanelShellViewModel().shellIntegrationReadiness,
createIniPanelShellIntegrationReadiness(createIniPanelShellViewModel().shellIntegrationManifest), createIniPanelShellIntegrationReadiness(createIniPanelShellViewModel().shellIntegrationManifest),
); );
assert.deepEqual(
createIniPanelShellViewModel().shellIntegrationWorkflowPlan,
createIniPanelShellIntegrationWorkflowPlan({
manifest: createIniPanelShellViewModel().shellIntegrationManifest,
readiness: createIniPanelShellViewModel().shellIntegrationReadiness,
}),
);
assert.equal(isSupportedIniPanelShellIntegrationManifest(createIniPanelShellViewModel().shellIntegrationManifest), true); assert.equal(isSupportedIniPanelShellIntegrationManifest(createIniPanelShellViewModel().shellIntegrationManifest), true);
assert.deepEqual(createIniPanelShellViewModel().launchApiSchema, createIniPanelLaunchApiSchema()); assert.deepEqual(createIniPanelShellViewModel().launchApiSchema, createIniPanelLaunchApiSchema());
assert.deepEqual(createIniPanelShellViewModel().launchApiManifest, createIniPanelLaunchApiManifest()); assert.deepEqual(createIniPanelShellViewModel().launchApiManifest, createIniPanelLaunchApiManifest());
@@ -186,6 +195,7 @@ assert.match(shellText, /\bexport function createIniPanelLaunchApiManifest\b/);
assert.match(shellText, /\bexport function createIniPanelShellIntegrationSchema\b/); assert.match(shellText, /\bexport function createIniPanelShellIntegrationSchema\b/);
assert.match(shellText, /\bexport function createIniPanelShellIntegrationManifest\b/); assert.match(shellText, /\bexport function createIniPanelShellIntegrationManifest\b/);
assert.match(shellText, /\bexport function createIniPanelShellIntegrationReadiness\b/); assert.match(shellText, /\bexport function createIniPanelShellIntegrationReadiness\b/);
assert.match(shellText, /\bexport function createIniPanelShellIntegrationWorkflowPlan\b/);
assert.match(shellText, /\bexport function isSupportedIniPanelControlPageApiManifest\b/); assert.match(shellText, /\bexport function isSupportedIniPanelControlPageApiManifest\b/);
assert.match(shellText, /\bexport function isSupportedIniPanelLaunchApiManifest\b/); assert.match(shellText, /\bexport function isSupportedIniPanelLaunchApiManifest\b/);
assert.match(shellText, /\bexport function isSupportedIniPanelShellIntegrationManifest\b/); assert.match(shellText, /\bexport function isSupportedIniPanelShellIntegrationManifest\b/);
@@ -217,6 +227,7 @@ assert.match(docText, /\bcreateIniPanelLaunchApiSchema\b/);
assert.match(docText, /\bcreateIniPanelShellIntegrationManifest\b/); assert.match(docText, /\bcreateIniPanelShellIntegrationManifest\b/);
assert.match(docText, /\bcreateIniPanelShellIntegrationReadiness\b/); assert.match(docText, /\bcreateIniPanelShellIntegrationReadiness\b/);
assert.match(docText, /\bcreateIniPanelShellIntegrationSchema\b/); assert.match(docText, /\bcreateIniPanelShellIntegrationSchema\b/);
assert.match(docText, /\bcreateIniPanelShellIntegrationWorkflowPlan\b/);
assert.match(docText, /\bisSupportedIniPanelControlPageApiManifest\b/); assert.match(docText, /\bisSupportedIniPanelControlPageApiManifest\b/);
assert.match(docText, /\bisSupportedIniPanelLaunchApiManifest\b/); assert.match(docText, /\bisSupportedIniPanelLaunchApiManifest\b/);
assert.match(docText, /\bisSupportedIniPanelShellIntegrationManifest\b/); assert.match(docText, /\bisSupportedIniPanelShellIntegrationManifest\b/);

View File

@@ -13,6 +13,7 @@ import {
createIniPanelShellIntegrationManifest, createIniPanelShellIntegrationManifest,
createIniPanelShellIntegrationReadiness, createIniPanelShellIntegrationReadiness,
createIniPanelShellIntegrationSchema, createIniPanelShellIntegrationSchema,
createIniPanelShellIntegrationWorkflowPlan,
getVisibleIniPanelEntries, getVisibleIniPanelEntries,
isSupportedIniPanelShellIntegrationManifest, isSupportedIniPanelShellIntegrationManifest,
} from "../../../runtime/ui/ini-panel/ui-shell.js"; } from "../../../runtime/ui/ini-panel/ui-shell.js";
@@ -26,6 +27,7 @@ const docText = readFileSync(resolve(root, "docs/panel-entry.md"), "utf8");
const schema = createIniPanelShellIntegrationSchema(); const schema = createIniPanelShellIntegrationSchema();
const manifest = createIniPanelShellIntegrationManifest(); const manifest = createIniPanelShellIntegrationManifest();
const readiness = createIniPanelShellIntegrationReadiness(manifest); const readiness = createIniPanelShellIntegrationReadiness(manifest);
const workflowPlan = createIniPanelShellIntegrationWorkflowPlan({ manifest, readiness });
assert.deepEqual(schema, { assert.deepEqual(schema, {
apiName: "ini-panel-shell-integration", apiName: "ini-panel-shell-integration",
@@ -91,6 +93,43 @@ assert.deepEqual(readiness, {
controlPage: "ini-panel-control-page", controlPage: "ini-panel-control-page",
}, },
}); });
assert.deepEqual(workflowPlan, {
phase: "ready",
ready: true,
controlEntryId: "control-view",
targetPage: {
entryId: "control-view",
href: "./control-page.html",
},
readiness,
requiredLaunchApiMethods: [
"getShellIntegrationManifest",
"getShellIntegrationReadiness",
],
requiredControlPageApiMethods: [
"getControlPageApiManifest",
"loadControlPageSessionState",
"readControlPageStatus",
],
missingLaunchApiMethods: [],
missingControlPageApiMethods: [],
missing: [],
readonlyStatusHandoff: {
loadSessionStateMethod: "loadControlPageSessionState",
readStatusMethod: "readControlPageStatus",
expectedStatusFields: [
"stateBundle",
"workflowStatus",
"overview",
"controlView",
"report",
"runReadiness",
"run",
"session",
"status",
],
},
});
const blockedManifest = { const blockedManifest = {
...createIniPanelShellIntegrationManifest(), ...createIniPanelShellIntegrationManifest(),
compatibility: { compatibility: {
@@ -122,6 +161,34 @@ assert.deepEqual(createIniPanelShellIntegrationReadiness(blockedManifest), {
controlPage: "ini-panel-control-page", controlPage: "ini-panel-control-page",
}, },
}); });
assert.deepEqual(
createIniPanelShellIntegrationWorkflowPlan({
manifest: blockedManifest,
readiness: createIniPanelShellIntegrationReadiness(blockedManifest),
}).missing,
["launchCompatibility"],
);
const missingTargetPlan = createIniPanelShellIntegrationWorkflowPlan({
manifest,
controlEntryId: "missing-entry",
});
assert.equal(missingTargetPlan.ready, false);
assert.deepEqual(missingTargetPlan.missing, ["controlTargetPage"]);
assert.equal(missingTargetPlan.targetPage, null);
const missingControlMethodManifest = {
...createIniPanelShellIntegrationManifest(),
controlPageApiManifest: {
...createControlPageBrowserApiManifest(),
methods: ["getControlPageApiManifest", "readControlPageStatus"],
},
};
const missingControlMethodPlan = createIniPanelShellIntegrationWorkflowPlan({
manifest: missingControlMethodManifest,
});
assert.equal(missingControlMethodPlan.ready, false);
assert.deepEqual(missingControlMethodPlan.missing, [
"controlPageApi.loadControlPageSessionState",
]);
const malformedReadiness = createIniPanelShellIntegrationReadiness({ const malformedReadiness = createIniPanelShellIntegrationReadiness({
apiName: "other", apiName: "other",
}); });
@@ -194,12 +261,14 @@ assert.deepEqual(customManifest.launchApiManifest.targetPages, [
assert.match(shellText, /\bexport function createIniPanelShellIntegrationSchema\b/); assert.match(shellText, /\bexport function createIniPanelShellIntegrationSchema\b/);
assert.match(shellText, /\bexport function createIniPanelShellIntegrationManifest\b/); assert.match(shellText, /\bexport function createIniPanelShellIntegrationManifest\b/);
assert.match(shellText, /\bexport function createIniPanelShellIntegrationReadiness\b/); assert.match(shellText, /\bexport function createIniPanelShellIntegrationReadiness\b/);
assert.match(shellText, /\bexport function createIniPanelShellIntegrationWorkflowPlan\b/);
assert.match(shellText, /\bexport function isSupportedIniPanelShellIntegrationManifest\b/); assert.match(shellText, /\bexport function isSupportedIniPanelShellIntegrationManifest\b/);
assert.match(launchText, /\bgetShellIntegrationSchema\b/); assert.match(launchText, /\bgetShellIntegrationSchema\b/);
assert.match(launchText, /\bgetShellIntegrationManifest\b/); assert.match(launchText, /\bgetShellIntegrationManifest\b/);
assert.match(launchText, /\bgetShellIntegrationReadiness\b/); assert.match(launchText, /\bgetShellIntegrationReadiness\b/);
assert.match(docText, /\bcreateIniPanelShellIntegrationManifest\b/); assert.match(docText, /\bcreateIniPanelShellIntegrationManifest\b/);
assert.match(docText, /\bcreateIniPanelShellIntegrationReadiness\b/); assert.match(docText, /\bcreateIniPanelShellIntegrationReadiness\b/);
assert.match(docText, /\bcreateIniPanelShellIntegrationWorkflowPlan\b/);
assert.match(docText, /\bisSupportedIniPanelShellIntegrationManifest\b/); assert.match(docText, /\bisSupportedIniPanelShellIntegrationManifest\b/);
assert.doesNotMatch(shellText, /\bparseGcode\b|\bcanonicalEvents\b|\btoolTable\b|\bplanner\b/); assert.doesNotMatch(shellText, /\bparseGcode\b|\bcanonicalEvents\b|\btoolTable\b|\bplanner\b/);

View File

@@ -13,6 +13,7 @@ import {
createIniPanelShellIntegrationManifest, createIniPanelShellIntegrationManifest,
createIniPanelShellIntegrationReadiness, createIniPanelShellIntegrationReadiness,
createIniPanelShellIntegrationSchema, createIniPanelShellIntegrationSchema,
createIniPanelShellIntegrationWorkflowPlan,
createIniPanelShellViewModel, createIniPanelShellViewModel,
createMachineSessionReadonlyStatus, createMachineSessionReadonlyStatus,
createMachineSessionReadonlyStatusApiManifest, createMachineSessionReadonlyStatusApiManifest,
@@ -64,6 +65,7 @@ assert.equal(typeof createIniPanelShellControlPageContract, "function");
assert.equal(typeof createIniPanelShellIntegrationManifest, "function"); assert.equal(typeof createIniPanelShellIntegrationManifest, "function");
assert.equal(typeof createIniPanelShellIntegrationReadiness, "function"); assert.equal(typeof createIniPanelShellIntegrationReadiness, "function");
assert.equal(typeof createIniPanelShellIntegrationSchema, "function"); assert.equal(typeof createIniPanelShellIntegrationSchema, "function");
assert.equal(typeof createIniPanelShellIntegrationWorkflowPlan, "function");
assert.equal(typeof loadMachineSessionForControlPageWorkflow, "function"); assert.equal(typeof loadMachineSessionForControlPageWorkflow, "function");
assert.equal(typeof readMachineSessionReadonlyStatus, "function"); assert.equal(typeof readMachineSessionReadonlyStatus, "function");
assert.equal(typeof refreshMachineSessionControlPage, "function"); assert.equal(typeof refreshMachineSessionControlPage, "function");
@@ -113,6 +115,13 @@ assert.deepEqual(
shellViewModel.shellIntegrationReadiness, shellViewModel.shellIntegrationReadiness,
createIniPanelShellIntegrationReadiness(shellViewModel.shellIntegrationManifest), createIniPanelShellIntegrationReadiness(shellViewModel.shellIntegrationManifest),
); );
assert.deepEqual(
shellViewModel.shellIntegrationWorkflowPlan,
createIniPanelShellIntegrationWorkflowPlan({
manifest: shellViewModel.shellIntegrationManifest,
readiness: shellViewModel.shellIntegrationReadiness,
}),
);
assert.equal( assert.equal(
isSupportedIniPanelShellIntegrationManifest(shellViewModel.shellIntegrationManifest), isSupportedIniPanelShellIntegrationManifest(shellViewModel.shellIntegrationManifest),
true, true,
@@ -144,6 +153,7 @@ assert.equal(
assert.equal(shellViewModel.controlPage.createController, createMachineSessionControlPageController); assert.equal(shellViewModel.controlPage.createController, createMachineSessionControlPageController);
assert.equal(shellViewModel.isSupportedShellIntegrationManifest, isSupportedIniPanelShellIntegrationManifest); assert.equal(shellViewModel.isSupportedShellIntegrationManifest, isSupportedIniPanelShellIntegrationManifest);
assert.equal(shellViewModel.createShellIntegrationReadiness, createIniPanelShellIntegrationReadiness); assert.equal(shellViewModel.createShellIntegrationReadiness, createIniPanelShellIntegrationReadiness);
assert.equal(shellViewModel.createShellIntegrationWorkflowPlan, createIniPanelShellIntegrationWorkflowPlan);
assert.deepEqual(shellViewModel.controlPage.contract, createIniPanelShellControlPageContract()); assert.deepEqual(shellViewModel.controlPage.contract, createIniPanelShellControlPageContract());
assert.equal(shellViewModel.controlPage.isSupportedBrowserApiManifest, isSupportedIniPanelControlPageApiManifest); assert.equal(shellViewModel.controlPage.isSupportedBrowserApiManifest, isSupportedIniPanelControlPageApiManifest);
assert.equal(shellViewModel.controlPage.loadSessionState, loadMachineSessionForControlPageWorkflow); assert.equal(shellViewModel.controlPage.loadSessionState, loadMachineSessionForControlPageWorkflow);