456 lines
18 KiB
JavaScript
456 lines
18 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { readFileSync } from "node:fs";
|
|
import { dirname, resolve } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
import {
|
|
INI_PANEL_ENTRIES,
|
|
analyzeIniRuntimeBoundaries,
|
|
createControlPageBrowserApiManifest,
|
|
createControlPageBrowserApiMethods,
|
|
createControlPageBrowserApiSchema,
|
|
createIniPanelLaunchApiManifest,
|
|
createIniPanelLauncherLinkViewModel,
|
|
createIniPanelShellApiSurfaceInventory,
|
|
createIniPanelShellControlPageContract,
|
|
createIniPanelShellIntegrationManifest,
|
|
createIniPanelShellIntegrationReadiness,
|
|
createIniPanelShellIntegrationSchema,
|
|
createIniPanelShellIntegrationWorkflowPlan,
|
|
createIniPanelShellSessionReadinessWorkflowReport,
|
|
createIniPanelShellViewModel,
|
|
createIniPanelShellWorkflowOverviewContract,
|
|
createIniPanelShellWorkflowOverviewEmbeddingMountDomContract,
|
|
createIniPanelShellWorkflowOverviewEmbeddingMountDomReadiness,
|
|
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDisplayViewModel,
|
|
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract,
|
|
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness,
|
|
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState,
|
|
createLinuxCncIniSdk,
|
|
createLinuxCncInterpSdk,
|
|
createMachineSessionSnapshotPayload,
|
|
createMachineSessionPersistenceDisplayViewModel,
|
|
createMachineSessionPersistenceRenderState,
|
|
createMachineSessionPersistenceSummary,
|
|
createProjectReleaseGateManifest,
|
|
createProjectReleaseGateResultMatrix,
|
|
createProjectReleaseReadinessArtifactValidation,
|
|
createProjectReleaseReadinessReport,
|
|
parseProjectReleaseReadinessArtifactJson,
|
|
createSessionSnapshot,
|
|
defaultMachinePaths,
|
|
gcodeFilenameFromProgramPath,
|
|
gcodeProgramPath,
|
|
getIniPanelEntryByHref,
|
|
getIniPanelEntryManifest,
|
|
getOpfsRoot,
|
|
getVisibleIniPanelEntries,
|
|
isSupportedIniPanelControlPageApiManifest,
|
|
isSupportedIniPanelLaunchApiManifest,
|
|
isSupportedIniPanelShellIntegrationManifest,
|
|
loadIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrl,
|
|
loadMachineSessionFromOpfs,
|
|
loadMachineSessionSnapshot,
|
|
loadMachineTextFiles,
|
|
loadMachineToolTableFromOpfs,
|
|
loadTextFile,
|
|
machineFilePaths,
|
|
machineIniPath,
|
|
mountIniPanelShellWorkflowOverviewEmbeddingMountState,
|
|
mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactState,
|
|
normalizeOpfsPath,
|
|
parameterFilePath,
|
|
planIniFileContextStaging,
|
|
planSimConfigStaging,
|
|
readMachineSessionReadiness,
|
|
renderIniPanelShellWorkflowOverviewEmbeddingMountState,
|
|
renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactState,
|
|
restoreMachineParametersFromOpfs,
|
|
saveMachineSessionSnapshot,
|
|
saveMachineTextFiles,
|
|
saveSessionSnapshot,
|
|
saveTextFile,
|
|
sessionSnapshotPath,
|
|
toolTablePath,
|
|
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson,
|
|
validateSessionSnapshot,
|
|
} from "../../../runtime/sdk/src/index.js";
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const root = resolve(__dirname, "../../..");
|
|
const sdkIndexText = readFileSync(resolve(root, "runtime/sdk/src/index.js"), "utf8");
|
|
const sdkReadmeText = readFileSync(resolve(root, "runtime/sdk/README.md"), "utf8");
|
|
const trackerText = readFileSync(resolve(root, "../PROJECT_COMPLETION_TRACKER.md"), "utf8");
|
|
|
|
const requiredExports = [
|
|
["createLinuxCncIniSdk", createLinuxCncIniSdk],
|
|
["createLinuxCncInterpSdk", createLinuxCncInterpSdk],
|
|
["createProjectReleaseGateManifest", createProjectReleaseGateManifest],
|
|
["createProjectReleaseGateResultMatrix", createProjectReleaseGateResultMatrix],
|
|
["createProjectReleaseReadinessArtifactValidation", createProjectReleaseReadinessArtifactValidation],
|
|
["createProjectReleaseReadinessReport", createProjectReleaseReadinessReport],
|
|
["parseProjectReleaseReadinessArtifactJson", parseProjectReleaseReadinessArtifactJson],
|
|
[
|
|
"validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson",
|
|
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson,
|
|
],
|
|
[
|
|
"loadIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrl",
|
|
loadIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrl,
|
|
],
|
|
["planIniFileContextStaging", planIniFileContextStaging],
|
|
["planSimConfigStaging", planSimConfigStaging],
|
|
["analyzeIniRuntimeBoundaries", analyzeIniRuntimeBoundaries],
|
|
["getIniPanelEntryManifest", getIniPanelEntryManifest],
|
|
["getIniPanelEntryByHref", getIniPanelEntryByHref],
|
|
["getVisibleIniPanelEntries", getVisibleIniPanelEntries],
|
|
["createIniPanelLauncherLinkViewModel", createIniPanelLauncherLinkViewModel],
|
|
["createMachineSessionPersistenceDisplayViewModel", createMachineSessionPersistenceDisplayViewModel],
|
|
["createMachineSessionPersistenceRenderState", createMachineSessionPersistenceRenderState],
|
|
["createMachineSessionPersistenceSummary", createMachineSessionPersistenceSummary],
|
|
["getOpfsRoot", getOpfsRoot],
|
|
["saveTextFile", saveTextFile],
|
|
["loadTextFile", loadTextFile],
|
|
["machineIniPath", machineIniPath],
|
|
["toolTablePath", toolTablePath],
|
|
["parameterFilePath", parameterFilePath],
|
|
["gcodeProgramPath", gcodeProgramPath],
|
|
["sessionSnapshotPath", sessionSnapshotPath],
|
|
["defaultMachinePaths", defaultMachinePaths],
|
|
["normalizeOpfsPath", normalizeOpfsPath],
|
|
["createMachineSessionSnapshotPayload", createMachineSessionSnapshotPayload],
|
|
["createSessionSnapshot", createSessionSnapshot],
|
|
["saveSessionSnapshot", saveSessionSnapshot],
|
|
["saveMachineSessionSnapshot", saveMachineSessionSnapshot],
|
|
["loadMachineSessionSnapshot", loadMachineSessionSnapshot],
|
|
["validateSessionSnapshot", validateSessionSnapshot],
|
|
["machineFilePaths", machineFilePaths],
|
|
["saveMachineTextFiles", saveMachineTextFiles],
|
|
["loadMachineTextFiles", loadMachineTextFiles],
|
|
["gcodeFilenameFromProgramPath", gcodeFilenameFromProgramPath],
|
|
["restoreMachineParametersFromOpfs", restoreMachineParametersFromOpfs],
|
|
["loadMachineToolTableFromOpfs", loadMachineToolTableFromOpfs],
|
|
["loadMachineSessionFromOpfs", loadMachineSessionFromOpfs],
|
|
["readMachineSessionReadiness", readMachineSessionReadiness],
|
|
["createControlPageBrowserApiSchema", createControlPageBrowserApiSchema],
|
|
["createControlPageBrowserApiManifest", createControlPageBrowserApiManifest],
|
|
["createControlPageBrowserApiMethods", createControlPageBrowserApiMethods],
|
|
["createIniPanelShellControlPageContract", createIniPanelShellControlPageContract],
|
|
["isSupportedIniPanelControlPageApiManifest", isSupportedIniPanelControlPageApiManifest],
|
|
["createIniPanelLaunchApiManifest", createIniPanelLaunchApiManifest],
|
|
["isSupportedIniPanelLaunchApiManifest", isSupportedIniPanelLaunchApiManifest],
|
|
["createIniPanelShellIntegrationSchema", createIniPanelShellIntegrationSchema],
|
|
["createIniPanelShellIntegrationManifest", createIniPanelShellIntegrationManifest],
|
|
["createIniPanelShellIntegrationReadiness", createIniPanelShellIntegrationReadiness],
|
|
["createIniPanelShellIntegrationWorkflowPlan", createIniPanelShellIntegrationWorkflowPlan],
|
|
["isSupportedIniPanelShellIntegrationManifest", isSupportedIniPanelShellIntegrationManifest],
|
|
["createIniPanelShellViewModel", createIniPanelShellViewModel],
|
|
["createIniPanelShellApiSurfaceInventory", createIniPanelShellApiSurfaceInventory],
|
|
["createIniPanelShellSessionReadinessWorkflowReport", createIniPanelShellSessionReadinessWorkflowReport],
|
|
["createIniPanelShellWorkflowOverviewContract", createIniPanelShellWorkflowOverviewContract],
|
|
[
|
|
"createIniPanelShellWorkflowOverviewEmbeddingMountDomContract",
|
|
createIniPanelShellWorkflowOverviewEmbeddingMountDomContract,
|
|
],
|
|
[
|
|
"createIniPanelShellWorkflowOverviewEmbeddingMountDomReadiness",
|
|
createIniPanelShellWorkflowOverviewEmbeddingMountDomReadiness,
|
|
],
|
|
[
|
|
"createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDisplayViewModel",
|
|
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDisplayViewModel,
|
|
],
|
|
[
|
|
"createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState",
|
|
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState,
|
|
],
|
|
[
|
|
"createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract",
|
|
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract,
|
|
],
|
|
[
|
|
"createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness",
|
|
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness,
|
|
],
|
|
[
|
|
"renderIniPanelShellWorkflowOverviewEmbeddingMountState",
|
|
renderIniPanelShellWorkflowOverviewEmbeddingMountState,
|
|
],
|
|
[
|
|
"renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactState",
|
|
renderIniPanelShellWorkflowOverviewReleaseReadinessArtifactState,
|
|
],
|
|
[
|
|
"mountIniPanelShellWorkflowOverviewEmbeddingMountState",
|
|
mountIniPanelShellWorkflowOverviewEmbeddingMountState,
|
|
],
|
|
[
|
|
"mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactState",
|
|
mountIniPanelShellWorkflowOverviewReleaseReadinessArtifactState,
|
|
],
|
|
];
|
|
|
|
for (const [name, value] of requiredExports) {
|
|
assert.equal(typeof value, "function", `${name} SDK export drift`);
|
|
assert.match(sdkIndexText, new RegExp(`\\b${name}\\b`));
|
|
assert.match(sdkReadmeText, new RegExp(`\\b${name}\\b`));
|
|
}
|
|
|
|
assert.equal(machineIniPath("sdk-mill"), "linuxcnc/machines/sdk-mill/machine.ini");
|
|
assert.deepEqual(defaultMachinePaths("sdk-mill"), machineFilePaths("sdk-mill"));
|
|
assert.equal(gcodeProgramPath("demo.ngc"), "linuxcnc/gcode/demo.ngc");
|
|
assert.equal(sessionSnapshotPath("sdk-session"), "linuxcnc/sessions/sdk-session/snapshot.json");
|
|
assert.equal(normalizeOpfsPath("linuxcnc/machines/sdk-mill/tool.tbl"), "linuxcnc/machines/sdk-mill/tool.tbl");
|
|
assert.equal(gcodeFilenameFromProgramPath("linuxcnc/gcode/demo.ngc"), "demo.ngc");
|
|
|
|
const releaseReadinessWaiting = createProjectReleaseReadinessReport();
|
|
assert.equal(releaseReadinessWaiting.apiName, "project-release-readiness-report");
|
|
assert.equal(releaseReadinessWaiting.ready, false);
|
|
assert.deepEqual(releaseReadinessWaiting.missing, ["project-release-gate"]);
|
|
assert.equal(releaseReadinessWaiting.simConfigInventory.unexpectedFail, 0);
|
|
assert.deepEqual(releaseReadinessWaiting.promotedBlockedFamilies, []);
|
|
assert.equal(
|
|
releaseReadinessWaiting.rows.find(({ id }) => id === "blocked-runtime-families")?.value,
|
|
"L4-USER-M-PROCESS, L4-TOOL-DB, L4-PYTHON-REMAP",
|
|
);
|
|
const releaseReadinessReady = createProjectReleaseReadinessReport({
|
|
observedOutputs: ["project_release_gate=ok"],
|
|
});
|
|
assert.equal(releaseReadinessReady.ready, true);
|
|
assert.equal(releaseReadinessReady.releaseGate.passed, true);
|
|
assert.deepEqual(releaseReadinessReady.gateManifest, createProjectReleaseGateManifest());
|
|
assert.equal(releaseReadinessReady.gateResultMatrix.rows.length, 10);
|
|
assert.equal(
|
|
createProjectReleaseGateResultMatrix({
|
|
observedOutputs: ["project_release_gate=ok"],
|
|
}).rows.find(({ id }) => id === "project-release-gate")?.passed,
|
|
true,
|
|
);
|
|
const releaseReadinessArtifact = parseProjectReleaseReadinessArtifactJson(JSON.stringify(createProjectReleaseReadinessReport({
|
|
gateResults: {
|
|
"diff-check": true,
|
|
"vendor-sync": true,
|
|
"standalone-cnc-semantics": true,
|
|
"interp-wasm": true,
|
|
"sim-config-inventory": true,
|
|
"ini-panel-browser": true,
|
|
"release-artifact-url-browser": true,
|
|
"ui-node-smokes": true,
|
|
"host-smokes": true,
|
|
"project-release-gate": true,
|
|
},
|
|
})));
|
|
assert.equal(releaseReadinessArtifact.apiName, "project-release-readiness-report");
|
|
assert.deepEqual(createProjectReleaseReadinessArtifactValidation(releaseReadinessArtifact), {
|
|
apiName: "project-release-readiness-artifact-validation",
|
|
validationVersion: 1,
|
|
phase: "ready",
|
|
ready: true,
|
|
missing: [],
|
|
artifactApiName: "project-release-readiness-report",
|
|
artifactVersion: 1,
|
|
gateCount: 10,
|
|
expectedGateCount: 10,
|
|
expectedGateIds: createProjectReleaseGateManifest().gateIds,
|
|
blockedRuntimeFamilies: [
|
|
"L4-USER-M-PROCESS",
|
|
"L4-TOOL-DB",
|
|
"L4-PYTHON-REMAP",
|
|
],
|
|
rows: [
|
|
{
|
|
id: "artifact",
|
|
label: "Readiness artifact",
|
|
value: "project-release-readiness-report",
|
|
},
|
|
{
|
|
id: "project-release-gate",
|
|
label: "Project release gate",
|
|
value: "passed",
|
|
},
|
|
{
|
|
id: "validation",
|
|
label: "Artifact validation",
|
|
value: "ready",
|
|
},
|
|
],
|
|
});
|
|
assert.deepEqual(
|
|
createProjectReleaseReadinessArtifactValidation({}).missing,
|
|
[
|
|
"apiName",
|
|
"reportVersion",
|
|
"phase",
|
|
"ready",
|
|
"missing",
|
|
"releaseGate.command",
|
|
"releaseGate.passed",
|
|
"releaseGate.expectedOutput",
|
|
"simConfigInventory.executed",
|
|
"simConfigInventory.passed",
|
|
"simConfigInventory.skipped",
|
|
"simConfigInventory.unexpectedFail",
|
|
"blockedRuntimeFamilies",
|
|
"gates.length",
|
|
"gates.passed",
|
|
"rows.project-release-gate",
|
|
],
|
|
);
|
|
assert.equal(
|
|
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson(JSON.stringify(releaseReadinessArtifact)).ready,
|
|
true,
|
|
);
|
|
assert.equal(
|
|
(await loadIniPanelShellWorkflowOverviewReleaseReadinessArtifactUrl({
|
|
artifactUrl: "/project-release-readiness.json",
|
|
fetchRef: async () => ({
|
|
ok: true,
|
|
status: 200,
|
|
text: async () => JSON.stringify(releaseReadinessArtifact),
|
|
}),
|
|
})).ready,
|
|
true,
|
|
);
|
|
assert.equal(
|
|
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactRenderState(
|
|
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDisplayViewModel(
|
|
validateIniPanelShellWorkflowOverviewReleaseReadinessArtifactJson(JSON.stringify(releaseReadinessArtifact)),
|
|
),
|
|
).dataset.handoffScope,
|
|
"workflow-overview-release-readiness-artifact",
|
|
);
|
|
assert.equal(
|
|
createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomContract().selectors.rows,
|
|
"[data-workflow-overview-release-readiness-artifact-rows]",
|
|
);
|
|
assert.equal(createIniPanelShellWorkflowOverviewReleaseReadinessArtifactDomReadiness().ready, false);
|
|
assert.equal(
|
|
createProjectReleaseReadinessReport({
|
|
observedOutputs: ["project_release_gate=ok"],
|
|
promotedRuntimeFamilies: ["L4-TOOL-DB"],
|
|
}).missing.includes("blocked-runtime-families"),
|
|
true,
|
|
);
|
|
|
|
assert.deepEqual(getIniPanelEntryManifest(), INI_PANEL_ENTRIES);
|
|
assert.deepEqual(getVisibleIniPanelEntries(), INI_PANEL_ENTRIES);
|
|
assert.deepEqual(getIniPanelEntryByHref("./control-page.html"), {
|
|
id: "control-view",
|
|
title: "Open read-only control view",
|
|
href: "./control-page.html",
|
|
});
|
|
assert.deepEqual(createIniPanelLauncherLinkViewModel(), [
|
|
{
|
|
entryId: "edit-run",
|
|
href: "./index.html",
|
|
label: "Open edit and run panel",
|
|
},
|
|
{
|
|
entryId: "control-view",
|
|
href: "./control-page.html",
|
|
label: "Open read-only control view",
|
|
},
|
|
{
|
|
entryId: "workflow-overview",
|
|
href: "./workflow-overview.html",
|
|
label: "Open shell handoff overview",
|
|
},
|
|
]);
|
|
assert.equal(
|
|
createMachineSessionPersistenceSummary({
|
|
state: {
|
|
badges: { opfs: "OPFS: ready" },
|
|
fields: { sessionSnapshot: "sdk-session/snapshot.json", sessionIni: "/work/session-machine.ini" },
|
|
sessionLoad: { iniWasmPath: "/work/session-machine.ini" },
|
|
sessionReadiness: { phase: "ready", ready: true, missing: [] },
|
|
},
|
|
}).rows.find(({ id }) => id === "session-load")?.value,
|
|
"loaded: /work/session-machine.ini",
|
|
);
|
|
assert.equal(
|
|
createMachineSessionPersistenceRenderState(
|
|
createMachineSessionPersistenceDisplayViewModel(createMachineSessionPersistenceSummary()),
|
|
).apiName,
|
|
"machine-session-persistence-render-state",
|
|
);
|
|
|
|
const controlPageApiSchema = createControlPageBrowserApiSchema();
|
|
const controlPageApiManifest = createControlPageBrowserApiManifest();
|
|
assert.equal(controlPageApiSchema.apiName, "ini-panel-control-page");
|
|
assert.equal(isSupportedIniPanelControlPageApiManifest(controlPageApiManifest), true);
|
|
assert.deepEqual(controlPageApiManifest.methods, createControlPageBrowserApiMethods());
|
|
assert.equal(
|
|
createIniPanelShellControlPageContract().readonlyStatusApiManifest.apiName,
|
|
"machine-session-readonly-status",
|
|
);
|
|
|
|
const launchManifest = createIniPanelLaunchApiManifest();
|
|
assert.equal(isSupportedIniPanelLaunchApiManifest(launchManifest), true);
|
|
assert.equal(
|
|
launchManifest.methods.includes("mountWorkflowOverviewEmbeddingMountState"),
|
|
true,
|
|
);
|
|
assert.deepEqual(
|
|
launchManifest.visibleEntries,
|
|
getVisibleIniPanelEntries().map(({ id, href, title }) => ({ id, href, title })),
|
|
);
|
|
|
|
const shellIntegrationManifest = createIniPanelShellIntegrationManifest();
|
|
assert.equal(createIniPanelShellIntegrationSchema().apiName, "ini-panel-shell-integration");
|
|
assert.equal(isSupportedIniPanelShellIntegrationManifest(shellIntegrationManifest), true);
|
|
assert.equal(createIniPanelShellIntegrationReadiness(shellIntegrationManifest).ready, true);
|
|
assert.equal(createIniPanelShellIntegrationWorkflowPlan({
|
|
manifest: shellIntegrationManifest,
|
|
}).ready, true);
|
|
assert.equal(
|
|
createIniPanelShellWorkflowOverviewContract().methodNames.includes("getWorkflowOverviewApiSurfaceInventory"),
|
|
true,
|
|
);
|
|
|
|
const shellViewModel = createIniPanelShellViewModel();
|
|
assert.equal(
|
|
shellViewModel.launchApiManifest.methods.includes("mountWorkflowOverviewEmbeddingMountState"),
|
|
true,
|
|
);
|
|
assert.equal(
|
|
shellViewModel.launchApiManifest.methods.includes("getShellSessionReadinessWorkflowReport"),
|
|
true,
|
|
);
|
|
assert.equal(
|
|
createIniPanelShellSessionReadinessWorkflowReport().apiName,
|
|
"ini-panel-shell-session-readiness-workflow-report",
|
|
);
|
|
assert.equal(
|
|
createIniPanelShellApiSurfaceInventory().apiName,
|
|
"ini-panel-shell-api-surface-inventory",
|
|
);
|
|
assert.equal(shellViewModel.shellApiSurfaceInventory.ready, true);
|
|
assert.equal(
|
|
shellViewModel.shellSessionHandoffWorkflowSummary.rows.find(
|
|
({ id }) => id === "persistence-summary",
|
|
)?.value,
|
|
"waiting: 5 missing",
|
|
);
|
|
assert.equal(
|
|
shellViewModel.shellSessionHandoffWorkflowSummary.rows.find(
|
|
({ id }) => id === "api-surface-inventory",
|
|
)?.value,
|
|
"ready: 6 rows",
|
|
);
|
|
assert.equal(
|
|
shellViewModel.mountWorkflowOverviewEmbeddingMountState,
|
|
mountIniPanelShellWorkflowOverviewEmbeddingMountState,
|
|
);
|
|
|
|
const blockedMount = mountIniPanelShellWorkflowOverviewEmbeddingMountState({ documentRef: null });
|
|
assert.equal(blockedMount.apiName, "ini-panel-shell-workflow-overview-embedding-mount-dom-mount");
|
|
assert.equal(blockedMount.ready, false);
|
|
assert.deepEqual(blockedMount.domReadiness.missing, ["document", "mount", "status", "rows"]);
|
|
|
|
assert.match(sdkReadmeText, /OPFS\/session persistence/);
|
|
assert.match(sdkReadmeText, /INI panel shell handoff/);
|
|
assert.match(sdkReadmeText, /workflow overview embedding/);
|
|
assert.match(trackerText, /SDK\/API surface/);
|
|
|
|
console.log("sdk_surface_node_smoke=ok");
|