mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
CI: Run e2e tests in parallel using multiple suites (#41748)
* Split suite1 to multiple e2e test suites * Update drone yaml * Add missing arg * Extract cypress install step * Change image on e2e tests step * Sync with main * Add cypress cache volume * Try with grafana/ci-e2e:12.19.0-1 image * Update grabpl version to 2.7.2 * Revert a11y failure back to 'always'
This commit is contained in:
committed by
GitHub
parent
d624230b5d
commit
db122e9b2c
19
e2e/various-suite/specs/bar-gauge.spec.ts
Normal file
19
e2e/various-suite/specs/bar-gauge.spec.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { e2e } from '@grafana/e2e';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
|
||||
e2e.scenario({
|
||||
describeName: 'Bar Gauge Panel',
|
||||
itName: 'Bar Gauge rendering e2e tests',
|
||||
addScenarioDataSource: false,
|
||||
addScenarioDashBoard: false,
|
||||
skipScenario: false,
|
||||
scenario: () => {
|
||||
// open Panel Tests - Bar Gauge
|
||||
e2e.flows.openDashboard({ uid: 'O6f11TZWk' });
|
||||
|
||||
e2e()
|
||||
.get(`[data-panelid=6] [data-testid^="${selectors.components.Panels.Visualization.BarGauge.valueV2}"]`)
|
||||
.should('have.css', 'color', 'rgb(242, 73, 92)')
|
||||
.contains('100');
|
||||
},
|
||||
});
|
||||
67
e2e/various-suite/specs/exemplars.spec.ts
Normal file
67
e2e/various-suite/specs/exemplars.spec.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import { e2e } from '@grafana/e2e';
|
||||
|
||||
const dataSourceName = 'PromExemplar';
|
||||
const addDataSource = () => {
|
||||
e2e.flows.addDataSource({
|
||||
type: 'Prometheus',
|
||||
expectedAlertMessage: 'Bad Gateway',
|
||||
name: dataSourceName,
|
||||
form: () => {
|
||||
e2e.components.DataSource.Prometheus.configPage.exemplarsAddButton().click();
|
||||
e2e.components.DataSource.Prometheus.configPage.internalLinkSwitch().check({ force: true });
|
||||
e2e.components.DataSourcePicker.inputV2().should('be.visible').click({ force: true });
|
||||
|
||||
e2e().contains('gdev-tempo').scrollIntoView().should('be.visible').click();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
describe('Exemplars', () => {
|
||||
beforeEach(() => {
|
||||
e2e.flows.login('admin', 'admin');
|
||||
|
||||
e2e()
|
||||
.request({ url: `/api/datasources/name/${dataSourceName}`, failOnStatusCode: false })
|
||||
.then((response) => {
|
||||
if (response.isOkStatusCode) {
|
||||
return;
|
||||
}
|
||||
addDataSource();
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to navigate to configured data source', () => {
|
||||
let intercept = 'prometheus';
|
||||
e2e().intercept('/api/ds/query', (req) => {
|
||||
if (intercept === 'prometheus') {
|
||||
// For second intercept, we want to send tempo response
|
||||
intercept = 'tempo';
|
||||
req.reply({ fixture: 'exemplars-query-response.json' });
|
||||
} else {
|
||||
req.reply({ fixture: 'tempo-response.json' });
|
||||
}
|
||||
});
|
||||
|
||||
e2e.pages.Explore.visit();
|
||||
|
||||
e2e.components.DataSourcePicker.input().should('be.visible').click();
|
||||
e2e().contains(dataSourceName).scrollIntoView().should('be.visible').click();
|
||||
|
||||
// we need to wait for the query-field being lazy-loaded, in two steps:
|
||||
// 1. first we wait for the text 'Loading...' to appear
|
||||
// 1. then we wait for the text 'Loading...' to disappear
|
||||
const monacoLoadingText = 'Loading...';
|
||||
e2e.components.QueryField.container().should('be.visible').should('have.text', monacoLoadingText);
|
||||
e2e.components.QueryField.container().should('be.visible').should('not.have.text', monacoLoadingText);
|
||||
|
||||
e2e.components.TimePicker.openButton().click();
|
||||
e2e.components.TimePicker.fromField().clear().type('2021-07-10 17:10:00');
|
||||
e2e.components.TimePicker.toField().clear().type('2021-07-10 17:30:00');
|
||||
e2e.components.TimePicker.applyTimeRange().click();
|
||||
e2e.components.QueryField.container().should('be.visible').type('exemplar-query_bucket{shift}{enter}');
|
||||
|
||||
e2e.components.DataSource.Prometheus.exemplarMarker().first().trigger('mouseover');
|
||||
e2e().contains('Query with gdev-tempo').click();
|
||||
e2e.components.TraceViewer.spanBar().should('have.length', 11);
|
||||
});
|
||||
});
|
||||
25
e2e/various-suite/specs/explore.spec.ts
Normal file
25
e2e/various-suite/specs/explore.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { e2e } from '@grafana/e2e';
|
||||
|
||||
e2e.scenario({
|
||||
describeName: 'Explore',
|
||||
itName: 'Basic path through Explore.',
|
||||
addScenarioDataSource: false,
|
||||
addScenarioDashBoard: false,
|
||||
skipScenario: false,
|
||||
scenario: () => {
|
||||
e2e.pages.Explore.visit();
|
||||
e2e.pages.Explore.General.container().should('have.length', 1);
|
||||
e2e.components.RefreshPicker.runButtonV2().should('have.length', 1);
|
||||
|
||||
e2e.components.DataSource.TestData.QueryTab.scenarioSelectContainer()
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
e2e().get('input[id*="test-data-scenario-select-"]').should('be.visible').click();
|
||||
});
|
||||
|
||||
cy.contains('CSV Metric Values').scrollIntoView().should('be.visible').click();
|
||||
|
||||
const canvases = e2e().get('canvas');
|
||||
canvases.should('have.length', 1);
|
||||
},
|
||||
});
|
||||
21
e2e/various-suite/specs/gauge.spec.ts
Normal file
21
e2e/various-suite/specs/gauge.spec.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { e2e } from '@grafana/e2e';
|
||||
|
||||
e2e.scenario({
|
||||
describeName: 'Gauge Panel',
|
||||
itName: 'Gauge rendering e2e tests',
|
||||
addScenarioDataSource: false,
|
||||
addScenarioDashBoard: false,
|
||||
skipScenario: false,
|
||||
scenario: () => {
|
||||
// open Panel Tests - Gauge
|
||||
e2e.flows.openDashboard({ uid: '_5rDmaQiz' });
|
||||
|
||||
cy.wait(1000);
|
||||
|
||||
// check that gauges are rendered
|
||||
e2e().get('body').find(`.flot-base`).should('have.length', 16);
|
||||
|
||||
// check that no panel errors exist
|
||||
e2e.components.Panels.Panel.headerCornerInfo('error').should('not.exist');
|
||||
},
|
||||
});
|
||||
148
e2e/various-suite/specs/inspect-drawer.spec.ts
Normal file
148
e2e/various-suite/specs/inspect-drawer.spec.ts
Normal file
@@ -0,0 +1,148 @@
|
||||
import { e2e } from '@grafana/e2e';
|
||||
|
||||
const PANEL_UNDER_TEST = '2 yaxis and axis labels';
|
||||
|
||||
e2e.scenario({
|
||||
describeName: 'Inspect drawer tests',
|
||||
itName: 'Tests various Inspect Drawer scenarios',
|
||||
addScenarioDataSource: false,
|
||||
addScenarioDashBoard: false,
|
||||
skipScenario: false,
|
||||
scenario: () => {
|
||||
// @ts-ignore some typing issue
|
||||
e2e().on('uncaught:exception', (err) => {
|
||||
if (err.stack?.indexOf("TypeError: Cannot read property 'getText' of null") !== -1) {
|
||||
// On occasion monaco editor will not have the time to be properly unloaded when we change the tab
|
||||
// and then the e2e test fails with the uncaught:exception:
|
||||
// TypeError: Cannot read property 'getText' of null
|
||||
// at Object.ai [as getFoldingRanges] (http://localhost:3001/public/build/monaco-json.worker.js:2:215257)
|
||||
// at e.getFoldingRanges (http://localhost:3001/public/build/monaco-json.worker.js:2:221188)
|
||||
// at e.fmr (http://localhost:3001/public/build/monaco-json.worker.js:2:116605)
|
||||
// at e._handleMessage (http://localhost:3001/public/build/monaco-json.worker.js:2:7414)
|
||||
// at Object.handleMessage (http://localhost:3001/public/build/monaco-json.worker.js:2:7018)
|
||||
// at e._handleMessage (http://localhost:3001/public/build/monaco-json.worker.js:2:5038)
|
||||
// at e.handleMessage (http://localhost:3001/public/build/monaco-json.worker.js:2:4606)
|
||||
// at e.onmessage (http://localhost:3001/public/build/monaco-json.worker.js:2:7097)
|
||||
// at Tt.self.onmessage (http://localhost:3001/public/build/monaco-json.worker.js:2:117109)
|
||||
|
||||
// return false to prevent the error from
|
||||
// failing this test
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
const viewPortWidth = e2e.config().viewportWidth;
|
||||
e2e.flows.openDashboard({ uid: '5SdHCadmz' });
|
||||
|
||||
// testing opening inspect drawer directly by clicking on Inspect in header menu
|
||||
e2e.flows.openPanelMenuItem(e2e.flows.PanelMenuItems.Inspect, PANEL_UNDER_TEST);
|
||||
|
||||
expectDrawerTabsAndContent();
|
||||
|
||||
expectDrawerExpandAndContract(viewPortWidth);
|
||||
|
||||
expectDrawerClose();
|
||||
|
||||
expectSubMenuScenario('Data');
|
||||
expectSubMenuScenario('Query');
|
||||
expectSubMenuScenario('Panel JSON', 'JSON');
|
||||
|
||||
e2e.flows.openPanelMenuItem(e2e.flows.PanelMenuItems.Edit, PANEL_UNDER_TEST);
|
||||
|
||||
e2e.components.QueryTab.queryInspectorButton().should('be.visible').click();
|
||||
|
||||
e2e.components.Drawer.General.title(`Inspect: ${PANEL_UNDER_TEST}`)
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
e2e.components.Tab.title('Query').should('be.visible');
|
||||
// query should be the active tab
|
||||
e2e.components.Tab.active().should('have.text', 'Query');
|
||||
});
|
||||
|
||||
e2e.components.PanelInspector.Query.content().should('be.visible');
|
||||
},
|
||||
});
|
||||
|
||||
const expectDrawerTabsAndContent = () => {
|
||||
e2e.components.Drawer.General.title(`Inspect: ${PANEL_UNDER_TEST}`)
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
e2e.components.Tab.title('Data').should('be.visible');
|
||||
// data should be the active tab
|
||||
e2e.components.Tab.active().within((li: JQuery<HTMLLIElement>) => {
|
||||
expect(li.text()).equals('Data');
|
||||
});
|
||||
e2e.components.PanelInspector.Data.content().should('be.visible');
|
||||
e2e.components.PanelInspector.Stats.content().should('not.exist');
|
||||
e2e.components.PanelInspector.Json.content().should('not.exist');
|
||||
e2e.components.PanelInspector.Query.content().should('not.exist');
|
||||
|
||||
// other tabs should also be visible, click on each to see if we get any console errors
|
||||
e2e.components.Tab.title('Stats').should('be.visible').click();
|
||||
e2e.components.PanelInspector.Stats.content().should('be.visible');
|
||||
e2e.components.PanelInspector.Data.content().should('not.exist');
|
||||
e2e.components.PanelInspector.Json.content().should('not.exist');
|
||||
e2e.components.PanelInspector.Query.content().should('not.exist');
|
||||
|
||||
e2e.components.Tab.title('JSON').should('be.visible').click();
|
||||
e2e.components.PanelInspector.Json.content().should('be.visible');
|
||||
e2e.components.PanelInspector.Data.content().should('not.exist');
|
||||
e2e.components.PanelInspector.Stats.content().should('not.exist');
|
||||
e2e.components.PanelInspector.Query.content().should('not.exist');
|
||||
|
||||
e2e.components.Tab.title('Query').should('be.visible').click();
|
||||
|
||||
e2e.components.PanelInspector.Query.content().should('be.visible');
|
||||
e2e.components.PanelInspector.Data.content().should('not.exist');
|
||||
e2e.components.PanelInspector.Stats.content().should('not.exist');
|
||||
e2e.components.PanelInspector.Json.content().should('not.exist');
|
||||
});
|
||||
};
|
||||
|
||||
const expectDrawerClose = () => {
|
||||
// close using close button
|
||||
e2e.components.Drawer.General.close().click();
|
||||
e2e.components.Drawer.General.title(`Inspect: ${PANEL_UNDER_TEST}`).should('not.exist');
|
||||
};
|
||||
|
||||
const expectDrawerExpandAndContract = (viewPortWidth: number) => {
|
||||
// try expand button
|
||||
// drawer should take up half the screen
|
||||
e2e.components.Drawer.General.rcContentWrapper()
|
||||
.should('be.visible')
|
||||
.should('have.css', 'width', `${viewPortWidth / 2}px`);
|
||||
|
||||
e2e.components.Drawer.General.expand().click();
|
||||
e2e.components.Drawer.General.contract().should('be.visible');
|
||||
|
||||
// drawer should take up the whole screen
|
||||
e2e.components.Drawer.General.rcContentWrapper()
|
||||
.should('be.visible')
|
||||
.should('have.css', 'width', `${viewPortWidth}px`);
|
||||
|
||||
// try contract button
|
||||
e2e.components.Drawer.General.contract().click();
|
||||
e2e.components.Drawer.General.expand().should('be.visible');
|
||||
|
||||
e2e.components.Drawer.General.rcContentWrapper()
|
||||
.should('be.visible')
|
||||
.should('have.css', 'width', `${viewPortWidth / 2}px`);
|
||||
};
|
||||
|
||||
const expectSubMenuScenario = (subMenu: string, tabTitle?: string) => {
|
||||
tabTitle = tabTitle ?? subMenu;
|
||||
// testing opening inspect drawer from sub menus under Inspect in header menu
|
||||
e2e.components.Panels.Panel.title(PANEL_UNDER_TEST).scrollIntoView().should('be.visible').click();
|
||||
|
||||
// sub menus are in the DOM but not visible and because there is no hover support in Cypress force click
|
||||
// https://github.com/cypress-io/cypress-example-recipes/blob/master/examples/testing-dom__hover-hidden-elements/cypress/integration/hover-hidden-elements-spec.js
|
||||
e2e.components.Panels.Panel.headerItems(subMenu).click({ force: true });
|
||||
|
||||
// data should be the default tab
|
||||
e2e.components.Tab.title(tabTitle).should('be.visible');
|
||||
e2e.components.Tab.active().should('have.text', tabTitle);
|
||||
|
||||
expectDrawerClose();
|
||||
};
|
||||
18
e2e/various-suite/specs/pie-chart.spec.ts
Normal file
18
e2e/various-suite/specs/pie-chart.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { e2e } from '@grafana/e2e';
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
|
||||
e2e.scenario({
|
||||
describeName: 'Pie Chart Panel',
|
||||
itName: 'Pie Chart rendering e2e tests',
|
||||
addScenarioDataSource: false,
|
||||
addScenarioDashBoard: false,
|
||||
skipScenario: false,
|
||||
scenario: () => {
|
||||
// open Panel Tests - Pie Chart
|
||||
e2e.flows.openDashboard({ uid: 'lVE-2YFMz' });
|
||||
|
||||
e2e()
|
||||
.get(`[data-panelid=11] [aria-label^="${selectors.components.Panels.Visualization.PieChart.svgSlice}"]`)
|
||||
.should('have.length', 5);
|
||||
},
|
||||
});
|
||||
32
e2e/various-suite/specs/query-editor.spec.ts
Normal file
32
e2e/various-suite/specs/query-editor.spec.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
import { e2e } from '@grafana/e2e';
|
||||
|
||||
e2e.scenario({
|
||||
describeName: 'Query editor',
|
||||
itName: 'Undo should work in query editor for prometheus.',
|
||||
addScenarioDataSource: false,
|
||||
addScenarioDashBoard: false,
|
||||
skipScenario: false,
|
||||
scenario: () => {
|
||||
e2e.pages.Explore.visit();
|
||||
e2e.components.DataSourcePicker.inputV2().should('be.visible').click();
|
||||
|
||||
cy.contains('gdev-prometheus').scrollIntoView().should('be.visible').click();
|
||||
const queryText = 'http_requests_total';
|
||||
|
||||
// we need to wait for the query-field being lazy-loaded, in two steps:
|
||||
// it is a two-step process:
|
||||
// 1. first we wait for the text 'Loading...' to appear
|
||||
// 1. then we wait for the text 'Loading...' to disappear
|
||||
const monacoLoadingText = 'Loading...';
|
||||
e2e.components.QueryField.container().should('be.visible').should('have.text', monacoLoadingText);
|
||||
e2e.components.QueryField.container().should('be.visible').should('not.have.text', monacoLoadingText);
|
||||
|
||||
e2e.components.QueryField.container().type(queryText).type('{backspace}');
|
||||
|
||||
cy.contains(queryText.slice(0, -1)).should('be.visible');
|
||||
|
||||
e2e.components.QueryField.container().type(e2e.typings.undo());
|
||||
|
||||
cy.contains(queryText).should('be.visible');
|
||||
},
|
||||
});
|
||||
35
e2e/various-suite/specs/select-focus.spec.ts
Normal file
35
e2e/various-suite/specs/select-focus.spec.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { e2e } from '@grafana/e2e';
|
||||
|
||||
e2e.scenario({
|
||||
describeName: 'Select focus/unfocus tests',
|
||||
itName: 'Tests select focus/unfocus scenarios',
|
||||
addScenarioDataSource: false,
|
||||
addScenarioDashBoard: false,
|
||||
skipScenario: false,
|
||||
scenario: () => {
|
||||
e2e.flows.openDashboard({ uid: '5SdHCadmz' });
|
||||
e2e.components.PageToolbar.item('Dashboard settings').click();
|
||||
|
||||
e2e.components.FolderPicker.containerV2()
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
e2e().get('#dashboard-folder-input').should('be.visible').click();
|
||||
});
|
||||
|
||||
e2e.components.Select.option().should('be.visible').first().click();
|
||||
|
||||
e2e.components.FolderPicker.containerV2()
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
e2e().get('#dashboard-folder-input').should('exist').should('have.focus');
|
||||
});
|
||||
|
||||
e2e.pages.Dashboard.Settings.General.title().click();
|
||||
|
||||
e2e.components.FolderPicker.containerV2()
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
e2e().get('#dashboard-folder-input').should('exist').should('not.have.focus');
|
||||
});
|
||||
},
|
||||
});
|
||||
15
e2e/various-suite/specs/solo-route.spec.ts
Normal file
15
e2e/various-suite/specs/solo-route.spec.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { e2e } from '@grafana/e2e';
|
||||
|
||||
e2e.scenario({
|
||||
describeName: 'Solo Route',
|
||||
itName: 'Can view panels with shared queries in fullsceen',
|
||||
addScenarioDataSource: false,
|
||||
addScenarioDashBoard: false,
|
||||
skipScenario: false,
|
||||
scenario: () => {
|
||||
// open Panel Tests - Bar Gauge
|
||||
e2e.pages.SoloPanel.visit('ZqZnVvFZz/datasource-tests-shared-queries?orgId=1&panelId=4');
|
||||
|
||||
e2e().get('canvas').should('have.length', 6);
|
||||
},
|
||||
});
|
||||
37
e2e/various-suite/specs/trace-view-scrolling.spec.ts
Normal file
37
e2e/various-suite/specs/trace-view-scrolling.spec.ts
Normal file
@@ -0,0 +1,37 @@
|
||||
import { e2e } from '@grafana/e2e';
|
||||
|
||||
describe('Trace view', () => {
|
||||
it('Can lazy load big traces', () => {
|
||||
e2e.flows.login('admin', 'admin');
|
||||
e2e()
|
||||
.intercept('GET', '**/api/traces/long-trace', {
|
||||
fixture: 'long-trace-response.json',
|
||||
})
|
||||
.as('longTrace');
|
||||
|
||||
e2e.pages.Explore.visit();
|
||||
|
||||
e2e.components.DataSourcePicker.inputV2().should('be.visible').click();
|
||||
|
||||
e2e().contains('gdev-jaeger').scrollIntoView().should('be.visible').click();
|
||||
|
||||
e2e.components.QueryField.container().should('be.visible').type('long-trace');
|
||||
|
||||
e2e().wait(500);
|
||||
|
||||
e2e.components.RefreshPicker.runButtonV2().should('be.visible').click();
|
||||
|
||||
e2e().wait('@longTrace');
|
||||
|
||||
e2e.components.TraceViewer.spanBar().should('be.visible');
|
||||
|
||||
e2e.components.TraceViewer.spanBar()
|
||||
.its('length')
|
||||
.then((oldLength) => {
|
||||
e2e.pages.Explore.General.scrollBar().scrollTo('center');
|
||||
|
||||
// After scrolling we should load more spans
|
||||
e2e.components.TraceViewer.spanBar().its('length').should('be.gt', oldLength);
|
||||
});
|
||||
});
|
||||
});
|
||||
29
e2e/various-suite/specs/visualization-suggestions.ts
Normal file
29
e2e/various-suite/specs/visualization-suggestions.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { e2e } from '@grafana/e2e';
|
||||
|
||||
e2e.scenario({
|
||||
describeName: 'Visualization suggestions',
|
||||
itName: 'Should be shown and clickable',
|
||||
addScenarioDataSource: false,
|
||||
addScenarioDashBoard: false,
|
||||
skipScenario: false,
|
||||
scenario: () => {
|
||||
e2e.flows.openDashboard({ uid: 'aBXrJ0R7z', queryParams: { editPanel: 9 } });
|
||||
|
||||
// Try visualization suggestions
|
||||
e2e.components.PanelEditor.toggleVizPicker().click();
|
||||
e2e().contains('Suggestions').click();
|
||||
cy.wait(3000);
|
||||
|
||||
// Verify we see suggestions
|
||||
e2e.components.VisualizationPreview.card('Line chart').should('be.visible');
|
||||
|
||||
// Verify search works
|
||||
e2e().get('[placeholder="Search for..."]').type('Table');
|
||||
// Should no longer see line chart
|
||||
e2e.components.VisualizationPreview.card('Line chart').should('not.exist');
|
||||
|
||||
// Select a visualisation
|
||||
e2e.components.VisualizationPreview.card('Table').click();
|
||||
e2e.components.Panels.Visualization.Table.header().should('be.visible');
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user