diff --git a/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/HostActionsDropdown.tests.tsx b/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/HostActionsDropdown.tests.tsx
new file mode 100644
index 0000000000..60e24eb160
--- /dev/null
+++ b/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/HostActionsDropdown.tests.tsx
@@ -0,0 +1,306 @@
+import React from "react";
+import { noop } from "lodash";
+import { screen } from "@testing-library/react";
+
+import { createCustomRenderer } from "test/test-utils";
+import HostActionsDropdown from "./HostActionsDropdown";
+
+describe("Host Actions Dropdown", () => {
+ describe("Transfer action", () => {
+ it("renders the Transfer action when on premium tier and the user is a global admin", async () => {
+ const render = createCustomRenderer({
+ context: {
+ app: {
+ isPremiumTier: true,
+ isGlobalAdmin: true,
+ },
+ },
+ });
+
+ const { user } = render(
+
+ );
+
+ await user.click(screen.getByText("Actions"));
+
+ expect(screen.getByText("Transfer")).toBeInTheDocument();
+ });
+
+ it("renders the Transfer action when on premium tier and the user is a global maintainer", async () => {
+ const render = createCustomRenderer({
+ context: {
+ app: {
+ isPremiumTier: true,
+ isGlobalMaintainer: true,
+ },
+ },
+ });
+
+ const { user } = render(
+
+ );
+
+ await user.click(screen.getByText("Actions"));
+
+ expect(screen.getByText("Transfer")).toBeInTheDocument();
+ });
+ });
+
+ it("renders the Query action as disabled if the host is offline", async () => {
+ const render = createCustomRenderer();
+
+ const { user } = render(
+
+ );
+
+ await user.click(screen.getByText("Actions"));
+
+ expect(screen.getByText("Query").parentNode).toHaveClass("is-disabled");
+ });
+
+ it("renders the Show Disk Encryption Key action when on premium tier and we store the disk encryption key", async () => {
+ const render = createCustomRenderer({
+ context: {
+ app: {
+ isPremiumTier: true,
+ },
+ },
+ });
+
+ const { user } = render(
+
+ );
+
+ await user.click(screen.getByText("Actions"));
+
+ expect(screen.getByText("Show disk encryption key")).toBeInTheDocument();
+ });
+
+ describe("Turn off MDM action", () => {
+ it("renders the action when the host is enrolled in mdm and the user is a global admin", async () => {
+ const render = createCustomRenderer({
+ context: {
+ app: {
+ isMdmFeatureFlagEnabled: true, // TODO: remove when we release MDM
+ isGlobalAdmin: true,
+ },
+ },
+ });
+
+ const { user } = render(
+
+ );
+
+ await user.click(screen.getByText("Actions"));
+
+ expect(screen.getByText("Turn off MDM")).toBeInTheDocument();
+ });
+
+ it("renders the action when the host is enrolled in mdm and the user is a global maintainer", async () => {
+ const render = createCustomRenderer({
+ context: {
+ app: {
+ isMdmFeatureFlagEnabled: true, // TODO: remove when we release MDM
+ isGlobalMaintainer: true,
+ },
+ },
+ });
+
+ const { user } = render(
+
+ );
+
+ await user.click(screen.getByText("Actions"));
+
+ expect(screen.getByText("Turn off MDM")).toBeInTheDocument();
+ });
+
+ it("renders the action when the host is enrolled in mdm and the user is a team admin", async () => {
+ const render = createCustomRenderer({
+ context: {
+ app: {
+ isMdmFeatureFlagEnabled: true, // TODO: remove when we release MDM
+ isTeamAdmin: true,
+ },
+ },
+ });
+
+ const { user } = render(
+
+ );
+
+ await user.click(screen.getByText("Actions"));
+
+ expect(screen.getByText("Turn off MDM")).toBeInTheDocument();
+ });
+
+ it("renders the action when the host is enrolled in mdm and the user is a team maintainer", async () => {
+ const render = createCustomRenderer({
+ context: {
+ app: {
+ isMdmFeatureFlagEnabled: true, // TODO: remove when we release MDM
+ isTeamMaintainer: true,
+ },
+ },
+ });
+
+ const { user } = render(
+
+ );
+
+ await user.click(screen.getByText("Actions"));
+
+ expect(screen.getByText("Turn off MDM")).toBeInTheDocument();
+ });
+
+ it("renders as disabled when the host is offline", async () => {
+ const render = createCustomRenderer({
+ context: {
+ app: {
+ isMdmFeatureFlagEnabled: true, // TODO: remove when we release MDM
+ isTeamMaintainer: true,
+ },
+ },
+ });
+
+ const { user, debug } = render(
+
+ );
+
+ await user.click(screen.getByText("Actions"));
+
+ debug();
+
+ expect(screen.getByText("Turn off MDM").parentNode).toHaveClass(
+ "is-disabled"
+ );
+ });
+ });
+
+ describe("Delete action", () => {
+ it("renders when the user is a global admin", async () => {
+ const render = createCustomRenderer({
+ context: {
+ app: {
+ isGlobalAdmin: true,
+ },
+ },
+ });
+
+ const { user } = render(
+
+ );
+
+ await user.click(screen.getByText("Actions"));
+
+ expect(screen.getByText("Delete")).toBeInTheDocument();
+ });
+
+ it("renders when the user is a global maintainer", async () => {
+ const render = createCustomRenderer({
+ context: {
+ app: {
+ isGlobalMaintainer: true,
+ },
+ },
+ });
+
+ const { user } = render(
+
+ );
+
+ await user.click(screen.getByText("Actions"));
+
+ expect(screen.getByText("Delete")).toBeInTheDocument();
+ });
+
+ it("renders when the user is a team admin", async () => {
+ const render = createCustomRenderer({
+ context: {
+ app: {
+ isTeamAdmin: true,
+ },
+ },
+ });
+
+ const { user } = render(
+
+ );
+
+ await user.click(screen.getByText("Actions"));
+
+ expect(screen.getByText("Delete")).toBeInTheDocument();
+ });
+
+ it("renders when the user is a team maintainer", async () => {
+ const render = createCustomRenderer({
+ context: {
+ app: {
+ isTeamMaintainer: true,
+ },
+ },
+ });
+
+ const { user } = render(
+
+ );
+
+ await user.click(screen.getByText("Actions"));
+
+ expect(screen.getByText("Delete")).toBeInTheDocument();
+ });
+ });
+});
diff --git a/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/HostActionsDropdown.tsx b/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/HostActionsDropdown.tsx
index 005a24012d..8e589ccb90 100644
--- a/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/HostActionsDropdown.tsx
+++ b/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/HostActionsDropdown.tsx
@@ -1,7 +1,6 @@
import React, { useContext } from "react";
import { MdmEnrollmentStatus } from "interfaces/mdm";
-import permissionUtils from "utilities/permissions";
import { AppContext } from "context/app";
// @ts-ignore
@@ -11,40 +10,38 @@ import { generateHostActionOptions } from "./helpers";
const baseClass = "host-actions-dropdown";
interface IHostActionsDropdownProps {
- onSelect: (value: string) => void;
- teamId: number | null;
hostStatus: string;
hostMdmEnrollemntStatus: MdmEnrollmentStatus | null;
doesStoreEncryptionKey?: boolean;
+ onSelect: (value: string) => void;
}
const HostActionsDropdown = ({
onSelect,
- teamId,
hostStatus,
hostMdmEnrollemntStatus,
doesStoreEncryptionKey,
}: IHostActionsDropdownProps) => {
const {
- currentUser,
isPremiumTier = false,
isGlobalAdmin = false,
isGlobalMaintainer = false,
+ isMdmFeatureFlagEnabled = false,
+ isTeamAdmin = false,
+ isTeamMaintainer = false,
} = useContext(AppContext);
const options = generateHostActionOptions({
isPremiumTier,
isGlobalAdmin,
isGlobalMaintainer,
- isTeamAdmin: permissionUtils.isTeamAdmin(currentUser, teamId ?? null),
- isTeamMaintainer: permissionUtils.isTeamMaintainer(
- currentUser,
- teamId ?? null
- ),
+ isTeamAdmin,
+ isTeamMaintainer,
isHostOnline: hostStatus === "online",
isEnrolledInMdm: ["On (automatic)", "On (manual)"].includes(
hostMdmEnrollemntStatus ?? ""
),
+ isMdmFeatureFlagEnabled,
doesStoreEncryptionKey: doesStoreEncryptionKey ?? false,
});
diff --git a/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/_styles.scss b/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/_styles.scss
index 2cf8f38146..d17ab557e7 100644
--- a/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/_styles.scss
+++ b/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/_styles.scss
@@ -68,10 +68,14 @@
width: 188px;
left: unset;
top: unset;
- max-height: 220px;
+ max-height: none;
padding: $pad-small;
position: absolute;
left: -120px;
+
+ .Select-menu {
+ max-height: none;
+ }
}
.Select-arrow {
@@ -94,4 +98,4 @@
}
}
}
-}
\ No newline at end of file
+}
diff --git a/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/helpers.ts b/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/helpers.ts
index 5ebcdd0f23..fce1f7a5d6 100644
--- a/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/helpers.ts
+++ b/frontend/pages/hosts/details/HostDetailsPage/HostActionsDropdown/helpers.ts
@@ -38,6 +38,7 @@ interface IHostActionConfigOptions {
isTeamMaintainer: boolean;
isHostOnline: boolean;
isEnrolledInMdm: boolean;
+ isMdmFeatureFlagEnabled: boolean; // TODO: remove when we release MDM
doesStoreEncryptionKey: boolean;
}
@@ -53,8 +54,10 @@ const canEditMdm = (config: IHostActionConfigOptions) => {
isTeamAdmin,
isTeamMaintainer,
isEnrolledInMdm,
+ isMdmFeatureFlagEnabled,
} = config;
return (
+ isMdmFeatureFlagEnabled &&
isEnrolledInMdm &&
(isGlobalAdmin || isGlobalMaintainer || isTeamAdmin || isTeamMaintainer)
);
diff --git a/frontend/pages/hosts/details/HostDetailsPage/HostDetailsPage.tsx b/frontend/pages/hosts/details/HostDetailsPage/HostDetailsPage.tsx
index 4273011c18..0b6a9420bb 100644
--- a/frontend/pages/hosts/details/HostDetailsPage/HostDetailsPage.tsx
+++ b/frontend/pages/hosts/details/HostDetailsPage/HostDetailsPage.tsx
@@ -540,7 +540,6 @@ const HostDetailsPage = ({
return (