From 7ce53d8804818873f2165d4b0a9c9c26a6d2fdfa Mon Sep 17 00:00:00 2001 From: RachelElysia <71795832+RachelElysia@users.noreply.github.com> Date: Tue, 11 Nov 2025 12:12:31 -0500 Subject: [PATCH] Fleet UI: Fix .ipa installers relies on mdm and not scripts enabled (#35522) --- .../HostInstallerActionCell.tests.tsx | 86 +++++++++++++++++++ .../HostInstallerActionCell.tsx | 20 ++++- 2 files changed, 102 insertions(+), 4 deletions(-) diff --git a/frontend/pages/hosts/details/cards/HostSoftwareLibrary/HostInstallerActionCell/HostInstallerActionCell.tests.tsx b/frontend/pages/hosts/details/cards/HostSoftwareLibrary/HostInstallerActionCell/HostInstallerActionCell.tests.tsx index 54ef3fe988..c6f96f2394 100644 --- a/frontend/pages/hosts/details/cards/HostSoftwareLibrary/HostInstallerActionCell/HostInstallerActionCell.tests.tsx +++ b/frontend/pages/hosts/details/cards/HostSoftwareLibrary/HostInstallerActionCell/HostInstallerActionCell.tests.tsx @@ -118,6 +118,92 @@ describe("getButtonActionState helper function", () => { expect(result.installTooltip).toBeUndefined(); expect(result.uninstallTooltip).toBeUndefined(); }); + it("returns enabled buttons and no tooltips for isMyDevicePage", () => { + const result = getActionButtonState({ + hostScriptsEnabled: false, // ignored when isMyDevicePage + status: null, + appStoreApp: null, + softwareId: 1, + softwarePackage: mockSoftwarePackage, + hostMDMEnrolled: false, + isMyDevicePage: true, + installedVersionsDetected: true, + }); + expect(result).toEqual({ + installDisabled: false, + uninstallDisabled: false, + moreDisabled: false, + }); + }); + + it("disables both buttons and sets tooltips when host scripts are off and package is not IPA/appStore and script versions not detected", () => { + const result = getActionButtonState({ + hostScriptsEnabled: false, + status: null, + appStoreApp: null, + softwareId: 1, + softwarePackage: mockSoftwarePackage, + hostMDMEnrolled: false, + installedVersionsDetected: false, + }); + expect(result).toEqual({ + installDisabled: true, + installTooltip: "To install, turn on host scripts.", + uninstallDisabled: true, + uninstallTooltip: "To uninstall, turn on host scripts.", + moreDisabled: true, + }); + }); + + it("disables install button for IPA/appStore if hostMDMEnrolled is false", () => { + const result = getActionButtonState({ + hostScriptsEnabled: true, + status: null, + appStoreApp: mockAppStoreApp, + softwareId: 1, + softwarePackage: mockSoftwarePackage, + hostMDMEnrolled: false, + installedVersionsDetected: true, + }); + expect(result.installDisabled).toBe(true); + expect(result.uninstallDisabled).toBe(true); + expect(result.installTooltip).toBe( + "To install, turn on MDM for this host." + ); + }); + + it("returns enabled buttons and no tooltips for non-IPA, scripts enabled", () => { + const result = getActionButtonState({ + hostScriptsEnabled: true, + status: null, + appStoreApp: null, + softwareId: 1, + softwarePackage: mockSoftwarePackage, + hostMDMEnrolled: true, + installedVersionsDetected: true, + }); + expect(result.installDisabled).toBe(false); + expect(result.uninstallDisabled).toBe(false); + expect(result.installTooltip).toBeUndefined(); + expect(result.uninstallTooltip).toBeUndefined(); + expect(result.moreDisabled).toBe(false); + }); + + it("returns disabled uninstall and enabled install for IPA/appStore app with MDM enrolled", () => { + const result = getActionButtonState({ + hostScriptsEnabled: true, + status: null, + appStoreApp: mockAppStoreApp, + softwareId: 1, + softwarePackage: mockSoftwarePackage, + hostMDMEnrolled: true, + installedVersionsDetected: true, + }); + expect(result.installDisabled).toBe(false); + expect(result.uninstallDisabled).toBe(true); + expect(result.installTooltip).toBeUndefined(); + expect(result.uninstallTooltip).toBeUndefined(); + }); }); describe("HostInstallerActionCell component", () => { diff --git a/frontend/pages/hosts/details/cards/HostSoftwareLibrary/HostInstallerActionCell/HostInstallerActionCell.tsx b/frontend/pages/hosts/details/cards/HostSoftwareLibrary/HostInstallerActionCell/HostInstallerActionCell.tsx index 5abea448bc..7633a5de36 100644 --- a/frontend/pages/hosts/details/cards/HostSoftwareLibrary/HostInstallerActionCell/HostInstallerActionCell.tsx +++ b/frontend/pages/hosts/details/cards/HostSoftwareLibrary/HostInstallerActionCell/HostInstallerActionCell.tsx @@ -73,10 +73,16 @@ export const getActionButtonState = ({ hostScriptsEnabled, status, appStoreApp, + softwarePackage, hostMDMEnrolled, isMyDevicePage, installedVersionsDetected, }: IGetActionButtonStateProps): IActionButtonState => { + // Determine platform and management method + const platform = softwarePackage?.platform || ""; + const isIpaOrAppStore = ["ipados", "ios"].includes(platform) || !!appStoreApp; + + // Pending states take priority const isPending = ["pending_install", "pending_uninstall"].includes( status || "" ); @@ -105,7 +111,8 @@ export const getActionButtonState = ({ /** If scripts are not enabled, software actions disabled with tooltip on * Host details > Software > Library but doesn't show to Fleet Desktop > Self-service. */ - if (!hostScriptsEnabled && !appStoreApp) { + const requiresScripts = !isIpaOrAppStore; + if (requiresScripts && !hostScriptsEnabled) { return { installDisabled: true, uninstallDisabled: true, @@ -116,8 +123,8 @@ export const getActionButtonState = ({ } /** If MDM is not enrolled, software actions disabled with tooltip on - Host details > Software > Library but doesn't show Fleet Desktop > Self-service */ - if (appStoreApp) { + * Host details > Software > Library but doesn't show Fleet Desktop > Self-service */ + if (isIpaOrAppStore) { return { installDisabled: !hostMDMEnrolled, uninstallDisabled: true, @@ -127,7 +134,12 @@ export const getActionButtonState = ({ }; } - return { installDisabled: false, uninstallDisabled: false }; + // Default: actions enabled, no tooltips + return { + installDisabled: false, + uninstallDisabled: false, + moreDisabled: false, + }; }; const getMoreActionsDropdownOptions = (