diff --git a/ui/__mocks__/copy-to-clipboard.js b/ui/__mocks__/copy-to-clipboard.js
new file mode 100644
index 000000000..d30cebfdf
--- /dev/null
+++ b/ui/__mocks__/copy-to-clipboard.js
@@ -0,0 +1,6 @@
+// mock copy-to-clipboard since it throws errors in tests
+// and we don't really need to copy anything, only ensure we're calling it
+
+const copy = jest.fn();
+
+export default copy;
diff --git a/ui/src/Components/Grid/AlertGrid/AlertGroup/GroupHeader/GroupMenu.js b/ui/src/Components/Grid/AlertGrid/AlertGroup/GroupHeader/GroupMenu.js
index d61f1f72c..b337576f8 100644
--- a/ui/src/Components/Grid/AlertGrid/AlertGroup/GroupHeader/GroupMenu.js
+++ b/ui/src/Components/Grid/AlertGrid/AlertGroup/GroupHeader/GroupMenu.js
@@ -150,4 +150,4 @@ const GroupMenu = observer(
}
);
-export { GroupMenu };
+export { GroupMenu, MenuContent };
diff --git a/ui/src/Components/Grid/AlertGrid/AlertGroup/GroupHeader/GroupMenu.test.js b/ui/src/Components/Grid/AlertGrid/AlertGroup/GroupHeader/GroupMenu.test.js
new file mode 100644
index 000000000..eb8c3a7ff
--- /dev/null
+++ b/ui/src/Components/Grid/AlertGrid/AlertGroup/GroupHeader/GroupMenu.test.js
@@ -0,0 +1,81 @@
+import React from "react";
+
+import { mount } from "enzyme";
+
+import copy from "copy-to-clipboard";
+
+import { MockAlertGroup } from "__mocks__/Alerts.js";
+import { SilenceFormStore } from "Stores/SilenceFormStore";
+import { GroupMenu, MenuContent } from "./GroupMenu";
+
+let silenceFormStore;
+
+beforeEach(() => {
+ silenceFormStore = new SilenceFormStore();
+});
+
+const MockAfterClick = jest.fn();
+
+const MountedGroupMenu = group => {
+ return mount();
+};
+
+describe("", () => {
+ it("is collapsed by default", () => {
+ const group = MockAlertGroup({ alertname: "Fake Alert" }, [], [], {});
+ const tree = MountedGroupMenu(group);
+ expect(tree.instance().collapse.value).toBe(true);
+ });
+
+ it("clicking toggle sets collapse value to 'false'", () => {
+ const group = MockAlertGroup({ alertname: "Fake Alert" }, [], [], {});
+ const tree = MountedGroupMenu(group);
+ const toggle = tree.find("a.cursor-pointer");
+ toggle.simulate("click");
+ expect(tree.instance().collapse.value).toBe(false);
+ });
+
+ it("handleClickOutside() call sets collapse value to 'true'", () => {
+ const group = MockAlertGroup({ alertname: "Fake Alert" }, [], [], {});
+ const tree = MountedGroupMenu(group);
+
+ const toggle = tree.find("a.cursor-pointer");
+ toggle.simulate("click");
+ expect(tree.instance().collapse.value).toBe(false);
+
+ tree.instance().handleClickOutside();
+
+ expect(tree.instance().collapse.value).toBe(true);
+ });
+});
+
+const MountedMenuContent = group => {
+ return mount(
+
+ );
+};
+
+describe("", () => {
+ it("clicking on 'Copy' icon copies the link to clickboard", () => {
+ const group = MockAlertGroup({ alertname: "Fake Alert" }, [], [], {});
+ const tree = MountedMenuContent(group);
+ const button = tree.find(".dropdown-item").at(0);
+ button.simulate("click");
+ expect(copy).toHaveBeenCalledTimes(1);
+ });
+
+ it("clicking on 'Silence' icon opens the silence form modal", () => {
+ const group = MockAlertGroup({ alertname: "Fake Alert" }, [], [], {});
+ const tree = MountedMenuContent(group);
+ const button = tree.find(".dropdown-item").at(1);
+ button.simulate("click");
+ expect(silenceFormStore.toggle.visible).toBe(true);
+ });
+});