推进 INI 面板 shell integration workflow plan
This commit is contained in:
@@ -20,6 +20,7 @@ import {
|
||||
createIniPanelShellIntegrationManifest,
|
||||
createIniPanelShellIntegrationReadiness,
|
||||
createIniPanelShellIntegrationSchema,
|
||||
createIniPanelShellIntegrationWorkflowPlan,
|
||||
createIniPanelShellViewModel,
|
||||
getIniPanelEntryByHref,
|
||||
getVisibleIniPanelEntries,
|
||||
@@ -124,6 +125,10 @@ Use `createIniPanelShellIntegrationReadiness()` or
|
||||
needs a read-only `ready`/`blocked` status, failed check names, API names, and
|
||||
counts for pages, methods, and persistence capabilities before mounting any
|
||||
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
|
||||
`tests/browser/ini_panel_shell_integration_workflow_smoke.html` verifies the
|
||||
same external shell handoff: read integration manifest, pass readiness gate,
|
||||
|
||||
@@ -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()) {
|
||||
const shellIntegrationManifest = createIniPanelShellIntegrationManifest(entries);
|
||||
const shellIntegrationReadiness = createIniPanelShellIntegrationReadiness(shellIntegrationManifest);
|
||||
return {
|
||||
pages: entries.map(({ id, href, title }) => ({
|
||||
id,
|
||||
@@ -335,11 +392,16 @@ export function createIniPanelShellViewModel(entries = getVisibleIniPanelEntries
|
||||
launcherLinks: createIniPanelLauncherLinkViewModel(entries),
|
||||
shellIntegrationSchema: createIniPanelShellIntegrationSchema(),
|
||||
shellIntegrationManifest,
|
||||
shellIntegrationReadiness: createIniPanelShellIntegrationReadiness(shellIntegrationManifest),
|
||||
shellIntegrationReadiness,
|
||||
shellIntegrationWorkflowPlan: createIniPanelShellIntegrationWorkflowPlan({
|
||||
manifest: shellIntegrationManifest,
|
||||
readiness: shellIntegrationReadiness,
|
||||
}),
|
||||
launchApiSchema: createIniPanelLaunchApiSchema(),
|
||||
launchApiManifest: createIniPanelLaunchApiManifest(entries),
|
||||
isSupportedShellIntegrationManifest: isSupportedIniPanelShellIntegrationManifest,
|
||||
createShellIntegrationReadiness: createIniPanelShellIntegrationReadiness,
|
||||
createShellIntegrationWorkflowPlan: createIniPanelShellIntegrationWorkflowPlan,
|
||||
controlPage: {
|
||||
browserApiSchema: createControlPageBrowserApiSchema(),
|
||||
browserApiManifest: createControlPageBrowserApiManifest(),
|
||||
|
||||
@@ -17,6 +17,7 @@ import {
|
||||
createIniPanelShellIntegrationManifest,
|
||||
createIniPanelShellIntegrationReadiness,
|
||||
createIniPanelShellIntegrationSchema,
|
||||
createIniPanelShellIntegrationWorkflowPlan,
|
||||
createIniPanelShellViewModel,
|
||||
createMachineSessionReadonlyStatus,
|
||||
createMachineSessionReadonlyStatusApiManifest,
|
||||
@@ -63,6 +64,7 @@ const requiredShellExports = [
|
||||
"createIniPanelShellIntegrationManifest",
|
||||
"createIniPanelShellIntegrationReadiness",
|
||||
"createIniPanelShellIntegrationSchema",
|
||||
"createIniPanelShellIntegrationWorkflowPlan",
|
||||
"createIniPanelShellViewModel",
|
||||
"getIniPanelEntryByHref",
|
||||
"getVisibleIniPanelEntries",
|
||||
@@ -133,6 +135,13 @@ assert.deepEqual(
|
||||
createIniPanelShellViewModel().shellIntegrationReadiness,
|
||||
createIniPanelShellIntegrationReadiness(createIniPanelShellViewModel().shellIntegrationManifest),
|
||||
);
|
||||
assert.deepEqual(
|
||||
createIniPanelShellViewModel().shellIntegrationWorkflowPlan,
|
||||
createIniPanelShellIntegrationWorkflowPlan({
|
||||
manifest: createIniPanelShellViewModel().shellIntegrationManifest,
|
||||
readiness: createIniPanelShellViewModel().shellIntegrationReadiness,
|
||||
}),
|
||||
);
|
||||
assert.equal(isSupportedIniPanelShellIntegrationManifest(createIniPanelShellViewModel().shellIntegrationManifest), true);
|
||||
assert.deepEqual(createIniPanelShellViewModel().launchApiSchema, createIniPanelLaunchApiSchema());
|
||||
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 createIniPanelShellIntegrationManifest\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 isSupportedIniPanelLaunchApiManifest\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, /\bcreateIniPanelShellIntegrationReadiness\b/);
|
||||
assert.match(docText, /\bcreateIniPanelShellIntegrationSchema\b/);
|
||||
assert.match(docText, /\bcreateIniPanelShellIntegrationWorkflowPlan\b/);
|
||||
assert.match(docText, /\bisSupportedIniPanelControlPageApiManifest\b/);
|
||||
assert.match(docText, /\bisSupportedIniPanelLaunchApiManifest\b/);
|
||||
assert.match(docText, /\bisSupportedIniPanelShellIntegrationManifest\b/);
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
createIniPanelShellIntegrationManifest,
|
||||
createIniPanelShellIntegrationReadiness,
|
||||
createIniPanelShellIntegrationSchema,
|
||||
createIniPanelShellIntegrationWorkflowPlan,
|
||||
getVisibleIniPanelEntries,
|
||||
isSupportedIniPanelShellIntegrationManifest,
|
||||
} 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 manifest = createIniPanelShellIntegrationManifest();
|
||||
const readiness = createIniPanelShellIntegrationReadiness(manifest);
|
||||
const workflowPlan = createIniPanelShellIntegrationWorkflowPlan({ manifest, readiness });
|
||||
|
||||
assert.deepEqual(schema, {
|
||||
apiName: "ini-panel-shell-integration",
|
||||
@@ -91,6 +93,43 @@ assert.deepEqual(readiness, {
|
||||
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 = {
|
||||
...createIniPanelShellIntegrationManifest(),
|
||||
compatibility: {
|
||||
@@ -122,6 +161,34 @@ assert.deepEqual(createIniPanelShellIntegrationReadiness(blockedManifest), {
|
||||
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({
|
||||
apiName: "other",
|
||||
});
|
||||
@@ -194,12 +261,14 @@ assert.deepEqual(customManifest.launchApiManifest.targetPages, [
|
||||
assert.match(shellText, /\bexport function createIniPanelShellIntegrationSchema\b/);
|
||||
assert.match(shellText, /\bexport function createIniPanelShellIntegrationManifest\b/);
|
||||
assert.match(shellText, /\bexport function createIniPanelShellIntegrationReadiness\b/);
|
||||
assert.match(shellText, /\bexport function createIniPanelShellIntegrationWorkflowPlan\b/);
|
||||
assert.match(shellText, /\bexport function isSupportedIniPanelShellIntegrationManifest\b/);
|
||||
assert.match(launchText, /\bgetShellIntegrationSchema\b/);
|
||||
assert.match(launchText, /\bgetShellIntegrationManifest\b/);
|
||||
assert.match(launchText, /\bgetShellIntegrationReadiness\b/);
|
||||
assert.match(docText, /\bcreateIniPanelShellIntegrationManifest\b/);
|
||||
assert.match(docText, /\bcreateIniPanelShellIntegrationReadiness\b/);
|
||||
assert.match(docText, /\bcreateIniPanelShellIntegrationWorkflowPlan\b/);
|
||||
assert.match(docText, /\bisSupportedIniPanelShellIntegrationManifest\b/);
|
||||
assert.doesNotMatch(shellText, /\bparseGcode\b|\bcanonicalEvents\b|\btoolTable\b|\bplanner\b/);
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
createIniPanelShellIntegrationManifest,
|
||||
createIniPanelShellIntegrationReadiness,
|
||||
createIniPanelShellIntegrationSchema,
|
||||
createIniPanelShellIntegrationWorkflowPlan,
|
||||
createIniPanelShellViewModel,
|
||||
createMachineSessionReadonlyStatus,
|
||||
createMachineSessionReadonlyStatusApiManifest,
|
||||
@@ -64,6 +65,7 @@ assert.equal(typeof createIniPanelShellControlPageContract, "function");
|
||||
assert.equal(typeof createIniPanelShellIntegrationManifest, "function");
|
||||
assert.equal(typeof createIniPanelShellIntegrationReadiness, "function");
|
||||
assert.equal(typeof createIniPanelShellIntegrationSchema, "function");
|
||||
assert.equal(typeof createIniPanelShellIntegrationWorkflowPlan, "function");
|
||||
assert.equal(typeof loadMachineSessionForControlPageWorkflow, "function");
|
||||
assert.equal(typeof readMachineSessionReadonlyStatus, "function");
|
||||
assert.equal(typeof refreshMachineSessionControlPage, "function");
|
||||
@@ -113,6 +115,13 @@ assert.deepEqual(
|
||||
shellViewModel.shellIntegrationReadiness,
|
||||
createIniPanelShellIntegrationReadiness(shellViewModel.shellIntegrationManifest),
|
||||
);
|
||||
assert.deepEqual(
|
||||
shellViewModel.shellIntegrationWorkflowPlan,
|
||||
createIniPanelShellIntegrationWorkflowPlan({
|
||||
manifest: shellViewModel.shellIntegrationManifest,
|
||||
readiness: shellViewModel.shellIntegrationReadiness,
|
||||
}),
|
||||
);
|
||||
assert.equal(
|
||||
isSupportedIniPanelShellIntegrationManifest(shellViewModel.shellIntegrationManifest),
|
||||
true,
|
||||
@@ -144,6 +153,7 @@ assert.equal(
|
||||
assert.equal(shellViewModel.controlPage.createController, createMachineSessionControlPageController);
|
||||
assert.equal(shellViewModel.isSupportedShellIntegrationManifest, isSupportedIniPanelShellIntegrationManifest);
|
||||
assert.equal(shellViewModel.createShellIntegrationReadiness, createIniPanelShellIntegrationReadiness);
|
||||
assert.equal(shellViewModel.createShellIntegrationWorkflowPlan, createIniPanelShellIntegrationWorkflowPlan);
|
||||
assert.deepEqual(shellViewModel.controlPage.contract, createIniPanelShellControlPageContract());
|
||||
assert.equal(shellViewModel.controlPage.isSupportedBrowserApiManifest, isSupportedIniPanelControlPageApiManifest);
|
||||
assert.equal(shellViewModel.controlPage.loadSessionState, loadMachineSessionForControlPageWorkflow);
|
||||
|
||||
Reference in New Issue
Block a user