diff --git a/ui/src/Components/Grid/AlertGrid/AlertGroup/Silence/index.test.js b/ui/src/Components/Grid/AlertGrid/AlertGroup/Silence/index.test.js
index dd23a3930..04a742b91 100644
--- a/ui/src/Components/Grid/AlertGrid/AlertGroup/Silence/index.test.js
+++ b/ui/src/Components/Grid/AlertGrid/AlertGroup/Silence/index.test.js
@@ -16,7 +16,6 @@ const mockAfterUpdate = jest.fn();
const alertmanager = {
name: "default",
- uri: "file:///mock",
state: "suppressed",
startsAt: "2000-01-01T10:00:00Z",
endsAt: "0001-01-01T00:00:00Z",
@@ -62,6 +61,7 @@ beforeEach(() => {
{
name: "default",
uri: "file:///mock",
+ publicURI: "http://example.com",
error: ""
}
]
@@ -78,12 +78,12 @@ afterEach(() => {
clear();
});
-const MountedSilence = () => {
+const MountedSilence = alertmanagerState => {
return mount(
@@ -91,27 +91,36 @@ const MountedSilence = () => {
);
};
+const ShallowSilenceDetails = () => {
+ return shallow(
+
+ );
+};
+
describe("", () => {
it("matches snapshot when data is present in alertStore", () => {
- const tree = MountedSilence().find("Silence");
+ const tree = MountedSilence(alertmanager).find("Silence");
expect(toDiffableHtml(tree.html())).toMatchSnapshot();
});
it("renders full silence when data is present in alertStore", () => {
- const tree = MountedSilence().find("Silence");
+ const tree = MountedSilence(alertmanager).find("Silence");
const fallback = tree.find("FallbackSilenceDesciption");
expect(fallback).toHaveLength(0);
});
it("matches snapshot when data is not present in alertStore", () => {
alertStore.data.silences = {};
- const tree = MountedSilence().find("Silence");
+ const tree = MountedSilence(alertmanager).find("Silence");
expect(toDiffableHtml(tree.html())).toMatchSnapshot();
});
it("renders FallbackSilenceDesciption when Alertmanager data is not present in alertStore", () => {
alertStore.data.silences = {};
- const tree = MountedSilence();
+ const tree = MountedSilence(alertmanager);
const fallback = tree.find("FallbackSilenceDesciption");
expect(fallback).toHaveLength(1);
expect(tree.text()).toBe(
@@ -121,7 +130,7 @@ describe("", () => {
it("renders FallbackSilenceDesciption when silence data is not present in alertStore", () => {
alertStore.data.silences.default = {};
- const tree = MountedSilence();
+ const tree = MountedSilence(alertmanager);
const fallback = tree.find("FallbackSilenceDesciption");
expect(fallback).toHaveLength(1);
expect(tree.text()).toBe(
@@ -130,7 +139,7 @@ describe("", () => {
});
it("clicking on expand toggle shows silence details", () => {
- const tree = MountedSilence();
+ const tree = MountedSilence(alertmanager);
const toggle = tree.find("a.float-right.cursor-pointer");
toggle.simulate("click");
const details = tree.find("SilenceDetails");
@@ -138,7 +147,7 @@ describe("", () => {
});
it("matches snapshot with expaned details", () => {
- const tree = MountedSilence().find("Silence");
+ const tree = MountedSilence(alertmanager).find("Silence");
tree.instance().collapse.toggle();
expect(toDiffableHtml(tree.html())).toMatchSnapshot();
});
@@ -146,26 +155,42 @@ describe("", () => {
it("renders comment as link when jiraURL is set", () => {
alertStore.data.silences.default[silence.id].jiraURL =
"http://jira.example.com";
- const tree = MountedSilence().find("Silence");
+ const tree = MountedSilence(alertmanager).find("Silence");
const link = tree.find("a[href='http://jira.example.com']");
expect(link).toHaveLength(1);
expect(link.text()).toBe("Fake silence");
});
it("clears progress timer on unmount", () => {
- const tree = MountedSilence().find("Silence");
+ const tree = MountedSilence(alertmanager).find("Silence");
const instance = tree.instance();
expect(instance.progressTimer).toBeTruthy();
instance.componentWillUnmount();
expect(instance.progressTimer).toBeNull();
});
-});
-const ShallowSilenceDetails = () => {
- return shallow(
-
- );
-};
+ it("getAlertmanager() returns alertmanager object from alertStore.data.upstreams.instances", () => {
+ const tree = MountedSilence(alertmanager).find("Silence");
+ const instance = tree.instance();
+ const am = instance.getAlertmanager();
+ expect(am).toEqual({
+ name: "default",
+ uri: "file:///mock",
+ publicURI: "http://example.com",
+ error: ""
+ });
+ });
+
+ it("getAlertmanager() return object with only name if given name is not in alertStore", () => {
+ const missingAlertmanager = { ...alertmanager, name: "notDefault" };
+ const tree = MountedSilence(missingAlertmanager).find("Silence");
+ const instance = tree.instance();
+ const am = instance.getAlertmanager();
+ expect(am).toEqual({
+ name: "notDefault"
+ });
+ });
+});
describe("", () => {
it("unexpired silence endsAt label uses 'secondary' class", () => {
@@ -180,25 +205,33 @@ describe("", () => {
const endsAt = tree.find("span.badge").at(1);
expect(endsAt.html()).toMatch(/badge-danger/);
});
+
+ it("id links to Alertmanager silence view via alertmanager.uri", () => {
+ const tree = ShallowSilenceDetails();
+ const link = tree.find("a");
+ expect(link.props().href).toBe(
+ "file:///mock/#/silences/4cf5fd82-1edd-4169-99d1-ff8415e72179"
+ );
+ });
});
describe("", () => {
it("renders with class 'danger' and no progressbar when expired", () => {
advanceTo(new Date(2001, 0, 1, 23, 0, 0));
- const tree = MountedSilence();
+ const tree = MountedSilence(alertmanager);
expect(tree.html()).toMatch(/badge-danger/);
expect(tree.text()).toMatch(/Expired a year ago/);
});
it("progressbar uses class 'danger' when > 90%", () => {
advanceTo(new Date(2000, 0, 1, 19, 30, 0));
- const tree = MountedSilence();
+ const tree = MountedSilence(alertmanager);
expect(tree.html()).toMatch(/progress-bar bg-danger/);
});
it("progressbar uses class 'danger' when > 75%", () => {
advanceTo(new Date(2000, 0, 1, 17, 45, 0));
- const tree = MountedSilence();
+ const tree = MountedSilence(alertmanager);
expect(tree.html()).toMatch(/progress-bar bg-warning/);
});
@@ -206,7 +239,7 @@ describe("", () => {
const startsAt = new Date(2000, 0, 1, 10, 0, 0);
const endsAt = new Date(2000, 0, 1, 20, 0, 0);
- const tree = MountedSilence().find("Silence");
+ const tree = MountedSilence(alertmanager).find("Silence");
const instance = tree.instance();
const value = toJS(instance.progress.value);
diff --git a/ui/src/Components/SilenceModal/SilenceModalContent.js b/ui/src/Components/SilenceModal/SilenceModalContent.js
index a975870ff..ff83d4493 100644
--- a/ui/src/Components/SilenceModal/SilenceModalContent.js
+++ b/ui/src/Components/SilenceModal/SilenceModalContent.js
@@ -47,6 +47,7 @@ const SilenceModalContent = observer(
{silenceFormStore.data.inProgress ? (
) : (
diff --git a/ui/src/Components/SilenceModal/SilenceSubmitController.js b/ui/src/Components/SilenceModal/SilenceSubmitController.js
index 93149add9..7a2de3f5c 100644
--- a/ui/src/Components/SilenceModal/SilenceSubmitController.js
+++ b/ui/src/Components/SilenceModal/SilenceSubmitController.js
@@ -8,11 +8,12 @@ import { SilenceSubmitProgress } from "./SilenceSubmitProgress";
class SilenceSubmitController extends Component {
static propTypes = {
+ alertStore: PropTypes.object.isRequired,
silenceFormStore: PropTypes.object.isRequired
};
render() {
- const { silenceFormStore } = this.props;
+ const { silenceFormStore, alertStore } = this.props;
return (
@@ -23,6 +24,7 @@ class SilenceSubmitController extends Component {
name={am.label}
uri={am.value}
payload={silenceFormStore.data.toAlertmanagerPayload}
+ alertStore={alertStore}
/>
))}
diff --git a/ui/src/Components/SilenceModal/SilenceSubmitController.test.js b/ui/src/Components/SilenceModal/SilenceSubmitController.test.js
index c8be7db3f..facc04ffc 100644
--- a/ui/src/Components/SilenceModal/SilenceSubmitController.test.js
+++ b/ui/src/Components/SilenceModal/SilenceSubmitController.test.js
@@ -2,21 +2,27 @@ import React from "react";
import { shallow } from "enzyme";
+import { AlertStore } from "Stores/AlertStore";
import {
SilenceFormStore,
MatcherValueToObject
} from "Stores/SilenceFormStore";
import { SilenceSubmitController } from "./SilenceSubmitController";
+let alertStore;
let silenceFormStore;
beforeEach(() => {
+ alertStore = new AlertStore([]);
silenceFormStore = new SilenceFormStore();
});
const ShallowSilenceSubmitController = () => {
return shallow(
-
+
);
};
diff --git a/ui/src/Components/SilenceModal/SilenceSubmitProgress.js b/ui/src/Components/SilenceModal/SilenceSubmitProgress.js
index a19fd2fa3..103f3a32e 100644
--- a/ui/src/Components/SilenceModal/SilenceSubmitProgress.js
+++ b/ui/src/Components/SilenceModal/SilenceSubmitProgress.js
@@ -46,7 +46,8 @@ const SilenceSubmitProgress = observer(
static propTypes = {
name: PropTypes.string.isRequired,
uri: PropTypes.string.isRequired,
- payload: PropTypes.object.isRequired
+ payload: PropTypes.object.isRequired,
+ alertStore: PropTypes.object.isRequired
};
submitState = observable(
@@ -83,13 +84,22 @@ const SilenceSubmitProgress = observer(
};
parseAlertmanagerResponse = response => {
- const { uri } = this.props;
+ const { name, alertStore } = this.props;
+
+ const alertmanager = alertStore.data.getAlertmanagerByName(name);
if (response.status === "success") {
- const link = (
-
- );
- this.submitState.markDone(link);
+ if (alertmanager) {
+ const link = (
+
+ );
+ this.submitState.markDone(link);
+ } else {
+ this.submitState.markDone(response.data.silenceId);
+ }
} else if (response.status === "error") {
this.submitState.markFailed(response.error);
} else {
diff --git a/ui/src/Components/SilenceModal/SilenceSubmitProgress.test.js b/ui/src/Components/SilenceModal/SilenceSubmitProgress.test.js
index eb64be239..355e1e159 100644
--- a/ui/src/Components/SilenceModal/SilenceSubmitProgress.test.js
+++ b/ui/src/Components/SilenceModal/SilenceSubmitProgress.test.js
@@ -2,14 +2,34 @@ import React from "react";
import { mount } from "enzyme";
+import toDiffableHtml from "diffable-html";
+
+import { AlertStore } from "Stores/AlertStore";
import { SilenceSubmitProgress } from "./SilenceSubmitProgress";
+let alertStore;
+
+beforeEach(() => {
+ alertStore = new AlertStore([]);
+ alertStore.data.upstreams = {
+ instances: [
+ {
+ name: "mockAlertmanager",
+ uri: "file:///mock",
+ publicURI: "http://example.com",
+ error: ""
+ }
+ ]
+ };
+});
+
const MountedSilenceSubmitProgress = () => {
return mount(
);
};
@@ -49,6 +69,21 @@ describe("", () => {
expect(silenceLink.text()).toBe("123456789");
});
+ it("renders returned silence ID as text if alertmanager is not found in AlertStore", async () => {
+ fetch.mockResponseOnce(
+ JSON.stringify({ status: "success", data: { silenceId: "123456789" } })
+ );
+ alertStore.data.upstreams.instances = [];
+ const tree = MountedSilenceSubmitProgress();
+ await expect(tree.instance().submitState.fetch).resolves.toBe("success");
+ // force re-render
+ tree.update();
+ const silenceLink = tree.find("a");
+ expect(silenceLink).toHaveLength(0);
+ const idDiv = tree.find("div.flex-fill").at(2);
+ expect(toDiffableHtml(idDiv.html())).toMatchSnapshot();
+ });
+
it("renders returned error message on failed fetch", async () => {
fetch.mockRejectOnce(new Error("mock error message"));
const tree = MountedSilenceSubmitProgress();
diff --git a/ui/src/Components/SilenceModal/__snapshots__/SilenceSubmitProgress.test.js.snap b/ui/src/Components/SilenceModal/__snapshots__/SilenceSubmitProgress.test.js.snap
new file mode 100644
index 000000000..23a21fae0
--- /dev/null
+++ b/ui/src/Components/SilenceModal/__snapshots__/SilenceSubmitProgress.test.js.snap
@@ -0,0 +1,9 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[` renders returned silence ID as text if alertmanager is not found in AlertStore 1`] = `
+"
+
+ 123456789
+
+"
+`;
diff --git a/ui/src/Stores/AlertStore.js b/ui/src/Stores/AlertStore.js
index 1380ff992..3bb9362e8 100644
--- a/ui/src/Stores/AlertStore.js
+++ b/ui/src/Stores/AlertStore.js
@@ -134,9 +134,12 @@ class AlertStore {
counters: {},
groups: {},
silences: {},
- upstreams: { instances: [] }
+ upstreams: { instances: [] },
+ getAlertmanagerByName(name) {
+ return this.upstreams.instances.find(am => am.name === name);
+ }
},
- {},
+ { getAlertmanagerByName: action },
{ name: "API Response data" }
);