The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/e2e-playwright/various-suite/prometheus-editor.spec.ts

287 lines
11 KiB

import { Page } from 'playwright-core';
import { test, expect, E2ESelectorGroups } from '@grafana/plugin-e2e';
import { getResources } from '../utils/prometheus-helpers';
// TODO: fix some tests. Race conditions with other tests in the file cause some to fail.
test.describe.skip(
'Prometheus query editor',
{
tag: ['@various', '@wip'],
},
() => {
const DATASOURCE_ID = 'Prometheus';
type EditorType = 'Code' | 'Builder';
/**
* Create and save a Prometheus data source, navigate to code or builder
*/
async function navigateToEditor(page: Page, selectors: E2ESelectorGroups, editorType: string, name: string) {
// Navigate to add data source page
await page.goto('/datasources/new');
// Select the Prometheus data source
const prometheusPlugin = page.getByRole('button', { name: DATASOURCE_ID });
await prometheusPlugin.scrollIntoViewIfNeeded();
await expect(prometheusPlugin).toBeVisible();
await prometheusPlugin.click();
// Choose default editor
const defaultEditor = page.getByTestId(selectors.components.DataSource.Prometheus.configPage.defaultEditor);
await defaultEditor.scrollIntoViewIfNeeded();
await expect(defaultEditor).toBeVisible();
await defaultEditor.click();
await selectOption(page, editorType, selectors);
// Add URL for DS to save without error
const connectionSettings = page.getByLabel(
selectors.components.DataSource.Prometheus.configPage.connectionSettings
);
await connectionSettings.fill('http://prom-url:9090');
// Name the DS
const nameInput = page.getByTestId(selectors.pages.DataSource.name);
await nameInput.clear();
await nameInput.fill(name);
const saveAndTestButton = page.getByTestId(selectors.pages.DataSource.saveAndTest);
await saveAndTestButton.click();
// Visit explore
await page.goto('/explore');
// Choose the right DS
const dataSourcePicker = page.getByTestId(selectors.components.DataSourcePicker.container);
await expect(dataSourcePicker).toBeVisible();
await dataSourcePicker.click();
const dataSourceOption = page.getByRole('button', { name: `${name} ${DATASOURCE_ID}`, exact: true });
await dataSourceOption.scrollIntoViewIfNeeded();
await expect(dataSourceOption).toBeVisible();
await dataSourceOption.click();
}
test('should have a kickstart component', async ({ page, selectors }) => {
await navigateToEditor(page, selectors, 'Code', 'prometheus');
const queryPatterns = page.getByTestId(selectors.components.QueryBuilder.queryPatterns);
await queryPatterns.scrollIntoViewIfNeeded();
await expect(queryPatterns).toBeVisible();
});
test('should have an explain component', async ({ page, selectors }) => {
await navigateToEditor(page, selectors, 'Code', 'prometheus');
const explain = page.getByTestId(selectors.components.DataSource.Prometheus.queryEditor.explain);
await explain.scrollIntoViewIfNeeded();
await expect(explain).toBeVisible();
});
test('should have an editor toggle component', async ({ page, selectors }) => {
await navigateToEditor(page, selectors, 'Code', 'prometheus');
const editorToggle = page.getByTestId(selectors.components.DataSource.Prometheus.queryEditor.editorToggle);
await editorToggle.scrollIntoViewIfNeeded();
await expect(editorToggle).toBeVisible();
});
test('should have an options component with legend, format, step, type and exemplars', async ({
page,
selectors,
}) => {
await navigateToEditor(page, selectors, 'Code', 'prometheus');
// Open options
const options = page.getByTestId(selectors.components.DataSource.Prometheus.queryEditor.options);
await options.scrollIntoViewIfNeeded();
await expect(options).toBeVisible();
await options.click();
// Check options
const legend = page.getByTestId(selectors.components.DataSource.Prometheus.queryEditor.legend);
await legend.scrollIntoViewIfNeeded();
await expect(legend).toBeVisible();
const format = page.getByTestId(selectors.components.DataSource.Prometheus.queryEditor.format);
await format.scrollIntoViewIfNeeded();
await expect(format).toBeVisible();
const step = page.locator('[data-test-id="prometheus-step"]');
await step.scrollIntoViewIfNeeded();
await expect(step).toBeVisible();
const type = page.getByTestId(selectors.components.DataSource.Prometheus.queryEditor.type);
await type.scrollIntoViewIfNeeded();
await expect(type).toBeVisible();
const exemplars = page.getByTestId('prometheus-exemplars');
await exemplars.scrollIntoViewIfNeeded();
await expect(exemplars).toBeVisible();
});
test.describe('Code editor', () => {
test('navigates to the code editor with editor type as code', async ({ page, selectors }) => {
await navigateToEditor(page, selectors, 'Code', 'prometheusCode');
});
test('navigates to the code editor and opens the metrics browser with metric search, labels, label values, and all components', async ({
page,
selectors,
}) => {
await navigateToEditor(page, selectors, 'Code', 'prometheusCode');
await getResources(page);
const queryField = page.getByTestId(selectors.components.DataSource.Prometheus.queryEditor.code.queryField);
await expect(queryField).toBeVisible();
const metricsBrowserButton = page.getByTestId(
selectors.components.DataSource.Prometheus.queryEditor.code.metricsBrowser.openButton
);
await metricsBrowserButton.click();
const selectMetric = page.getByTestId(
selectors.components.DataSource.Prometheus.queryEditor.code.metricsBrowser.selectMetric
);
await expect(selectMetric).toBeVisible();
const labelNamesFilter = page.getByTestId(
selectors.components.DataSource.Prometheus.queryEditor.code.metricsBrowser.labelNamesFilter
);
await expect(labelNamesFilter).toBeVisible();
const labelValuesFilter = page.getByTestId(
selectors.components.DataSource.Prometheus.queryEditor.code.metricsBrowser.labelValuesFilter
);
await expect(labelValuesFilter).toBeVisible();
const useQuery = page.getByTestId(
selectors.components.DataSource.Prometheus.queryEditor.code.metricsBrowser.useQuery
);
await expect(useQuery).toBeVisible();
const useAsRateQuery = page.getByTestId(
selectors.components.DataSource.Prometheus.queryEditor.code.metricsBrowser.useAsRateQuery
);
await expect(useAsRateQuery).toBeVisible();
const validateSelector = page.getByTestId(
selectors.components.DataSource.Prometheus.queryEditor.code.metricsBrowser.validateSelector
);
await expect(validateSelector).toBeVisible();
const clear = page.getByTestId(
selectors.components.DataSource.Prometheus.queryEditor.code.metricsBrowser.clear
);
await expect(clear).toBeVisible();
});
test('selects a metric in the metrics browser and uses the query', async ({ page, selectors }) => {
await navigateToEditor(page, selectors, 'Code', 'prometheusCode');
await getResources(page);
const metricsBrowserButton = page.getByTestId(
selectors.components.DataSource.Prometheus.queryEditor.code.metricsBrowser.openButton
);
await metricsBrowserButton.click();
const selectMetric = page.getByTestId(
selectors.components.DataSource.Prometheus.queryEditor.code.metricsBrowser.selectMetric
);
await expect(selectMetric).toBeVisible();
await selectMetric.fill('met');
const metricList = page.getByTestId(
selectors.components.DataSource.Prometheus.queryEditor.code.metricsBrowser.metricList
);
await expect(metricList).toBeVisible();
const metricOption = metricList.getByText('metric1');
await expect(metricOption).toBeVisible();
await metricOption.click();
const useQuery = page.getByTestId(
selectors.components.DataSource.Prometheus.queryEditor.code.metricsBrowser.useQuery
);
await expect(useQuery).toBeVisible();
await useQuery.click();
const queryField = page.getByTestId(selectors.components.DataSource.Prometheus.queryEditor.code.queryField);
await expect(queryField).toBeVisible();
await expect(queryField).toContainText('metric1');
});
});
test.describe('Query builder', () => {
test('navigates to the query builder with editor type as code', async ({ page, selectors }) => {
await navigateToEditor(page, selectors, 'Builder', 'prometheusBuilder');
});
test('the query builder contains metric select, label filters and operations', async ({ page, selectors }) => {
await navigateToEditor(page, selectors, 'Builder', 'prometheusBuilder');
await getResources(page);
const metricSelect = page.getByTestId(
selectors.components.DataSource.Prometheus.queryEditor.builder.metricSelect
);
await expect(metricSelect).toBeVisible();
const labelSelect = page.getByTestId(selectors.components.QueryBuilder.labelSelect);
await expect(labelSelect).toBeVisible();
const matchOperatorSelect = page.getByTestId(selectors.components.QueryBuilder.matchOperatorSelect);
await expect(matchOperatorSelect).toBeVisible();
const valueSelect = page.getByTestId(selectors.components.QueryBuilder.valueSelect);
await expect(valueSelect).toBeVisible();
});
test('can select a metric and provide a hint', async ({ page, selectors }) => {
await navigateToEditor(page, selectors, 'Builder', 'prometheusBuilder');
await getResources(page);
const metricSelect = page.getByTestId(
selectors.components.DataSource.Prometheus.queryEditor.builder.metricSelect
);
await expect(metricSelect).toBeVisible();
await metricSelect.click();
await page.getByText('metric1').click();
const hints = page.getByTestId(selectors.components.DataSource.Prometheus.queryEditor.builder.hints);
await expect(hints).toContainText('hint: add rate');
});
test('should have the metrics explorer opened via the metric select', async ({ page, selectors }) => {
await navigateToEditor(page, selectors, 'Builder', 'prometheusBuilder');
await getResources(page);
const metricSelect = page.getByTestId(
selectors.components.DataSource.Prometheus.queryEditor.builder.metricSelect
);
await expect(metricSelect).toBeVisible();
await metricSelect.click();
await selectOption(page, 'Metrics explorer', selectors);
const metricsExplorer = page.getByTestId(
selectors.components.DataSource.Prometheus.queryEditor.builder.metricsExplorer
);
await expect(metricsExplorer).toBeVisible();
});
});
}
);
async function selectOption(page: Page, option: string, selectors: E2ESelectorGroups) {
const optionElement = page.getByTestId(selectors.components.Select.option).filter({ hasText: option });
await expect(optionElement).toBeVisible();
await optionElement.click();
}