mirror of
https://github.com/prymitive/karma
synced 2026-05-05 03:16:51 +00:00
feat(ui): use alertList endpoint for silence previews
This commit is contained in:
committed by
Łukasz Mierzwa
parent
f13cd9a112
commit
daffb98381
@@ -1,5 +1,11 @@
|
||||
# Changelog
|
||||
|
||||
## [unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- Added dedicated API endpoint for silence previews.
|
||||
|
||||
## v0.87
|
||||
|
||||
### Added
|
||||
|
||||
@@ -1,33 +1,10 @@
|
||||
import { FC, useState } from "react";
|
||||
|
||||
import type { AlertStore } from "Stores/AlertStore";
|
||||
import type { APIAlertGroupT } from "Models/APITypes";
|
||||
import { IsMobile } from "Common/Device";
|
||||
import { hashObject } from "Common/Hash";
|
||||
import StaticLabel from "Components/Labels/StaticLabel";
|
||||
import { PageSelect } from "Components/Pagination";
|
||||
|
||||
// take a list of groups and outputs a list of label sets, this ignores
|
||||
// the receiver, so we'll end up with only unique alerts
|
||||
const GroupListToUniqueLabelsList = (
|
||||
groups: APIAlertGroupT[]
|
||||
): { [labelName: string]: string }[] => {
|
||||
const alerts: { [alertHash: string]: { [labelName: string]: string } } = {};
|
||||
for (const group of groups) {
|
||||
for (const alert of group.alerts) {
|
||||
const alertLabels = Object.assign(
|
||||
{},
|
||||
group.labels,
|
||||
group.shared.labels,
|
||||
alert.labels
|
||||
);
|
||||
const alertHash = hashObject(alertLabels);
|
||||
alerts[alertHash] = alertLabels;
|
||||
}
|
||||
}
|
||||
return Object.values(alerts);
|
||||
};
|
||||
|
||||
const LabelSetList: FC<{
|
||||
alertStore: AlertStore;
|
||||
labelsList: { [labelName: string]: string }[];
|
||||
@@ -77,4 +54,4 @@ const LabelSetList: FC<{
|
||||
);
|
||||
};
|
||||
|
||||
export { LabelSetList, GroupListToUniqueLabelsList };
|
||||
export { LabelSetList };
|
||||
|
||||
@@ -3,7 +3,6 @@ import { mount } from "enzyme";
|
||||
import { advanceTo, clear } from "jest-date-mock";
|
||||
|
||||
import { useFetchGetMock } from "__fixtures__/useFetchGet";
|
||||
import { EmptyAPIResponse } from "__fixtures__/Fetch";
|
||||
import { AlertStore } from "Stores/AlertStore";
|
||||
import { useFetchGet } from "Hooks/useFetchGet";
|
||||
import { PaginatedAlertList } from ".";
|
||||
@@ -76,6 +75,23 @@ describe("<PaginatedAlertList />", () => {
|
||||
});
|
||||
|
||||
it("renders LabelSetList with StaticLabel on mount", () => {
|
||||
useFetchGetMock.fetch.setMockedData({
|
||||
response: {
|
||||
alerts: [
|
||||
{
|
||||
alertname: "Fake Alert",
|
||||
foo: "1",
|
||||
bar: "2",
|
||||
},
|
||||
],
|
||||
},
|
||||
error: undefined,
|
||||
isLoading: false,
|
||||
isRetrying: false,
|
||||
retryCount: 0,
|
||||
get: jest.fn(),
|
||||
cancelGet: jest.fn(),
|
||||
});
|
||||
const tree = mount(
|
||||
<PaginatedAlertList alertStore={alertStore} filters={["foo=bar"]} />
|
||||
);
|
||||
@@ -85,7 +101,7 @@ describe("<PaginatedAlertList />", () => {
|
||||
|
||||
it("renders empty LabelSetList with empty response", () => {
|
||||
useFetchGetMock.fetch.setMockedData({
|
||||
response: EmptyAPIResponse(),
|
||||
response: { alerts: [] },
|
||||
error: null,
|
||||
isLoading: false,
|
||||
isRetrying: false,
|
||||
@@ -106,6 +122,23 @@ describe("<PaginatedAlertList />", () => {
|
||||
});
|
||||
|
||||
it("renders StaticLabel after fetch", () => {
|
||||
useFetchGetMock.fetch.setMockedData({
|
||||
response: {
|
||||
alerts: [
|
||||
{
|
||||
alertname: "Fake Alert",
|
||||
foo: "1",
|
||||
bar: "2",
|
||||
},
|
||||
],
|
||||
},
|
||||
error: undefined,
|
||||
isLoading: false,
|
||||
isRetrying: false,
|
||||
retryCount: 0,
|
||||
get: jest.fn(),
|
||||
cancelGet: jest.fn(),
|
||||
});
|
||||
const tree = mount(
|
||||
<PaginatedAlertList
|
||||
alertStore={alertStore}
|
||||
@@ -119,7 +152,7 @@ describe("<PaginatedAlertList />", () => {
|
||||
|
||||
it("handles empty grid response correctly", () => {
|
||||
useFetchGetMock.fetch.setMockedData({
|
||||
response: EmptyAPIResponse(),
|
||||
response: { alerts: [] },
|
||||
error: null,
|
||||
isLoading: false,
|
||||
isRetrying: false,
|
||||
|
||||
@@ -4,12 +4,9 @@ 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 type { APIAlertsResponseT } from "Models/APITypes";
|
||||
import type { AlertListResponseT } from "Models/APITypes";
|
||||
import { AlertStore, FormatBackendURI, FormatAlertsQ } from "Stores/AlertStore";
|
||||
import {
|
||||
LabelSetList,
|
||||
GroupListToUniqueLabelsList,
|
||||
} from "Components/LabelSetList";
|
||||
import { LabelSetList } from "Components/LabelSetList";
|
||||
import { useFetchGet } from "Hooks/useFetchGet";
|
||||
|
||||
const FetchError: FC<{ message: ReactNode }> = ({ message }) => (
|
||||
@@ -34,8 +31,8 @@ const PaginatedAlertList: FC<{
|
||||
filters: string[];
|
||||
title?: string;
|
||||
}> = ({ alertStore, filters, title }) => {
|
||||
const { response, error, isLoading } = useFetchGet<APIAlertsResponseT>(
|
||||
FormatBackendURI("alerts.json?") + FormatAlertsQ(filters)
|
||||
const { response, error, isLoading } = useFetchGet<AlertListResponseT>(
|
||||
FormatBackendURI("alertList.json?") + FormatAlertsQ(filters)
|
||||
);
|
||||
|
||||
return error ? (
|
||||
@@ -45,9 +42,7 @@ const PaginatedAlertList: FC<{
|
||||
) : (
|
||||
<LabelSetList
|
||||
alertStore={alertStore}
|
||||
labelsList={GroupListToUniqueLabelsList(
|
||||
response.grids.length ? response.grids[0].alertGroups : []
|
||||
)}
|
||||
labelsList={response.alerts}
|
||||
title={title}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -3,7 +3,6 @@ import { mount } from "enzyme";
|
||||
import toDiffableHtml from "diffable-html";
|
||||
|
||||
import { useFetchGetMock } from "__fixtures__/useFetchGet";
|
||||
import { EmptyAPIResponse } from "__fixtures__/Fetch";
|
||||
import {
|
||||
SilenceFormStore,
|
||||
NewEmptyMatcher,
|
||||
@@ -35,6 +34,15 @@ const MountedMatchCounter = () => {
|
||||
|
||||
describe("<MatchCounter />", () => {
|
||||
it("matches snapshot", () => {
|
||||
useFetchGetMock.fetch.setMockedData({
|
||||
response: { alerts: Array(25).map((i) => ({ alertname: `alert${i}` })) },
|
||||
error: null,
|
||||
isLoading: false,
|
||||
isRetrying: false,
|
||||
retryCount: 0,
|
||||
get: jest.fn(),
|
||||
cancelGet: jest.fn(),
|
||||
});
|
||||
const tree = MountedMatchCounter();
|
||||
expect(toDiffableHtml(tree.html())).toMatchSnapshot();
|
||||
});
|
||||
@@ -86,10 +94,8 @@ describe("<MatchCounter />", () => {
|
||||
});
|
||||
|
||||
it("totalAlerts is 0 after mount", () => {
|
||||
const r = EmptyAPIResponse();
|
||||
r.totalAlerts = 0;
|
||||
useFetchGetMock.fetch.setMockedData({
|
||||
response: r,
|
||||
response: { alerts: [] },
|
||||
error: null,
|
||||
isLoading: false,
|
||||
isRetrying: false,
|
||||
@@ -103,6 +109,15 @@ describe("<MatchCounter />", () => {
|
||||
});
|
||||
|
||||
it("updates totalAlerts after successful fetch", () => {
|
||||
useFetchGetMock.fetch.setMockedData({
|
||||
response: { alerts: Array(25).map((i) => ({ alertname: `alert${i}` })) },
|
||||
error: null,
|
||||
isLoading: false,
|
||||
isRetrying: false,
|
||||
retryCount: 0,
|
||||
get: jest.fn(),
|
||||
cancelGet: jest.fn(),
|
||||
});
|
||||
const tree = MountedMatchCounter();
|
||||
expect(tree.text()).toBe("25");
|
||||
});
|
||||
@@ -111,7 +126,7 @@ describe("<MatchCounter />", () => {
|
||||
MountedMatchCounter();
|
||||
expect(
|
||||
(useFetchGet as jest.MockedFunction<typeof useFetchGet>).mock.calls[0][0]
|
||||
).toBe("./alerts.json?q=foo%3Dbar");
|
||||
).toBe("./alertList.json?q=foo%3Dbar");
|
||||
});
|
||||
|
||||
it("sends correct query string for a 'foo=~bar' matcher", () => {
|
||||
@@ -119,7 +134,7 @@ describe("<MatchCounter />", () => {
|
||||
MountedMatchCounter();
|
||||
expect(
|
||||
(useFetchGet as jest.MockedFunction<typeof useFetchGet>).mock.calls[0][0]
|
||||
).toBe("./alerts.json?q=foo%3D~%5Ebar%24");
|
||||
).toBe("./alertList.json?q=foo%3D~%5Ebar%24");
|
||||
});
|
||||
|
||||
it("sends correct query string for a 'foo=~(bar|baz)' matcher", () => {
|
||||
@@ -129,7 +144,7 @@ describe("<MatchCounter />", () => {
|
||||
MountedMatchCounter();
|
||||
expect(
|
||||
(useFetchGet as jest.MockedFunction<typeof useFetchGet>).mock.calls[0][0]
|
||||
).toBe("./alerts.json?q=foo%3D~%5E%28bar%7Cbaz%29%24");
|
||||
).toBe("./alertList.json?q=foo%3D~%5E%28bar%7Cbaz%29%24");
|
||||
});
|
||||
|
||||
it("selecting one Alertmanager instance appends it to the filters", () => {
|
||||
@@ -142,7 +157,7 @@ describe("<MatchCounter />", () => {
|
||||
MountedMatchCounter();
|
||||
expect(
|
||||
(useFetchGet as jest.MockedFunction<typeof useFetchGet>).mock.calls[0][0]
|
||||
).toBe("./alerts.json?q=foo%3Dbar&q=%40alertmanager%3D~%5E%28am1%29%24");
|
||||
).toBe("./alertList.json?q=foo%3Dbar&q=%40alertmanager%3D~%5E%28am1%29%24");
|
||||
});
|
||||
|
||||
it("selecting two Alertmanager instances appends it correctly to the filters", () => {
|
||||
@@ -160,7 +175,7 @@ describe("<MatchCounter />", () => {
|
||||
expect(
|
||||
(useFetchGet as jest.MockedFunction<typeof useFetchGet>).mock.calls[0][0]
|
||||
).toBe(
|
||||
"./alerts.json?q=foo%3Dbar&q=%40alertmanager%3D~%5E%28am1%7Cam2%29%24"
|
||||
"./alertList.json?q=foo%3Dbar&q=%40alertmanager%3D~%5E%28am1%7Cam2%29%24"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@ 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 type { APIAlertsResponseT } from "Models/APITypes";
|
||||
import type { AlertListResponseT } from "Models/APITypes";
|
||||
import { FormatBackendURI, FormatAlertsQ } from "Stores/AlertStore";
|
||||
import type { SilenceFormStore, MatcherWithIDT } from "Stores/SilenceFormStore";
|
||||
import { TooltipWrapper } from "Components/TooltipWrapper";
|
||||
@@ -23,8 +23,8 @@ const MatchCounter: FC<{
|
||||
}
|
||||
|
||||
const { response, error, isLoading, isRetrying } =
|
||||
useFetchGet<APIAlertsResponseT>(
|
||||
FormatBackendURI("alerts.json?") + FormatAlertsQ(filters)
|
||||
useFetchGet<AlertListResponseT>(
|
||||
FormatBackendURI("alertList.json?") + FormatAlertsQ(filters)
|
||||
);
|
||||
|
||||
return error ? (
|
||||
@@ -47,7 +47,7 @@ const MatchCounter: FC<{
|
||||
className={isRetrying ? "text-danger" : ""}
|
||||
/>
|
||||
) : (
|
||||
Math.max(response.totalAlerts, 0)
|
||||
response.alerts.length
|
||||
)}
|
||||
</span>
|
||||
</TooltipWrapper>
|
||||
|
||||
@@ -9,87 +9,79 @@ exports[`<SilencePreview /> matches snapshot 1`] = `
|
||||
</p>
|
||||
<div>
|
||||
<ul class=\\"list-group list-group-flush mb-3\\">
|
||||
<li class=\\"list-group-item px-0 pt-2 pb-1\\">
|
||||
<span class=\\"components-label badge bg-dark components-label-dark \\">
|
||||
<span class=\\"components-label-name\\">
|
||||
alertname:
|
||||
</span>
|
||||
<span class=\\"components-label-value\\">
|
||||
foo
|
||||
</span>
|
||||
</span>
|
||||
<span class=\\"components-label badge bg-default components-label-dark \\">
|
||||
<span class=\\"components-label-name\\">
|
||||
job:
|
||||
</span>
|
||||
<span class=\\"components-label-value\\">
|
||||
foo
|
||||
</span>
|
||||
</span>
|
||||
<span class=\\"components-label badge bg-default components-label-dark \\">
|
||||
<span class=\\"components-label-name\\">
|
||||
instance:
|
||||
</span>
|
||||
<span class=\\"components-label-value\\">
|
||||
foo1
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
<li class=\\"list-group-item px-0 pt-2 pb-1\\">
|
||||
<span class=\\"components-label badge bg-dark components-label-dark \\">
|
||||
<span class=\\"components-label-name\\">
|
||||
alertname:
|
||||
</span>
|
||||
<span class=\\"components-label-value\\">
|
||||
bar
|
||||
</span>
|
||||
</span>
|
||||
<span class=\\"components-label badge bg-default components-label-dark \\">
|
||||
<span class=\\"components-label-name\\">
|
||||
job:
|
||||
</span>
|
||||
<span class=\\"components-label-value\\">
|
||||
bar
|
||||
</span>
|
||||
</span>
|
||||
<span class=\\"components-label badge bg-default components-label-dark \\">
|
||||
<span class=\\"components-label-name\\">
|
||||
instance:
|
||||
</span>
|
||||
<span class=\\"components-label-value\\">
|
||||
bar1
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
<li class=\\"list-group-item px-0 pt-2 pb-1\\">
|
||||
<span class=\\"components-label badge bg-dark components-label-dark \\">
|
||||
<span class=\\"components-label-name\\">
|
||||
alertname:
|
||||
</span>
|
||||
<span class=\\"components-label-value\\">
|
||||
bar
|
||||
</span>
|
||||
</span>
|
||||
<span class=\\"components-label badge bg-default components-label-dark \\">
|
||||
<span class=\\"components-label-name\\">
|
||||
job:
|
||||
</span>
|
||||
<span class=\\"components-label-value\\">
|
||||
bar
|
||||
</span>
|
||||
</span>
|
||||
<span class=\\"components-label badge bg-default components-label-dark \\">
|
||||
<span class=\\"components-label-name\\">
|
||||
instance:
|
||||
</span>
|
||||
<span class=\\"components-label-value\\">
|
||||
bar2
|
||||
</span>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class=\\"components-pagination\\">
|
||||
<div class=\\"mt-3\\">
|
||||
<ul class=\\"pagination justify-content-center\\">
|
||||
<li class=\\"page-item disabled\\">
|
||||
<a class=\\"page-link\\"
|
||||
href=\\"#\\"
|
||||
aria-label=\\"Go to previous page\\"
|
||||
>
|
||||
<svg aria-hidden=\\"true\\"
|
||||
focusable=\\"false\\"
|
||||
data-prefix=\\"fas\\"
|
||||
data-icon=\\"angle-left\\"
|
||||
class=\\"svg-inline--fa fa-angle-left fa-w-8 \\"
|
||||
role=\\"img\\"
|
||||
xmlns=\\"http://www.w3.org/2000/svg\\"
|
||||
viewbox=\\"0 0 256 512\\"
|
||||
>
|
||||
<path fill=\\"currentColor\\"
|
||||
d=\\"M31.7 239l136-136c9.4-9.4 24.6-9.4 33.9 0l22.6 22.6c9.4 9.4 9.4 24.6 0 33.9L127.9 256l96.4 96.4c9.4 9.4 9.4 24.6 0 33.9L201.7 409c-9.4 9.4-24.6 9.4-33.9 0l-136-136c-9.5-9.4-9.5-24.6-.1-34z\\"
|
||||
>
|
||||
</path>
|
||||
</svg>
|
||||
</a>
|
||||
</li>
|
||||
<li class=\\"page-item active\\">
|
||||
<a class=\\"page-link font-weight-bold\\"
|
||||
href=\\"#\\"
|
||||
aria-label=\\"Go to page number 1\\"
|
||||
>
|
||||
1
|
||||
</a>
|
||||
</li>
|
||||
<li class=\\"page-item\\">
|
||||
<a class=\\"page-link\\"
|
||||
href=\\"#\\"
|
||||
aria-label=\\"Go to page number 2\\"
|
||||
>
|
||||
2
|
||||
</a>
|
||||
</li>
|
||||
<li class=\\"page-item\\">
|
||||
<a class=\\"page-link\\"
|
||||
href=\\"#\\"
|
||||
aria-label=\\"Go to page number 3\\"
|
||||
>
|
||||
3
|
||||
</a>
|
||||
</li>
|
||||
<li class=\\"page-item\\">
|
||||
<a class=\\"page-link\\"
|
||||
href=\\"#\\"
|
||||
aria-label=\\"Go to next page\\"
|
||||
>
|
||||
<svg aria-hidden=\\"true\\"
|
||||
focusable=\\"false\\"
|
||||
data-prefix=\\"fas\\"
|
||||
data-icon=\\"angle-right\\"
|
||||
class=\\"svg-inline--fa fa-angle-right fa-w-8 \\"
|
||||
role=\\"img\\"
|
||||
xmlns=\\"http://www.w3.org/2000/svg\\"
|
||||
viewbox=\\"0 0 256 512\\"
|
||||
>
|
||||
<path fill=\\"currentColor\\"
|
||||
d=\\"M224.3 273l-136 136c-9.4 9.4-24.6 9.4-33.9 0l-22.6-22.6c-9.4-9.4-9.4-24.6 0-33.9l96.4-96.4-96.4-96.4c-9.4-9.4-9.4-24.6 0-33.9L54.3 103c9.4-9.4 24.6-9.4 33.9 0l136 136c9.5 9.4 9.5 24.6.1 34z\\"
|
||||
>
|
||||
</path>
|
||||
</svg>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,8 +2,6 @@ import { mount } from "enzyme";
|
||||
|
||||
import toDiffableHtml from "diffable-html";
|
||||
|
||||
import { EmptyAPIResponse } from "__fixtures__/Fetch";
|
||||
import { MockAlertGroup, MockAlert } from "__fixtures__/Alerts";
|
||||
import { AlertStore } from "Stores/AlertStore";
|
||||
import { SilenceFormStore, NewEmptyMatcher } from "Stores/SilenceFormStore";
|
||||
import { useFetchGet } from "Hooks/useFetchGet";
|
||||
@@ -30,43 +28,6 @@ afterEach(() => {
|
||||
(useFetchGet as jest.MockedFunction<typeof useFetchGetMock>).mockReset();
|
||||
});
|
||||
|
||||
const MockAPIResponse = () => {
|
||||
const response = EmptyAPIResponse();
|
||||
|
||||
response.grids = [
|
||||
{
|
||||
labelName: "",
|
||||
labelValue: "",
|
||||
alertGroups: [
|
||||
MockAlertGroup(
|
||||
{ alertname: "foo" },
|
||||
[MockAlert([], { instance: "foo1" }, "active")],
|
||||
[],
|
||||
{ job: "foo" },
|
||||
{}
|
||||
),
|
||||
MockAlertGroup(
|
||||
{ alertname: "bar" },
|
||||
[
|
||||
MockAlert([], { instance: "bar1" }, "active"),
|
||||
MockAlert([], { instance: "bar2" }, "active"),
|
||||
],
|
||||
[],
|
||||
{ job: "bar" },
|
||||
{}
|
||||
),
|
||||
],
|
||||
totalGroups: 2,
|
||||
stateCount: {
|
||||
unprocessed: 1,
|
||||
suppressed: 2,
|
||||
active: 3,
|
||||
},
|
||||
},
|
||||
];
|
||||
return response;
|
||||
};
|
||||
|
||||
const MountedSilencePreview = () => {
|
||||
return mount(
|
||||
<SilencePreview
|
||||
@@ -88,7 +49,7 @@ describe("<SilencePreview />", () => {
|
||||
]);
|
||||
MountedSilencePreview();
|
||||
expect(useFetchGet).toHaveBeenCalledWith(
|
||||
"./alerts.json?q=foo%3Dbar&q=%40alertmanager%3D~%5E%28amValue%29%24"
|
||||
"./alertList.json?q=foo%3Dbar&q=%40alertmanager%3D~%5E%28amValue%29%24"
|
||||
);
|
||||
});
|
||||
|
||||
@@ -98,13 +59,13 @@ describe("<SilencePreview />", () => {
|
||||
]);
|
||||
MountedSilencePreview();
|
||||
expect(useFetchGet).toHaveBeenCalledWith(
|
||||
"./alerts.json?q=foo%3Dbar&q=%40alertmanager%3D~%5E%28am1%7Cam2%29%24"
|
||||
"./alertList.json?q=foo%3Dbar&q=%40alertmanager%3D~%5E%28am1%7Cam2%29%24"
|
||||
);
|
||||
});
|
||||
|
||||
it("matches snapshot", () => {
|
||||
useFetchGetMock.fetch.setMockedData({
|
||||
response: MockAPIResponse(),
|
||||
response: { alerts: Array(25).map((i) => ({ alertname: `alert${i}` })) },
|
||||
error: undefined,
|
||||
isLoading: false,
|
||||
isRetrying: false,
|
||||
@@ -132,6 +93,15 @@ describe("<SilencePreview />", () => {
|
||||
});
|
||||
|
||||
it("renders StaticLabel after fetch", () => {
|
||||
useFetchGetMock.fetch.setMockedData({
|
||||
response: { alerts: [{ alertname: "Fake Alert", foo: "1", bar: "1" }] },
|
||||
error: undefined,
|
||||
isLoading: false,
|
||||
isRetrying: false,
|
||||
retryCount: 0,
|
||||
get: jest.fn(),
|
||||
cancelGet: jest.fn(),
|
||||
});
|
||||
const tree = MountedSilencePreview();
|
||||
expect(tree.text()).toMatch(/Affected alerts/);
|
||||
expect(tree.find("StaticLabel")).toHaveLength(3);
|
||||
@@ -139,7 +109,7 @@ describe("<SilencePreview />", () => {
|
||||
|
||||
it("handles empty grid response correctly", () => {
|
||||
useFetchGetMock.fetch.setMockedData({
|
||||
response: EmptyAPIResponse(),
|
||||
response: { alerts: [] },
|
||||
error: undefined,
|
||||
isLoading: false,
|
||||
isRetrying: false,
|
||||
|
||||
@@ -7,7 +7,7 @@ import { storiesOf } from "@storybook/react";
|
||||
import addHours from "date-fns/addHours";
|
||||
import addDays from "date-fns/addDays";
|
||||
|
||||
import { MockSilence } from "../../__fixtures__/Alerts";
|
||||
import { MockSilence, MockAlert } from "../../__fixtures__/Alerts";
|
||||
import { AlertStore } from "../../Stores/AlertStore";
|
||||
import { Settings } from "../../Stores/Settings";
|
||||
import {
|
||||
@@ -120,21 +120,21 @@ storiesOf("SilenceModal", module)
|
||||
silenceFormStore.tab.current = "editor";
|
||||
|
||||
fetchMock.mock(
|
||||
"begin:/alerts.json?q=cluster",
|
||||
{ totalAlerts: 0 },
|
||||
"begin:/alertList.json?q=cluster",
|
||||
{ alerts: [] },
|
||||
{
|
||||
overwriteRoutes: true,
|
||||
}
|
||||
);
|
||||
fetchMock.mock(
|
||||
"begin:/alerts.json?q=instance",
|
||||
{ totalAlerts: 23 },
|
||||
"begin:/alertList.json?q=instance",
|
||||
{ alerts: Array(23).fill(MockAlert([], {}, "active")) },
|
||||
{
|
||||
overwriteRoutes: true,
|
||||
}
|
||||
);
|
||||
fetchMock.mock(
|
||||
"begin:/alerts.json?q=tooLong",
|
||||
"begin:/alertList.json?q=tooLong",
|
||||
{
|
||||
body: "error",
|
||||
status: 503,
|
||||
|
||||
@@ -219,3 +219,7 @@ export interface HistoryResponseT {
|
||||
error: string;
|
||||
samples: HistorySampleT[];
|
||||
}
|
||||
|
||||
export interface AlertListResponseT {
|
||||
alerts: LabelsT[];
|
||||
}
|
||||
|
||||
@@ -2,9 +2,18 @@ import { useState, useEffect, useCallback } from "react";
|
||||
|
||||
import { MockAPIResponse, MockSilenceResponse } from "__fixtures__/Fetch";
|
||||
import type { FetchGetResultT } from "Hooks/useFetchGet";
|
||||
import type { APIAlertsResponseT, APIManagedSilenceT } from "Models/APITypes";
|
||||
import type {
|
||||
APIAlertsResponseT,
|
||||
APIManagedSilenceT,
|
||||
AlertListResponseT,
|
||||
} from "Models/APITypes";
|
||||
|
||||
type responseT = null | string[] | APIAlertsResponseT | APIManagedSilenceT[];
|
||||
type responseT =
|
||||
| null
|
||||
| string[]
|
||||
| APIAlertsResponseT
|
||||
| APIManagedSilenceT[]
|
||||
| AlertListResponseT;
|
||||
|
||||
interface mockedDataT {
|
||||
response: undefined | responseT;
|
||||
@@ -92,6 +101,10 @@ const useFetchGetMock = (
|
||||
re: /^\.\/alerts\.json\?q=/,
|
||||
response: MockAPIResponse(),
|
||||
},
|
||||
{
|
||||
re: /^\.\/alertList\.json\?q=/,
|
||||
response: { alerts: [{ instance: "foo" }] },
|
||||
},
|
||||
// silence browser
|
||||
{
|
||||
re: /^.\/silences\.json\?/,
|
||||
|
||||
Reference in New Issue
Block a user