Chore: Remove duplicated various-suite cypress tests (#109737)
* remove duplicated various-suite cypress tests and update CODEOWNERS for playwright versions * assign missing CODEOWNERS
This commit is contained in:
+43
-3
@@ -411,9 +411,14 @@
|
||||
/public/locales/i18next-parser-enterprise.config.cjs @grafana/grafana-frontend-platform
|
||||
/public/app/core/internationalization/ @grafana/grafana-frontend-platform
|
||||
/e2e/ @grafana/grafana-frontend-platform
|
||||
/e2e-playwright/ @grafana/grafana-frontend-platform
|
||||
/e2e-playwright/cloud-plugins-suite/ @grafana/partner-datasources
|
||||
/e2e-playwright/dashboard-new-layouts @grafana/dashboards-squad
|
||||
/e2e-playwright/dashboard-new-layouts/ @grafana/dashboards-squad
|
||||
/e2e-playwright/dashboards-search-suite/ @grafana/dashboards-squad
|
||||
/e2e-playwright/dashboards/DashboardLiveTest.json @grafana/dashboards-squad
|
||||
/e2e-playwright/dashboards/DataLinkWithoutSlugTest.json @grafana/dashboards-squad
|
||||
/e2e-playwright/dashboards/PanelSandboxDashboard.json @grafana/plugins-platform-frontend
|
||||
/e2e-playwright/dashboards/TestDashboard.json @grafana/dashboards-squad @grafana/grafana-search-navigate-organise
|
||||
/e2e-playwright/dashboards/TestV2Dashboard.json @grafana/dashboards-squad
|
||||
/e2e-playwright/dashboards-suite/dashboard-browse-nested.spec.ts @grafana/grafana-search-navigate-organise
|
||||
/e2e-playwright/dashboards-suite/dashboard-browse.spec.ts @grafana/grafana-search-navigate-organise
|
||||
/e2e-playwright/dashboards-suite/dashboard-export-image.spec.ts @grafana/sharing-squad
|
||||
@@ -447,6 +452,9 @@
|
||||
/e2e-playwright/dashboards-suite/templating-dashboard-links-and-variables.spec.ts @grafana/dashboards-squad
|
||||
/e2e-playwright/dashboards-suite/textbox-variables.spec.ts @grafana/dashboards-squad
|
||||
/e2e-playwright/dashboards-suite/utils/makeDashboard.ts @grafana/grafana-search-navigate-organise
|
||||
/e2e-playwright/fixtures/exemplars-query-response.json @grafana/observability-traces-and-profiling
|
||||
/e2e-playwright/fixtures/long-trace-response.json @grafana/observability-traces-and-profiling
|
||||
/e2e-playwright/fixtures/tempo-response.json @grafana/oss-big-tent
|
||||
/e2e-playwright/panels-suite/dashlist.spec.ts @grafana/grafana-search-navigate-organise
|
||||
/e2e-playwright/panels-suite/datagrid-data-change.spec.ts @grafana/dataviz-squad
|
||||
/e2e-playwright/panels-suite/datagrid-editing-features.spec.ts @grafana/dataviz-squad
|
||||
@@ -458,10 +466,42 @@
|
||||
/e2e-playwright/panels-suite/panelEdit_queries.spec.ts @grafana/dashboards-squad
|
||||
/e2e-playwright/panels-suite/panelEdit_transforms.spec.ts @grafana/datapro
|
||||
/e2e-playwright/panels-suite/table-kitchenSink.spec.ts @grafana/dataviz-squad
|
||||
/e2e-playwright/panels-suite/table-markdown.spec.ts @grafana/dataviz-squad
|
||||
/e2e-playwright/panels-suite/table-sparkline.spec.ts @grafana/dataviz-squad
|
||||
/e2e-playwright/plugin-e2e/ @grafana/oss-big-tent @grafana/partner-datasources
|
||||
/e2e-playwright/plugin-e2e/plugin-e2e-api-tests/ @grafana/plugins-platform-frontend
|
||||
/e2e-playwright/test-plugins/grafana-extensionstest-app/ @grafana/plugins-platform-frontend
|
||||
/e2e-playwright/smoke-tests-suite/ @grafana/grafana-frontend-platform
|
||||
/e2e-playwright/start-server @grafana/grafana-frontend-platform
|
||||
/e2e-playwright/storybook/ @grafana/grafana-frontend-platform
|
||||
/e2e-playwright/test-plugins/ @grafana/plugins-platform-frontend
|
||||
/e2e-playwright/unauthenticated/login.spec.ts @grafana/grafana-frontend-platform
|
||||
/e2e-playwright/utils/ @grafana/grafana-frontend-platform
|
||||
/e2e-playwright/various-suite/bar-gauge.spec.ts @grafana/dataviz-squad
|
||||
/e2e-playwright/various-suite/bookmarks.spec.ts @grafana/grafana-search-navigate-organise
|
||||
/e2e-playwright/various-suite/exemplars.spec.ts @grafana/observability-traces-and-profiling
|
||||
/e2e-playwright/various-suite/explore.spec.ts @grafana/observability-traces-and-profiling
|
||||
/e2e-playwright/various-suite/filter-annotations.spec.ts @grafana/dashboards-squad
|
||||
/e2e-playwright/various-suite/frontend-sandbox-app.spec.ts @grafana/plugins-platform-frontend
|
||||
/e2e-playwright/various-suite/frontend-sandbox-datasource.spec.ts @grafana/plugins-platform-frontend
|
||||
/e2e-playwright/various-suite/gauge.spec.ts @grafana/dataviz-squad
|
||||
/e2e-playwright/various-suite/graph-auto-migrate.spec.ts @grafana/dataviz-squad
|
||||
/e2e-playwright/various-suite/inspect-drawer.spec.ts @grafana/dashboards-squad
|
||||
/e2e-playwright/various-suite/keybinds.spec.ts @grafana/grafana-frontend-platform
|
||||
/e2e-playwright/various-suite/loki-query-builder.spec.ts @grafana/oss-big-tent
|
||||
/e2e-playwright/various-suite/loki-table-explore-to-dash.spec.ts @grafana/oss-big-tent
|
||||
/e2e-playwright/various-suite/migrate-to-cloud.spec.ts @grafana/grafana-operator-experience-squad
|
||||
/e2e-playwright/various-suite/navigation.spec.ts @grafana/grafana-search-navigate-organise
|
||||
/e2e-playwright/various-suite/pie-chart.spec.ts @grafana/dataviz-squad
|
||||
/e2e-playwright/various-suite/prometheus-annotations.spec.ts @grafana/oss-big-tent
|
||||
/e2e-playwright/various-suite/prometheus-config.spec.ts @grafana/oss-big-tent
|
||||
/e2e-playwright/various-suite/prometheus-editor.spec.ts @grafana/oss-big-tent
|
||||
/e2e-playwright/various-suite/prometheus-variable-editor.spec.ts @grafana/oss-big-tent
|
||||
/e2e-playwright/various-suite/query-editor.spec.ts @grafana/observability-traces-and-profiling
|
||||
/e2e-playwright/various-suite/return-to-previous.spec.ts @grafana/grafana-search-navigate-organise
|
||||
/e2e-playwright/various-suite/solo-route.spec.ts @grafana/dashboards-squad
|
||||
/e2e-playwright/various-suite/trace-view-scrolling.spec.ts @grafana/observability-traces-and-profiling
|
||||
/e2e-playwright/various-suite/verify-i18n.spec.ts @grafana/grafana-frontend-platform
|
||||
/e2e-playwright/various-suite/visualization-suggestions.spec.ts @grafana/dashboards-squad
|
||||
|
||||
# Packages
|
||||
/packages/README.md @grafana/grafana-frontend-platform
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
import { e2e } from '../utils';
|
||||
|
||||
describe('Select focus/unfocus tests', () => {
|
||||
beforeEach(() => {
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
|
||||
});
|
||||
|
||||
it.skip('Tests select focus/unfocus scenarios', () => {
|
||||
e2e.flows.openDashboard({ uid: '5SdHCadmz' });
|
||||
e2e.components.PageToolbar.item('Dashboard settings').click();
|
||||
|
||||
e2e.components.FolderPicker.containerV2()
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
cy.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(() => {
|
||||
cy.get('#dashboard-folder-input').should('exist').should('have.focus');
|
||||
});
|
||||
|
||||
e2e.pages.Dashboard.Settings.General.title().click();
|
||||
|
||||
e2e.components.FolderPicker.containerV2()
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
cy.get('#dashboard-folder-input').should('exist').should('not.have.focus');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,20 +0,0 @@
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
|
||||
import { e2e } from '../utils';
|
||||
|
||||
describe('Bar Gauge Panel', () => {
|
||||
beforeEach(() => {
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
|
||||
});
|
||||
|
||||
it('Bar Gauge rendering e2e tests', () => {
|
||||
// open Panel Tests - Bar Gauge
|
||||
e2e.flows.openDashboard({ uid: 'O6f11TZWk' });
|
||||
|
||||
cy.get(
|
||||
`[data-viz-panel-key="panel-6"] [data-testid^="${selectors.components.Panels.Visualization.BarGauge.valueV2}"]`
|
||||
)
|
||||
.should('have.css', 'color', 'rgb(242, 73, 92)')
|
||||
.contains('100');
|
||||
});
|
||||
});
|
||||
@@ -1,75 +0,0 @@
|
||||
import { e2e } from '../utils';
|
||||
import { fromBaseUrl } from '../utils/support/url';
|
||||
|
||||
describe('Pin nav items', () => {
|
||||
beforeEach(() => {
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
e2e.flows.setDefaultUserPreferences();
|
||||
});
|
||||
|
||||
it('should pin the selected menu item and add it as a Bookmarks menu item child', () => {
|
||||
cy.visit(fromBaseUrl('/'), {
|
||||
onBeforeLoad: (win) => {
|
||||
win.localStorage.setItem('grafana.navigation.docked', 'true'); // Make sure the menu is docked
|
||||
},
|
||||
});
|
||||
|
||||
e2e.components.NavMenu.Menu()
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
cy.get('ul[aria-label="Navigation"]').should('be.visible').as('navList');
|
||||
|
||||
// Check if the Bookmark section is visible
|
||||
cy.get('@navList').children().eq(1).should('be.visible').as('bookmarksItem');
|
||||
cy.get('@bookmarksItem').should('contain.text', 'Bookmarks');
|
||||
|
||||
// Check if the Adminstration section is visible
|
||||
cy.get('@navList').children().last().should('be.visible').as('adminItem');
|
||||
cy.get('@adminItem').should('contain.text', 'Administration');
|
||||
cy.get('@adminItem').within(() => {
|
||||
cy.get('button[aria-label="Add to Bookmarks"]').should('exist').click({ force: true });
|
||||
});
|
||||
|
||||
// Check if the Administration menu item is visible in the Bookmarks section
|
||||
cy.get('@bookmarksItem').within(() => {
|
||||
// Expand the Bookmarks section
|
||||
cy.get('button[aria-label="Expand section: Bookmarks"]').should('exist').click({ force: true });
|
||||
cy.get('a').should('contain.text', 'Administration').should('be.visible');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should unpin the item and remove it from the Bookmarks section', () => {
|
||||
// Set Administration as a pinned item and reload the page
|
||||
e2e.flows.setUserPreferences({ navbar: { bookmarkUrls: ['/admin'] } });
|
||||
|
||||
cy.visit(fromBaseUrl('/'), {
|
||||
onBeforeLoad: (win) => {
|
||||
win.localStorage.setItem('grafana.navigation.docked', 'true'); // Make sure the menu is docked
|
||||
},
|
||||
});
|
||||
|
||||
e2e.components.NavMenu.Menu()
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
cy.get('ul[aria-label="Navigation"]').should('be.visible').as('navList');
|
||||
|
||||
// Check if the Bookmark section is visible
|
||||
cy.get('@navList').children().eq(1).should('be.visible').as('bookmarksItem');
|
||||
cy.get('@bookmarksItem').should('contain.text', 'Bookmarks');
|
||||
cy.get('@bookmarksItem').within(() => {
|
||||
// Expand the Bookmarks section
|
||||
cy.get('button[aria-label="Expand section: Bookmarks"]').should('exist').click({ force: true });
|
||||
cy.get('a').should('contain.text', 'Administration').should('be.visible');
|
||||
cy.get('button[aria-label="Remove from Bookmarks"]').should('exist').click({ force: true });
|
||||
});
|
||||
|
||||
cy.get('@bookmarksItem', { timeout: 60000 }).within(() => {
|
||||
cy.get('a').should('have.length', 1).should('not.contain.text', 'Administration');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,76 +0,0 @@
|
||||
import { e2e } from '../utils';
|
||||
import { waitForMonacoToLoad } from '../utils/support/monaco';
|
||||
|
||||
const dataSourceName = 'PromExemplar';
|
||||
const addDataSource = () => {
|
||||
e2e.flows.addDataSource({
|
||||
type: 'Prometheus',
|
||||
expectedAlertMessage: 'Prometheus',
|
||||
name: dataSourceName,
|
||||
form: () => {
|
||||
e2e.components.DataSource.Prometheus.configPage.exemplarsAddButton().click();
|
||||
e2e.components.DataSource.Prometheus.configPage.internalLinkSwitch().check({ force: true });
|
||||
e2e.components.DataSource.Prometheus.configPage.connectionSettings().type('http://prom-url:9090');
|
||||
cy.get('[data-testid="data-testid Data source picker select container"]').click();
|
||||
|
||||
cy.contains('gdev-tempo').scrollIntoView().should('be.visible').click();
|
||||
},
|
||||
});
|
||||
};
|
||||
// Skipping due to race conditions with same old arch test e2e/various-suite/exemplars.spec.ts
|
||||
describe.skip('Exemplars', () => {
|
||||
beforeEach(() => {
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
|
||||
|
||||
cy.request({
|
||||
url: `${Cypress.env('BASE_URL')}/api/datasources/name/${dataSourceName}`,
|
||||
failOnStatusCode: false,
|
||||
}).then((response) => {
|
||||
if (response.isOkStatusCode) {
|
||||
return;
|
||||
}
|
||||
addDataSource();
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to navigate to configured data source', () => {
|
||||
cy.intercept(
|
||||
{
|
||||
pathname: '/api/ds/query',
|
||||
},
|
||||
(req) => {
|
||||
const datasourceType = req.body.queries[0].datasource.type;
|
||||
if (datasourceType === 'prometheus') {
|
||||
req.reply({ fixture: 'exemplars-query-response.json' });
|
||||
} else if (datasourceType === 'tempo') {
|
||||
req.reply({ fixture: 'tempo-response.json' });
|
||||
} else {
|
||||
req.reply({});
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
e2e.pages.Explore.visit();
|
||||
|
||||
e2e.components.DataSourcePicker.container().should('be.visible').click();
|
||||
cy.contains(dataSourceName).scrollIntoView().should('be.visible').click();
|
||||
|
||||
// Switch to code editor
|
||||
e2e.components.RadioButton.container().filter(':contains("Code")').click();
|
||||
|
||||
// Wait for lazy loading Monaco
|
||||
waitForMonacoToLoad();
|
||||
|
||||
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}');
|
||||
|
||||
cy.get(`[data-testid="time-series-zoom-to-data"]`).click();
|
||||
|
||||
e2e.components.DataSource.Prometheus.exemplarMarker().first().trigger('mousemove', { force: true });
|
||||
cy.contains('Query with gdev-tempo').click();
|
||||
e2e.components.TraceViewer.spanBar().should('have.length', 11);
|
||||
});
|
||||
});
|
||||
@@ -1,22 +0,0 @@
|
||||
import { e2e } from '../utils';
|
||||
|
||||
describe('Explore', () => {
|
||||
beforeEach(() => {
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
|
||||
});
|
||||
|
||||
it('Basic path through Explore.', () => {
|
||||
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()
|
||||
.scrollIntoView()
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
cy.get('input[id*="test-data-scenario-select-"]').should('be.visible').click();
|
||||
});
|
||||
|
||||
cy.contains('CSV Metric Values').scrollIntoView().should('be.visible').click();
|
||||
});
|
||||
});
|
||||
@@ -1,73 +0,0 @@
|
||||
import { e2e } from '../utils';
|
||||
const DASHBOARD_ID = 'ed155665';
|
||||
|
||||
// Skipping due to race conditions with same old arch test e2e/various-suite/filter-annotations.spec.ts
|
||||
describe.skip('Annotations filtering', () => {
|
||||
beforeEach(() => {
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
|
||||
});
|
||||
|
||||
it('Tests switching filter type updates the UI accordingly', () => {
|
||||
e2e.flows.openDashboard({ uid: DASHBOARD_ID });
|
||||
|
||||
e2e.components.NavToolbar.editDashboard.editButton().should('be.visible').click();
|
||||
e2e.components.NavToolbar.editDashboard.settingsButton().should('be.visible').click();
|
||||
|
||||
e2e.components.Tab.title('Annotations').click();
|
||||
cy.contains('New query').click();
|
||||
e2e.pages.Dashboard.Settings.Annotations.Settings.name().clear().type('Red - Panel two');
|
||||
|
||||
e2e.pages.Dashboard.Settings.Annotations.NewAnnotation.showInLabel()
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
// All panels
|
||||
e2e.components.Annotations.annotationsTypeInput().find('input').type('All panels{enter}', { force: true });
|
||||
e2e.components.Annotations.annotationsChoosePanelInput().should('not.exist');
|
||||
|
||||
// All panels except
|
||||
e2e.components.Annotations.annotationsTypeInput()
|
||||
.find('input')
|
||||
.type('All panels except{enter}', { force: true });
|
||||
e2e.components.Annotations.annotationsChoosePanelInput().should('be.visible');
|
||||
|
||||
// Selected panels
|
||||
e2e.components.Annotations.annotationsTypeInput().find('input').type('Selected panels{enter}', { force: true });
|
||||
e2e.components.Annotations.annotationsChoosePanelInput()
|
||||
.should('be.visible')
|
||||
.find('input')
|
||||
.type('Panel two{enter}', { force: true });
|
||||
});
|
||||
|
||||
cy.get('body').click();
|
||||
|
||||
e2e.components.NavToolbar.editDashboard.backToDashboardButton().should('be.visible').click();
|
||||
|
||||
e2e.pages.Dashboard.Controls()
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
e2e.pages.Dashboard.SubMenu.submenuItemLabels('Red - Panel two')
|
||||
.should('be.visible')
|
||||
.parent()
|
||||
.within((el) => {
|
||||
cy.get('input')
|
||||
.should('be.checked')
|
||||
.uncheck({ force: true })
|
||||
.should('not.be.checked')
|
||||
.check({ force: true });
|
||||
});
|
||||
|
||||
e2e.pages.Dashboard.SubMenu.submenuItemLabels('Red, only panel 1')
|
||||
.should('be.visible')
|
||||
.parent()
|
||||
.within((el) => {
|
||||
cy.get('input').should('be.checked');
|
||||
});
|
||||
});
|
||||
|
||||
e2e.components.Panels.Panel.title('Panel one')
|
||||
.should('exist')
|
||||
.within(() => {
|
||||
e2e.pages.Dashboard.Annotations.marker().should('exist').should('have.length', 4);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,71 +0,0 @@
|
||||
import { e2e } from '../utils';
|
||||
|
||||
const APP_ID = 'sandbox-app-test';
|
||||
|
||||
describe('Datasource sandbox', () => {
|
||||
before(() => {
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'), true);
|
||||
cy.request({
|
||||
url: `${Cypress.env('BASE_URL')}/api/plugins/${APP_ID}/settings`,
|
||||
method: 'POST',
|
||||
body: {
|
||||
enabled: true,
|
||||
},
|
||||
});
|
||||
});
|
||||
beforeEach(() => {
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'), true);
|
||||
});
|
||||
|
||||
describe('App Page', () => {
|
||||
describe('Sandbox disabled', () => {
|
||||
beforeEach(() => {
|
||||
cy.window().then((win) => {
|
||||
win.localStorage.setItem('grafana.featureToggles', 'pluginsFrontendSandbox=0');
|
||||
});
|
||||
});
|
||||
|
||||
it('Loads the app page without the sandbox div wrapper', () => {
|
||||
cy.visit(`/a/${APP_ID}`);
|
||||
cy.wait(200); // wait to prevent false positives because cypress checks too fast
|
||||
cy.get('div[data-plugin-sandbox="sandbox-app-test"]').should('not.exist');
|
||||
cy.get('div[data-testid="sandbox-app-test-page-one"]').should('exist');
|
||||
});
|
||||
|
||||
it('Loads the app configuration without the sandbox div wrapper', () => {
|
||||
cy.visit(`/plugins/${APP_ID}`);
|
||||
cy.wait(200); // wait to prevent false positives because cypress checks too fast
|
||||
cy.get('div[data-plugin-sandbox="sandbox-app-test"]').should('not.exist');
|
||||
cy.get('div[data-testid="sandbox-app-test-config-page"]').should('exist');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Sandbox enabled', () => {
|
||||
beforeEach(() => {
|
||||
cy.window().then((win) => {
|
||||
win.localStorage.setItem('grafana.featureToggles', 'pluginsFrontendSandbox=1');
|
||||
});
|
||||
});
|
||||
|
||||
it('Loads the app page with the sandbox div wrapper', () => {
|
||||
cy.visit(`/a/${APP_ID}`);
|
||||
cy.get('div[data-plugin-sandbox="sandbox-app-test"]').should('exist');
|
||||
cy.get('div[data-testid="sandbox-app-test-page-one"]').should('exist');
|
||||
});
|
||||
|
||||
it('Loads the app configuration with the sandbox div wrapper', () => {
|
||||
cy.visit(`/plugins/${APP_ID}`);
|
||||
cy.get('div[data-plugin-sandbox="sandbox-app-test"]').should('exist');
|
||||
cy.get('div[data-testid="sandbox-app-test-config-page"]').should('exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
e2e.flows.revertAllChanges();
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cy.clearCookies();
|
||||
});
|
||||
});
|
||||
@@ -1,18 +0,0 @@
|
||||
import { e2e } from '../utils';
|
||||
|
||||
describe('Gauge Panel', () => {
|
||||
beforeEach(() => {
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
|
||||
});
|
||||
|
||||
it('Gauge rendering e2e tests', () => {
|
||||
// open Panel Tests - Gauge
|
||||
e2e.flows.openDashboard({ uid: '_5rDmaQiz' });
|
||||
|
||||
// check that gauges are rendered
|
||||
cy.get('body').find(`.flot-base`).should('have.length', 16);
|
||||
|
||||
// check that no panel errors exist
|
||||
e2e.components.Panels.Panel.headerCornerInfo('error').should('not.exist');
|
||||
});
|
||||
});
|
||||
@@ -1,61 +0,0 @@
|
||||
import { e2e } from '../utils';
|
||||
|
||||
const DASHBOARD_ID = 'XMjIZPmik';
|
||||
const DASHBOARD_NAME = 'Panel Tests - Graph Time Regions';
|
||||
const UPLOT_MAIN_DIV_SELECTOR = '[data-testid="uplot-main-div"]';
|
||||
|
||||
describe('Auto-migrate graph panel', () => {
|
||||
beforeEach(() => {
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
|
||||
});
|
||||
|
||||
it('Graph panel is auto-migrated', () => {
|
||||
e2e.flows.openDashboard({ uid: DASHBOARD_ID });
|
||||
cy.contains(DASHBOARD_NAME).should('be.visible');
|
||||
cy.get(UPLOT_MAIN_DIV_SELECTOR).should('not.exist');
|
||||
|
||||
e2e.flows.openDashboard({ uid: DASHBOARD_ID });
|
||||
|
||||
cy.get(UPLOT_MAIN_DIV_SELECTOR).should('exist');
|
||||
});
|
||||
|
||||
it('Annotation markers exist for time regions', () => {
|
||||
e2e.flows.openDashboard({ uid: DASHBOARD_ID });
|
||||
cy.contains(DASHBOARD_NAME).should('be.visible');
|
||||
cy.get(UPLOT_MAIN_DIV_SELECTOR).should('not.exist');
|
||||
|
||||
e2e.flows.openDashboard({ uid: DASHBOARD_ID });
|
||||
|
||||
e2e.components.Panels.Panel.title('Business Hours')
|
||||
.should('exist')
|
||||
.within(() => {
|
||||
e2e.pages.Dashboard.Annotations.marker().should('exist');
|
||||
});
|
||||
|
||||
e2e.components.Panels.Panel.title("Sunday's 20-23")
|
||||
.should('exist')
|
||||
.within(() => {
|
||||
e2e.pages.Dashboard.Annotations.marker().should('exist');
|
||||
});
|
||||
|
||||
e2e.components.Panels.Panel.title('Each day of week')
|
||||
.should('exist')
|
||||
.within(() => {
|
||||
e2e.pages.Dashboard.Annotations.marker().should('exist');
|
||||
});
|
||||
|
||||
cy.scrollTo('bottom');
|
||||
|
||||
e2e.components.Panels.Panel.title('05:00')
|
||||
.should('exist')
|
||||
.within(() => {
|
||||
e2e.pages.Dashboard.Annotations.marker().should('exist');
|
||||
});
|
||||
|
||||
e2e.components.Panels.Panel.title('From 22:00 to 00:30 (crossing midnight)')
|
||||
.should('exist')
|
||||
.within(() => {
|
||||
e2e.pages.Dashboard.Annotations.marker().should('exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,125 +0,0 @@
|
||||
import { e2e } from '../utils';
|
||||
|
||||
const PANEL_UNDER_TEST = 'Value reducers 1';
|
||||
|
||||
describe('Inspect drawer tests', () => {
|
||||
beforeEach(() => {
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
|
||||
});
|
||||
|
||||
it('Tests various Inspect Drawer scenarios', () => {
|
||||
// @ts-ignore some typing issue
|
||||
cy.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;
|
||||
});
|
||||
|
||||
e2e.flows.openDashboard({ uid: 'wfTJJL5Wz' });
|
||||
|
||||
e2e.components.Panels.Panel.title(PANEL_UNDER_TEST).scrollIntoView().should('be.visible');
|
||||
e2e.components.Panels.Panel.menu(PANEL_UNDER_TEST).click({ force: true }); // force click because menu is hidden and show on hover
|
||||
e2e.components.Panels.Panel.menuItems('Inspect').trigger('mouseover', { force: true });
|
||||
e2e.components.Panels.Panel.menuItems('Data').click({ force: true });
|
||||
|
||||
expectDrawerTabsAndContent();
|
||||
|
||||
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 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');
|
||||
e2e.components.Panels.Panel.menu(PANEL_UNDER_TEST).click({ force: true }); // force click because menu is hidden and show on hover
|
||||
// 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
|
||||
|
||||
// simulate hover on Inspector menu item to display sub menus
|
||||
e2e.components.Panels.Panel.menuItems('Inspect').trigger('mouseover', { force: true });
|
||||
e2e.components.Panels.Panel.menuItems(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();
|
||||
};
|
||||
@@ -1,64 +0,0 @@
|
||||
import { e2e } from '../utils';
|
||||
import { fromBaseUrl } from '../utils/support/url';
|
||||
|
||||
// Skipping due to race conditions with same old arch test e2e/various-suite/keybinds.spec.ts
|
||||
describe.skip('Keyboard shortcuts', () => {
|
||||
beforeEach(() => {
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
|
||||
|
||||
cy.visit(fromBaseUrl('/'));
|
||||
|
||||
// wait for the page to load
|
||||
e2e.components.Panels.Panel.title('Latest from the blog').should('be.visible');
|
||||
});
|
||||
|
||||
it('sequence shortcuts should work', () => {
|
||||
cy.get('body').type('ge');
|
||||
e2e.pages.Explore.General.container().should('be.visible');
|
||||
|
||||
cy.get('body').type('gp');
|
||||
e2e.components.UserProfile.preferencesSaveButton().should('be.visible');
|
||||
|
||||
cy.get('body').type('gh');
|
||||
e2e.components.Panels.Panel.title('Latest from the blog').should('be.visible');
|
||||
});
|
||||
|
||||
it('ctrl+z should zoom out the time range', () => {
|
||||
cy.get('body').type('ge');
|
||||
e2e.pages.Explore.General.container().should('be.visible');
|
||||
|
||||
// Time range is 1 minute, so each shortcut press should jump back or forward by 1 minute
|
||||
e2e.flows.setTimeRange({
|
||||
from: '2024-06-05 10:05:00',
|
||||
to: '2024-06-05 10:06:00',
|
||||
zone: 'Browser',
|
||||
});
|
||||
e2e.components.RefreshPicker.runButtonV2().should('have.text', 'Run query');
|
||||
|
||||
cy.get('body').type('{ctrl}z');
|
||||
e2e.components.RefreshPicker.runButtonV2().should('have.text', 'Run query');
|
||||
let expectedRange = `Time range selected: 2024-06-05 10:03:30 to 2024-06-05 10:07:30`;
|
||||
e2e.components.TimePicker.openButton().should('have.attr', 'aria-label', expectedRange);
|
||||
});
|
||||
|
||||
it('time range shortcuts should work', () => {
|
||||
cy.get('body').type('ge');
|
||||
e2e.pages.Explore.General.container().should('be.visible');
|
||||
|
||||
// Time range is 1 minute, so each shortcut press should jump back or forward by 1 minute
|
||||
e2e.flows.setTimeRange({
|
||||
from: '2024-06-05 10:05:00',
|
||||
to: '2024-06-05 10:06:00',
|
||||
zone: 'Browser',
|
||||
});
|
||||
e2e.components.RefreshPicker.runButtonV2().should('have.text', 'Run query');
|
||||
let expectedRange = `Time range selected: 2024-06-05 10:05:00 to 2024-06-05 10:06:00`;
|
||||
e2e.components.TimePicker.openButton().should('have.attr', 'aria-label', expectedRange);
|
||||
|
||||
cy.log('Trying one shift-left');
|
||||
cy.get('body').type('t{leftarrow}');
|
||||
e2e.components.RefreshPicker.runButtonV2().should('have.text', 'Run query');
|
||||
expectedRange = `Time range selected: 2024-06-05 10:04:00 to 2024-06-05 10:05:00`; // 1 min back
|
||||
e2e.components.TimePicker.openButton().should('have.attr', 'aria-label', expectedRange);
|
||||
});
|
||||
});
|
||||
@@ -1,106 +0,0 @@
|
||||
import { e2e } from '../utils';
|
||||
|
||||
const MISSING_LABEL_FILTER_ERROR_MESSAGE = 'Select at least 1 label filter (label and value)';
|
||||
const dataSourceName = 'LokiBuilder';
|
||||
const addDataSource = () => {
|
||||
e2e.flows.addDataSource({
|
||||
type: 'Loki',
|
||||
expectedAlertMessage: 'Unable to connect with Loki. Please check the server logs for more details.',
|
||||
name: dataSourceName,
|
||||
form: () => {
|
||||
cy.get('#connection-url').type('http://loki-url:3100');
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const finalQuery = 'rate({instance=~"instance1|instance2"} | logfmt | __error__=`` [$__auto]';
|
||||
|
||||
describe('Loki query builder', () => {
|
||||
beforeEach(() => {
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
|
||||
|
||||
cy.request({
|
||||
url: `${Cypress.env('BASE_URL')}/api/datasources/name/${dataSourceName}`,
|
||||
failOnStatusCode: false,
|
||||
}).then((response) => {
|
||||
if (response.isOkStatusCode) {
|
||||
return;
|
||||
}
|
||||
addDataSource();
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to use all modes', () => {
|
||||
cy.intercept(/labels\?/, (req) => {
|
||||
req.reply({ status: 'success', data: ['instance', 'job', 'source'] });
|
||||
}).as('labelsRequest');
|
||||
|
||||
cy.intercept(/series?/, (req) => {
|
||||
req.reply({ status: 'success', data: [{ instance: 'instance1' }] });
|
||||
});
|
||||
|
||||
cy.intercept(/values/, (req) => {
|
||||
req.reply({ status: 'success', data: ['instance1', 'instance2'] });
|
||||
}).as('valuesRequest');
|
||||
|
||||
cy.intercept(/index\/stats/, (req) => {
|
||||
req.reply({ streams: 2, chunks: 2660, bytes: 2721792, entries: 14408 });
|
||||
});
|
||||
|
||||
// Go to Explore and choose Loki data source
|
||||
e2e.pages.Explore.visit();
|
||||
e2e.components.DataSourcePicker.container().should('be.visible').click();
|
||||
cy.contains(dataSourceName).scrollIntoView().should('be.visible').click();
|
||||
|
||||
// Start in builder mode, click and choose query pattern
|
||||
e2e.components.QueryBuilder.queryPatterns().click();
|
||||
cy.contains('Log query starters').click();
|
||||
cy.contains('Use this query').click();
|
||||
cy.contains('No pipeline errors').should('be.visible');
|
||||
cy.contains('Logfmt').should('be.visible');
|
||||
cy.contains('{} | logfmt | __error__=``').should('be.visible');
|
||||
|
||||
// Add operation
|
||||
cy.contains('Operations').should('be.visible').click();
|
||||
cy.contains('Range functions').should('be.visible').click();
|
||||
cy.contains('Rate').should('be.visible').click();
|
||||
cy.contains('rate({} | logfmt | __error__=`` [$__auto]').should('be.visible');
|
||||
|
||||
// Check for expected error
|
||||
cy.contains(MISSING_LABEL_FILTER_ERROR_MESSAGE).should('be.visible');
|
||||
|
||||
// Add labels to remove error
|
||||
e2e.components.QueryBuilder.labelSelect().should('be.visible').click();
|
||||
// wait until labels are loaded and set on the component before starting to type
|
||||
e2e.components.QueryBuilder.inputSelect().type('i');
|
||||
cy.wait('@labelsRequest');
|
||||
e2e.components.QueryBuilder.inputSelect().type('nstance{enter}');
|
||||
e2e.components.QueryBuilder.matchOperatorSelect()
|
||||
.should('be.visible')
|
||||
.click({ force: true })
|
||||
.children('div')
|
||||
.children('input')
|
||||
.type('=~{enter}', { force: true });
|
||||
e2e.components.QueryBuilder.valueSelect().should('be.visible').click();
|
||||
e2e.components.QueryBuilder.valueSelect().children('div').children('input').type('instance1{enter}');
|
||||
cy.wait('@valuesRequest');
|
||||
e2e.components.QueryBuilder.valueSelect().children('div').children('input').type('instance2{enter}');
|
||||
|
||||
cy.contains(MISSING_LABEL_FILTER_ERROR_MESSAGE).should('not.exist');
|
||||
cy.contains(finalQuery).should('be.visible');
|
||||
|
||||
// Change to code editor
|
||||
e2e.components.RadioButton.container().filter(':contains("Code")').click();
|
||||
|
||||
// We need to test this manually because the final query is split into separate DOM elements using cy.contains(finalQuery).should('be.visible'); does not detect the query.
|
||||
cy.contains('rate').should('be.visible');
|
||||
cy.contains('instance1|instance2').should('be.visible');
|
||||
cy.contains('logfmt').should('be.visible');
|
||||
cy.contains('__error__').should('be.visible');
|
||||
cy.contains('$__auto').should('be.visible');
|
||||
|
||||
// Checks the explain mode toggle
|
||||
cy.contains('label', 'Explain').click();
|
||||
cy.contains('Fetch all log lines matching label filters.').should('be.visible');
|
||||
});
|
||||
});
|
||||
@@ -1,225 +0,0 @@
|
||||
import { e2e } from '../utils';
|
||||
|
||||
const dataSourceName = 'LokiEditor';
|
||||
const addDataSource = () => {
|
||||
e2e.flows.addDataSource({
|
||||
type: 'Loki',
|
||||
expectedAlertMessage: 'Unable to connect with Loki. Please check the server logs for more details.',
|
||||
name: dataSourceName,
|
||||
form: () => {
|
||||
cy.get('#connection-url').type('http://loki-url:3100');
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const lokiQueryResult = {
|
||||
status: 'success',
|
||||
results: {
|
||||
A: {
|
||||
status: 200,
|
||||
frames: [
|
||||
{
|
||||
schema: {
|
||||
refId: 'A',
|
||||
meta: {
|
||||
typeVersion: [0, 0],
|
||||
custom: {
|
||||
frameType: 'LabeledTimeValues',
|
||||
},
|
||||
stats: [
|
||||
{
|
||||
displayName: 'Summary: bytes processed per second',
|
||||
unit: 'Bps',
|
||||
value: 223921,
|
||||
},
|
||||
{
|
||||
displayName: 'Summary: total bytes processed',
|
||||
unit: 'decbytes',
|
||||
value: 4156,
|
||||
},
|
||||
{
|
||||
displayName: 'Summary: exec time',
|
||||
unit: 's',
|
||||
value: 0.01856,
|
||||
},
|
||||
],
|
||||
executedQueryString: 'Expr: {targetLabelName="targetLabelValue"}',
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'labels',
|
||||
type: 'other',
|
||||
typeInfo: {
|
||||
frame: 'json.RawMessage',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Time',
|
||||
type: 'time',
|
||||
typeInfo: {
|
||||
frame: 'time.Time',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Line',
|
||||
type: 'string',
|
||||
typeInfo: {
|
||||
frame: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'tsNs',
|
||||
type: 'string',
|
||||
typeInfo: {
|
||||
frame: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'id',
|
||||
type: 'string',
|
||||
typeInfo: {
|
||||
frame: 'string',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
data: {
|
||||
values: [
|
||||
[
|
||||
{
|
||||
targetLabelName: 'targetLabelValue',
|
||||
instance: 'server\\1',
|
||||
job: '"grafana/data"',
|
||||
nonIndexed: 'value',
|
||||
place: 'moon',
|
||||
re: 'one.two$three^four',
|
||||
source: 'data',
|
||||
},
|
||||
],
|
||||
[1700077283237],
|
||||
[
|
||||
'{"_entry":"log text with ANSI \\u001b[31mpart of the text\\u001b[0m [149702545]","counter":"22292","float":"NaN","wave":-0.5877852522916832,"label":"val3","level":"info"}',
|
||||
],
|
||||
['1700077283237000000'],
|
||||
['1700077283237000000_9b025d35'],
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
describe.skip('Loki Query Editor', () => {
|
||||
beforeEach(() => {
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
e2e.flows.revertAllChanges();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.setLocalStorage('grafana.featureToggles', 'logsExploreTableVisualisation=1');
|
||||
});
|
||||
it('Should be able to add explore table to dashboard', () => {
|
||||
addDataSource();
|
||||
|
||||
cy.intercept(/labels?/, (req) => {
|
||||
req.reply({ status: 'success', data: ['instance', 'job', 'source'] });
|
||||
});
|
||||
|
||||
cy.intercept(/series?/, (req) => {
|
||||
req.reply({ status: 'success', data: [{ instance: 'instance1' }] });
|
||||
});
|
||||
|
||||
cy.intercept(/\/api\/ds\/query\?ds_type=loki?/, (req) => {
|
||||
req.reply(lokiQueryResult);
|
||||
});
|
||||
|
||||
// Go to Explore and choose Loki data source
|
||||
e2e.pages.Explore.visit();
|
||||
e2e.components.DataSourcePicker.container().should('be.visible').click();
|
||||
cy.contains(dataSourceName).scrollIntoView().should('be.visible').click();
|
||||
|
||||
cy.contains('Code').click({ force: true });
|
||||
|
||||
// Wait for lazy loading
|
||||
// const monacoLoadingText = 'Loading...';
|
||||
|
||||
// e2e.components.QueryField.container().should('be.visible').should('have.text', monacoLoadingText);
|
||||
e2e.components.QueryField.container()
|
||||
.find('.view-overlays[role="presentation"]')
|
||||
.get('.cdr')
|
||||
.then(($el) => {
|
||||
const win = $el[0].ownerDocument.defaultView;
|
||||
const after = win.getComputedStyle($el[0], '::after');
|
||||
const content = after.getPropertyValue('content');
|
||||
expect(content).to.eq('"Enter a Loki query (run with Shift+Enter)"');
|
||||
});
|
||||
|
||||
// Write a simple query
|
||||
e2e.components.QueryField.container().type('query').type('{instance="instance1"');
|
||||
cy.get('.monaco-editor textarea:first').should(($el) => {
|
||||
expect($el.val()).to.eq('query{instance="instance1"}');
|
||||
});
|
||||
|
||||
// Submit the query
|
||||
e2e.components.QueryField.container().type('{shift+enter}');
|
||||
// Assert the no-data message is not visible
|
||||
cy.get('[data-testid="explore-no-data"]').should('not.exist');
|
||||
|
||||
// Click on the table toggle
|
||||
cy.contains('Table').click({ force: true });
|
||||
|
||||
// One row with two cells
|
||||
cy.get('[role="cell"]').should('have.length', 2);
|
||||
|
||||
cy.contains('label', 'targetLabelName').scrollIntoView();
|
||||
cy.contains('label', 'targetLabelName').should('be.visible');
|
||||
cy.contains('label', 'targetLabelName').click();
|
||||
cy.contains('label', 'targetLabelName').within(() => {
|
||||
cy.get('input[type="checkbox"]').check({ force: true });
|
||||
});
|
||||
|
||||
cy.contains('label', 'targetLabelName').within(() => {
|
||||
cy.get('input[type="checkbox"]').should('be.checked');
|
||||
});
|
||||
|
||||
const exploreCells = cy.get('[role="cell"]');
|
||||
|
||||
// Now we should have a row with 3 columns
|
||||
exploreCells.should('have.length', 3);
|
||||
// And a value of "targetLabelValue"
|
||||
exploreCells.should('contain', 'targetLabelValue');
|
||||
|
||||
const addToButton = cy.get('[aria-label="Add"]');
|
||||
addToButton.should('be.visible');
|
||||
addToButton.click();
|
||||
|
||||
const addToDashboardButton = cy.get('[aria-label="Add to dashboard"]');
|
||||
|
||||
// Now let's add this to a dashboard
|
||||
addToDashboardButton.should('be.visible');
|
||||
addToDashboardButton.click();
|
||||
|
||||
const addPanelToDashboardButton = cy.contains('Add panel to dashboard');
|
||||
addPanelToDashboardButton.should('be.visible');
|
||||
|
||||
const openDashboardButton = cy.contains('Open dashboard');
|
||||
openDashboardButton.should('be.visible');
|
||||
openDashboardButton.click();
|
||||
|
||||
const panel = cy.get('[data-viz-panel-key="panel-1"]');
|
||||
panel.should('be.visible');
|
||||
|
||||
const cells = panel.find('[role="table"] [role="cell"]');
|
||||
// Should have 3 columns
|
||||
cells.should('have.length', 3);
|
||||
// Cells contain strings found in log line
|
||||
cells.contains('"wave":-0.5877852522916832');
|
||||
|
||||
// column has correct value of "targetLabelValue", need to requery the DOM because of the .contains call above
|
||||
cy.get('[data-viz-panel-key="panel-1"]').find('[role="table"] [role="cell"]').contains('targetLabelValue');
|
||||
});
|
||||
});
|
||||
@@ -1,60 +0,0 @@
|
||||
import { e2e } from '../utils';
|
||||
import { fromBaseUrl } from '../utils/support/url';
|
||||
|
||||
describe('Docked Navigation', () => {
|
||||
beforeEach(() => {
|
||||
// This is a breakpoint where the mega menu can be docked (and docked is the default state)
|
||||
cy.viewport(1280, 800);
|
||||
cy.clearAllLocalStorage();
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
|
||||
|
||||
cy.visit(fromBaseUrl('/'));
|
||||
});
|
||||
|
||||
it('should remain un-docked when reloading the page', () => {
|
||||
// Undock the menu
|
||||
cy.get('[aria-label="Undock menu"]').click();
|
||||
|
||||
e2e.components.NavMenu.Menu().should('not.exist');
|
||||
|
||||
cy.reload();
|
||||
e2e.components.NavMenu.Menu().should('not.exist');
|
||||
});
|
||||
|
||||
it('Can re-dock after undock', () => {
|
||||
// Undock the menu
|
||||
cy.get('[aria-label="Undock menu"]').click();
|
||||
cy.get('[aria-label="Open menu"]').click();
|
||||
cy.get('[aria-label="Dock menu"]').click();
|
||||
|
||||
e2e.components.NavMenu.Menu().should('be.visible');
|
||||
});
|
||||
|
||||
it('should remain in same state when navigating to another page', () => {
|
||||
// Undock the menu
|
||||
cy.get('[aria-label="Undock menu"]').click();
|
||||
|
||||
// Navigate
|
||||
cy.get('[aria-label="Open menu"]').click();
|
||||
cy.contains('a', 'Administration').click();
|
||||
|
||||
// Still undocked
|
||||
e2e.components.NavMenu.Menu().should('not.exist');
|
||||
|
||||
// dock the menu
|
||||
cy.get('[aria-label="Open menu"]').click();
|
||||
cy.get('[aria-label="Dock menu"]').click();
|
||||
|
||||
// Navigate
|
||||
cy.contains('a', 'Users').click();
|
||||
// Still docked
|
||||
e2e.components.NavMenu.Menu().should('be.visible');
|
||||
});
|
||||
|
||||
it('should undock on smaller viewport sizes', () => {
|
||||
cy.viewport(1120, 1080);
|
||||
cy.reload();
|
||||
|
||||
e2e.components.NavMenu.Menu().should('not.exist');
|
||||
});
|
||||
});
|
||||
@@ -1,18 +0,0 @@
|
||||
import { selectors } from '@grafana/e2e-selectors';
|
||||
|
||||
import { e2e } from '../utils';
|
||||
|
||||
describe('Pie Chart Panel', () => {
|
||||
beforeEach(() => {
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
|
||||
});
|
||||
|
||||
it('Pie Chart rendering e2e tests', () => {
|
||||
// open Panel Tests - Pie Chart
|
||||
e2e.flows.openDashboard({ uid: 'lVE-2YFMz' });
|
||||
|
||||
cy.get(
|
||||
`[data-viz-panel-key="panel-11"] [data-testid^="${selectors.components.Panels.Visualization.PieChart.svgSlice}"]`
|
||||
).should('have.length', 5);
|
||||
});
|
||||
});
|
||||
@@ -1,74 +0,0 @@
|
||||
import { e2e } from '../utils';
|
||||
import { addDashboard } from '../utils/flows';
|
||||
|
||||
import { createPromDS, getResources } from './helpers/prometheus-helpers';
|
||||
|
||||
const DATASOURCE_ID = 'Prometheus';
|
||||
|
||||
const DATASOURCE_NAME = 'aprometheusAnnotationDS';
|
||||
|
||||
/**
|
||||
* Click dashboard settings and then the variables tab
|
||||
*
|
||||
*/
|
||||
function navigateToAnnotations() {
|
||||
e2e.components.NavToolbar.editDashboard.editButton().should('be.visible').click();
|
||||
e2e.components.NavToolbar.editDashboard.settingsButton().should('be.visible').click();
|
||||
e2e.components.Tab.title('Annotations').click();
|
||||
}
|
||||
|
||||
function addPrometheusAnnotation(annotationName: string) {
|
||||
e2e.pages.Dashboard.Settings.Annotations.List.addAnnotationCTAV2().click();
|
||||
getResources();
|
||||
e2e.pages.Dashboard.Settings.Annotations.Settings.name().clear().type(annotationName);
|
||||
e2e.components.DataSourcePicker.container().should('be.visible').click();
|
||||
cy.contains(DATASOURCE_NAME).scrollIntoView().should('be.visible').click();
|
||||
}
|
||||
|
||||
describe('Prometheus annotations', () => {
|
||||
beforeEach(() => {
|
||||
createPromDS(DATASOURCE_ID, DATASOURCE_NAME);
|
||||
});
|
||||
|
||||
it('should navigate to variable query editor', () => {
|
||||
const annotationName = 'promAnnotation';
|
||||
addDashboard();
|
||||
navigateToAnnotations();
|
||||
addPrometheusAnnotation(annotationName);
|
||||
|
||||
e2e.components.DataSource.Prometheus.queryEditor.code.metricsBrowser
|
||||
.openButton()
|
||||
.contains('Metrics browser')
|
||||
.click();
|
||||
|
||||
e2e.components.DataSource.Prometheus.queryEditor.code.metricsBrowser.selectMetric().should('exist').type('met');
|
||||
|
||||
e2e.components.DataSource.Prometheus.queryEditor.code.metricsBrowser
|
||||
.metricList()
|
||||
.should('exist')
|
||||
.contains('metric1')
|
||||
.click();
|
||||
|
||||
e2e.components.DataSource.Prometheus.queryEditor.code.metricsBrowser.useQuery().should('exist').click();
|
||||
|
||||
e2e.components.DataSource.Prometheus.queryEditor.code.queryField().should('exist').contains('metric1');
|
||||
|
||||
// check for other parts of the annotations
|
||||
// min step
|
||||
e2e.components.DataSource.Prometheus.annotations.minStep().should('exist');
|
||||
|
||||
// title
|
||||
e2e.components.DataSource.Prometheus.annotations.title().scrollIntoView().should('exist');
|
||||
// tags
|
||||
e2e.components.DataSource.Prometheus.annotations.tags().scrollIntoView().should('exist');
|
||||
// text
|
||||
e2e.components.DataSource.Prometheus.annotations.text().scrollIntoView().should('exist');
|
||||
// series value as timestamp
|
||||
e2e.components.DataSource.Prometheus.annotations.seriesValueAsTimestamp().scrollIntoView().should('exist');
|
||||
|
||||
e2e.components.NavToolbar.editDashboard.backToDashboardButton().should('be.visible').click();
|
||||
|
||||
// check that annotation exists
|
||||
cy.get('body').contains(annotationName);
|
||||
});
|
||||
});
|
||||
@@ -1,32 +0,0 @@
|
||||
import { e2e } from '../utils';
|
||||
import { waitForMonacoToLoad } from '../utils/support/monaco';
|
||||
|
||||
describe('Query editor', () => {
|
||||
beforeEach(() => {
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
|
||||
});
|
||||
|
||||
// x-ing to bypass this flaky test.
|
||||
// Will rewrite in plugin-e2e with this issue
|
||||
xit('Undo should work in query editor for prometheus -- test CI.', () => {
|
||||
e2e.pages.Explore.visit();
|
||||
e2e.components.DataSourcePicker.container().should('be.visible').click();
|
||||
|
||||
cy.contains('gdev-prometheus').scrollIntoView().should('be.visible').click();
|
||||
const queryText = `rate(http_requests_total{job="grafana"}[5m])`;
|
||||
|
||||
e2e.components.RadioButton.container().filter(':contains("Code")').should('be.visible').click();
|
||||
|
||||
waitForMonacoToLoad();
|
||||
|
||||
e2e.components.QueryField.container().type(queryText, { parseSpecialCharSequences: false }).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');
|
||||
|
||||
e2e.components.Alert.alertV2('error').should('not.be.visible');
|
||||
});
|
||||
});
|
||||
@@ -1,71 +0,0 @@
|
||||
import { e2e } from '../utils';
|
||||
|
||||
describe('ReturnToPrevious button', () => {
|
||||
beforeEach(() => {
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
|
||||
|
||||
cy.visit('/alerting/list');
|
||||
e2e.components.AlertRules.groupToggle().first().click();
|
||||
e2e.components.AlertRules.toggle().click();
|
||||
cy.get('a[title="View"]').click();
|
||||
cy.url().as('alertRuleUrl');
|
||||
cy.get('a').contains('View panel').click();
|
||||
});
|
||||
|
||||
it('should appear when changing context and go back to alert rule when clicking "Back"', () => {
|
||||
// check whether all elements of RTP are available
|
||||
e2e.components.ReturnToPrevious.buttonGroup().should('be.visible');
|
||||
e2e.components.ReturnToPrevious.dismissButton().should('be.visible');
|
||||
e2e.components.ReturnToPrevious.backButton()
|
||||
.find('span')
|
||||
.contains('Back to e2e-ReturnToPrevious-test')
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
// check whether the RTP button leads back to alert rule
|
||||
cy.get('@alertRuleUrl').then((alertRuleUrl) => {
|
||||
cy.url().should('eq', alertRuleUrl);
|
||||
});
|
||||
});
|
||||
|
||||
it('should disappear when clicking "Dismiss"', () => {
|
||||
e2e.components.ReturnToPrevious.dismissButton().should('be.visible').click();
|
||||
e2e.components.ReturnToPrevious.buttonGroup().should('not.exist');
|
||||
});
|
||||
|
||||
it('should not persist when going back to the alert rule details view', () => {
|
||||
e2e.components.ReturnToPrevious.buttonGroup().should('be.visible');
|
||||
|
||||
cy.visit('/alerting/list');
|
||||
e2e.components.AlertRules.groupToggle().first().click();
|
||||
cy.get('a[title="View"]').click();
|
||||
e2e.components.ReturnToPrevious.buttonGroup().should('not.exist');
|
||||
});
|
||||
|
||||
it('should override the button label and change the href when user changes alert rules', () => {
|
||||
e2e.components.ReturnToPrevious.backButton()
|
||||
.find('span')
|
||||
.contains('Back to e2e-ReturnToPrevious-test')
|
||||
.should('be.visible');
|
||||
|
||||
cy.visit('/alerting/list');
|
||||
|
||||
e2e.components.AlertRules.groupToggle().last().click();
|
||||
cy.get('a[title="View"]').click();
|
||||
cy.url().as('alertRule2Url');
|
||||
cy.get('a').contains('View panel').click();
|
||||
|
||||
e2e.components.ReturnToPrevious.backButton()
|
||||
.find('span')
|
||||
.contains('Back to e2e-ReturnToPrevious-test-2')
|
||||
.should('be.visible')
|
||||
.click();
|
||||
|
||||
e2e.components.ReturnToPrevious.buttonGroup().should('not.exist');
|
||||
|
||||
// check whether the RTP button leads back to alert rule
|
||||
cy.get('@alertRule2Url').then((alertRule2Url) => {
|
||||
cy.url().should('eq', alertRule2Url);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,34 +0,0 @@
|
||||
import { e2e } from '../utils';
|
||||
|
||||
describe('Select focus/unfocus tests', () => {
|
||||
beforeEach(() => {
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
|
||||
});
|
||||
|
||||
it.skip('Tests select focus/unfocus scenarios', () => {
|
||||
e2e.flows.openDashboard({ uid: '5SdHCadmz' });
|
||||
e2e.components.PageToolbar.item('Dashboard settings').click();
|
||||
|
||||
e2e.components.FolderPicker.containerV2()
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
cy.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(() => {
|
||||
cy.get('#dashboard-folder-input').should('exist').should('have.focus');
|
||||
});
|
||||
|
||||
e2e.pages.Dashboard.Settings.General.title().click();
|
||||
|
||||
e2e.components.FolderPicker.containerV2()
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
cy.get('#dashboard-folder-input').should('exist').should('not.have.focus');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,44 +0,0 @@
|
||||
import { e2e } from '../utils';
|
||||
|
||||
describe('Solo Route', () => {
|
||||
beforeEach(() => {
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
|
||||
});
|
||||
|
||||
it('Can view panels with shared queries in fullscreen', () => {
|
||||
// open Panel Tests - Bar Gauge
|
||||
e2e.pages.SoloPanel.visit('ZqZnVvFZz/datasource-tests-shared-queries?orgId=1&panelId=4');
|
||||
|
||||
cy.get('canvas').should('have.length', 6);
|
||||
});
|
||||
|
||||
it('Can view solo panel in scenes', () => {
|
||||
// open Panel Tests - Graph NG
|
||||
e2e.pages.SoloPanel.visit(
|
||||
'TkZXxlNG3/panel-tests-graph-ng?orgId=1&from=1699954597665&to=1699956397665&panelId=54&__feature.dashboardSceneSolo=true'
|
||||
);
|
||||
|
||||
e2e.components.Panels.Panel.title('Interpolation: Step before').should('exist');
|
||||
cy.contains('uplot-main-div').should('not.exist');
|
||||
});
|
||||
|
||||
it('Can view solo repeated panel in scenes', () => {
|
||||
// open Panel Tests - Graph NG
|
||||
e2e.pages.SoloPanel.visit(
|
||||
'templating-repeating-panels/templating-repeating-panels?orgId=1&from=1699934989607&to=1699956589607&panelId=A$panel-2&__feature.dashboardSceneSolo=true'
|
||||
);
|
||||
|
||||
e2e.components.Panels.Panel.title('server=A').should('exist');
|
||||
cy.contains('uplot-main-div').should('not.exist');
|
||||
});
|
||||
|
||||
it('Can view solo in repeated row and panel in scenes', () => {
|
||||
// open Panel Tests - Graph NG
|
||||
e2e.pages.SoloPanel.visit(
|
||||
'Repeating-rows-uid/repeating-rows?orgId=1&var-server=A&var-server=B&var-server=D&var-pod=1&var-pod=2&var-pod=3&panelId=B$2$panel-2&__feature.dashboardSceneSolo=true'
|
||||
);
|
||||
|
||||
e2e.components.Panels.Panel.title('server = B, pod = Rob').should('exist');
|
||||
cy.contains('uplot-main-div').should('not.exist');
|
||||
});
|
||||
});
|
||||
@@ -1,64 +0,0 @@
|
||||
import { e2e } from '../utils';
|
||||
import { fromBaseUrl } from '../utils/support/url';
|
||||
|
||||
describe('Verify i18n', () => {
|
||||
const I18N_USER = 'i18n-test';
|
||||
const I18N_PASSWORD = 'i18n-test';
|
||||
|
||||
// create a new user to isolate the language changes from other tests
|
||||
before(() => {
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
|
||||
cy.request({
|
||||
method: 'POST',
|
||||
url: fromBaseUrl('/api/admin/users'),
|
||||
body: {
|
||||
email: I18N_USER,
|
||||
login: I18N_USER,
|
||||
name: I18N_USER,
|
||||
password: I18N_PASSWORD,
|
||||
},
|
||||
}).then((response) => {
|
||||
cy.wrap(response.body.uid).as('uid');
|
||||
});
|
||||
});
|
||||
|
||||
// remove the user created in the before hook
|
||||
after(() => {
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
|
||||
cy.get('@uid').then((uid) => {
|
||||
cy.request({
|
||||
method: 'DELETE',
|
||||
url: fromBaseUrl(`/api/admin/users/${uid}`),
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
e2e.flows.login(I18N_USER, I18N_PASSWORD);
|
||||
});
|
||||
|
||||
// map between languages in the language picker and the corresponding translation of the 'Language' label
|
||||
const languageMap: Record<string, string> = {
|
||||
Deutsch: 'Sprache',
|
||||
English: 'Language',
|
||||
Español: 'Idioma',
|
||||
Français: 'Langue',
|
||||
'Português Brasileiro': 'Idioma',
|
||||
'中文(简体)': '语言',
|
||||
};
|
||||
|
||||
// basic test which loops through the defined languages in the picker
|
||||
// and verifies that the corresponding label is translated correctly
|
||||
it('loads all the languages correctly', () => {
|
||||
cy.visit('/profile');
|
||||
const LANGUAGE_SELECTOR = '[id="language-preference-select"]';
|
||||
cy.wrap(Object.entries(languageMap)).each(([language, label]: [string, string]) => {
|
||||
cy.get(LANGUAGE_SELECTOR).should('not.be.disabled');
|
||||
cy.get(LANGUAGE_SELECTOR).click();
|
||||
cy.get(LANGUAGE_SELECTOR).clear().type(language).type('{downArrow}{enter}');
|
||||
e2e.components.UserProfile.preferencesSaveButton().click();
|
||||
cy.contains('label', label).should('be.visible');
|
||||
cy.get(LANGUAGE_SELECTOR).should('have.value', language);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,27 +0,0 @@
|
||||
import { e2e } from '../utils';
|
||||
|
||||
describe('Visualization suggestions', () => {
|
||||
beforeEach(() => {
|
||||
e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'));
|
||||
});
|
||||
|
||||
it('Should be shown and clickable', () => {
|
||||
e2e.flows.openDashboard({ uid: 'aBXrJ0R7z', queryParams: { '__feature.tableNextGen': false, editPanel: 9 } });
|
||||
|
||||
// Try visualization suggestions
|
||||
e2e.components.PanelEditor.toggleVizPicker().click();
|
||||
e2e.components.RadioButton.container().filter(':contains("Suggestions")').click();
|
||||
|
||||
// Verify we see suggestions
|
||||
e2e.components.VisualizationPreview.card('Line chart').should('be.visible');
|
||||
|
||||
// Verify search works
|
||||
cy.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