diff --git a/ui/src/Components/SilenceModal/LabelNameInput.test.js b/ui/src/Components/SilenceModal/LabelNameInput.test.js
new file mode 100644
index 000000000..dbcc8934e
--- /dev/null
+++ b/ui/src/Components/SilenceModal/LabelNameInput.test.js
@@ -0,0 +1,89 @@
+import React from "react";
+
+import { shallow, mount } from "enzyme";
+
+import { NewEmptyMatcher, MatcherValueToObject } from "Stores/SilenceFormStore";
+import { LabelNameInput } from "./LabelNameInput";
+
+let matcher;
+
+beforeEach(() => {
+ matcher = NewEmptyMatcher();
+ matcher.name = "name";
+ matcher.suggestions.names = [
+ MatcherValueToObject("job"),
+ MatcherValueToObject("cluster")
+ ];
+ matcher.suggestions.values = [
+ MatcherValueToObject("foo"),
+ MatcherValueToObject("bar")
+ ];
+});
+
+const ShallowLabelNameInput = () => {
+ return shallow();
+};
+
+const MountedLabelNameInput = () => {
+ return mount();
+};
+
+const ValidateSuggestions = () => {
+ const tree = MountedLabelNameInput();
+ // click on the react-select component doesn't seem to trigger options
+ // rendering in tests, so change the input instead
+ tree.find("input").simulate("change", { target: { value: "f" } });
+ return tree;
+};
+
+describe("", () => {
+ it("matches snapshot", () => {
+ const tree = ShallowLabelNameInput();
+ expect(tree).toMatchSnapshot();
+ });
+
+ it("renders suggestions", () => {
+ const tree = ValidateSuggestions();
+ const options = tree.find("[role='option']");
+ expect(options).toHaveLength(2);
+ expect(options.at(0).text()).toBe("job");
+ expect(options.at(1).text()).toBe("cluster");
+ });
+
+ it("clicking on options updates the matcher", () => {
+ const tree = ValidateSuggestions();
+ const option = tree.find("[role='option']").at(0);
+ option.simulate("click");
+ expect(matcher.name).toBe("job");
+ });
+
+ it("populates suggestions on mount", done => {
+ fetch
+ .once(JSON.stringify(["name1", "name2", "name3"]))
+ .once(JSON.stringify(["value1", "value2", "value3"]));
+ ShallowLabelNameInput();
+ // use timeout since mount will call fetch
+ setTimeout(() => {
+ expect(matcher.suggestions.names).toHaveLength(3);
+ for (let i = 0; i < 3; i++) {
+ expect(matcher.suggestions.names[i]).toMatchObject(
+ MatcherValueToObject(`name${i + 1}`)
+ );
+ expect(matcher.suggestions.values[i]).toMatchObject(
+ MatcherValueToObject(`value${i + 1}`)
+ );
+ }
+ done();
+ }, 100);
+ });
+
+ it("suggestions are empited on failed fetch", done => {
+ fetch.mockReject(new Error("fake error message"));
+ ShallowLabelNameInput();
+ // use timeout since mount will call fetch
+ setTimeout(() => {
+ expect(matcher.suggestions.names).toHaveLength(0);
+ done();
+ }, 100);
+ });
+});
diff --git a/ui/src/Components/SilenceModal/LabelValueInput.test.js b/ui/src/Components/SilenceModal/LabelValueInput.test.js
new file mode 100644
index 000000000..2fc487d2d
--- /dev/null
+++ b/ui/src/Components/SilenceModal/LabelValueInput.test.js
@@ -0,0 +1,88 @@
+import React from "react";
+
+import { shallow, mount } from "enzyme";
+
+import { NewEmptyMatcher, MatcherValueToObject } from "Stores/SilenceFormStore";
+import { LabelValueInput } from "./LabelValueInput";
+
+let matcher;
+
+beforeEach(() => {
+ matcher = NewEmptyMatcher();
+ matcher.name = "name";
+ matcher.suggestions.names = [
+ MatcherValueToObject("job"),
+ MatcherValueToObject("cluster")
+ ];
+ matcher.suggestions.values = [
+ MatcherValueToObject("foo"),
+ MatcherValueToObject("bar")
+ ];
+});
+
+const ShallowLabelValueInput = () => {
+ return shallow();
+};
+
+const MountedLabelValueInput = () => {
+ return mount();
+};
+
+const ValidateSuggestions = () => {
+ const tree = MountedLabelValueInput();
+ // click on the react-select component doesn't seem to trigger options
+ // rendering in tests, so change the input instead
+ tree.find("input").simulate("change", { target: { value: "f" } });
+ return tree;
+};
+
+describe("", () => {
+ it("matches snapshot", () => {
+ const tree = ShallowLabelValueInput();
+ expect(tree).toMatchSnapshot();
+ });
+
+ it("renders suggestions", () => {
+ const tree = ValidateSuggestions();
+ const options = tree.find("[role='option']");
+ expect(options).toHaveLength(2);
+ expect(options.at(0).text()).toBe("foo");
+ expect(options.at(1).text()).toBe("bar");
+ });
+
+ it("clicking on options appends them to matcher.values", () => {
+ const tree = ValidateSuggestions();
+ const options = tree.find("[role='option']");
+ options.at(0).simulate("click");
+ options.at(1).simulate("click");
+ expect(matcher.values).toHaveLength(2);
+ expect(matcher.values).toContainEqual(MatcherValueToObject("foo"));
+ expect(matcher.values).toContainEqual(MatcherValueToObject("bar"));
+ });
+
+ it("selecting one option doesn't force matcher.isRegex=true", () => {
+ const tree = ValidateSuggestions();
+ expect(matcher.isRegex).toBe(false);
+ const options = tree.find("[role='option']");
+ options.at(0).simulate("click");
+ expect(matcher.isRegex).toBe(false);
+ });
+
+ it("selecting one option when matcher.isRegex=true changes it back to false", () => {
+ matcher.isRegex = true;
+ const tree = ValidateSuggestions();
+ expect(matcher.isRegex).toBe(true);
+ const options = tree.find("[role='option']");
+ options.at(0).simulate("click");
+ expect(matcher.isRegex).toBe(false);
+ });
+
+ it("selecting multiple options forces matcher.isRegex=true", () => {
+ const tree = ValidateSuggestions();
+ expect(matcher.isRegex).toBe(false);
+ const options = tree.find("[role='option']");
+ options.at(0).simulate("click");
+ options.at(1).simulate("click");
+ expect(matcher.isRegex).toBe(true);
+ });
+});
diff --git a/ui/src/Components/SilenceModal/__snapshots__/LabelNameInput.test.js.snap b/ui/src/Components/SilenceModal/__snapshots__/LabelNameInput.test.js.snap
new file mode 100644
index 000000000..402cf5405
--- /dev/null
+++ b/ui/src/Components/SilenceModal/__snapshots__/LabelNameInput.test.js.snap
@@ -0,0 +1,41 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[` matches snapshot 1`] = `
+
+`;
diff --git a/ui/src/Components/SilenceModal/__snapshots__/LabelValueInput.test.js.snap b/ui/src/Components/SilenceModal/__snapshots__/LabelValueInput.test.js.snap
new file mode 100644
index 000000000..bd95bf6d4
--- /dev/null
+++ b/ui/src/Components/SilenceModal/__snapshots__/LabelValueInput.test.js.snap
@@ -0,0 +1,37 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[` matches snapshot 1`] = `
+
+`;