mirror of
https://github.com/prymitive/karma
synced 2026-05-07 03:26:52 +00:00
fix(ui): add grid labels to history query
Grid labels got stripped from groups, so we need to manually include them in history queries
This commit is contained in:
committed by
Łukasz Mierzwa
parent
9aef8fb73f
commit
7d91b7f394
@@ -16,10 +16,15 @@ import {
|
||||
RainbowHistoryResponse,
|
||||
FailedHistoryResponse,
|
||||
} from "__fixtures__/AlertHistory";
|
||||
import type { APIAlertGroupT, HistoryResponseT } from "Models/APITypes";
|
||||
import type {
|
||||
APIAlertGroupT,
|
||||
APIGridT,
|
||||
HistoryResponseT,
|
||||
} from "Models/APITypes";
|
||||
import { AlertHistory } from ".";
|
||||
|
||||
let group: APIAlertGroupT;
|
||||
let grid: APIGridT;
|
||||
|
||||
const MockGroup = (groupName: string) => {
|
||||
const group = MockAlertGroup(
|
||||
@@ -49,14 +54,123 @@ beforeEach(() => {
|
||||
jest.useFakeTimers();
|
||||
advanceTo(new Date(Date.UTC(2000, 1, 1, 0, 0, 0)));
|
||||
group = MockGroup("fakeGroup");
|
||||
grid = {
|
||||
labelName: "foo",
|
||||
labelValue: "bar",
|
||||
alertGroups: [],
|
||||
totalGroups: 0,
|
||||
stateCount: {
|
||||
active: 0,
|
||||
suppressed: 0,
|
||||
unprocessed: 0,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fetchMock.resetHistory();
|
||||
fetchMock.reset();
|
||||
clear();
|
||||
});
|
||||
|
||||
describe("<AlertHistory />", () => {
|
||||
it("send a correct payload with empty grid", async () => {
|
||||
fetchMock.resetHistory();
|
||||
fetchMock.mock(
|
||||
"*",
|
||||
{
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(EmptyHistoryResponse),
|
||||
},
|
||||
{
|
||||
overwriteRoutes: true,
|
||||
}
|
||||
);
|
||||
|
||||
grid.labelName = "";
|
||||
grid.labelValue = "";
|
||||
MockAlerts(3);
|
||||
const tree = mount(<AlertHistory group={group} grid={grid}></AlertHistory>);
|
||||
await act(async () => {
|
||||
await fetchMock.flush(true);
|
||||
});
|
||||
expect(fetchMock.calls()).toHaveLength(1);
|
||||
expect(fetchMock.calls()[0][1]?.body).toStrictEqual(
|
||||
JSON.stringify({
|
||||
sources: [
|
||||
"https://secure.example.com/graph",
|
||||
"http://plain.example.com/",
|
||||
],
|
||||
labels: { alertname: "Fake Alert", groupName: "fakeGroup" },
|
||||
})
|
||||
);
|
||||
tree.unmount();
|
||||
});
|
||||
|
||||
it("send a correct payload with non-empty grid", async () => {
|
||||
fetchMock.resetHistory();
|
||||
fetchMock.mock(
|
||||
"*",
|
||||
{
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(EmptyHistoryResponse),
|
||||
},
|
||||
{
|
||||
overwriteRoutes: true,
|
||||
}
|
||||
);
|
||||
|
||||
MockAlerts(3);
|
||||
const tree = mount(<AlertHistory group={group} grid={grid}></AlertHistory>);
|
||||
await act(async () => {
|
||||
await fetchMock.flush(true);
|
||||
});
|
||||
expect(fetchMock.calls()).toHaveLength(1);
|
||||
expect(fetchMock.calls()[0][1]?.body).toStrictEqual(
|
||||
JSON.stringify({
|
||||
sources: [
|
||||
"https://secure.example.com/graph",
|
||||
"http://plain.example.com/",
|
||||
],
|
||||
labels: { alertname: "Fake Alert", groupName: "fakeGroup", foo: "bar" },
|
||||
})
|
||||
);
|
||||
tree.unmount();
|
||||
});
|
||||
|
||||
it("send a correct payload with @cluster grid", async () => {
|
||||
fetchMock.resetHistory();
|
||||
fetchMock.mock(
|
||||
"*",
|
||||
{
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(EmptyHistoryResponse),
|
||||
},
|
||||
{
|
||||
overwriteRoutes: true,
|
||||
}
|
||||
);
|
||||
|
||||
grid.labelName = "@cluster";
|
||||
grid.labelValue = "prod";
|
||||
MockAlerts(3);
|
||||
const tree = mount(<AlertHistory group={group} grid={grid}></AlertHistory>);
|
||||
await act(async () => {
|
||||
await fetchMock.flush(true);
|
||||
});
|
||||
expect(fetchMock.calls()).toHaveLength(1);
|
||||
expect(fetchMock.calls()[0][1]?.body).toStrictEqual(
|
||||
JSON.stringify({
|
||||
sources: [
|
||||
"https://secure.example.com/graph",
|
||||
"http://plain.example.com/",
|
||||
],
|
||||
labels: { alertname: "Fake Alert", groupName: "fakeGroup" },
|
||||
})
|
||||
);
|
||||
tree.unmount();
|
||||
});
|
||||
|
||||
it("matches snapshot with empty response", async () => {
|
||||
fetchMock.resetHistory();
|
||||
fetchMock.mock(
|
||||
@@ -71,7 +185,7 @@ describe("<AlertHistory />", () => {
|
||||
);
|
||||
|
||||
MockAlerts(3);
|
||||
const tree = mount(<AlertHistory group={group}></AlertHistory>);
|
||||
const tree = mount(<AlertHistory group={group} grid={grid}></AlertHistory>);
|
||||
await act(async () => {
|
||||
await fetchMock.flush(true);
|
||||
});
|
||||
@@ -94,7 +208,7 @@ describe("<AlertHistory />", () => {
|
||||
);
|
||||
|
||||
MockAlerts(3);
|
||||
const tree = mount(<AlertHistory group={group}></AlertHistory>);
|
||||
const tree = mount(<AlertHistory group={group} grid={grid}></AlertHistory>);
|
||||
await act(async () => {
|
||||
await fetchMock.flush(true);
|
||||
});
|
||||
@@ -122,7 +236,7 @@ describe("<AlertHistory />", () => {
|
||||
] as any);
|
||||
|
||||
MockAlerts(3);
|
||||
const tree = mount(<AlertHistory group={group}></AlertHistory>);
|
||||
const tree = mount(<AlertHistory group={group} grid={grid}></AlertHistory>);
|
||||
await act(async () => {
|
||||
await fetchMock.flush(true);
|
||||
});
|
||||
@@ -151,7 +265,7 @@ describe("<AlertHistory />", () => {
|
||||
] as any);
|
||||
|
||||
MockAlerts(3);
|
||||
const tree = mount(<AlertHistory group={group}></AlertHistory>);
|
||||
const tree = mount(<AlertHistory group={group} grid={grid}></AlertHistory>);
|
||||
await act(async () => {
|
||||
await fetchMock.flush(true);
|
||||
});
|
||||
@@ -188,7 +302,7 @@ describe("<AlertHistory />", () => {
|
||||
);
|
||||
|
||||
MockAlerts(3);
|
||||
const tree = mount(<AlertHistory group={group}></AlertHistory>);
|
||||
const tree = mount(<AlertHistory group={group} grid={grid}></AlertHistory>);
|
||||
await act(async () => {
|
||||
await fetchMock.flush(true);
|
||||
});
|
||||
@@ -211,7 +325,7 @@ describe("<AlertHistory />", () => {
|
||||
);
|
||||
|
||||
MockAlerts(3);
|
||||
const tree = mount(<AlertHistory group={group}></AlertHistory>);
|
||||
const tree = mount(<AlertHistory group={group} grid={grid}></AlertHistory>);
|
||||
await act(async () => {
|
||||
await fetchMock.flush(true);
|
||||
});
|
||||
@@ -329,6 +443,17 @@ describe("<AlertHistory />", () => {
|
||||
}
|
||||
g.alerts.push(alert);
|
||||
}
|
||||
const gr = {
|
||||
labelName: "foo",
|
||||
labelValue: "bar",
|
||||
alertGroups: [],
|
||||
totalGroups: 0,
|
||||
stateCount: {
|
||||
active: 0,
|
||||
suppressed: 0,
|
||||
unprocessed: 0,
|
||||
},
|
||||
};
|
||||
|
||||
it(`${testCase.title}`, async () => {
|
||||
fetchMock.resetHistory();
|
||||
@@ -343,7 +468,7 @@ describe("<AlertHistory />", () => {
|
||||
}
|
||||
);
|
||||
|
||||
const tree = mount(<AlertHistory group={g}></AlertHistory>);
|
||||
const tree = mount(<AlertHistory group={g} grid={gr}></AlertHistory>);
|
||||
await act(async () => {
|
||||
await fetchMock.flush(true);
|
||||
});
|
||||
|
||||
@@ -3,7 +3,11 @@ import { FC, useEffect, useState } from "react";
|
||||
import { useInView } from "react-intersection-observer";
|
||||
|
||||
import { FormatBackendURI } from "Stores/AlertStore";
|
||||
import type { APIAlertGroupT, HistoryResponseT } from "Models/APITypes";
|
||||
import type {
|
||||
APIAlertGroupT,
|
||||
APIGridT,
|
||||
HistoryResponseT,
|
||||
} from "Models/APITypes";
|
||||
import { useFetchAny, UpstreamT } from "Hooks/useFetchAny";
|
||||
import { TooltipWrapper } from "Components/TooltipWrapper";
|
||||
|
||||
@@ -22,12 +26,21 @@ const GetUTCSeconds = (): number => {
|
||||
return (now.getTime() + now.getTimezoneOffset()) / 1000;
|
||||
};
|
||||
|
||||
export const AlertHistory: FC<{ group: APIAlertGroupT }> = ({ group }) => {
|
||||
export const AlertHistory: FC<{ group: APIAlertGroupT; grid: APIGridT }> = ({
|
||||
group,
|
||||
grid,
|
||||
}) => {
|
||||
const [ref, inView] = useInView({ triggerOnce: true });
|
||||
|
||||
const [lastUpdate, setLastUpdate] = useState<number>(GetUTCSeconds());
|
||||
const [upstreams, setUpstreams] = useState<UpstreamT[]>([]);
|
||||
const [labels] = useState({ ...group.labels, ...group.shared.labels });
|
||||
const [labels] = useState({
|
||||
...group.labels,
|
||||
...group.shared.labels,
|
||||
...(grid.labelName !== "" && grid.labelName[0] !== "@"
|
||||
? { [grid.labelName]: grid.labelValue }
|
||||
: {}),
|
||||
});
|
||||
const [sources] = useState(group.shared.sources);
|
||||
const { response, error } = useFetchAny<HistoryResponseT>(upstreams);
|
||||
const [cachedResponse, setCachedResponse] = useState<HistoryResponseT | null>(
|
||||
|
||||
@@ -170,7 +170,7 @@ const AlertGroup: FC<{
|
||||
{isCollapsed ? null : (
|
||||
<div className="card-body px-2 py-1 components-grid-alertgrid-card">
|
||||
{alertStore.settings.values.historyEnabled ? (
|
||||
<AlertHistory group={group} />
|
||||
<AlertHistory group={group} grid={grid} />
|
||||
) : null}
|
||||
<ul className="list-group">
|
||||
{group.alerts
|
||||
|
||||
Reference in New Issue
Block a user