e2e: adds panel editor tests for test data queries (#23996)
(cherry picked from commit 55ac97dccc)
This commit is contained in:
committed by
Arve Knudsen
parent
bd7cf1edd0
commit
a0d2add655
@@ -0,0 +1,146 @@
|
|||||||
|
import { e2e } from '@grafana/e2e';
|
||||||
|
import { expect } from '../../../public/test/lib/common';
|
||||||
|
|
||||||
|
const PANEL_UNDER_TEST = 'Random walk series';
|
||||||
|
|
||||||
|
e2e.scenario({
|
||||||
|
describeName: 'Panel edit tests - queries',
|
||||||
|
itName: 'Testes various Panel edit queries scenarios',
|
||||||
|
addScenarioDataSource: false,
|
||||||
|
addScenarioDashBoard: false,
|
||||||
|
skipScenario: false,
|
||||||
|
scenario: () => {
|
||||||
|
e2e.flows.openDashboard('5SdHCadmz');
|
||||||
|
|
||||||
|
e2e.flows.openPanelMenuItem(e2e.flows.PanelMenuItems.Edit, PANEL_UNDER_TEST);
|
||||||
|
|
||||||
|
// New panel editor opens when navigating from Panel menu
|
||||||
|
e2e.components.PanelEditor.General.content().should('be.visible');
|
||||||
|
|
||||||
|
// Queries tab is rendered and open by default
|
||||||
|
e2e.components.PanelEditor.DataPane.content().should('be.visible');
|
||||||
|
|
||||||
|
// We expect row with refId A to exist and be visible
|
||||||
|
e2e.components.QueryEditorRows.rows().within(rows => {
|
||||||
|
expect(rows.length).equals(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add query button should be visible and clicking on it should create a new row
|
||||||
|
e2e.components.QueryTab.addQuery()
|
||||||
|
.scrollIntoView()
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
|
||||||
|
// We expect row with refId A and B to exist and be visible
|
||||||
|
e2e.components.QueryEditorRows.rows().within(rows => {
|
||||||
|
expect(rows.length).equals(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Remove refId A
|
||||||
|
e2e.components.QueryEditorRow.actionButton('Remove query')
|
||||||
|
.eq(0)
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
|
||||||
|
// We expect row with refId B to exist and be visible
|
||||||
|
e2e.components.QueryEditorRows.rows().within(rows => {
|
||||||
|
expect(rows.length).equals(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Duplicate refId B
|
||||||
|
e2e.components.QueryEditorRow.actionButton('Duplicate query')
|
||||||
|
.eq(0)
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
|
||||||
|
// We expect row with refId Band and A to exist and be visible
|
||||||
|
e2e.components.QueryEditorRows.rows().within(rows => {
|
||||||
|
expect(rows.length).equals(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Change to CSV Metric Values scenario for A
|
||||||
|
e2e.components.DataSource.TestData.QueryTab.scenarioSelect()
|
||||||
|
.eq(1)
|
||||||
|
.select('CSV Metric Values');
|
||||||
|
|
||||||
|
// Change order or query rows
|
||||||
|
// Check the order of the rows before
|
||||||
|
e2e.components.QueryEditorRows.rows()
|
||||||
|
.eq(0)
|
||||||
|
.within(() => {
|
||||||
|
e2e.components.QueryEditorRow.title('B').should('be.visible');
|
||||||
|
});
|
||||||
|
|
||||||
|
e2e.components.QueryEditorRows.rows()
|
||||||
|
.eq(1)
|
||||||
|
.within(() => {
|
||||||
|
e2e.components.QueryEditorRow.title('A').should('be.visible');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Change so A is first
|
||||||
|
e2e.components.QueryEditorRow.actionButton('Move query up')
|
||||||
|
.eq(1)
|
||||||
|
.click();
|
||||||
|
|
||||||
|
// Check the order of the rows after change
|
||||||
|
e2e.components.QueryEditorRows.rows()
|
||||||
|
.eq(0)
|
||||||
|
.within(() => {
|
||||||
|
e2e.components.QueryEditorRow.title('A').should('be.visible');
|
||||||
|
});
|
||||||
|
|
||||||
|
e2e.components.QueryEditorRows.rows()
|
||||||
|
.eq(1)
|
||||||
|
.within(() => {
|
||||||
|
e2e.components.QueryEditorRow.title('B').should('be.visible');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Disable / enable row
|
||||||
|
expectInspectorResultAndClose(keys => {
|
||||||
|
const length = keys.length;
|
||||||
|
expect(keys[length - 2].innerText).equals('A:');
|
||||||
|
expect(keys[length - 1].innerText).equals('B:');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Disable row with refId B
|
||||||
|
e2e.components.QueryEditorRow.actionButton('Disable/enable query')
|
||||||
|
.eq(1)
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
|
||||||
|
expectInspectorResultAndClose(keys => {
|
||||||
|
const length = keys.length;
|
||||||
|
expect(keys[length - 1].innerText).equals('A:');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Enable row with refId B
|
||||||
|
e2e.components.QueryEditorRow.actionButton('Disable/enable query')
|
||||||
|
.eq(1)
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
|
||||||
|
expectInspectorResultAndClose(keys => {
|
||||||
|
const length = keys.length;
|
||||||
|
expect(keys[length - 2].innerText).equals('A:');
|
||||||
|
expect(keys[length - 1].innerText).equals('B:');
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const expectInspectorResultAndClose = (expectCallBack: (keys: any[]) => void) => {
|
||||||
|
e2e.components.QueryTab.queryInspectorButton()
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
|
||||||
|
e2e.components.PanelInspector.Query.refreshButton()
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
|
||||||
|
e2e.components.PanelInspector.Query.jsonObjectKeys()
|
||||||
|
.should('be.visible')
|
||||||
|
.within((keys: any) => expectCallBack(keys));
|
||||||
|
|
||||||
|
e2e.components.Drawer.General.close()
|
||||||
|
.should('be.visible')
|
||||||
|
.click();
|
||||||
|
};
|
||||||
@@ -67,6 +67,8 @@ export const Components = {
|
|||||||
},
|
},
|
||||||
Query: {
|
Query: {
|
||||||
content: 'Panel inspector Query content',
|
content: 'Panel inspector Query content',
|
||||||
|
refreshButton: 'Panel inspector Query refresh button',
|
||||||
|
jsonObjectKeys: () => '.json-formatter-key',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Tab: {
|
Tab: {
|
||||||
@@ -76,6 +78,14 @@ export const Components = {
|
|||||||
QueryTab: {
|
QueryTab: {
|
||||||
content: 'Query editor tab content',
|
content: 'Query editor tab content',
|
||||||
queryInspectorButton: 'Query inspector button',
|
queryInspectorButton: 'Query inspector button',
|
||||||
|
addQuery: 'Query editor add query button',
|
||||||
|
},
|
||||||
|
QueryEditorRows: {
|
||||||
|
rows: 'Query editor row',
|
||||||
|
},
|
||||||
|
QueryEditorRow: {
|
||||||
|
actionButton: (title: string) => `${title} query operation action`,
|
||||||
|
title: (refId: string) => `Query editor row title ${refId}`,
|
||||||
},
|
},
|
||||||
AlertTab: {
|
AlertTab: {
|
||||||
content: 'Alert editor tab content',
|
content: 'Alert editor tab content',
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import { IconName, IconButton, stylesFactory, useTheme } from '@grafana/ui';
|
import { IconButton, IconName, stylesFactory, useTheme } from '@grafana/ui';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { css } from 'emotion';
|
import { css } from 'emotion';
|
||||||
import { GrafanaTheme } from '@grafana/data';
|
import { GrafanaTheme } from '@grafana/data';
|
||||||
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
|
|
||||||
interface QueryOperationActionProps {
|
interface QueryOperationActionProps {
|
||||||
icon: IconName;
|
icon: IconName;
|
||||||
@@ -27,7 +28,7 @@ export const QueryOperationAction: React.FC<QueryOperationActionProps> = ({ icon
|
|||||||
disabled={!!disabled}
|
disabled={!!disabled}
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
surface="header"
|
surface="header"
|
||||||
aria-label={`${title} query operation action`}
|
aria-label={selectors.components.QueryEditorRow.actionButton(title)}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import { renderOrCallToRender, Icon, stylesFactory, useTheme, HorizontalGroup } from '@grafana/ui';
|
import { HorizontalGroup, Icon, renderOrCallToRender, stylesFactory, useTheme } from '@grafana/ui';
|
||||||
import { GrafanaTheme } from '@grafana/data';
|
import { GrafanaTheme } from '@grafana/data';
|
||||||
import { css } from 'emotion';
|
import { css } from 'emotion';
|
||||||
import { useUpdateEffect } from 'react-use';
|
import { useUpdateEffect } from 'react-use';
|
||||||
|
|||||||
@@ -198,7 +198,11 @@ export class QueryInspector extends PureComponent<Props, State> {
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.toolbar}>
|
<div className={styles.toolbar}>
|
||||||
<Button icon="sync" onClick={this.onIssueNewQuery}>
|
<Button
|
||||||
|
icon="sync"
|
||||||
|
onClick={this.onIssueNewQuery}
|
||||||
|
aria-label={selectors.components.PanelInspector.Query.refreshButton}
|
||||||
|
>
|
||||||
Refresh
|
Refresh
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
|||||||
@@ -271,7 +271,12 @@ export class QueriesTab extends PureComponent<Props, State> {
|
|||||||
return (
|
return (
|
||||||
<HorizontalGroup spacing="md" align="flex-start">
|
<HorizontalGroup spacing="md" align="flex-start">
|
||||||
{showAddButton && (
|
{showAddButton && (
|
||||||
<Button icon="plus" onClick={this.onAddQueryClick} variant="secondary">
|
<Button
|
||||||
|
icon="plus"
|
||||||
|
onClick={this.onAddQueryClick}
|
||||||
|
variant="secondary"
|
||||||
|
aria-label={selectors.components.QueryTab.addQuery}
|
||||||
|
>
|
||||||
Query
|
Query
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import { QueryEditorRowTitle } from './QueryEditorRowTitle';
|
|||||||
import { QueryOperationRow } from 'app/core/components/QueryOperationRow/QueryOperationRow';
|
import { QueryOperationRow } from 'app/core/components/QueryOperationRow/QueryOperationRow';
|
||||||
import { QueryOperationAction } from 'app/core/components/QueryOperationRow/QueryOperationAction';
|
import { QueryOperationAction } from 'app/core/components/QueryOperationRow/QueryOperationAction';
|
||||||
import { DashboardModel } from '../state/DashboardModel';
|
import { DashboardModel } from '../state/DashboardModel';
|
||||||
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
panel: PanelModel;
|
panel: PanelModel;
|
||||||
@@ -282,11 +283,13 @@ export class QueryEditorRow extends PureComponent<Props, State> {
|
|||||||
const editor = this.renderPluginEditor();
|
const editor = this.renderPluginEditor();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<QueryOperationRow title={this.renderTitle} actions={this.renderActions} onOpen={this.onOpen}>
|
<div aria-label={selectors.components.QueryEditorRows.rows}>
|
||||||
<div className={rowClasses}>
|
<QueryOperationRow title={this.renderTitle} actions={this.renderActions} onOpen={this.onOpen}>
|
||||||
<ErrorBoundaryAlert>{editor}</ErrorBoundaryAlert>
|
<div className={rowClasses}>
|
||||||
</div>
|
<ErrorBoundaryAlert>{editor}</ErrorBoundaryAlert>
|
||||||
</QueryOperationRow>
|
</div>
|
||||||
|
</QueryOperationRow>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import React from 'react';
|
|||||||
import { css } from 'emotion';
|
import { css } from 'emotion';
|
||||||
import { DataQuery, DataSourceApi, GrafanaTheme } from '@grafana/data';
|
import { DataQuery, DataSourceApi, GrafanaTheme } from '@grafana/data';
|
||||||
import { HorizontalGroup, stylesFactory, useTheme } from '@grafana/ui';
|
import { HorizontalGroup, stylesFactory, useTheme } from '@grafana/ui';
|
||||||
|
import { selectors } from '@grafana/e2e-selectors';
|
||||||
|
|
||||||
interface QueryEditorRowTitleProps {
|
interface QueryEditorRowTitleProps {
|
||||||
query: DataQuery;
|
query: DataQuery;
|
||||||
@@ -24,7 +25,7 @@ export const QueryEditorRowTitle: React.FC<QueryEditorRowTitleProps> = ({
|
|||||||
const styles = getQueryEditorRowTitleStyles(theme);
|
const styles = getQueryEditorRowTitleStyles(theme);
|
||||||
return (
|
return (
|
||||||
<HorizontalGroup align="center">
|
<HorizontalGroup align="center">
|
||||||
<div className={styles.refId}>
|
<div className={styles.refId} aria-label={selectors.components.QueryEditorRow.title(query.refId)}>
|
||||||
<span>{query.refId}</span>
|
<span>{query.refId}</span>
|
||||||
{inMixedMode && <em className={styles.contextInfo}> ({datasource.name})</em>}
|
{inMixedMode && <em className={styles.contextInfo}> ({datasource.name})</em>}
|
||||||
{disabled && <em className={styles.contextInfo}> Disabled</em>}
|
{disabled && <em className={styles.contextInfo}> Disabled</em>}
|
||||||
|
|||||||
Reference in New Issue
Block a user