The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
grafana/public/app/features/alerting/unified/components/rules/EditRuleGroupModal.test.tsx

196 lines
6.8 KiB

import { render } from '@testing-library/react';
import * as React from 'react';
import { Provider } from 'react-redux';
import { byLabelText, byTestId, byText, byTitle } from 'testing-library-selector';
import { CombinedRuleNamespace } from 'app/types/unified-alerting';
import {
mockCombinedRule,
mockCombinedRuleNamespace,
mockDataSource,
mockPromAlertingRule,
mockPromRecordingRule,
mockRulerAlertingRule,
mockRulerRecordingRule,
mockRulerRuleGroup,
mockStore,
} from '../../mocks';
import { GRAFANA_RULES_SOURCE_NAME } from '../../utils/datasource';
import { EditCloudGroupModal } from './EditRuleGroupModal';
const ui = {
input: {
namespace: byLabelText(/^Folder|^Namespace/, { exact: true }),
group: byLabelText(/Evaluation group/),
interval: byLabelText(/Evaluation interval/),
},
folderLink: byTitle(/Go to folder/), // <a> without a href has the generic role
table: byTestId('dynamic-table'),
tableRows: byTestId('row'),
noRulesText: byText('This group does not contain alert rules.'),
};
mockRulerRuleGroup({
name: 'group1',
rules: [
mockRulerRecordingRule({
record: 'instance:node_num_cpu:sum',
expr: 'count without (cpu) (count without (mode) (node_cpu_seconds_total{job="integrations/node_exporter"}))',
labels: { type: 'cpu' },
}),
mockRulerAlertingRule({ alert: 'nonRecordingRule' }),
],
});
jest.mock('app/types', () => ({
...jest.requireActual('app/types'),
useDispatch: () => jest.fn(),
}));
function getProvidersWrapper() {
return function Wrapper({ children }: React.PropsWithChildren<{}>) {
const store = mockStore(() => null);
return <Provider store={store}>{children}</Provider>;
};
}
describe('EditGroupModal', () => {
it('Should disable all inputs but interval when intervalEditOnly is set', async () => {
const namespace = mockCombinedRuleNamespace({
name: 'my-alerts',
rulesSource: mockDataSource(),
Alerting: Add limits and move state and label matching filters to the BE (#66267) * 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>
3 years ago
groups: [{ name: 'default-group', interval: '90s', rules: [], totals: {} }],
});
const group = namespace.groups[0];
render(<EditCloudGroupModal namespace={namespace} group={group} intervalEditOnly onClose={() => jest.fn()} />, {
wrapper: getProvidersWrapper(),
});
expect(await ui.input.namespace.find()).toHaveAttribute('readonly');
expect(ui.input.group.get()).toHaveAttribute('readonly');
expect(ui.input.interval.get()).not.toHaveAttribute('readonly');
});
});
describe('EditGroupModal component on cloud alert rules', () => {
const promDsSettings = mockDataSource({ name: 'Prometheus-1', uid: 'Prometheus-1' });
const alertingRule = mockCombinedRule({
namespace: undefined,
promRule: mockPromAlertingRule({ name: 'alerting-rule-cpu' }),
rulerRule: mockRulerAlertingRule({ alert: 'alerting-rule-cpu' }),
});
const recordingRule1 = mockCombinedRule({
namespace: undefined,
promRule: mockPromRecordingRule({ name: 'recording-rule-memory' }),
rulerRule: mockRulerRecordingRule({ record: 'recording-rule-memory' }),
});
const recordingRule2 = mockCombinedRule({
namespace: undefined,
promRule: mockPromRecordingRule({ name: 'recording-rule-cpu' }),
rulerRule: mockRulerRecordingRule({ record: 'recording-rule-cpu' }),
});
it('Should show alert table in case of having some non-recording rules in the group', async () => {
const promNs = mockCombinedRuleNamespace({
name: 'prometheus-ns',
rulesSource: promDsSettings,
Alerting: Add limits and move state and label matching filters to the BE (#66267) * 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>
3 years ago
groups: [
{ name: 'default-group', interval: '90s', rules: [alertingRule, recordingRule1, recordingRule2], totals: {} },
],
});
const group = promNs.groups[0];
render(<EditCloudGroupModal namespace={promNs} group={group} onClose={() => jest.fn()} />, {
wrapper: getProvidersWrapper(),
});
expect(await ui.input.namespace.find()).toHaveValue('prometheus-ns');
expect(ui.input.namespace.get()).not.toHaveAttribute('readonly');
expect(ui.input.group.get()).toHaveValue('default-group');
expect(ui.tableRows.getAll()).toHaveLength(1); // Only one rule is non-recording
expect(ui.tableRows.getAll()[0]).toHaveTextContent('alerting-rule-cpu');
});
it('Should not show alert table in case of having exclusively recording rules in the group', async () => {
const promNs = mockCombinedRuleNamespace({
name: 'prometheus-ns',
rulesSource: promDsSettings,
Alerting: Add limits and move state and label matching filters to the BE (#66267) * 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>
3 years ago
groups: [{ name: 'default-group', interval: '90s', rules: [recordingRule1, recordingRule2], totals: {} }],
});
const group = promNs.groups[0];
render(<EditCloudGroupModal namespace={promNs} group={group} onClose={jest.fn()} />, {
wrapper: getProvidersWrapper(),
});
expect(ui.table.query()).not.toBeInTheDocument();
expect(await ui.noRulesText.find()).toBeInTheDocument();
});
});
describe('EditGroupModal component on grafana-managed alert rules', () => {
const grafanaNamespace: CombinedRuleNamespace = {
name: 'namespace1',
rulesSource: GRAFANA_RULES_SOURCE_NAME,
groups: [
{
name: 'grafanaGroup1',
interval: '30s',
rules: [
mockCombinedRule({
namespace: undefined,
promRule: mockPromAlertingRule({ name: 'high-cpu-1' }),
rulerRule: mockRulerAlertingRule({ alert: 'high-cpu-1' }),
}),
mockCombinedRule({
namespace: undefined,
promRule: mockPromAlertingRule({ name: 'high-memory' }),
rulerRule: mockRulerAlertingRule({ alert: 'high-memory' }),
}),
],
Alerting: Add limits and move state and label matching filters to the BE (#66267) * 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>
3 years ago
totals: {},
},
],
};
const grafanaGroup1 = grafanaNamespace.groups[0];
it('Should show alert table', async () => {
render(<EditCloudGroupModal namespace={grafanaNamespace} group={grafanaGroup1} onClose={jest.fn()} />, {
wrapper: getProvidersWrapper(),
});
expect(await ui.input.namespace.find()).toHaveValue('namespace1');
expect(ui.input.group.get()).toHaveValue('grafanaGroup1');
expect(ui.input.interval.get()).toHaveValue('30s');
expect(ui.tableRows.getAll()).toHaveLength(2);
expect(ui.tableRows.getAll()[0]).toHaveTextContent('high-cpu-1');
expect(ui.tableRows.getAll()[1]).toHaveTextContent('high-memory');
});
it('Should have folder input in readonly mode', async () => {
render(<EditCloudGroupModal namespace={grafanaNamespace} group={grafanaGroup1} onClose={jest.fn()} />, {
wrapper: getProvidersWrapper(),
});
expect(await ui.input.namespace.find()).toHaveAttribute('readonly');
});
it('Should not display folder link if no folderUrl provided', async () => {
render(<EditCloudGroupModal namespace={grafanaNamespace} group={grafanaGroup1} onClose={jest.fn()} />, {
wrapper: getProvidersWrapper(),
});
expect(await ui.input.namespace.find()).toHaveValue('namespace1');
expect(ui.folderLink.query()).not.toBeInTheDocument();
});
});