DashboardScenes: Optimise e2e test and add panels suite (#88170)

* refactor tests after adding additional data-testids

* add panels-suite e2e tests

* wip: add missing selectors

* finalise panels-suite tests

* clean up

* adjust workflow for test run

* restore workflow
This commit is contained in:
Sergej-Vlasov 2024-05-24 14:22:11 +01:00 committed by GitHub
parent 859b3ff78b
commit fbb5fd71f9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 968 additions and 220 deletions

View File

@ -3,6 +3,7 @@ name: Run dashboard scenes e2e
on:
schedule:
- cron: "0 8 * * 1-5" # every day at 08:00UTC on weekdays
# push # uncomment for test run during PR
env:
ARCH: linux-amd64

View File

@ -43,8 +43,8 @@ describe('Repeating a panel horizontally', () => {
cy.get('input').click();
});
e2e.components.Select.option().contains('1').click();
e2e.components.Select.option().contains('3').click();
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('1').click();
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('3').click();
// blur the dropdown
cy.get('body').click();

View File

@ -44,8 +44,8 @@ describe('Repeating a panel vertically', () => {
cy.get('input').click();
});
e2e.components.Select.option().contains('1').click();
e2e.components.Select.option().contains('3').click();
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('1').click();
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('3').click();
// blur the dropdown
cy.get('body').click();

View File

@ -1,7 +1,7 @@
import { e2e } from '../utils';
const PAGE_UNDER_TEST = 'dtpl2Ctnk/repeating-an-empty-row';
describe.skip('Repeating empty rows', () => {
describe('Repeating empty rows', () => {
beforeEach(() => {
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
});
@ -38,8 +38,8 @@ describe.skip('Repeating empty rows', () => {
cy.get('input').click();
});
e2e.components.Select.option().contains('1').click();
e2e.components.Select.option().contains('3').click();
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('1').click();
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('3').click();
// blur the dropdown
cy.get('body').click();

View File

@ -18,72 +18,46 @@ describe('Variables - Load options from Url', () => {
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('A')
.should('be.visible')
.children()
.children()
.first()
.click();
.within(() => {
cy.get('input').click();
});
e2e.components.Select.option().parent().should('have.length', 9);
e2e.components.Select.option()
.first()
.should('have.text', 'All')
.parent()
.next()
.should('have.text', 'A')
.next()
.should('have.text', 'B')
.next()
.should('have.text', 'C')
.next()
.should('have.text', 'D');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('All').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('A').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('B').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('C').should('be.visible');
cy.get('body').click(0, 0);
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('AA')
.should('be.visible')
.children()
.children()
.first()
.click();
.within(() => {
cy.get('input').click();
});
e2e.components.Select.option().parent().should('have.length', 9);
e2e.components.Select.option()
.first()
.should('have.text', 'All')
.parent()
.next()
.should('have.text', 'AA')
.next()
.should('have.text', 'AB')
.next()
.should('have.text', 'AC')
.next()
.should('have.text', 'AD');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('All').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AA').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AB').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AC').should('be.visible');
cy.get('body').click(0, 0);
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('$__all')
.should('be.visible')
.children()
.children()
.first()
.click();
.within(() => {
cy.get('input').click();
});
e2e.components.Select.option().parent().should('have.length', 9);
e2e.components.Select.option()
.first()
.should('have.text', 'All')
.parent()
.next()
.should('have.text', 'AAA')
.next()
.should('have.text', 'AAB')
.next()
.should('have.text', 'AAC')
.next()
.should('have.text', 'AAD');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('All').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AAA').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AAB').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AAC').should('be.visible');
});
it('options set in url should load correct options', () => {
@ -97,73 +71,46 @@ describe('Variables - Load options from Url', () => {
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('B')
.should('be.visible')
.children()
.children()
.first()
.click();
.within(() => {
cy.get('input').click();
});
e2e.components.Select.option().parent().should('have.length', 9);
e2e.components.Select.option()
.first()
.should('have.text', 'All')
.parent()
.next()
.should('have.text', 'A')
.next()
.should('have.text', 'B')
.next()
.should('have.text', 'C')
.next()
.should('have.text', 'D');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('All').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('A').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('B').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('C').should('be.visible');
cy.get('body').click(0, 0);
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('BB')
.should('be.visible')
.children()
.children()
.first()
.click();
.within(() => {
cy.get('input').click();
});
e2e.components.Select.option().parent().should('have.length', 9);
e2e.components.Select.option()
.first()
.should('have.text', 'All')
.parent()
.next()
.should('have.text', 'BA')
.next()
.should('have.text', 'BB')
.next()
.should('have.text', 'BC')
.next()
.should('have.text', 'BD');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('All').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BA').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BB').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BC').should('be.visible');
cy.get('body').click(0, 0);
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('BBB')
.should('be.visible')
.children()
.children()
.first()
.click();
.within(() => {
cy.get('input').click();
});
e2e.components.Select.option().parent().should('have.length', 9);
e2e.components.Select.option()
.first()
.should('have.text', 'All')
.parent()
.next()
.should('have.text', 'BBA')
.next()
.should('have.text', 'BBB')
.next()
.should('have.text', 'BBC')
.next()
.should('have.text', 'BBD');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('All').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BBA').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BBB').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BBC').should('be.visible');
});
it('options set in url that do not exist should load correct options', () => {
@ -188,23 +135,16 @@ describe('Variables - Load options from Url', () => {
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('X')
.should('be.visible')
.children()
.children()
.first()
.click();
.within(() => {
cy.get('input').click();
});
e2e.components.Select.option().parent().should('have.length', 9);
e2e.components.Select.option()
.first()
.should('have.text', 'All')
.parent()
.next()
.should('have.text', 'A')
.next()
.should('have.text', 'B')
.next()
.should('have.text', 'C');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('All').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('A').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('B').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('C').should('be.visible');
cy.get('body').click();

View File

@ -12,8 +12,13 @@ describe('Variables - Set options from ui', () => {
it('clicking a value that is not part of dependents options should change these to All', () => {
e2e.flows.openDashboard({ uid: `${PAGE_UNDER_TEST}?orgId=1&var-datacenter=A&var-server=AA&var-pod=AAA` });
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('A').should('be.visible').click().click();
e2e.components.Select.option().contains('B').click();
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('A')
.should('be.visible')
.within(() => {
cy.get('input').click();
});
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('A').should('be.visible').click();
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('B').should('be.visible').click();
cy.get('body').click();
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('B').scrollIntoView().should('be.visible');
@ -27,21 +32,16 @@ describe('Variables - Set options from ui', () => {
});
e2e.components.Select.option().parent().should('have.length', 9);
e2e.components.Select.option()
.first()
.should('have.text', 'All')
.parent()
.next()
.should('have.text', 'BA')
.next()
.should('have.text', 'BB')
.next()
.should('have.text', 'BC');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('All').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BA').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BB').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BC').should('be.visible');
cy.get('body').click();
e2e.pages.Dashboard.SubMenu.submenuItemLabels('pod')
.next()
.parent()
.within(() => {
cy.get('input').click();
});
@ -49,22 +49,13 @@ describe('Variables - Set options from ui', () => {
// length is 11 because of virtualized select options
e2e.components.Select.option().parent().should('have.length', 11);
e2e.components.Select.option()
.first()
.should('have.text', 'All')
.parent()
.next()
.should('have.text', 'BAA')
.next()
.should('have.text', 'BAB')
.next()
.should('have.text', 'BAC')
.next()
.should('have.text', 'BAD')
.next()
.should('have.text', 'BAE')
.next()
.should('have.text', 'BAF');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('All').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BAA').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BAB').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BAC').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BAD').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BAE').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BAF').should('be.visible');
});
it('adding a value that is not part of dependents options should add the new values dependant options', () => {
@ -80,7 +71,7 @@ describe('Variables - Set options from ui', () => {
.within(() => {
cy.get('input').click();
});
e2e.components.Select.option().contains('B').click();
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('B').should('be.visible').click();
cy.get('body').click();
cy.wait('@query');
@ -97,18 +88,11 @@ describe('Variables - Set options from ui', () => {
e2e.components.Select.option().should('have.length', 11);
e2e.components.Select.option()
.first()
.should('have.text', 'All')
.parent()
.next()
.should('have.text', 'AA')
.next()
.should('have.text', 'AB')
.next()
.should('have.text', 'AC')
.next()
.should('have.text', 'AD');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('All').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AA').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AB').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AC').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AD').should('be.visible');
cy.get('body').click();
@ -120,16 +104,10 @@ describe('Variables - Set options from ui', () => {
e2e.components.Select.option().should('have.length', 9);
e2e.components.Select.option()
.first()
.should('have.text', 'All')
.parent()
.next()
.should('have.text', 'AAA')
.next()
.should('have.text', 'AAB')
.next()
.should('have.text', 'AAC');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('All').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AAA').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AAB').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AAC').should('be.visible');
});
it('removing a value that is part of dependents options should remove the new values dependant options', () => {
@ -143,23 +121,18 @@ describe('Variables - Set options from ui', () => {
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('A,B')
.should('be.visible')
.children()
.first()
.click();
.within(() => {
cy.get('input').click();
});
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('A').should('be.visible').click();
cy.get('body').click();
cy.wait('@query');
cy.get(`[aria-label="${selectors.components.LoadingIndicator.icon}"]`).should('not.exist');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('B')
.scrollIntoView()
.should('be.visible')
.within(() => {
cy.get('input').click();
});
cy.get('body').click();
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('B').should('be.visible');
cy.get(`[aria-label="${selectors.components.LoadingIndicator.icon}"]`).should('not.exist');
@ -171,16 +144,10 @@ describe('Variables - Set options from ui', () => {
e2e.components.Select.option().should('have.length', 9);
e2e.components.Select.option()
.first()
.should('have.text', 'All')
.parent()
.next()
.should('have.text', 'BA')
.next()
.should('have.text', 'BB')
.next()
.should('have.text', 'BC');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('All').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BA').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BB').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BC').should('be.visible');
cy.get('body').click(0, 0);
@ -191,15 +158,8 @@ describe('Variables - Set options from ui', () => {
});
e2e.components.Select.option().should('have.length', 9);
e2e.components.Select.option()
.first()
.should('have.text', 'All')
.parent()
.next()
.should('have.text', 'BBA')
.next()
.should('have.text', 'BBB')
.next()
.should('have.text', 'BBC');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BBA').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BBB').should('be.visible');
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BBC').should('be.visible');
});
});

View File

@ -34,24 +34,20 @@ describe('Templating', () => {
e2e.components.DashboardLinks.dropDown().should('be.visible').click().wait('@tagsTemplatingSearch');
// verify all links, should have All value
verifyLinks('var-custom=p1&var-custom=p2&var-custom=p3');
cy.get('body').click();
e2e.pages.Dashboard.SubMenu.submenuItemLabels('custom')
.next()
.should('have.text', 'All')
.parent()
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('$__all')
.should('be.visible')
.within(() => {
cy.get('input').click();
});
e2e.components.Select.option().contains('p2').click();
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('p2').should('be.visible').click();
cy.get('body').click();
e2e.components.NavToolbar.container().click();
e2e.components.DashboardLinks.dropDown()
.scrollIntoView()
.should('be.visible')

View File

@ -0,0 +1,41 @@
import { e2e } from '../../utils';
const PAGE_UNDER_TEST = 'a6801696-cc53-4196-b1f9-2403e3909185/panel-tests-dashlist-variables';
describe('DashList panel', () => {
beforeEach(() => {
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
});
// this is to prevent the fix for https://github.com/grafana/grafana/issues/76800 from regressing
it('should pass current variable values correctly when `Include current template variable values` is set', () => {
e2e.flows.openDashboard({ uid: PAGE_UNDER_TEST });
// check the initial value of the urls contain the variable value correctly
e2e.components.Panels.Panel.title('Include time range and variables enabled')
.should('be.visible')
.within(() => {
cy.get('a').each(($el) => {
cy.wrap($el).should('have.attr', 'href').and('contain', 'var-server=A');
});
});
// update variable to b
e2e.pages.Dashboard.SubMenu.submenuItemLabels('server')
.parent()
.within(() => {
cy.get('input').click();
});
e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('B').click();
// blur the dropdown
cy.get('body').click();
// check the urls are updated with the new variable value
e2e.components.Panels.Panel.title('Include time range and variables enabled')
.should('be.visible')
.within(() => {
cy.get('a').each(($el) => {
cy.wrap($el).should('have.attr', 'href').and('contain', 'var-server=B');
});
});
});
});

View File

@ -0,0 +1,36 @@
import { e2e } from '../../utils';
const DASHBOARD_ID = 'c01bf42b-b783-4447-a304-8554cee1843b';
const DATAGRID_SELECT_SERIES = 'Datagrid Select series';
//TODO enable this test when panel goes live
describe.skip('Datagrid data changes', () => {
beforeEach(() => {
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
});
it('Tests changing data in the grid', () => {
e2e.flows.openDashboard({ uid: DASHBOARD_ID, queryParams: { editPanel: 1 } });
// Check that the data is series A
e2e.components.PanelEditor.OptionsPane.fieldLabel(DATAGRID_SELECT_SERIES).should('be.visible');
cy.get('[data-testid="glide-cell-2-0"]').should('have.text', '1');
cy.get('[data-testid="glide-cell-2-1"]').should('have.text', '20');
cy.get('[data-testid="glide-cell-2-2"]').should('have.text', '90');
// Change the series to B
e2e.components.PanelEditor.OptionsPane.fieldLabel(DATAGRID_SELECT_SERIES).find('input').type('B {enter}');
cy.get('[data-testid="glide-cell-2-3"]').should('have.text', '30');
cy.get('[data-testid="glide-cell-2-4"]').should('have.text', '40');
cy.get('[data-testid="glide-cell-2-5"]').should('have.text', '50');
// Edit datagrid which triggers a snapshot query
cy.get('.dvn-scroller').click(200, 100);
cy.get('[data-testid="glide-cell-2-1"]').should('have.attr', 'aria-selected', 'true');
cy.get('body').type('12{enter}', { delay: 500 });
cy.get('[data-testid="data-testid Confirm Modal Danger Button"]').click();
cy.get('[data-testid="query-editor-row"]').contains('Snapshot');
});
});

View File

@ -0,0 +1,159 @@
import { e2e } from '../../utils';
const DASHBOARD_ID = 'c01bf42b-b783-4447-a304-8554cee1843b';
const DATAGRID_CANVAS = 'data-grid-canvas';
//TODO enable this test when panel goes live
describe.skip('Datagrid data changes', () => {
beforeEach(() => {
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
});
it('Tests changing data in the grid', () => {
e2e.flows.openDashboard({ uid: DASHBOARD_ID, queryParams: { editPanel: 1 } });
// Edit datagrid which triggers a snapshot query
cy.get('.dvn-scroller').click(200, 100);
cy.get('[data-testid="glide-cell-2-1"]').should('have.attr', 'aria-selected', 'true');
cy.get('body').type('123{enter}', { delay: 500 });
cy.get('[data-testid="data-testid Confirm Modal Danger Button"]').click();
// Delete a cell
cy.get('.dvn-scroller').click(200, 200);
cy.get('body').type('{del}');
cy.get('[data-testid="glide-cell-2-4"]').should('have.text', 0);
// Delete a selection
cy.get('.dvn-scroller').click(50, 100, { shiftKey: true });
cy.get('body').type('{del}');
cy.get('[data-testid="glide-cell-2-3"]').should('have.text', 0);
cy.get('[data-testid="glide-cell-2-2"]').should('have.text', 0);
cy.get('[data-testid="glide-cell-2-1"]').should('have.text', 0);
cy.get('[data-testid="glide-cell-2-0"]').should('have.text', 1);
cy.get('[data-testid="glide-cell-1-3"]').should('have.text', '');
cy.get('[data-testid="glide-cell-1-2"]').should('have.text', '');
cy.get('[data-testid="glide-cell-1-1"]').should('have.text', '');
cy.get('[data-testid="glide-cell-1-0"]').should('not.have.text', '');
// Clear column through context menu
cy.get('.dvn-scroller').rightclick(200, 100);
cy.get('[aria-label="Context menu"]').click(100, 120); // click clear column
cy.get('[data-testid="glide-cell-2-0"]').should('have.text', 0);
cy.get('[data-testid="glide-cell-2-4"]').should('have.text', 0);
// Clear row through context menu
cy.get('.dvn-scroller').click(200, 220);
cy.get('body').type('1123{enter}', { delay: 500 });
cy.get('.dvn-scroller').rightclick(200, 220);
cy.get('[aria-label="Context menu"]').click(100, 100); // click clear row
cy.get('[data-testid="glide-cell-1-4"]').should('have.text', '');
cy.get('[data-testid="glide-cell-2-4"]').should('have.text', 0);
// get the data back
cy.reload();
// Clear row through row selector
cy.get('.dvn-scroller').click(20, 190, { waitForAnimations: true });
cy.get('.dvn-scroller').click(20, 90, { shiftKey: true, waitForAnimations: true }); // with shift to select all rows between clicks
cy.get('body').type('{del}');
cy.get('[data-testid="data-testid Confirm Modal Danger Button"]').click();
cy.get('[data-testid="glide-cell-1-4"]').should('have.text', '');
cy.get('[data-testid="glide-cell-1-3"]').should('have.text', '');
cy.get('[data-testid="glide-cell-1-2"]').should('have.text', '');
cy.get('[data-testid="glide-cell-1-1"]').should('have.text', '');
cy.get('[data-testid="glide-cell-2-4"]').should('have.text', 0);
cy.get('[data-testid="glide-cell-2-3"]').should('have.text', 0);
cy.get('[data-testid="glide-cell-2-2"]').should('have.text', 0);
cy.get('[data-testid="glide-cell-2-1"]').should('have.text', 0);
cy.wait(1000);
cy.reload();
cy.get('.dvn-scroller').click(20, 190, { waitForAnimations: true });
cy.get('.dvn-scroller').click(20, 90, { commandKey: true, waitForAnimations: true }); // with cmd to select only clicked rows
cy.get('body').type('{del}');
cy.get('[data-testid="data-testid Confirm Modal Danger Button"]').click();
cy.get('[data-testid="glide-cell-1-1"]').should('have.text', '');
cy.get('[data-testid="glide-cell-2-1"]').should('have.text', 0);
cy.get('[data-testid="glide-cell-2-4"]').should('have.text', 0);
cy.get('[data-testid="glide-cell-1-4"]').should('have.text', '');
// Remove all data
cy.get('.dvn-scroller').rightclick(100, 100);
cy.get('body').click(150, 420);
cy.get(`[data-testid="${DATAGRID_CANVAS}"] th`).should('have.length', 0);
cy.reload();
// Delete column through header dropdown menu
cy.get('.dvn-scroller').click(250, 15); // click header dropdown
cy.get('body').click(450, 420); // click delete column
cy.get('[data-testid="data-testid Confirm Modal Danger Button"]').click();
cy.get(`[data-testid="${DATAGRID_CANVAS}"] th`).should('have.length', 1);
// Delete row through context menu
cy.get('.dvn-scroller').rightclick(100, 100);
cy.get('[aria-label="Context menu"]').click(10, 10);
cy.get(`[data-testid="${DATAGRID_CANVAS}"] tbody tr`).should('have.length', 6); // there are 5 data rows + 1 for the add new row btns
// Delete rows through row selector
cy.get('.dvn-scroller').click(20, 190, { waitForAnimations: true });
cy.get('.dvn-scroller').click(20, 90, { shiftKey: true, waitForAnimations: true }); // with shift to select all rows between clicks
cy.get('.dvn-scroller').rightclick(100, 100);
cy.get('[aria-label="Context menu"]').click(10, 10);
cy.get(`[data-testid="${DATAGRID_CANVAS}"] tbody tr`).should('have.length', 2); // there are 1 data rows + 1 for the add new row btns
cy.reload();
cy.get('.dvn-scroller').click(20, 190, { waitForAnimations: true });
cy.get('.dvn-scroller').click(20, 90, { commandKey: true, waitForAnimations: true }); // with shift to select all rows between clicks
cy.get('.dvn-scroller').rightclick(40, 90);
cy.get('[aria-label="Context menu"]').click(10, 10);
cy.get('[data-testid="data-testid Confirm Modal Danger Button"]').click();
cy.get(`[data-testid="${DATAGRID_CANVAS}"] tbody tr`).should('have.length', 5); // there are 5 data rows + 1 for the add new row btns
// Delete column through context menu
cy.get('.dvn-scroller').rightclick(100, 100);
cy.get('[aria-label="Context menu"]').click(10, 50);
cy.get(`[data-testid="${DATAGRID_CANVAS}"] th`).should('have.length', 1);
cy.reload();
cy.wait(3000);
// Add a new column
cy.get('body').click(350, 200).type('New Column{enter}');
cy.get('[data-testid="data-testid Confirm Modal Danger Button"]').click();
cy.get('body')
.click(350, 230)
.type('Value 1{enter}')
.type('Value 2{enter}')
.type('Value 3{enter}')
.type('Value 4{enter}')
.type('Value 5{enter}')
.type('Value 6{enter}');
cy.get(`[data-testid="${DATAGRID_CANVAS}"] th`).should('have.length', 3);
// Rename a column
cy.get('.dvn-scroller').click(250, 15); // click header dropdown
cy.get('body').click(450, 380).type('{selectall}{backspace}Renamed column{enter}');
cy.get(`[data-testid="${DATAGRID_CANVAS}"] th`).contains('Renamed column');
// Change column field type
cy.get('.dvn-scroller').click(310, 15);
cy.get('[aria-label="Context menu"]').click(50, 50);
cy.get('.dvn-scroller').click(200, 100);
cy.get('body').type('Str Value{enter}');
cy.get(`[data-testid="${DATAGRID_CANVAS}"] tr`).contains('Str Value');
// Select all rows through row selection
cy.get('.dvn-scroller').click(10, 10, { waitForAnimations: true });
cy.get(`[data-testid="${DATAGRID_CANVAS}"] [aria-selected="true"]`).should('have.length', 6);
// Add a new row
cy.get('.dvn-scroller').click(200, 250);
cy.get('body').type('123');
cy.get('.dvn-scroller').click(50, 250);
cy.get('body').type('Val{enter}');
cy.get(`[data-testid="${DATAGRID_CANVAS}"] tbody tr`).contains('Val');
cy.get(`[data-testid="${DATAGRID_CANVAS}"] tbody tr`).should('have.length', 8);
});
});

View File

@ -0,0 +1,128 @@
import panelSandboxDashboard from '../../dashboards/PanelSandboxDashboard.json';
import { e2e } from '../../utils';
const DASHBOARD_ID = 'c46b2460-16b7-42a5-82d1-b07fbf431950';
describe('Panel sandbox', () => {
beforeEach(() => {
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'), true);
return e2e.flows.importDashboard(panelSandboxDashboard, 1000, true);
});
describe('Sandbox disabled', () => {
beforeEach(() => {
cy.window().then((win) => {
win.localStorage.setItem('grafana.featureToggles', 'pluginsFrontendSandbox=0');
});
cy.reload();
});
it('Add iframes to body', () => {
// this button adds iframes to the body
cy.get('[data-testid="button-create-iframes"]').click();
const iframeIds = [
'createElementIframe',
'innerHTMLIframe',
'appendIframe',
'prependIframe',
'afterIframe',
'beforeIframe',
'outerHTMLIframe',
'parseFromStringIframe',
'insertBeforeIframe',
'replaceChildIframe',
];
iframeIds.forEach((id) => {
cy.get(`#${id}`).should('exist');
});
});
it('Reaches out of panel div', () => {
// this button reaches out of the panel div and modifies the element dataset
cy.get('[data-testid="button-reach-out"]').click();
cy.get('[data-sandbox-test="true"]').should('exist');
});
it('Reaches out of the panel editor', () => {
e2e.flows.openDashboard({
uid: DASHBOARD_ID,
queryParams: {
editPanel: 1,
},
});
cy.get('[data-testid="panel-editor-custom-editor-input"]').should('not.be.disabled');
cy.get('[data-testid="panel-editor-custom-editor-input"]').type('x', { force: true });
cy.get('[data-sandbox-test="panel-editor"]').should('exist');
});
});
describe('Sandbox enabled', () => {
beforeEach(() => {
cy.window().then((win) => {
win.localStorage.setItem('grafana.featureToggles', 'pluginsFrontendSandbox=1');
});
cy.reload();
});
it('Does not add iframes to body', () => {
// this button adds 3 iframes to the body
cy.get('[data-testid="button-create-iframes"]').click();
cy.wait(100); // small delay to prevent false positives from too fast tests
const iframeIds = [
'createElementIframe',
'innerHTMLIframe',
'appendIframe',
'prependIframe',
'afterIframe',
'beforeIframe',
'outerHTMLIframe',
'parseFromStringIframe',
'insertBeforeIframe',
'replaceChildIframe',
];
iframeIds.forEach((id) => {
cy.get(`#${id}`).should('not.exist');
});
});
it('Does not reaches out of panel div', () => {
// this button reaches out of the panel div and modifies the element dataset
cy.get('[data-testid="button-reach-out"]').click();
cy.wait(100); // small delay to prevent false positives from too fast tests
cy.get('[data-sandbox-test="true"]').should('not.exist');
});
it('Does not Reaches out of the panel editor', () => {
e2e.flows.openDashboard({
uid: DASHBOARD_ID,
queryParams: {
editPanel: 1,
},
});
cy.get('[data-testid="panel-editor-custom-editor-input"]').should('not.be.disabled');
cy.get('[data-testid="panel-editor-custom-editor-input"]').type('x', { force: true });
cy.wait(100); // small delay to prevent false positives from too fast tests
cy.get('[data-sandbox-test="panel-editor"]').should('not.exist');
});
it('Can access specific window global variables', () => {
cy.get('[data-testid="button-test-globals"]').click();
cy.get('[data-sandbox-global="Prism"]').should('be.visible');
cy.get('[data-sandbox-global="jQuery"]').should('be.visible');
cy.get('[data-sandbox-global="location"]').should('be.visible');
});
});
afterEach(() => {
e2e.flows.revertAllChanges();
});
after(() => {
return cy.clearCookies();
});
});

View File

@ -0,0 +1,99 @@
import { e2e } from '../../utils';
const DASHBOARD_ID = 'P2jR04WVk';
const MAP_LAYERS_TYPE = 'Map layers Layer type';
const MAP_LAYERS_DATA = 'Map layers Data';
const MAP_LAYERS_GEOJSON = 'Map layers GeoJSON URL';
describe('Geomap layer types', () => {
beforeEach(() => {
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
});
it('Tests changing the layer type', () => {
e2e.flows.openDashboard({ uid: DASHBOARD_ID, queryParams: { editPanel: 1 } });
cy.get('[data-testid="layer-drag-drop-list"]').should('be.visible');
e2e.components.PanelEditor.OptionsPane.fieldLabel(MAP_LAYERS_TYPE).should('be.visible');
cy.get('[data-testid="layer-drag-drop-list"]').contains('markers');
// Heatmap
e2e.components.PanelEditor.OptionsPane.fieldLabel(MAP_LAYERS_TYPE).type('Heatmap{enter}');
cy.get('[data-testid="layer-drag-drop-list"]').contains('heatmap');
e2e.components.PanelEditor.OptionsPane.fieldLabel(MAP_LAYERS_DATA).should('be.visible');
// e2e.components.PanelEditor.General.content().should('be.visible');
// GeoJSON
e2e.components.PanelEditor.OptionsPane.fieldLabel(MAP_LAYERS_TYPE).type('GeoJSON{enter}');
cy.get('[data-testid="layer-drag-drop-list"]').contains('geojson');
e2e.components.PanelEditor.OptionsPane.fieldLabel(MAP_LAYERS_DATA).should('not.exist');
e2e.components.PanelEditor.OptionsPane.fieldLabel(MAP_LAYERS_GEOJSON).should('be.visible');
// e2e.components.PanelEditor.General.content().should('be.visible');
// Open Street Map
e2e.components.PanelEditor.OptionsPane.fieldLabel(MAP_LAYERS_TYPE).type('Open Street Map{enter}');
cy.get('[data-testid="layer-drag-drop-list"]').contains('osm-standard');
e2e.components.PanelEditor.OptionsPane.fieldLabel(MAP_LAYERS_DATA).should('not.exist');
e2e.components.PanelEditor.OptionsPane.fieldLabel(MAP_LAYERS_GEOJSON).should('not.exist');
// e2e.components.PanelEditor.General.content().should('be.visible');
// CARTO basemap
e2e.components.PanelEditor.OptionsPane.fieldLabel(MAP_LAYERS_TYPE).type('CARTO basemap{enter}');
cy.get('[data-testid="layer-drag-drop-list"]').contains('carto');
e2e.components.PanelEditor.OptionsPane.fieldLabel('Map layers Show labels').should('be.visible');
e2e.components.PanelEditor.OptionsPane.fieldLabel('Map layers Theme').should('be.visible');
// e2e.components.PanelEditor.General.content().should('be.visible');
// ArcGIS MapServer
e2e.components.PanelEditor.OptionsPane.fieldLabel(MAP_LAYERS_TYPE).type('ArcGIS MapServer{enter}');
cy.get('[data-testid="layer-drag-drop-list"]').contains('esri-xyz');
e2e.components.PanelEditor.OptionsPane.fieldLabel('Map layers Server instance').should('be.visible');
// e2e.components.PanelEditor.General.content().should('be.visible');
// XYZ Tile layer
e2e.components.PanelEditor.OptionsPane.fieldLabel(MAP_LAYERS_TYPE).type('XYZ Tile layer{enter}');
cy.get('[data-testid="layer-drag-drop-list"]').contains('xyz');
e2e.components.PanelEditor.OptionsPane.fieldLabel('Map layers URL template').should('be.visible');
e2e.components.PanelEditor.OptionsPane.fieldLabel('Map layers Attribution').should('be.visible');
// e2e.components.PanelEditor.General.content().should('be.visible');
});
it.skip('Tests changing the layer type (alpha)', () => {
e2e.flows.openDashboard({ uid: DASHBOARD_ID, queryParams: { editPanel: 1 } });
cy.get('[data-testid="layer-drag-drop-list"]').should('be.visible');
e2e.components.PanelEditor.OptionsPane.fieldLabel(MAP_LAYERS_TYPE).should('be.visible');
cy.get('[data-testid="layer-drag-drop-list"]').contains('markers');
// Icon at last point (Alpha)
e2e.components.PanelEditor.OptionsPane.fieldLabel(MAP_LAYERS_TYPE).type('Icon at last point{enter}');
cy.get('[data-testid="layer-drag-drop-list"]').contains('last-point-tracker');
e2e.components.PanelEditor.OptionsPane.fieldLabel(MAP_LAYERS_DATA).should('be.visible');
e2e.components.PanelEditor.General.content().should('be.visible');
// Dynamic GeoJSON (Alpha)
e2e.components.PanelEditor.OptionsPane.fieldLabel(MAP_LAYERS_TYPE).type('Dynamic GeoJSON{enter}');
cy.get('[data-testid="layer-drag-drop-list"]').contains('dynamic-geojson');
e2e.components.PanelEditor.OptionsPane.fieldLabel(MAP_LAYERS_DATA).should('be.visible');
e2e.components.PanelEditor.OptionsPane.fieldLabel(MAP_LAYERS_GEOJSON).should('be.visible');
e2e.components.PanelEditor.OptionsPane.fieldLabel('Map layers ID Field').should('be.visible');
e2e.components.PanelEditor.General.content().should('be.visible');
// Night / Day (Alpha)
e2e.components.PanelEditor.OptionsPane.fieldLabel(MAP_LAYERS_TYPE).type('Night / Day{enter}');
cy.get('[data-testid="layer-drag-drop-list"]').contains('dayNight');
e2e.components.PanelEditor.OptionsPane.fieldLabel(MAP_LAYERS_DATA).should('be.visible');
e2e.components.PanelEditor.OptionsPane.fieldLabel('Map layers Show').should('be.visible');
e2e.components.PanelEditor.OptionsPane.fieldLabel('Map layers Night region color').should('be.visible');
e2e.components.PanelEditor.OptionsPane.fieldLabel('Map layers Display sun').should('be.visible');
e2e.components.PanelEditor.General.content().should('be.visible');
// Route (Alpha)
e2e.components.PanelEditor.OptionsPane.fieldLabel(MAP_LAYERS_TYPE).type('Route{enter}');
cy.get('[data-testid="layer-drag-drop-list"]').contains('route');
e2e.components.PanelEditor.OptionsPane.fieldLabel(MAP_LAYERS_DATA).should('be.visible');
e2e.components.PanelEditor.OptionsPane.fieldLabel('Map layers Location').should('be.visible');
e2e.components.PanelEditor.OptionsPane.fieldLabel('Map layers Style').should('be.visible');
e2e.components.PanelEditor.OptionsPane.fieldLabel('Map layers Line width').should('be.visible');
e2e.components.PanelEditor.General.content().should('be.visible');
});
});

View File

@ -0,0 +1,58 @@
import { e2e } from '../../utils';
const DASHBOARD_ID = 'P2jR04WVk';
describe('Geomap layer controls options', () => {
beforeEach(() => {
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
});
it('Tests map controls options', () => {
e2e.flows.openDashboard({ uid: DASHBOARD_ID, queryParams: { editPanel: 1 } });
e2e.components.OptionsGroup.group('Map controls').scrollIntoView().should('exist');
// Show zoom
e2e.components.PanelEditor.showZoomField()
.should('exist')
.within(() => {
cy.get('input[type="checkbox"]').check({ force: true });
});
cy.contains('+');
cy.get('.ol-zoom').should('exist');
// Show attribution
e2e.components.PanelEditor.showAttributionField()
.should('exist')
.within(() => {
cy.get('input[type="checkbox"]').check({ force: true });
});
cy.get('.ol-attribution').should('exist');
// Show scale
e2e.components.PanelEditor.showScaleField()
.should('exist')
.within(() => {
cy.get('input[type="checkbox"]').check({ force: true });
});
cy.get('.ol-scale-line').should('exist');
// Show measure tool
e2e.components.PanelEditor.showMeasureField()
.should('exist')
.within(() => {
cy.get('input[type="checkbox"]').check({ force: true });
});
e2e.components.PanelEditor.measureButton().should('exist');
// Show debug
e2e.components.PanelEditor.showDebugField()
.should('exist')
.within(() => {
cy.get('input[type="checkbox"]').check({ force: true });
});
e2e.components.DebugOverlay.wrapper().should('exist');
});
});

View File

@ -0,0 +1,98 @@
import { e2e } from '../../utils';
const DASHBOARD_ID = 'P2jR04WVk';
describe('Geomap spatial operations', () => {
beforeEach(() => {
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
});
it('Tests location auto option', () => {
e2e.flows.openDashboard({ uid: DASHBOARD_ID, queryParams: { editPanel: 1 } });
e2e.components.Tab.title('Transformations').should('be.visible').click();
e2e.components.Transforms.addTransformationButton().scrollIntoView().should('be.visible').click();
e2e.components.TransformTab.newTransform('Spatial operations').scrollIntoView().should('be.visible').click();
e2e.components.Transforms.SpatialOperations.actionLabel().type('Prepare spatial field{enter}');
e2e.components.Transforms.SpatialOperations.locationLabel().should('be.visible');
e2e.components.Transforms.SpatialOperations.locationLabel().type('Auto{enter}');
e2e.components.PanelEditor.toggleTableView().click({ force: true });
e2e.components.Panels.Visualization.Table.header()
.should('be.visible')
.within(() => {
cy.contains('Point').should('be.visible');
});
});
it('Tests location coords option', () => {
e2e.flows.openDashboard({ uid: DASHBOARD_ID, queryParams: { editPanel: 1 } });
e2e.components.Tab.title('Transformations').should('be.visible').click();
e2e.components.Transforms.addTransformationButton().scrollIntoView().should('be.visible').click();
e2e.components.TransformTab.newTransform('Spatial operations').scrollIntoView().should('be.visible').click();
e2e.components.Transforms.SpatialOperations.actionLabel().type('Prepare spatial field{enter}');
e2e.components.Transforms.SpatialOperations.locationLabel().should('be.visible');
e2e.components.Transforms.SpatialOperations.locationLabel().type('Coords{enter}');
e2e.components.Transforms.SpatialOperations.location.coords.latitudeFieldLabel().should('be.visible');
e2e.components.Transforms.SpatialOperations.location.coords.latitudeFieldLabel().type('Lat{enter}');
e2e.components.Transforms.SpatialOperations.location.coords.longitudeFieldLabel().should('be.visible');
e2e.components.Transforms.SpatialOperations.location.coords.longitudeFieldLabel().type('Lng{enter}');
e2e.components.PanelEditor.toggleTableView().click({ force: true });
e2e.components.Panels.Visualization.Table.header()
.should('be.visible')
.within(() => {
cy.contains('Point').should('be.visible');
});
});
it('Tests geoshash field column appears in table view', () => {
e2e.flows.openDashboard({ uid: DASHBOARD_ID, queryParams: { editPanel: 1 } });
e2e.components.Tab.title('Transformations').should('be.visible').click();
e2e.components.Transforms.addTransformationButton().scrollIntoView().should('be.visible').click();
e2e.components.TransformTab.newTransform('Spatial operations').scrollIntoView().should('be.visible').click();
e2e.components.Transforms.SpatialOperations.actionLabel().type('Prepare spatial field{enter}');
e2e.components.Transforms.SpatialOperations.locationLabel().should('be.visible');
e2e.components.Transforms.SpatialOperations.locationLabel().type('Geohash{enter}');
e2e.components.Transforms.SpatialOperations.location.geohash
.geohashFieldLabel()
.should('be.visible')
.type('State{enter}');
e2e.components.PanelEditor.toggleTableView().click({ force: true });
e2e.components.Panels.Visualization.Table.header()
.should('be.visible')
.within(() => {
cy.contains('State 1').should('be.visible');
});
});
it('Tests location lookup option', () => {
e2e.flows.openDashboard({ uid: DASHBOARD_ID, queryParams: { editPanel: 1 } });
e2e.components.Tab.title('Transformations').should('be.visible').click();
e2e.components.Transforms.addTransformationButton().scrollIntoView().should('be.visible').click();
e2e.components.TransformTab.newTransform('Spatial operations').scrollIntoView().should('be.visible').click();
e2e.components.Transforms.SpatialOperations.actionLabel().type('Prepare spatial field{enter}');
e2e.components.Transforms.SpatialOperations.locationLabel().should('be.visible');
e2e.components.Transforms.SpatialOperations.locationLabel().type('Lookup{enter}');
e2e.components.Transforms.SpatialOperations.location.lookup.lookupFieldLabel().should('be.visible');
e2e.components.Transforms.SpatialOperations.location.lookup.lookupFieldLabel().type('State{enter}');
e2e.components.Transforms.SpatialOperations.location.lookup.gazetteerFieldLabel().should('be.visible');
e2e.components.Transforms.SpatialOperations.location.lookup.gazetteerFieldLabel().type('USA States{enter}');
e2e.components.PanelEditor.toggleTableView().click({ force: true });
e2e.components.Panels.Visualization.Table.header()
.should('be.visible')
.within(() => {
cy.contains('Geometry').should('be.visible');
});
});
});

View File

@ -0,0 +1,103 @@
import { selectors } from '@grafana/e2e-selectors';
import { e2e } from '../../utils';
const PANEL_UNDER_TEST = 'Lines 500 data points';
describe('Panel edit tests', () => {
beforeEach(() => {
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
});
it('Tests various Panel edit scenarios', () => {
cy.intercept({
pathname: '/api/ds/query',
}).as('query');
e2e.flows.openDashboard({ uid: 'TkZXxlNG3' });
cy.wait('@query');
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()
.scrollIntoView()
.should('be.visible')
.within(() => {
e2e.components.Tab.title('Queries').should('be.visible');
// data should be the active tab
e2e.components.Tab.active().within((li: JQuery<HTMLLIElement>) => {
expect(li.text()).equals('Queries1'); // there's already a query so therefore Query + 1
});
// cy.get('[data-testid]="query-editor-rows"').should('be.visible');
cy.get(`[data-testid="${selectors.components.QueryTab.content}"]`).should('be.visible');
e2e.components.TransformTab.content().should('not.exist');
e2e.components.AlertTab.content().should('not.exist');
e2e.components.PanelAlertTabContent.content().should('not.exist');
// Bottom pane tabs
// Can change to Transform tab
e2e.components.Tab.title('Transformations').should('be.visible').click();
e2e.components.Tab.active().within((li: JQuery<HTMLLIElement>) => {
expect(li.text()).equals('Transformations0'); // there's no transform so therefore Transform + 0
});
e2e.components.Transforms.addTransformationButton().scrollIntoView().should('be.visible');
cy.get(`[data-testid="${selectors.components.QueryTab.content}"]`).should('not.exist');
e2e.components.AlertTab.content().should('not.exist');
e2e.components.PanelAlertTabContent.content().should('not.exist');
// Can change to Alerts tab (graph panel is the default vis so the alerts tab should be rendered)
e2e.components.Tab.title('Alert').scrollIntoView().should('be.visible').click();
e2e.components.Tab.active().should('have.text', 'Alert0'); // there's no alert so therefore Alert + 0
// Needs to be disabled until Grafana EE turns unified alerting on by default
// e2e.components.AlertTab.content().should('not.exist');
cy.get(`[data-testid="${selectors.components.QueryTab.content}"]`).should('not.exist');
e2e.components.TransformTab.content().should('not.exist');
// Needs to be disabled until Grafana EE turns unified alerting on by default
// e2e.components.PanelAlertTabContent.content().should('exist');
// e2e.components.PanelAlertTabContent.content().should('be.visible');
e2e.components.Tab.title('Queries').should('be.visible').click();
});
// Check that Time series is chosen
e2e.components.PanelEditor.toggleVizPicker().click();
e2e.components.PluginVisualization.item('Time series').should('be.visible');
e2e.components.PluginVisualization.current().should((e) => expect(e).to.contain('Time series'));
// Check that table view works
e2e.components.Panels.Panel.loadingBar().should('not.exist');
e2e.components.PanelEditor.toggleTableView().click({ force: true });
e2e.components.Panels.Visualization.Table.header()
.should('be.visible')
.within(() => {
cy.contains('A-series').should('be.visible');
});
// Change to Text panel
e2e.components.PluginVisualization.item('Text').scrollIntoView().should('be.visible').click();
e2e.components.PanelEditor.toggleVizPicker().should((e) => expect(e).to.contain('Text'));
// Data pane should not be rendered
e2e.components.PanelEditor.DataPane.content().should('not.exist');
// Change to Table panel
e2e.components.PanelEditor.toggleVizPicker().click();
e2e.components.PluginVisualization.item('Table').scrollIntoView().should('be.visible').click();
e2e.components.PanelEditor.toggleVizPicker().should((e) => expect(e).to.contain('Table'));
// Data pane should be rendered
e2e.components.PanelEditor.DataPane.content().should('be.visible');
// Field & Overrides tabs (need to switch to React based vis, i.e. Table)
e2e.components.PanelEditor.toggleTableView().click({ force: true }).click({ force: true });
e2e.components.PanelEditor.OptionsPane.fieldLabel('Table Show table header').should('be.visible');
e2e.components.PanelEditor.OptionsPane.fieldLabel('Table Column width').should('be.visible');
});
});

View File

@ -0,0 +1,99 @@
import { e2e } from '../../utils';
const flakyTimeout = 10000;
describe('Panel edit tests - queries', () => {
beforeEach(() => {
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
});
it('Tests various Panel edit queries scenarios', () => {
e2e.flows.openDashboard({ uid: '5SdHCadmz', queryParams: { editPanel: 3 } });
// 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({ timeout: flakyTimeout }).should('have.length', 2);
// Remove refId A
e2e.components.QueryEditorRow.actionButton('Remove query').eq(0).scrollIntoView();
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({ timeout: flakyTimeout }).should('have.length', 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().should('have.length', 2);
// Change to CSV Metric Values scenario for A
e2e.components.DataSource.TestData.QueryTab.scenarioSelectContainer()
.first()
.should('be.visible')
.within(() => {
cy.get('input[id*="test-data-scenario-select-"]').eq(0).should('be.visible').click();
});
cy.contains('CSV Metric Values').scrollIntoView().should('be.visible').eq(0).click();
// Disable / enable row
expectInspectorResultAndClose((keys) => {
const length = keys.length;
const resultIds = new Set<string>([
keys[length - 2].innerText, // last 2
keys[length - 1].innerText, // last 2
]);
expect(resultIds.has('A:')).equals(true);
expect(resultIds.has('B:')).equals(true);
});
// Hide response for row with refId A
e2e.components.QueryEditorRow.actionButton('Hide response').eq(1).should('be.visible').click();
expectInspectorResultAndClose((keys) => {
const length = keys.length;
expect(keys[length - 1].innerText).equals('B:');
});
// Show response for row with refId A
e2e.components.QueryEditorRow.actionButton('Hide response').eq(1).should('be.visible').click();
expectInspectorResultAndClose((keys) => {
const length = keys.length;
const resultIds = new Set<string>([
keys[length - 2].innerText, // last 2
keys[length - 1].innerText, // last 2
]);
expect(resultIds.has('A:')).equals(true);
expect(resultIds.has('B:')).equals(true);
});
});
});
const expectInspectorResultAndClose = (expectCallBack: (keys: JQuery<HTMLElement>) => void) => {
e2e.components.QueryTab.queryInspectorButton().should('be.visible').click();
e2e.components.PanelInspector.Query.refreshButton().should('be.visible').click();
e2e.components.PanelInspector.Query.jsonObjectKeys({ timeout: flakyTimeout })
.should('be.visible')
.should((keys) => expectCallBack(keys));
e2e.components.Drawer.General.close().should('be.visible').click();
};

View File

@ -0,0 +1,28 @@
import { e2e } from '../../utils';
describe('Panel edit tests - transformations', () => {
beforeEach(() => {
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
});
it('Tests transformations editor', () => {
e2e.flows.openDashboard({ uid: 'TkZXxlNG3', queryParams: { editPanel: 47 } });
e2e.components.Tab.title('Transformations').should('be.visible').click();
e2e.components.Transforms.addTransformationButton().scrollIntoView().should('be.visible').click();
e2e.components.TransformTab.newTransform('Reduce').scrollIntoView().should('be.visible').click();
e2e.components.Transforms.Reduce.calculationsLabel().scrollIntoView().should('be.visible');
e2e.components.Transforms.Reduce.modeLabel().should('be.visible');
});
it('Tests case where transformations can be disabled and not clear out panel data', () => {
e2e.flows.openDashboard({ uid: 'TkZXxlNG3', queryParams: { editPanel: 47 } });
e2e.components.Tab.title('Transformations').should('be.visible').click();
e2e.components.Transforms.addTransformationButton().scrollIntoView().should('be.visible').click();
e2e.components.TransformTab.newTransform('Reduce').scrollIntoView().should('be.visible').click();
e2e.components.Transforms.disableTransformationButton().should('be.visible').click();
e2e.components.Panels.Panel.PanelDataErrorMessage().should('not.exist');
});
});

View File

@ -258,7 +258,7 @@
"@grafana/prometheus": "workspace:*",
"@grafana/runtime": "workspace:*",
"@grafana/saga-icons": "workspace:*",
"@grafana/scenes": "^4.21.0",
"@grafana/scenes": "^4.23.1",
"@grafana/schema": "workspace:*",
"@grafana/sql": "workspace:*",
"@grafana/ui": "workspace:*",

View File

@ -3,6 +3,7 @@ import React from 'react';
import { Unsubscribable } from 'rxjs';
import { GrafanaTheme2 } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import {
SceneComponentProps,
SceneObjectBase,
@ -144,7 +145,7 @@ function PanelDataPaneRendered({ model }: SceneComponentProps<PanelDataPane>) {
const currentTab = tabs.find((t) => t.tabId === tab);
return (
<div className={styles.dataPane}>
<div className={styles.dataPane} data-testid={selectors.components.PanelEditor.DataPane.content}>
<TabsBar hideBorder={true} className={styles.tabsBar}>
{tabs.map((t, index) => {
return (

View File

@ -189,7 +189,7 @@ export function PanelDataQueriesTabRendered({ model }: SceneComponentProps<Panel
const showAddButton = !isSharedDashboardQuery(dsSettings.name);
return (
<>
<div data-testid={selectors.components.QueryTab.content}>
<QueryGroupTopSection
data={data}
dsSettings={dsSettings}
@ -232,7 +232,7 @@ export function PanelDataQueriesTabRendered({ model }: SceneComponentProps<Panel
)}
{model.renderExtraActions()}
</Stack>
</>
</div>
);
}

View File

@ -2,6 +2,7 @@ import { css, cx } from '@emotion/css';
import React from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { selectors } from '@grafana/e2e-selectors';
import { SceneComponentProps } from '@grafana/scenes';
import { Button, ToolbarButton, useStyles2 } from '@grafana/ui';
@ -32,7 +33,7 @@ export function PanelEditorRenderer({ model }: SceneComponentProps<PanelEditor>)
return (
<>
<NavToolbarActions dashboard={dashboard} />
<div {...containerProps}>
<div {...containerProps} data-testid={selectors.components.PanelEditor.General.content}>
<div {...primaryProps} className={cx(primaryProps.className, styles.body)}>
<VizAndDataPane model={model} />
</div>

View File

@ -3047,13 +3047,13 @@ __metadata:
linkType: soft
"@grafana/e2e-selectors@npm:^10.4.1":
version: 10.4.2
resolution: "@grafana/e2e-selectors@npm:10.4.2"
version: 10.4.3
resolution: "@grafana/e2e-selectors@npm:10.4.3"
dependencies:
"@grafana/tsconfig": "npm:^1.2.0-rc1"
tslib: "npm:2.6.2"
typescript: "npm:5.3.3"
checksum: 10/a8eb622ff0137eb759cead6d7cc81c1fc9e00a6666655cf3043ea8ba23aada8e1148810471ac92911b412854028a527fd75be7a9519e4fa7826a111c555b5ffb
checksum: 10/c8799f2f4440e22f3a39f41e8ec465fe35ae2c459142e52486ce88dd176cef8212905151b03d9c48e1708c5a0f342d74054bfecb84e64dc9bf0f459c36c0464b
languageName: node
linkType: hard
@ -3501,9 +3501,9 @@ __metadata:
languageName: unknown
linkType: soft
"@grafana/scenes@npm:^4.21.0":
version: 4.21.1
resolution: "@grafana/scenes@npm:4.21.1"
"@grafana/scenes@npm:^4.23.1":
version: 4.23.1
resolution: "@grafana/scenes@npm:4.23.1"
dependencies:
"@grafana/e2e-selectors": "npm:^10.4.1"
react-grid-layout: "npm:1.3.4"
@ -3517,7 +3517,7 @@ __metadata:
"@grafana/ui": ^10.4.1
react: ^18.0.0
react-dom: ^18.0.0
checksum: 10/f0aa7d71f1d1d5d93f53314bc87da5e45e788b0020ab19c9f4e482025dff9e9d6424af1bf7e9e0cb3fcb7bdddddfa03567e481ea2645a1852369e27a002cde59
checksum: 10/7d0ad670cf5b93b8d82e09091fa3bf8f257cd07fcd1a2205f510f417be2b64132fbe889b566e5212ecb5d096c7eaf78e762a961b123143c20b68567a28935e41
languageName: node
linkType: hard
@ -16736,7 +16736,7 @@ __metadata:
"@grafana/prometheus": "workspace:*"
"@grafana/runtime": "workspace:*"
"@grafana/saga-icons": "workspace:*"
"@grafana/scenes": "npm:^4.21.0"
"@grafana/scenes": "npm:^4.23.1"
"@grafana/schema": "workspace:*"
"@grafana/sql": "workspace:*"
"@grafana/tsconfig": "npm:^1.3.0-rc1"