diff --git a/public/app/features/alerting/unified/api/annotations.test.ts b/public/app/features/alerting/unified/api/annotations.test.ts index ca52b08ca65..183c103f58c 100644 --- a/public/app/features/alerting/unified/api/annotations.test.ts +++ b/public/app/features/alerting/unified/api/annotations.test.ts @@ -1,10 +1,17 @@ import '@grafana/runtime'; -import { fetchAnnotations } from './annotations'; +import { fetchAnnotations, sortStateHistory } from './annotations'; +import { StateHistoryItem } from 'app/types/unified-alerting'; -const get = jest.fn(); +const get = jest.fn(() => { + return new Promise((resolve) => { + resolve(undefined); + }); +}); jest.mock('@grafana/runtime', () => ({ - getBackendSrv: () => ({ get }), + getBackendSrv: () => ({ + get, + }), })); describe('annotations', () => { @@ -16,3 +23,41 @@ describe('annotations', () => { expect(get).toBeCalledWith('/api/annotations', { alertId: ALERT_ID }); }); }); + +describe(sortStateHistory, () => { + describe('should stably sort', () => { + describe('when timeEnd is different', () => { + it('should not sort by rule id', () => { + let data: StateHistoryItem[] = [ + { timeEnd: 23, time: 22, id: 1 } as StateHistoryItem, + { timeEnd: 22, time: 21, id: 3 } as StateHistoryItem, + { timeEnd: 22, time: 22, id: 2 } as StateHistoryItem, + { timeEnd: 24, id: 3 } as StateHistoryItem, + ]; + + data.sort(sortStateHistory); + expect(data[0].timeEnd).toBe(24); + expect(data[1].timeEnd).toBe(23); + expect(data[2].time).toBe(22); + expect(data[3].id).toBe(3); + }); + }); + + describe('when only the rule id is different', () => { + it('should sort by rule id', () => { + let data: StateHistoryItem[] = [ + { timeEnd: 23, time: 22, id: 1 } as StateHistoryItem, + { timeEnd: 23, time: 22, id: 3 } as StateHistoryItem, + { timeEnd: 23, time: 22, id: 2 } as StateHistoryItem, + { timeEnd: 23, time: 22, id: 6 } as StateHistoryItem, + ]; + + data.sort(sortStateHistory); + expect(data[0].id).toBe(6); + expect(data[1].id).toBe(3); + expect(data[2].id).toBe(2); + expect(data[3].id).toBe(1); + }); + }); + }); +}); diff --git a/public/app/features/alerting/unified/api/annotations.ts b/public/app/features/alerting/unified/api/annotations.ts index 2df5ee2cacd..39195dc1f48 100644 --- a/public/app/features/alerting/unified/api/annotations.ts +++ b/public/app/features/alerting/unified/api/annotations.ts @@ -2,7 +2,37 @@ import { getBackendSrv } from '@grafana/runtime'; import { StateHistoryItem } from 'app/types/unified-alerting'; export function fetchAnnotations(alertId: string): Promise { - return getBackendSrv().get('/api/annotations', { - alertId, - }); + return getBackendSrv() + .get('/api/annotations', { + alertId, + }) + .then((result) => { + return result?.sort(sortStateHistory); + }); +} + +export function sortStateHistory(a: StateHistoryItem, b: StateHistoryItem): number { + const compareDesc = (a: number, b: number): number => { + // Larger numbers first. + if (a > b) { + return -1; + } + + if (b > a) { + return 1; + } + return 0; + }; + + const endNeq = compareDesc(a.timeEnd, b.timeEnd); + if (endNeq) { + return endNeq; + } + + const timeNeq = compareDesc(a.time, b.time); + if (timeNeq) { + return timeNeq; + } + + return compareDesc(a.id, b.id); } diff --git a/public/app/features/alerting/unified/components/rules/StateHistory.test.tsx b/public/app/features/alerting/unified/components/rules/StateHistory.test.tsx deleted file mode 100644 index 31d0bc9e188..00000000000 --- a/public/app/features/alerting/unified/components/rules/StateHistory.test.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { StateHistoryItem } from 'app/types/unified-alerting'; -import { sortStateHistory } from './StateHistory'; - -describe(sortStateHistory, () => { - describe('should stably sort', () => { - describe('when timeEnd is different', () => { - it('should not sort by rule id', () => { - let data: StateHistoryItem[] = [ - { timeEnd: 23, time: 22, id: 1 } as StateHistoryItem, - { timeEnd: 22, time: 21, id: 3 } as StateHistoryItem, - { timeEnd: 22, time: 22, id: 2 } as StateHistoryItem, - { timeEnd: 24, id: 3 } as StateHistoryItem, - ]; - - data.sort(sortStateHistory); - expect(data[0].timeEnd).toBe(24); - expect(data[1].timeEnd).toBe(23); - expect(data[2].time).toBe(22); - expect(data[3].id).toBe(3); - }); - }); - - describe('when only the rule id is different', () => { - it('should sort by rule id', () => { - let data: StateHistoryItem[] = [ - { timeEnd: 23, time: 22, id: 1 } as StateHistoryItem, - { timeEnd: 23, time: 22, id: 3 } as StateHistoryItem, - { timeEnd: 23, time: 22, id: 2 } as StateHistoryItem, - { timeEnd: 23, time: 22, id: 6 } as StateHistoryItem, - ]; - - data.sort(sortStateHistory); - expect(data[0].id).toBe(6); - expect(data[1].id).toBe(3); - expect(data[2].id).toBe(2); - expect(data[3].id).toBe(1); - }); - }); - }); -}); diff --git a/public/app/features/alerting/unified/components/rules/StateHistory.tsx b/public/app/features/alerting/unified/components/rules/StateHistory.tsx index 75d17e883fe..f7050eb198c 100644 --- a/public/app/features/alerting/unified/components/rules/StateHistory.tsx +++ b/public/app/features/alerting/unified/components/rules/StateHistory.tsx @@ -24,32 +24,6 @@ interface RuleStateHistoryProps { alertId: string; } -function sortStateHistory(a: StateHistoryItem, b: StateHistoryItem): number { - const compareDesc = (a: number, b: number): number => { - // Larger numbers first. - if (a > b) { - return -1; - } - - if (b > a) { - return 1; - } - return 0; - }; - - const endNeq = compareDesc(a.timeEnd, b.timeEnd); - if (endNeq) { - return endNeq; - } - - const timeNeq = compareDesc(a.time, b.time); - if (timeNeq) { - return timeNeq; - } - - return compareDesc(a.id, b.id); -} - const StateHistory: FC = ({ alertId }) => { const { loading, error, result = [] } = useManagedAlertStateHistory(alertId); @@ -68,7 +42,6 @@ const StateHistory: FC = ({ alertId }) => { ]; const items: StateHistoryRow[] = result - .sort(sortStateHistory) .reduce((acc: StateHistoryRowItem[], item, index) => { acc.push({ id: String(item.id), @@ -150,7 +123,4 @@ function hasMatchingPrecedingState(index: number, items: StateHistoryItem[]): bo return previousHistoryItem.newState === currentHistoryItem.prevState; } -export { - StateHistory, - sortStateHistory, // exported for testing. -}; +export { StateHistory };