", () => {
expect(silenceFormStore.toggle.blurred).toBe(false);
});
- it("renders ProgressMessage while loading preview", () => {
- useFetchGet.fetch.setMockedData({
- response: null,
- error: false,
- isLoading: true,
- isRetrying: false,
- });
- const tree = MountedDeleteSilenceModalContent();
- expect(tree.find("ProgressMessage")).toHaveLength(1);
- });
-
- it("renders LabelSetList with StaticLabel on mount", () => {
- const tree = MountedDeleteSilenceModalContent();
- expect(tree.find("LabelSetList")).toHaveLength(1);
- expect(tree.find("StaticLabel")).toHaveLength(3);
- });
-
- it("renders empty LabelSetList with empty response", () => {
- useFetchGet.fetch.setMockedData({
- response: EmptyAPIResponse(),
- error: false,
- isLoading: false,
- isRetrying: false,
- });
- const tree = MountedDeleteSilenceModalContent();
- expect(tree.find("LabelSetList")).toHaveLength(1);
- expect(tree.find("StaticLabel")).toHaveLength(0);
- });
-
- it("fetches affected alerts on mount", () => {
- MountedDeleteSilenceModalContent();
- expect(useFetchGet).toHaveBeenCalled();
- });
-
- it("renders StaticLabel after fetch", () => {
- const tree = MountedDeleteSilenceModalContent();
- expect(tree.text()).toMatch(/Affected alerts/);
- expect(tree.find("StaticLabel")).toHaveLength(3);
- });
-
- it("handles empty grid response correctly", () => {
- useFetchGet.fetch.setMockedData({
- response: EmptyAPIResponse(),
- error: false,
- isLoading: false,
- isRetrying: false,
- });
- const tree = MountedDeleteSilenceModalContent();
- expect(tree.text()).toMatch(/No alerts matched/);
- });
-
- it("renders ErrorMessage on failed preview fetch", () => {
- useFetchGet.fetch.setMockedData({
- response: null,
- error: "fake error",
- isLoading: false,
- isRetrying: false,
- });
- const tree = MountedDeleteSilenceModalContent();
- expect(tree.find("ErrorMessage")).toHaveLength(1);
- });
-
it("sends a DELETE request after clicking 'Confirm' button", () => {
const tree = MountedDeleteSilenceModalContent();
tree.find(".btn-danger").simulate("click");
diff --git a/ui/src/Components/PaginatedAlertList/index.js b/ui/src/Components/PaginatedAlertList/index.js
new file mode 100644
index 000000000..efe3bfe0a
--- /dev/null
+++ b/ui/src/Components/PaginatedAlertList/index.js
@@ -0,0 +1,60 @@
+import React from "react";
+import PropTypes from "prop-types";
+
+import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
+import { faExclamationCircle } from "@fortawesome/free-solid-svg-icons/faExclamationCircle";
+import { faSpinner } from "@fortawesome/free-solid-svg-icons/faSpinner";
+
+import { AlertStore, FormatBackendURI, FormatAlertsQ } from "Stores/AlertStore";
+import {
+ LabelSetList,
+ GroupListToUniqueLabelsList,
+} from "Components/LabelSetList";
+import { useFetchGet } from "Hooks/useFetchGet";
+
+const FetchError = ({ message }) => (
+
+);
+FetchError.propTypes = {
+ message: PropTypes.node.isRequired,
+};
+
+const Placeholder = () => (
+
+
+
+
+
+);
+
+const PaginatedAlertList = ({ alertStore, filters, title }) => {
+ const { response, error, isLoading } = useFetchGet(
+ FormatBackendURI("alerts.json?") + FormatAlertsQ(filters)
+ );
+
+ return isLoading ? (
+
+ ) : error ? (
+
+ ) : (
+
+ );
+};
+PaginatedAlertList.propTypes = {
+ alertStore: PropTypes.instanceOf(AlertStore).isRequired,
+ filters: PropTypes.arrayOf(PropTypes.string).isRequired,
+ title: PropTypes.string,
+};
+
+export { PaginatedAlertList };
diff --git a/ui/src/Components/PaginatedAlertList/index.test.js b/ui/src/Components/PaginatedAlertList/index.test.js
new file mode 100644
index 000000000..fab2dab01
--- /dev/null
+++ b/ui/src/Components/PaginatedAlertList/index.test.js
@@ -0,0 +1,125 @@
+import React from "react";
+
+import { mount } from "enzyme";
+
+import { advanceTo, clear } from "jest-date-mock";
+
+import { EmptyAPIResponse } from "__mocks__/Fetch";
+import { AlertStore } from "Stores/AlertStore";
+import { useFetchGet } from "Hooks/useFetchGet";
+import { useFetchDelete } from "Hooks/useFetchDelete";
+import { PaginatedAlertList } from ".";
+
+let alertStore;
+
+beforeEach(() => {
+ advanceTo(new Date(Date.UTC(2000, 0, 1, 0, 30, 0)));
+ jest.useFakeTimers();
+
+ alertStore = new AlertStore([]);
+
+ alertStore.data.upstreams = {
+ instances: [
+ {
+ name: "am1",
+ cluster: "am",
+ uri: "http://localhost:9093",
+ readonly: false,
+ error: "",
+ version: "0.17.0",
+ headers: {},
+ corsCredentials: "include",
+ clusterMembers: ["am1"],
+ },
+ ],
+ clusters: { am: ["am1"] },
+ };
+});
+
+afterEach(() => {
+ jest.restoreAllMocks();
+ useFetchGet.mockReset();
+ useFetchDelete.mockReset();
+ clear();
+ document.body.className = "";
+});
+
+describe("
", () => {
+ it("renders Placeholder while loading preview", () => {
+ useFetchGet.fetch.setMockedData({
+ response: null,
+ error: false,
+ isLoading: true,
+ isRetrying: false,
+ });
+ const tree = mount(
+
+ );
+ expect(tree.find("Placeholder")).toHaveLength(1);
+ });
+
+ it("renders LabelSetList with StaticLabel on mount", () => {
+ const tree = mount(
+
+ );
+ expect(tree.find("LabelSetList")).toHaveLength(1);
+ expect(tree.find("StaticLabel")).toHaveLength(3);
+ });
+
+ it("renders empty LabelSetList with empty response", () => {
+ useFetchGet.fetch.setMockedData({
+ response: EmptyAPIResponse(),
+ error: false,
+ isLoading: false,
+ isRetrying: false,
+ });
+ const tree = mount(
+
+ );
+ expect(tree.find("LabelSetList")).toHaveLength(1);
+ expect(tree.find("StaticLabel")).toHaveLength(0);
+ });
+
+ it("fetches affected alerts on mount", () => {
+ mount(
);
+ expect(useFetchGet).toHaveBeenCalled();
+ });
+
+ it("renders StaticLabel after fetch", () => {
+ const tree = mount(
+
+ );
+ expect(tree.text()).toMatch(/Affected alerts/);
+ expect(tree.find("StaticLabel")).toHaveLength(3);
+ });
+
+ it("handles empty grid response correctly", () => {
+ useFetchGet.fetch.setMockedData({
+ response: EmptyAPIResponse(),
+ error: false,
+ isLoading: false,
+ isRetrying: false,
+ });
+ const tree = mount(
+
+ );
+ expect(tree.text()).toMatch(/No alerts matched/);
+ });
+
+ it("renders FetchError on failed preview fetch", () => {
+ useFetchGet.fetch.setMockedData({
+ response: null,
+ error: "fake error",
+ isLoading: false,
+ isRetrying: false,
+ });
+ const tree = mount(
+
+ );
+ expect(tree.find("FetchError")).toHaveLength(1);
+ });
+});
diff --git a/ui/src/Components/SilenceModal/SilencePreview/index.js b/ui/src/Components/SilenceModal/SilencePreview/index.js
index ac9f83aeb..a91000eaa 100644
--- a/ui/src/Components/SilenceModal/SilencePreview/index.js
+++ b/ui/src/Components/SilenceModal/SilencePreview/index.js
@@ -4,63 +4,26 @@ import PropTypes from "prop-types";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faArrowLeft } from "@fortawesome/free-solid-svg-icons/faArrowLeft";
import { faCheckCircle } from "@fortawesome/free-solid-svg-icons/faCheckCircle";
-import { faExclamationCircle } from "@fortawesome/free-solid-svg-icons/faExclamationCircle";
-import { faSpinner } from "@fortawesome/free-solid-svg-icons/faSpinner";
-import { AlertStore, FormatBackendURI, FormatAlertsQ } from "Stores/AlertStore";
+import { AlertStore } from "Stores/AlertStore";
import { SilenceFormStore } from "Stores/SilenceFormStore";
-import {
- LabelSetList,
- GroupListToUniqueLabelsList,
-} from "Components/LabelSetList";
-import { useFetchGet } from "Hooks/useFetchGet";
+import { PaginatedAlertList } from "Components/PaginatedAlertList";
import { MatcherToFilter, AlertManagersToFilter } from "../Matchers";
-const FetchError = ({ message }) => (
-
-);
-FetchError.propTypes = {
- message: PropTypes.node.isRequired,
-};
-
-const Placeholder = () => (
-
-
-
-
-
-);
-
const SilencePreview = ({ alertStore, silenceFormStore }) => {
const filters = [
...silenceFormStore.data.matchers.map((m) => MatcherToFilter(m)),
AlertManagersToFilter(silenceFormStore.data.alertmanagers),
];
- const { response, error, isLoading } = useFetchGet(
- FormatBackendURI("alerts.json?") + FormatAlertsQ(filters)
- );
-
return (
- {isLoading ? (
-
- ) : error ? (
-
- ) : (
-
- )}
+