diff --git a/e2e/suite1/specs/panel-edit.spec.ts b/e2e/suite1/specs/panelEdit_base.spec.ts
similarity index 100%
rename from e2e/suite1/specs/panel-edit.spec.ts
rename to e2e/suite1/specs/panelEdit_base.spec.ts
diff --git a/e2e/suite1/specs/panelEdit_queries.spec.ts b/e2e/suite1/specs/panelEdit_queries.spec.ts
new file mode 100644
index 00000000000..96f34c0bce0
--- /dev/null
+++ b/e2e/suite1/specs/panelEdit_queries.spec.ts
@@ -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();
+};
diff --git a/packages/grafana-e2e-selectors/src/selectors/components.ts b/packages/grafana-e2e-selectors/src/selectors/components.ts
index 781a809367e..54e55a4bd3e 100644
--- a/packages/grafana-e2e-selectors/src/selectors/components.ts
+++ b/packages/grafana-e2e-selectors/src/selectors/components.ts
@@ -67,6 +67,8 @@ export const Components = {
},
Query: {
content: 'Panel inspector Query content',
+ refreshButton: 'Panel inspector Query refresh button',
+ jsonObjectKeys: () => '.json-formatter-key',
},
},
Tab: {
@@ -76,6 +78,14 @@ export const Components = {
QueryTab: {
content: 'Query editor tab content',
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: {
content: 'Alert editor tab content',
diff --git a/public/app/core/components/QueryOperationRow/QueryOperationAction.tsx b/public/app/core/components/QueryOperationRow/QueryOperationAction.tsx
index 20b016146f0..f109b3c0d7a 100644
--- a/public/app/core/components/QueryOperationRow/QueryOperationAction.tsx
+++ b/public/app/core/components/QueryOperationRow/QueryOperationAction.tsx
@@ -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 { css } from 'emotion';
import { GrafanaTheme } from '@grafana/data';
+import { selectors } from '@grafana/e2e-selectors';
interface QueryOperationActionProps {
icon: IconName;
@@ -27,7 +28,7 @@ export const QueryOperationAction: React.FC