完善 working6 gmoccapy 页面诊断边界

This commit is contained in:
2026-06-27 00:01:01 -04:00
parent f964cedf66
commit 0e1e9d61a8
22 changed files with 2336 additions and 18 deletions

View File

@@ -20,6 +20,10 @@ assert.equal(model.nativePaths.hal.path.includes("HAL shared memory"), true);
assert.equal(model.nativePaths.hardwareButtons.path.includes("_button_pin_changed"), true);
assert.equal(model.nativePaths.halPins.path.includes("hal_glib.GPin value_changed"), true);
assert.equal(model.nativePaths.remap.path.includes("Python remap prolog/ngc/epilog"), true);
assert.equal(model.nativePaths.filePage.path.includes("IconFileSelection1"), true);
assert.equal(model.nativePaths.macroPage.path.includes("_on_btn_macro_pressed"), true);
assert.equal(model.nativePaths.toolEditorPage.path.includes("tooledit1.reload()"), true);
assert.equal(model.nativePaths.nativePages.path.includes("Web implementation matrix"), true);
assert.deepEqual(model.webPath.path, ["button", "store.dispatch", "linuxcnc-task-policy", "runtime/status snapshot", "UI/Three.js"]);
assert.equal(model.startupStages.length, 9);
@@ -46,8 +50,15 @@ for (const actionId of [
"coolant",
"hardware-button",
"hal-pin-input",
"hal-settings-unlock",
"hal-jog-pin",
"hal-tool-measurement",
"hal-user-message",
"hal-warning-confirm",
"file-page",
"macro-page",
"tool-editor-page",
"native-page-diagnostic",
]) {
assert.equal(actionIds.includes(actionId), true, `${actionId} missing`);
}
@@ -80,6 +91,11 @@ assert.equal(halPinMapping.gate.includes("counts require count-enable"), true);
assert.equal(halPinMapping.gate.includes("direct-value requires analog-enable"), true);
assert.equal(halPinMapping.gate.includes("delete-message pins are rising-edge only"), true);
const settingsUnlockMapping = model.actionMappings.find((mapping) => mapping.actionId === "hal-settings-unlock");
assert.equal(settingsUnlockMapping.nativeCommand, "_on_unlock_settings_changed");
assert.equal(settingsUnlockMapping.gate.includes("unlock_way"), true);
assert.equal(settingsUnlockMapping.gate.includes("HAL unlock"), true);
const halJogMapping = model.actionMappings.find((mapping) => mapping.actionId === "hal-jog-pin");
assert.equal(halJogMapping.webAction, "GMOCAPY_HAL_PIN jog.axis/jog-inc");
assert.equal(halJogMapping.nativeCommand.includes("_on_pin_jog_changed"), true);
@@ -87,16 +103,44 @@ assert.equal(halJogMapping.nativeCommand.includes("_on_pin_incr_changed"), true)
assert.equal(halJogMapping.gate.includes("press/release level"), true);
assert.equal(halJogMapping.gate.includes("increment pins are rising-edge only"), true);
const toolMeasurementMapping = model.actionMappings.find((mapping) => mapping.actionId === "hal-tool-measurement");
assert.equal(toolMeasurementMapping.nativeCommand.includes("_check_toolmeasurement"), true);
assert.equal(toolMeasurementMapping.nativeStatus.includes("probeheight"), true);
assert.equal(toolMeasurementMapping.gate.includes("no [TOOLSENSOR]"), true);
const userMessageMapping = model.actionMappings.find((mapping) => mapping.actionId === "hal-user-message");
assert.equal(userMessageMapping.nativeCommand.includes("_init_user_messages"), true);
assert.equal(userMessageMapping.nativeStatus.includes("messages.<pinname>"), true);
assert.equal(userMessageMapping.gate.includes("no MESSAGE_*"), true);
const warningConfirmMapping = model.actionMappings.find((mapping) => mapping.actionId === "hal-warning-confirm");
assert.equal(warningConfirmMapping.nativeCommand.includes("confirm_pin"), true);
assert.equal(warningConfirmMapping.gate, "level-polled while warning dialog is active");
const filePageMapping = model.actionMappings.find((mapping) => mapping.actionId === "file-page");
assert.equal(filePageMapping.nativeCommand.includes("IconFileSelection1"), true);
assert.equal(filePageMapping.gate.includes("native GTK file chooser"), true);
const macroPageMapping = model.actionMappings.find((mapping) => mapping.actionId === "macro-page");
assert.equal(macroPageMapping.webAction, "GMOCAPY_RUN_MACRO");
assert.equal(macroPageMapping.nativeCommand.includes("command.mdi"), true);
assert.equal(macroPageMapping.gate.includes("same as RUN_MDI"), true);
const toolEditorPageMapping = model.actionMappings.find((mapping) => mapping.actionId === "tool-editor-page");
assert.equal(toolEditorPageMapping.nativeCommand.includes("_show_tooledit_tab"), true);
assert.equal(toolEditorPageMapping.gate.includes("writeback is disabled"), true);
const nativePageMapping = model.actionMappings.find((mapping) => mapping.actionId === "native-page-diagnostic");
assert.equal(nativePageMapping.webAction, "GMOCAPY_NATIVE_PAGE");
assert.equal(nativePageMapping.gate.includes("do not emit fake GTK"), true);
const summary = createGmoccapyCommunicationSummary(model);
assert.equal(summary.apiName, "web-rtcp-5axis-gmoccapy-communication-model-summary");
assert.equal(summary.profileId, "gmoccapy-xyzab");
assert.equal(summary.nativePathCount, 6);
assert.equal(summary.nativePathCount, 10);
assert.equal(summary.startupStageCount, 9);
assert.equal(summary.actionCount, 19);
assert.equal(summary.actionCount, 26);
assert.equal(summary.pagePathCount, 4);
assert.equal(summary.postguiAfterHalcompReady, true);
assert.equal(summary.hasNativeNmlCommandPath, true);
assert.equal(summary.hasNativeHalPath, true);

View File

@@ -25,6 +25,7 @@ for (const groupName of [
"jog",
"override",
"operator-inputs",
"settings",
"tool",
"program",
"message",
@@ -44,7 +45,11 @@ assert.equal(groups.get("override").pins.includes("gmoccapy.spindle.reset-spindl
assert.equal(groups.get("operator-inputs").pins.includes("gmoccapy.ignore-limits"), true);
assert.equal(groups.get("operator-inputs").pins.includes("gmoccapy.optional-stop"), true);
assert.equal(groups.get("operator-inputs").pins.includes("gmoccapy.blockdelete"), true);
assert.equal(groups.get("settings").pins.includes("gmoccapy.unlock-settings"), true);
assert.equal(groups.get("tool").pins.includes("gmoccapy.toolchange-changed"), true);
assert.equal(groups.get("tool").pins.includes("gmoccapy.probeheight"), true);
assert.equal(groups.get("tool").pins.includes("gmoccapy.blockheight"), true);
assert.equal(groups.get("tool").pins.includes("gmoccapy.toolmeasurement"), true);
assert.equal(groups.get("program").pins.includes("gmoccapy.program.current-line"), true);
assert.equal(groups.get("message").pins.includes("gmoccapy.error"), true);
assert.equal(groups.get("spindle-postgui").pins.includes("gmoccapy.spindle_at_speed_led"), true);
@@ -90,14 +95,32 @@ assert.equal(model.hardwareButtons.bottomMain.find((button) => button.index ===
assert.equal(model.hardwareButtons.bottomMain.find((button) => button.index === 0).webDispatch.type, "HOME");
assert.equal(resolveGmoccapyHardwareButton("gmoccapy.v-button.button-4", model).webDispatch.mode, "auto");
assert.equal(resolveGmoccapyHardwareButton({ location: "bottom", index: 0 }, model).webDispatch.type, "HOME");
assert.equal(resolveGmoccapyHardwareButton({ location: "right", index: 6 }, model).webDispatch, undefined);
assert.equal(resolveGmoccapyHardwareButton({ location: "right", index: 6 }, model).webDispatch.pageId, "setup");
assert.equal(resolveGmoccapyHardwareButton("gmoccapy.h-button.button-9", model), null);
assert.equal(resolveGmoccapyHardwareButton({ location: "right", index: 5 }, model).webDispatch.type, "GMOCAPY_NATIVE_PAGE");
assert.equal(resolveGmoccapyHardwareButton({ location: "right", index: 5 }, model).webDispatch.pageId, "user-tabs");
assert.equal(resolveGmoccapyHardwareButton({ location: "bottom", index: 3 }, model).webDispatch.pageId, "tool-editor");
assert.equal(model.nativePages.filePage.nativeWidget, "IconFileSelection1");
assert.equal(model.nativePages.filePage.boundary, "native_GtkIconFileSelection_not_embedded_in_browser");
assert.equal(model.nativePages.macroPage.macros.length, 5);
assert.equal(model.nativePages.macroPage.macros.find((macro) => macro.name === "increment").args.length, 2);
assert.equal(model.nativePages.macroPage.boundary.includes("MDI"), true);
assert.equal(model.nativePages.toolEditorPage.editableInWeb, false);
assert.equal(model.nativePages.toolEditorPage.toolCount, 17);
assert.equal(model.nativePages.implementationMatrix.some((page) => page.pageId === "setup" && page.implementation === "diagnostic-only"), true);
assert.equal(model.nativePages.implementationMatrix.some((page) => page.pageId === "edit" && page.implementation === "native-only"), true);
assert.equal(model.nativePages.behavior.hardButtonsDoNotFakeNativePages, true);
assert.equal(model.nativePages.behavior.toolEditorKeepsIocontrolLoopback, true);
assert.equal(model.halPinActions.source.methods.includes("_optional_blocks"), true);
assert.equal(model.halPinActions.source.methods.includes("_blockdelete"), true);
assert.equal(model.halPinActions.source.methods.includes("_on_pin_jog_changed"), true);
assert.equal(model.halPinActions.source.methods.includes("_on_pin_incr_changed"), true);
assert.equal(model.halPinActions.source.methods.includes("_del_message_changed"), true);
assert.equal(model.halPinActions.source.methods.includes("_on_unlock_settings_changed"), true);
assert.equal(model.halPinActions.source.methods.includes("_check_toolmeasurement"), true);
assert.equal(model.halPinActions.source.methods.includes("_init_user_messages"), true);
assert.equal(model.halPinActions.jogPins.axes.length, 5);
assert.equal(model.halPinActions.jogPins.axes.find((entry) => entry.axis === "b").minus, "gmoccapy.jog.axis.jog-b-minus");
assert.equal(model.halPinActions.jogPins.increments.length, 6);
@@ -107,11 +130,13 @@ assert.equal(model.halPinActions.jogPins.increments[5].distance, 31.3563);
assert.equal(model.halPinActions.jogPins.turtlePin, "gmoccapy.jog.turtle-jog");
assert.equal(model.halPinActions.operatorPins.find((pin) => pin.pin === "gmoccapy.optional-stop").webState, "gmoccapyGui.optionalBlocks");
assert.equal(model.halPinActions.operatorPins.find((pin) => pin.pin === "gmoccapy.blockdelete").webState, "gmoccapyGui.optionalStop");
assert.equal(model.halPinActions.settingsPins.find((pin) => pin.pin === "gmoccapy.unlock-settings").prefDefault, "unlock_way=use");
assert.equal(model.halPinActions.overridePins.find((pin) => pin.target === "feed").countEnable, "gmoccapy.feed.feed-override.count-enable");
assert.equal(model.halPinActions.overridePins.find((pin) => pin.target === "spindle").reset, "gmoccapy.spindle.reset-spindle-override");
assert.equal(model.halPinActions.overridePins.find((pin) => pin.target === "jogVelocity").scalePref, "scale_jog_vel=140.4");
assert.equal(model.halPinActions.behavior.optionalStopPinCrossesToBlockDelete, true);
assert.equal(model.halPinActions.behavior.blockdeletePinCrossesToOptionalStop, true);
assert.equal(model.halPinActions.behavior.unlockSettingsLevelDriven, true);
assert.equal(model.halPinActions.behavior.jogAxisPinsPressRelease, true);
assert.equal(model.halPinActions.behavior.jogPinsUseTaskPolicyGate, true);
assert.equal(model.halPinActions.behavior.jogIncrementPinsRisingEdgeOnly, true);
@@ -124,6 +149,14 @@ assert.equal(model.halPinActions.messagePins.find((pin) => pin.pin === "gmoccapy
assert.equal(model.halPinActions.messagePins.find((pin) => pin.pin === "gmoccapy.warning-confirm").nativeCallback, "dialogs.warning_dialog periodic confirm_pin poll");
assert.equal(model.halPinActions.behavior.deleteMessageRisingEdgeOnly, true);
assert.equal(model.halPinActions.behavior.warningConfirmLevelPolled, true);
assert.equal(model.halPinActions.toolMeasurementPins.toolsensorConfigured, false);
assert.equal(model.halPinActions.toolMeasurementPins.pins.length, 5);
assert.equal(model.halPinActions.toolMeasurementPins.pins.find((pin) => pin.pin === "gmoccapy.toolmeasurement").direction, "HAL_OUT");
assert.equal(model.halPinActions.userMessages.configured, false);
assert.equal(model.halPinActions.userMessages.dynamicPinPatterns.includes("gmoccapy.messages.<pinname>-response"), true);
assert.equal(model.halPinActions.behavior.toolMeasurementPinsAreHalOut, true);
assert.equal(model.halPinActions.behavior.toolMeasurementDisabledWithoutToolsensor, true);
assert.equal(model.halPinActions.behavior.userMessagesDynamicIniOnly, true);
assert.equal(model.toolChange.strategy, "iocontrol-loopback");
assert.equal(model.toolChange.manualGmoccapyPinsConnected, false);
@@ -139,8 +172,8 @@ const summary = createGmoccapyHalSummary(model);
assert.equal(summary.apiName, "web-rtcp-5axis-gmoccapy-hal-model-summary");
assert.equal(summary.profileId, "gmoccapy-xyzab");
assert.equal(summary.halFileCount, 4);
assert.equal(summary.nativePinGroupCount, 8);
assert.equal(summary.nativePinCount >= 50, true);
assert.equal(summary.nativePinGroupCount, 9);
assert.equal(summary.nativePinCount >= 58, true);
assert.equal(summary.coreNetCount, 10);
assert.equal(summary.spindleNetCount, 4);
assert.equal(summary.postguiNetCount, 5);
@@ -152,16 +185,23 @@ assert.equal(summary.postguiToolUnlinkCount, 3);
assert.equal(summary.commentedManualToolChangeNetCount, 3);
assert.equal(summary.hardwareButtonVerticalCount, 7);
assert.equal(summary.hardwareButtonBottomMainCount, 4);
assert.equal(summary.mappedHardwareButtonCount, 7);
assert.equal(summary.mappedHardwareButtonCount, 6);
assert.equal(summary.hardwareButtonEdge, "rising-edge-only");
assert.equal(summary.hardwareButtonInsensitiveTarget, "ignored");
assert.equal(summary.operatorInputPinCount, 3);
assert.equal(summary.settingsInputPinCount, 1);
assert.equal(summary.overridePinTargetCount, 4);
assert.equal(summary.jogAxisPinCount, 10);
assert.equal(summary.jogIncrementPinCount, 6);
assert.equal(summary.messageInputPinCount, 3);
assert.equal(summary.toolMeasurementPinCount, 5);
assert.equal(summary.toolMeasurementEnabled, false);
assert.equal(summary.toolsensorConfigured, false);
assert.equal(summary.userMessagePinCount, 0);
assert.equal(summary.userMessagesConfigured, false);
assert.equal(summary.optionalStopPinCrossesToBlockDelete, true);
assert.equal(summary.blockdeletePinCrossesToOptionalStop, true);
assert.equal(summary.unlockSettingsLevelDriven, true);
assert.equal(summary.jogAxisPinsPressRelease, true);
assert.equal(summary.jogPinsUseTaskPolicyGate, true);
assert.equal(summary.jogIncrementPinsRisingEdgeOnly, true);
@@ -172,6 +212,21 @@ assert.equal(summary.directValueRequiresAnalogEnable, true);
assert.equal(summary.resetPinsRisingEdgeOnly, true);
assert.equal(summary.deleteMessageRisingEdgeOnly, true);
assert.equal(summary.warningConfirmLevelPolled, true);
assert.equal(summary.toolMeasurementPinsAreHalOut, true);
assert.equal(summary.toolMeasurementDisabledWithoutToolsensor, true);
assert.equal(summary.userMessagesDynamicIniOnly, true);
assert.equal(summary.nativePageCount, 12);
assert.equal(summary.implementedNativePageCount, 1);
assert.equal(summary.partialNativePageCount, 4);
assert.equal(summary.diagnosticOnlyNativePageCount, 5);
assert.equal(summary.nativeOnlyPageCount, 2);
assert.equal(summary.filePageImplementation, "partial");
assert.equal(summary.macroCount, 5);
assert.equal(summary.macroButtonsUseMdiGate, true);
assert.equal(summary.toolEditorImplementation, "diagnostic-only");
assert.equal(summary.toolEditorWritebackDisabled, true);
assert.equal(summary.hardButtonsDoNotFakeNativePages, true);
assert.equal(summary.unimplementedPagesDiagnosticOnly, true);
assert.equal(summary.semanticBoundary, model.semanticBoundary);
console.log("gmoccapy_hal_model_smoke=ok");

View File

@@ -215,7 +215,8 @@ assert.equal(hardButtonStore.getState().machine.allHomed, true);
hardButtonStore.dispatch({ type: "GMOCAPY_HARDWARE_BUTTON", pin: "gmoccapy.v-button.button-4", value: true });
assert.equal(hardButtonStore.getState().machine.mode, "auto");
hardButtonStore.dispatch({ type: "GMOCAPY_HARDWARE_BUTTON", pin: "gmoccapy.v-button.button-6", value: true });
assert.equal(hardButtonStore.getState().operatorMessage, "gmoccapy hardware button diagnostic-only: gmoccapy.v-button.button-6");
assert.equal(hardButtonStore.getState().gmoccapyGui.activeNativePage, "setup");
assert.equal(hardButtonStore.getState().operatorMessage, "gmoccapy native page diagnostic-only: setup");
hardButtonStore.dispatch({ type: "GMOCAPY_HARDWARE_BUTTON", pin: "gmoccapy.h-button.button-9", value: true });
assert.equal(hardButtonStore.getState().operatorMessage, "gmoccapy hardware button unmapped: gmoccapy.h-button.button-9");
@@ -231,6 +232,25 @@ assert.equal(halPinStore.getState().operatorMessage, "gmoccapy HAL optional-stop
halPinStore.dispatch({ type: "GMOCAPY_HAL_PIN", pin: "gmoccapy.blockdelete", value: true });
assert.equal(halPinStore.getState().gmoccapyGui.optionalStop, true);
assert.equal(halPinStore.getState().operatorMessage, "gmoccapy HAL blockdelete -> optional stop on");
halPinStore.dispatch({ type: "GMOCAPY_HAL_PIN", pin: "gmoccapy.unlock-settings", value: false });
assert.equal(halPinStore.getState().gmoccapyGui.settingsUnlockPin, false);
assert.equal(halPinStore.getState().gmoccapyGui.setupSensitive, true);
assert.equal(halPinStore.getState().operatorMessage, "gmoccapy HAL unlock-settings ignored: unlock_way is use");
halPinStore.dispatch({ type: "GMOCAPY_HAL_PIN", pin: "gmoccapy.unlock-settings", value: false, halUnlockMode: true });
assert.equal(halPinStore.getState().gmoccapyGui.settingsUnlockMode, "hal");
assert.equal(halPinStore.getState().gmoccapyGui.setupSensitive, false);
assert.equal(halPinStore.getState().operatorMessage, "gmoccapy HAL unlock-settings disabled setup");
halPinStore.dispatch({ type: "GMOCAPY_HAL_PIN", pin: "gmoccapy.unlock-settings", value: true });
assert.equal(halPinStore.getState().gmoccapyGui.settingsUnlockPin, true);
assert.equal(halPinStore.getState().gmoccapyGui.setupSensitive, true);
assert.equal(halPinStore.getState().operatorMessage, "gmoccapy HAL unlock-settings enabled setup");
halPinStore.dispatch({ type: "GMOCAPY_HAL_PIN", pin: "gmoccapy.blockheight", value: 12.5 });
assert.equal(halPinStore.getState().gmoccapyGui.blockHeight, 12.5);
assert.equal(halPinStore.getState().operatorMessage, "gmoccapy HAL tool measurement output recorded; XYZAB has no [TOOLSENSOR]");
halPinStore.dispatch({ type: "GMOCAPY_HAL_PIN", pin: "gmoccapy.toolmeasurement", value: true });
assert.equal(halPinStore.getState().gmoccapyGui.toolMeasurement, true);
halPinStore.dispatch({ type: "GMOCAPY_HAL_PIN", pin: "gmoccapy.messages.test", value: true });
assert.equal(halPinStore.getState().operatorMessage, "gmoccapy HAL user message pin unmapped: gmoccapy_XYZAB.ini defines no MESSAGE_* entries");
halPinStore.dispatch({ type: "GMOCAPY_HAL_PIN", pin: "gmoccapy.feed.feed-override.counts", value: 12 });
assert.equal(halPinStore.getState().feed.feedOverride, 100);
@@ -312,4 +332,41 @@ halMessageStore.dispatch({ type: "GMOCAPY_HAL_PIN", pin: "gmoccapy.warning-confi
assert.equal(halMessageStore.getState().gmoccapyGui.warningConfirm, false);
assert.equal(halMessageStore.getState().operatorMessage, "gmoccapy HAL warning-confirm cleared");
const nativePageStore = createSimulationStore();
nativePageStore.dispatch({ type: "SET_PROFILE", profileId: "gmoccapy-xyzab" });
nativePageStore.dispatch({ type: "GMOCAPY_HARDWARE_BUTTON", pin: "gmoccapy.v-button.button-6", value: true });
assert.equal(nativePageStore.getState().gmoccapyGui.activeNativePage, "setup");
assert.equal(nativePageStore.getState().gmoccapyGui.nativePageMode, "diagnostic-only");
assert.equal(nativePageStore.getState().operatorMessage, "gmoccapy native page diagnostic-only: setup");
nativePageStore.dispatch({ type: "GMOCAPY_HARDWARE_BUTTON", pin: "gmoccapy.h-button.button-3", value: true });
assert.equal(nativePageStore.getState().gmoccapyGui.activeNativePage, "tool-editor");
assert.equal(nativePageStore.getState().operatorMessage, "gmoccapy native page diagnostic-only: tool-editor");
nativePageStore.dispatch({ type: "GMOCAPY_PAGE_ACTION", pageId: "file-load", actionId: "open" });
assert.equal(nativePageStore.getState().gmoccapyGui.filePageStatus, "open");
assert.equal(nativePageStore.getState().operatorMessage.includes("native Gtk chooser diagnostic"), true);
nativePageStore.dispatch({ type: "GMOCAPY_TOOL_EDITOR_ACTION", actionId: "save" });
assert.equal(nativePageStore.getState().gmoccapyGui.toolEditorStatus, "writeback-blocked");
assert.equal(nativePageStore.getState().operatorMessage.includes("does not write tool.tbl"), true);
const macroBlockedStore = createSimulationStore();
macroBlockedStore.dispatch({ type: "SET_PROFILE", profileId: "gmoccapy-xyzab" });
macroBlockedStore.dispatch({ type: "GMOCAPY_RUN_MACRO", name: "halo_world" });
assert.equal(macroBlockedStore.getState().gmoccapyGui.macroLastName, "halo_world");
assert.equal(macroBlockedStore.getState().operatorMessage.includes("gmoccapy macro blocked"), true);
const macroReadyStore = createSimulationStore();
macroReadyStore.dispatch({ type: "SET_PROFILE", profileId: "gmoccapy-xyzab" });
macroReadyStore.dispatch({ type: "TOGGLE_POWER" });
macroReadyStore.dispatch({ type: "HOME" });
macroReadyStore.dispatch({ type: "SET_MODE", mode: "mdi" });
macroReadyStore.dispatch({
type: "GMOCAPY_RUN_MACRO",
name: "increment",
args: { xinc: 1.25, yinc: 2.5 },
});
assert.equal(macroReadyStore.getState().gmoccapyGui.activeNativePage, "mdi-macros");
assert.equal(macroReadyStore.getState().gmoccapyGui.macroLastCommand, "O<increment> call [1.25] [2.5]");
assert.equal(macroReadyStore.getState().machine.mdiCommand, "O<INCREMENT> CALL [1.25] [2.5]");
assert.equal(macroReadyStore.getState().operatorMessage, "gmoccapy macro MDI O<increment> call [1.25] [2.5]");
console.log("gmoccapy_xyzab_gates_smoke=ok");

View File

@@ -62,12 +62,37 @@ assert.equal(profile.halPins.includes("gmoccapy.jog.turtle-jog"), true);
assert.equal(profile.halPins.includes("gmoccapy.ignore-limits"), true);
assert.equal(profile.halPins.includes("gmoccapy.optional-stop"), true);
assert.equal(profile.halPins.includes("gmoccapy.blockdelete"), true);
assert.equal(profile.halPins.includes("gmoccapy.unlock-settings"), true);
assert.equal(profile.halPins.includes("gmoccapy.feed.feed-override.count-enable"), true);
assert.equal(profile.halPins.includes("gmoccapy.feed.reset-feed-override"), true);
assert.equal(profile.halPins.includes("gmoccapy.spindle.reset-spindle-override"), true);
assert.equal(profile.halPins.includes("gmoccapy.jog.jog-velocity.direct-value"), true);
assert.equal(profile.halPins.includes("gmoccapy.delete-message"), true);
assert.equal(profile.halPins.includes("gmoccapy.warning-confirm"), true);
assert.equal(profile.halPins.includes("gmoccapy.probeheight"), true);
assert.equal(profile.halPins.includes("gmoccapy.blockheight"), true);
assert.equal(profile.halPins.includes("gmoccapy.toolmeasurement"), true);
assert.equal(profile.halPins.includes("gmoccapy.searchvel"), true);
assert.equal(profile.halPins.includes("gmoccapy.probevel"), true);
assert.equal(profile.halPins.includes("gmoccapy.toolchange-confirm"), true);
assert.equal(profile.toolsensor.configured, false);
assert.equal(profile.toolsensor.useToolMeasurementPref, false);
assert.equal(profile.toolsensor.blockHeightPref, 0);
assert.equal(profile.toolsensor.reason.includes("no [TOOLSENSOR]"), true);
assert.equal(profile.userMessages.configured, false);
assert.equal(profile.userMessages.count, 0);
assert.equal(profile.userMessages.reason.includes("no [DISPLAY] MESSAGE_*"), true);
assert.equal(profile.nativePages.filePage.configured, true);
assert.equal(profile.nativePages.filePage.programPrefix, "../../nc_files/");
assert.equal(profile.nativePages.filePage.webImplementation, "partial");
assert.equal(profile.nativePages.macroPage.configured, true);
assert.equal(profile.nativePages.macroPage.count, 5);
assert.equal(profile.nativePages.macroPage.macros.find((macro) => macro.name === "increment").args.length, 2);
assert.equal(profile.nativePages.macroPage.macros.find((macro) => macro.name === "go_to_position").command, "O<go_to_position> call [X-pos] [Y-pos] [Z-pos]");
assert.equal(profile.nativePages.toolEditor.configured, true);
assert.equal(profile.nativePages.toolEditor.writebackEnabled, false);
assert.equal(profile.nativePages.toolEditor.toolCount, 17);
assert.equal(profile.nativePages.implementationMatrixBoundary.includes("diagnostic-only"), true);
assert.equal(profile.toolTable.toolCount, 17);
assert.equal(profile.macros.includes("go_to_position X-pos Y-pos Z-pos"), true);
assert.equal(profile.panelSchema.id, "gmoccapy-xyzab-hal-component");