mirror of
https://github.com/grafana/grafana.git
synced 2025-02-12 08:35:43 -06:00
* WIP * Add instance totals to combined rule. Use totals to display instances stats in the UI * WIP * add global summaries, fix TS errors * fix useCombined test * fix test * use activeAt from rule when available * Fix NaN in global stats * Add no data total to global summary * Add totals recalculation for filtered rules * Fix instances totals, remove instances filtering from alert list view * Update tests * Fetch alerts considering filtering label matchers * WIP - Fetch alerts appending state filter to endpoint * Fix multiple values for state in request being applyied * fix test * Calculate hidden by for grafana managed alerts * Use INSTANCES_DISPLAY_LIMIT constant for limiting alert instances instead of 1 * Rename matchers parameter according to API changes * Fix calculating total number of grafana instances * Rename matcher prop after previous change * Display button to remove max instances limit * Change matcher query param to be an array of strings * Add test for paramsWithMatcherAndState method * Refactor matcher to be an string array to be consistent with state * Use matcher query string as matcher object type (encoded JSON) * Avoind encoding matcher parameters twice * fix tests * Enable toggle for the limit/show all button and restore limit and filters when we come back from custom view * Move getMatcherListFromString method to utils/alertmanager.ts * Fix limit toggle button being shown when it's not necessary * Use filteredTotals from be response to calculate hidden by count * Fix variables not being replaced correctly * Fix total shown to be all the instances filtered without limits * Adress some PR review comments * Move paramsWithMatcherAndState inside prometheusUrlBuilder method --------- Co-authored-by: Gilles De Mey <gilles.de.mey@gmail.com> Co-authored-by: Konrad Lalik <konrad.lalik@grafana.com> Co-authored-by: Virginia Cepeda <virginia.cepeda@grafana.com>
194 lines
5.2 KiB
TypeScript
194 lines
5.2 KiB
TypeScript
import { render } from '@testing-library/react';
|
|
import userEvent from '@testing-library/user-event';
|
|
import React from 'react';
|
|
import { TestProvider } from 'test/helpers/TestProvider';
|
|
import { byTestId } from 'testing-library-selector';
|
|
|
|
import { FolderState } from 'app/types';
|
|
import { CombinedRuleNamespace } from 'app/types/unified-alerting';
|
|
|
|
import { AlertsFolderView } from './AlertsFolderView';
|
|
import { mockCombinedRule } from './mocks';
|
|
import { GRAFANA_RULES_SOURCE_NAME } from './utils/datasource';
|
|
|
|
const ui = {
|
|
filter: {
|
|
name: byTestId('name-filter'),
|
|
label: byTestId('label-filter'),
|
|
},
|
|
ruleList: {
|
|
row: byTestId('alert-card-row'),
|
|
},
|
|
};
|
|
|
|
const combinedNamespaceMock = jest.fn<CombinedRuleNamespace[], any>();
|
|
jest.mock('./hooks/useCombinedRuleNamespaces', () => ({
|
|
useCombinedRuleNamespaces: () => combinedNamespaceMock(),
|
|
}));
|
|
|
|
const mockFolder = (folderOverride: Partial<FolderState> = {}): FolderState => {
|
|
return {
|
|
id: 1,
|
|
title: 'Folder with alerts',
|
|
uid: 'folder-1',
|
|
hasChanged: false,
|
|
canSave: false,
|
|
url: '/folder-1',
|
|
version: 1,
|
|
permissions: [],
|
|
canViewFolderPermissions: false,
|
|
canDelete: false,
|
|
...folderOverride,
|
|
};
|
|
};
|
|
|
|
describe('AlertsFolderView tests', () => {
|
|
it('Should display grafana alert rules when the namespace name matches the folder name', () => {
|
|
// Arrange
|
|
const folder = mockFolder();
|
|
|
|
const grafanaNamespace: CombinedRuleNamespace = {
|
|
name: folder.title,
|
|
rulesSource: GRAFANA_RULES_SOURCE_NAME,
|
|
groups: [
|
|
{
|
|
name: 'group1',
|
|
rules: [
|
|
mockCombinedRule({ name: 'Test Alert 1' }),
|
|
mockCombinedRule({ name: 'Test Alert 2' }),
|
|
mockCombinedRule({ name: 'Test Alert 3' }),
|
|
],
|
|
totals: {},
|
|
},
|
|
{
|
|
name: 'group2',
|
|
rules: [
|
|
mockCombinedRule({ name: 'Test Alert 4' }),
|
|
mockCombinedRule({ name: 'Test Alert 5' }),
|
|
mockCombinedRule({ name: 'Test Alert 6' }),
|
|
],
|
|
totals: {},
|
|
},
|
|
],
|
|
};
|
|
|
|
combinedNamespaceMock.mockReturnValue([grafanaNamespace]);
|
|
|
|
// Act
|
|
render(
|
|
<TestProvider>
|
|
<AlertsFolderView folder={folder} />
|
|
</TestProvider>
|
|
);
|
|
|
|
// Assert
|
|
const alertRows = ui.ruleList.row.queryAll();
|
|
expect(alertRows).toHaveLength(6);
|
|
expect(alertRows[0]).toHaveTextContent('Test Alert 1');
|
|
expect(alertRows[1]).toHaveTextContent('Test Alert 2');
|
|
expect(alertRows[2]).toHaveTextContent('Test Alert 3');
|
|
expect(alertRows[3]).toHaveTextContent('Test Alert 4');
|
|
expect(alertRows[4]).toHaveTextContent('Test Alert 5');
|
|
expect(alertRows[5]).toHaveTextContent('Test Alert 6');
|
|
});
|
|
|
|
it('Should not display alert rules when the namespace name does not match the folder name', () => {
|
|
// Arrange
|
|
const folder = mockFolder();
|
|
|
|
const grafanaNamespace: CombinedRuleNamespace = {
|
|
name: 'Folder without alerts',
|
|
rulesSource: GRAFANA_RULES_SOURCE_NAME,
|
|
groups: [
|
|
{
|
|
name: 'default',
|
|
rules: [
|
|
mockCombinedRule({ name: 'Test Alert from other folder 1' }),
|
|
mockCombinedRule({ name: 'Test Alert from other folder 2' }),
|
|
],
|
|
totals: {},
|
|
},
|
|
],
|
|
};
|
|
|
|
combinedNamespaceMock.mockReturnValue([grafanaNamespace]);
|
|
|
|
// Act
|
|
render(
|
|
<TestProvider>
|
|
<AlertsFolderView folder={folder} />
|
|
</TestProvider>
|
|
);
|
|
|
|
// Assert
|
|
expect(ui.ruleList.row.queryAll()).toHaveLength(0);
|
|
});
|
|
|
|
it('Should filter alert rules by the name, case insensitive', async () => {
|
|
// Arrange
|
|
const folder = mockFolder();
|
|
|
|
const grafanaNamespace: CombinedRuleNamespace = {
|
|
name: folder.title,
|
|
rulesSource: GRAFANA_RULES_SOURCE_NAME,
|
|
groups: [
|
|
{
|
|
name: 'default',
|
|
rules: [mockCombinedRule({ name: 'CPU Alert' }), mockCombinedRule({ name: 'RAM usage alert' })],
|
|
totals: {},
|
|
},
|
|
],
|
|
};
|
|
|
|
combinedNamespaceMock.mockReturnValue([grafanaNamespace]);
|
|
|
|
// Act
|
|
render(
|
|
<TestProvider>
|
|
<AlertsFolderView folder={folder} />
|
|
</TestProvider>
|
|
);
|
|
|
|
await userEvent.type(ui.filter.name.get(), 'cpu');
|
|
|
|
// Assert
|
|
expect(ui.ruleList.row.queryAll()).toHaveLength(1);
|
|
expect(ui.ruleList.row.get()).toHaveTextContent('CPU Alert');
|
|
});
|
|
|
|
it('Should filter alert rule by labels', async () => {
|
|
// Arrange
|
|
const folder = mockFolder();
|
|
|
|
const grafanaNamespace: CombinedRuleNamespace = {
|
|
name: folder.title,
|
|
rulesSource: GRAFANA_RULES_SOURCE_NAME,
|
|
groups: [
|
|
{
|
|
name: 'default',
|
|
rules: [
|
|
mockCombinedRule({ name: 'CPU Alert', labels: {} }),
|
|
mockCombinedRule({ name: 'RAM usage alert', labels: { severity: 'critical' } }),
|
|
],
|
|
totals: {},
|
|
},
|
|
],
|
|
};
|
|
|
|
combinedNamespaceMock.mockReturnValue([grafanaNamespace]);
|
|
|
|
// Act
|
|
render(
|
|
<TestProvider>
|
|
<AlertsFolderView folder={folder} />
|
|
</TestProvider>
|
|
);
|
|
|
|
await userEvent.type(ui.filter.label.get(), 'severity=critical');
|
|
|
|
// Assert
|
|
expect(ui.ruleList.row.queryAll()).toHaveLength(1);
|
|
expect(ui.ruleList.row.get()).toHaveTextContent('RAM usage alert');
|
|
});
|
|
});
|