mirror of
https://github.com/grafana/grafana.git
synced 2024-12-23 07:34:08 -06:00
ReturnToPrevious: Add e2e test (#83115)
* feat: add incomplete unit test * refactor: add idea for unit test * feat: create new e2e test * feat: add some steps * feat: add comment * feat: complete prep work * feat: complete clean up * rebase * feat: add more steps to test flow * refactor: remove unit test * refactor: clean up * refactor: create a provisioned alert rule * refactor: change location and content * refactor: e2e test * refactor: betterer * refactor: move provisioned alert rule * refactor: make provisioning file available remote * refactor: clean up test * refactor: move provisioned alert rule * refactor: remove wait() * feat: restructure first test and add more tests * feat: add another provisioned alert rule * feat: add a new test * feat: complete new test * refactor: replace data-testid in alert rules * refactor: replace data-testid * refactor: fix tests for drone * refactor: fix third test after review * refactor: fix last test * temp * refactor: improve some things * refactor: adjust unit tests * refactor: remove assertions for alert rule details view * refactor: remove assertions * refactor: add check for button text * refactor: remove session storage * refactor: apply changes from code review * refactor: add codeowner * refactor * refactor * refactor: clean up * refactor: clean up * refactor: clean up * refactor: increase pa11y threshold for /alerting/list
This commit is contained in:
parent
9298a5fcb5
commit
d8a116e696
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
@ -172,6 +172,7 @@
|
||||
/devenv/bulk-dashboards/ @grafana/dashboards-squad
|
||||
/devenv/bulk-folders/ @grafana/grafana-frontend-platform
|
||||
/devenv/create_docker_compose.sh @grafana/backend-platform
|
||||
/devenv/alert_rules.yaml @grafana/alerting-backend-product
|
||||
/devenv/dashboards.yaml @grafana/dashboards-squad
|
||||
/devenv/datasources.yaml @grafana/backend-platform
|
||||
/devenv/datasources_docker.yaml @grafana/backend-platform
|
||||
|
@ -103,7 +103,7 @@ var config = {
|
||||
rootElement: '.main-view',
|
||||
// the unified alerting promotion alert's content contrast is too low
|
||||
// see https://github.com/grafana/grafana/pull/41829
|
||||
threshold: 6,
|
||||
threshold: 7,
|
||||
},
|
||||
{
|
||||
url: '${HOST}/datasources',
|
||||
|
158
devenv/alert_rules.yaml
Normal file
158
devenv/alert_rules.yaml
Normal file
@ -0,0 +1,158 @@
|
||||
apiVersion: 1
|
||||
groups:
|
||||
- orgId: 1
|
||||
name: testEvaluationGroup
|
||||
folder: gdev dashboards
|
||||
interval: 5m
|
||||
rules:
|
||||
- uid: bddn0v6f1kgzkc
|
||||
title: e2e-ReturnToPrevious-test
|
||||
condition: C
|
||||
data:
|
||||
- refId: A
|
||||
relativeTimeRange:
|
||||
from: 600
|
||||
to: 0
|
||||
datasourceUid: PD8C576611E62080A
|
||||
model:
|
||||
intervalMs: 1000
|
||||
maxDataPoints: 43200
|
||||
refId: A
|
||||
- refId: B
|
||||
datasourceUid: __expr__
|
||||
model:
|
||||
conditions:
|
||||
- evaluator:
|
||||
params: []
|
||||
type: gt
|
||||
operator:
|
||||
type: and
|
||||
query:
|
||||
params:
|
||||
- B
|
||||
reducer:
|
||||
params: []
|
||||
type: last
|
||||
type: query
|
||||
datasource:
|
||||
type: __expr__
|
||||
uid: __expr__
|
||||
expression: A
|
||||
intervalMs: 1000
|
||||
maxDataPoints: 43200
|
||||
reducer: last
|
||||
refId: B
|
||||
type: reduce
|
||||
- refId: C
|
||||
datasourceUid: __expr__
|
||||
model:
|
||||
conditions:
|
||||
- evaluator:
|
||||
params:
|
||||
- 0
|
||||
type: gt
|
||||
operator:
|
||||
type: and
|
||||
query:
|
||||
params:
|
||||
- C
|
||||
reducer:
|
||||
params: []
|
||||
type: last
|
||||
type: query
|
||||
datasource:
|
||||
type: __expr__
|
||||
uid: __expr__
|
||||
expression: B
|
||||
intervalMs: 1000
|
||||
maxDataPoints: 43200
|
||||
refId: C
|
||||
type: threshold
|
||||
dashboardUid: j6T00KRZz
|
||||
panelId: 7
|
||||
noDataState: NoData
|
||||
execErrState: Error
|
||||
for: 5m
|
||||
annotations:
|
||||
__dashboardUid__: j6T00KRZz
|
||||
__panelId__: "7"
|
||||
labels: {}
|
||||
isPaused: false
|
||||
- orgId: 1
|
||||
name: testEvaluationGroup2
|
||||
folder: gdev dashboards
|
||||
interval: 10m
|
||||
rules:
|
||||
- uid: dddyksihq7h1ca
|
||||
title: e2e-ReturnToPrevious-test-2
|
||||
condition: C
|
||||
data:
|
||||
- refId: A
|
||||
relativeTimeRange:
|
||||
from: 600
|
||||
to: 0
|
||||
datasourceUid: PD8C576611E62080A
|
||||
model:
|
||||
intervalMs: 1000
|
||||
maxDataPoints: 43200
|
||||
refId: A
|
||||
- refId: B
|
||||
datasourceUid: __expr__
|
||||
model:
|
||||
conditions:
|
||||
- evaluator:
|
||||
params: []
|
||||
type: gt
|
||||
operator:
|
||||
type: and
|
||||
query:
|
||||
params:
|
||||
- B
|
||||
reducer:
|
||||
params: []
|
||||
type: last
|
||||
type: query
|
||||
datasource:
|
||||
type: __expr__
|
||||
uid: __expr__
|
||||
expression: A
|
||||
intervalMs: 1000
|
||||
maxDataPoints: 43200
|
||||
reducer: last
|
||||
refId: B
|
||||
type: reduce
|
||||
- refId: C
|
||||
datasourceUid: __expr__
|
||||
model:
|
||||
conditions:
|
||||
- evaluator:
|
||||
params:
|
||||
- 0
|
||||
type: gt
|
||||
operator:
|
||||
type: and
|
||||
query:
|
||||
params:
|
||||
- C
|
||||
reducer:
|
||||
params: []
|
||||
type: last
|
||||
type: query
|
||||
datasource:
|
||||
type: __expr__
|
||||
uid: __expr__
|
||||
expression: B
|
||||
intervalMs: 1000
|
||||
maxDataPoints: 43200
|
||||
refId: C
|
||||
type: threshold
|
||||
dashboardUid: j6T00KRZz
|
||||
panelId: 3
|
||||
noDataState: NoData
|
||||
execErrState: Error
|
||||
for: 10m
|
||||
annotations:
|
||||
__dashboardUid__: j6T00KRZz
|
||||
__panelId__: "3"
|
||||
labels: {}
|
||||
isPaused: false
|
86
e2e/various-suite/return-to-previous.spec.ts
Normal file
86
e2e/various-suite/return-to-previous.spec.ts
Normal file
@ -0,0 +1,86 @@
|
||||
import { e2e } from '../utils';
|
||||
|
||||
describe('ReturnToPrevious button', () => {
|
||||
beforeEach(() => {
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
|
||||
cy.window().then((win) => {
|
||||
win.localStorage.setItem('grafana.featureToggles', 'returnToPrevious=1');
|
||||
});
|
||||
|
||||
cy.visit('/alerting/list');
|
||||
e2e.components.AlertRules.groupToggle().first().click();
|
||||
e2e.components.AlertRules.toggle().click();
|
||||
cy.get('a[title="View"]').click();
|
||||
cy.url().as('alertRuleUrl');
|
||||
cy.get('a').contains('View panel').click();
|
||||
});
|
||||
|
||||
it('should appear when changing context and go back to alert rule when clicking "Back"', () => {
|
||||
// make sure the dashboard finished loading
|
||||
cy.get('button[aria-label*="BarChart - Label Rotation & Skipping"]').should('be.visible');
|
||||
|
||||
// check whether all elements of RTP are available
|
||||
e2e.components.ReturnToPrevious.buttonGroup().should('be.visible');
|
||||
e2e.components.ReturnToPrevious.dismissButton().should('be.visible');
|
||||
e2e.components.ReturnToPrevious.backButton()
|
||||
.find('span')
|
||||
.contains('Back to e2e-ReturnToPrevious-test')
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
// check whether the RTP button leads back to alert rule
|
||||
cy.get('@alertRuleUrl').then((alertRuleUrl) => {
|
||||
cy.url().should('eq', alertRuleUrl);
|
||||
});
|
||||
});
|
||||
|
||||
it('should disappear when clicking "Dismiss"', () => {
|
||||
e2e.components.ReturnToPrevious.dismissButton().should('be.visible').click();
|
||||
e2e.components.ReturnToPrevious.buttonGroup().should('not.exist');
|
||||
});
|
||||
|
||||
it('should not persist when going back to the alert rule details view', () => {
|
||||
e2e.components.ReturnToPrevious.buttonGroup().should('be.visible');
|
||||
|
||||
// make sure the dashboard finished loading
|
||||
cy.get('button[aria-label*="BarChart - Label Rotation & Skipping"]').should('be.visible');
|
||||
|
||||
cy.visit('/alerting/list');
|
||||
e2e.components.AlertRules.groupToggle().first().click();
|
||||
cy.get('a[title="View"]').click();
|
||||
e2e.components.ReturnToPrevious.buttonGroup().should('not.exist');
|
||||
});
|
||||
|
||||
it('should override the button label and change the href when user changes alert rules', () => {
|
||||
// make sure the dashboard finished loading
|
||||
cy.get('button[aria-label*="BarChart - Label Rotation & Skipping"]').should('be.visible');
|
||||
|
||||
e2e.components.ReturnToPrevious.backButton()
|
||||
.find('span')
|
||||
.contains('Back to e2e-ReturnToPrevious-test')
|
||||
.should('be.visible');
|
||||
|
||||
cy.visit('/alerting/list');
|
||||
|
||||
e2e.components.AlertRules.groupToggle().last().click();
|
||||
cy.get('a[title="View"]').click();
|
||||
cy.url().as('alertRule2Url');
|
||||
cy.get('a').contains('View panel').click();
|
||||
|
||||
// make sure the dashboard finished loading
|
||||
cy.get('button[aria-label*="BarChart - Label Rotation & Skipping"]').should('be.visible');
|
||||
|
||||
e2e.components.ReturnToPrevious.backButton()
|
||||
.find('span')
|
||||
.contains('Back to e2e-ReturnToPrevious-test-2')
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
e2e.components.ReturnToPrevious.buttonGroup().should('not.exist');
|
||||
|
||||
// check whether the RTP button leads back to alert rule
|
||||
cy.get('@alertRule2Url').then((alertRule2Url) => {
|
||||
cy.url().should('eq', alertRule2Url);
|
||||
});
|
||||
});
|
||||
});
|
@ -293,6 +293,11 @@ export const Components = {
|
||||
AlertTab: {
|
||||
content: 'data-testid Alert editor tab content',
|
||||
},
|
||||
AlertRules: {
|
||||
groupToggle: 'data-testid group-collapse-toggle',
|
||||
toggle: 'data-testid collapse-toggle',
|
||||
expandedContent: 'data-testid expanded-content',
|
||||
},
|
||||
Alert: {
|
||||
/**
|
||||
* @deprecated use alertV2 from Grafana 8.3 instead
|
||||
@ -537,6 +542,11 @@ export const Components = {
|
||||
Tooltip: {
|
||||
container: 'data-testid tooltip',
|
||||
},
|
||||
ReturnToPrevious: {
|
||||
buttonGroup: 'data-testid dismissable button group',
|
||||
backButton: 'data-testid back',
|
||||
dismissButton: 'data-testid dismiss',
|
||||
},
|
||||
SQLQueryEditor: {
|
||||
selectColumn: 'data-testid select-column',
|
||||
selectAggregation: 'data-testid select-aggregation',
|
||||
|
@ -2,6 +2,7 @@ import { css } from '@emotion/css';
|
||||
import React from 'react';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { Button, ButtonGroup, useStyles2 } from '@grafana/ui';
|
||||
import { t } from 'app/core/internationalization';
|
||||
|
||||
@ -24,6 +25,7 @@ export const DismissableButton = ({ label, onClick, onDismiss }: DismissableButt
|
||||
onClick={onClick}
|
||||
title={label}
|
||||
className={styles.mainDismissableButton}
|
||||
data-testid={selectors.components.ReturnToPrevious.backButton}
|
||||
>
|
||||
{label}
|
||||
</Button>
|
||||
@ -34,6 +36,7 @@ export const DismissableButton = ({ label, onClick, onDismiss }: DismissableButt
|
||||
fill="outline"
|
||||
size="sm"
|
||||
onClick={onDismiss}
|
||||
data-testid={selectors.components.ReturnToPrevious.dismissButton}
|
||||
/>
|
||||
</ButtonGroup>
|
||||
);
|
||||
|
@ -2,6 +2,7 @@ import { css } from '@emotion/css';
|
||||
import React, { useCallback } from 'react';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { locationService } from '@grafana/runtime';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
import { useGrafana } from 'app/core/context/GrafanaContext';
|
||||
@ -28,7 +29,7 @@ export const ReturnToPrevious = ({ href, title }: ReturnToPreviousProps) => {
|
||||
}, [chrome]);
|
||||
|
||||
return (
|
||||
<div className={styles.returnToPrevious}>
|
||||
<div className={styles.returnToPrevious} data-testid={selectors.components.ReturnToPrevious.buttonGroup}>
|
||||
<DismissableButton
|
||||
label={t('return-to-previous.button.label', 'Back to {{title}}', { title })}
|
||||
onClick={handleOnClick}
|
||||
|
@ -4,6 +4,7 @@ import React from 'react';
|
||||
import { TestProvider } from 'test/helpers/TestProvider';
|
||||
import { byRole, byTestId, byText } from 'testing-library-selector';
|
||||
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { setDataSourceSrv } from '@grafana/runtime';
|
||||
import { AccessControlAction } from 'app/types';
|
||||
|
||||
@ -48,7 +49,7 @@ const ui = {
|
||||
groupCollapseToggle: byTestId('alert-group-collapse-toggle'),
|
||||
groupTable: byTestId('alert-group-table'),
|
||||
row: byTestId('row'),
|
||||
collapseToggle: byTestId('collapse-toggle'),
|
||||
collapseToggle: byTestId(selectors.components.AlertRules.toggle),
|
||||
silenceButton: byText('Silence'),
|
||||
sourceButton: byText('See source'),
|
||||
matcherInput: byTestId('search-query-input'),
|
||||
|
@ -6,6 +6,7 @@ import { TestProvider } from 'test/helpers/TestProvider';
|
||||
import { byRole, byTestId, byText } from 'testing-library-selector';
|
||||
|
||||
import { PluginExtensionTypes } from '@grafana/data';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import {
|
||||
DataSourceSrv,
|
||||
getPluginLinkExtensions,
|
||||
@ -113,11 +114,11 @@ const dataSources = {
|
||||
const ui = {
|
||||
ruleGroup: byTestId('rule-group'),
|
||||
cloudRulesSourceErrors: byTestId('cloud-rulessource-errors'),
|
||||
groupCollapseToggle: byTestId('group-collapse-toggle'),
|
||||
ruleCollapseToggle: byTestId('collapse-toggle'),
|
||||
groupCollapseToggle: byTestId(selectors.components.AlertRules.groupToggle),
|
||||
ruleCollapseToggle: byTestId(selectors.components.AlertRules.toggle),
|
||||
rulesTable: byTestId('rules-table'),
|
||||
ruleRow: byTestId('row'),
|
||||
expandedContent: byTestId('expanded-content'),
|
||||
expandedContent: byTestId(selectors.components.AlertRules.expandedContent),
|
||||
rulesFilterInput: byTestId('search-query-input'),
|
||||
moreErrorsButton: byRole('button', { name: /more errors/ }),
|
||||
editCloudGroupIcon: byTestId('edit-group'),
|
||||
@ -399,13 +400,13 @@ describe('RuleList', () => {
|
||||
// expand details of an instance
|
||||
await userEvent.click(ui.ruleCollapseToggle.get(instanceRows![0]));
|
||||
|
||||
const alertDetails = byTestId('expanded-content').get(instanceRows[0]);
|
||||
const alertDetails = byTestId(selectors.components.AlertRules.expandedContent).get(instanceRows[0]);
|
||||
expect(alertDetails).toHaveTextContent('Value2e+10');
|
||||
expect(alertDetails).toHaveTextContent('messagefirst alert message');
|
||||
|
||||
// collapse everything again
|
||||
await userEvent.click(ui.ruleCollapseToggle.get(instanceRows![0]));
|
||||
expect(byTestId('expanded-content').query(instanceRows[0])).not.toBeInTheDocument();
|
||||
expect(byTestId(selectors.components.AlertRules.expandedContent).query(instanceRows[0])).not.toBeInTheDocument();
|
||||
await userEvent.click(ui.ruleCollapseToggle.getAll(ruleRows[1])[0]);
|
||||
await userEvent.click(ui.groupCollapseToggle.get(groups[1]));
|
||||
expect(ui.rulesTable.query()).not.toBeInTheDocument();
|
||||
|
@ -2,6 +2,7 @@ import { css, cx } from '@emotion/css';
|
||||
import React, { ReactNode, useState } from 'react';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { IconButton, Pagination, useStyles2 } from '@grafana/ui';
|
||||
|
||||
import { usePagination } from '../hooks/usePagination';
|
||||
@ -125,7 +126,7 @@ export const DynamicTable = <T extends object>({
|
||||
<div className={cx(styles.cell, styles.expandCell)}>
|
||||
<IconButton
|
||||
tooltip={`${isItemExpanded ? 'Collapse' : 'Expand'} row`}
|
||||
data-testid="collapse-toggle"
|
||||
data-testid={selectors.components.AlertRules.toggle}
|
||||
name={isItemExpanded ? 'angle-down' : 'angle-right'}
|
||||
onClick={() => toggleExpanded(item)}
|
||||
/>
|
||||
@ -141,7 +142,10 @@ export const DynamicTable = <T extends object>({
|
||||
</div>
|
||||
))}
|
||||
{isItemExpanded && renderExpandedContent && (
|
||||
<div className={styles.expandedContentRow} data-testid="expanded-content">
|
||||
<div
|
||||
className={styles.expandedContentRow}
|
||||
data-testid={selectors.components.AlertRules.expandedContent}
|
||||
>
|
||||
{renderExpandedContent(item, index, items)}
|
||||
</div>
|
||||
)}
|
||||
|
@ -95,8 +95,8 @@ const AnnotationsStep = () => {
|
||||
Add more context in your notification messages.
|
||||
</Text>
|
||||
<NeedHelpInfo
|
||||
contentText={`Annotations add metadata to provide more information on the alert in your alert notification messages.
|
||||
For example, add a Summary annotation to tell you which value caused the alert to fire or which server it happened on.
|
||||
contentText={`Annotations add metadata to provide more information on the alert in your alert notification messages.
|
||||
For example, add a Summary annotation to tell you which value caused the alert to fire or which server it happened on.
|
||||
Annotations can contain a combination of text and template code.`}
|
||||
title="Annotations"
|
||||
/>
|
||||
|
@ -3,6 +3,7 @@ import pluralize from 'pluralize';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
import { Badge, ConfirmModal, HorizontalGroup, Icon, Spinner, Stack, Tooltip, useStyles2 } from '@grafana/ui';
|
||||
import { useDispatch } from 'app/types';
|
||||
import { CombinedRuleGroup, CombinedRuleNamespace } from 'app/types/unified-alerting';
|
||||
@ -225,7 +226,7 @@ export const RulesGroup = React.memo(({ group, namespace, expandAll, viewMode }:
|
||||
className={styles.collapseToggle}
|
||||
isCollapsed={isCollapsed}
|
||||
onToggle={setIsCollapsed}
|
||||
data-testid="group-collapse-toggle"
|
||||
data-testid={selectors.components.AlertRules.groupToggle}
|
||||
/>
|
||||
<Icon name={isCollapsed ? 'folder' : 'folder-open'} />
|
||||
{isCloudRulesSource(rulesSource) && (
|
||||
|
@ -30,6 +30,7 @@ mkdir $RUNDIR/conf
|
||||
mkdir $PROV_DIR
|
||||
mkdir $PROV_DIR/datasources
|
||||
mkdir $PROV_DIR/dashboards
|
||||
mkdir $PROV_DIR/alerting
|
||||
|
||||
cp ./scripts/grafana-server/custom.ini $RUNDIR/conf/custom.ini
|
||||
cp ./conf/defaults.ini $RUNDIR/conf/defaults.ini
|
||||
@ -49,6 +50,7 @@ echo -e "Copy provisioning setup from devenv"
|
||||
|
||||
cp devenv/datasources.yaml $PROV_DIR/datasources
|
||||
cp devenv/dashboards.yaml $PROV_DIR/dashboards
|
||||
cp devenv/alert_rules.yaml $PROV_DIR/alerting
|
||||
|
||||
cp -r devenv $RUNDIR
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user