测试数据查询
介绍
查询编辑器是数据源插件的核心部分,因为这是用户构建用于获取数据的查询的地方。您的数据源插件可以提供一个丰富的查询编辑器,允许针对不同 API 的各种查询类型。您的查询编辑器甚至可以具有视觉查询构建器、IntelliSense 和自动完成等功能。
测试查询编辑器是否加载
以下示例是一个简单的烟测试,用于验证数据源查询编辑器是否加载
import { test, expect } from '@grafana/plugin-e2e';
test('should render query editor', async ({ panelEditPage, readProvisionedDataSource }) => {
const ds = await readProvisionedDataSource({ fileName: 'datasources.yml' });
await panelEditPage.datasource.set(ds.name);
await expect(panelEditPage.getQueryEditorRow('A').getByRole('textbox', { name: 'Query Text' })).toBeVisible();
});
独立测试查询编辑器的部分
在以下示例中,查询编辑器通过向 /regions
发送请求加载区域,并在下拉菜单中填充之前过滤掉包含 gov
的那些区域。
<page>.mockResourceResponse
方法允许您模拟对数据源 资源 API 的请求的响应。为了测试过滤是否按预期工作,我们使用此方法模拟 /regions
响应并断言当点击区域下拉菜单时,只显示名称中不包含 -gov-
的区域。
test('should filter out govcloud regions', async ({ panelEditPage, selectors, readProvisionedDataSource }) => {
const regionsMock = ['us-gov-west-1', 'us-east-1', 'us-west-1', 'us-gov-east-1'];
const expectedRegions = ['us-east-1', 'us-west-1'];
const ds = await readProvisionedDataSource({ fileName: 'datasources.yaml' });
await panelEditPage.datasource.set(ds.name);
await panelEditPage.mockResourceResponse('regions', regionsMock);
await panelEditPage.getQueryEditorRow('A').getByText('Regions').click();
await expect(panelEditPage.getByGrafanaSelector(selectors.components.Select.option)).toHaveText(expectedRegions);
});
测试整个数据流
以下示例展示了测试插件整个查询数据流的集成测试。
在端到端测试中调用第三方API可能会有用,但也可能存在安全问题,并可能导致您的CI管道出现不可靠性。您应该仔细考虑,并考虑使用模拟代替。
test('data query should be successful when the query is valid', async ({
panelEditPage,
readProvisionedDataSource,
}) => {
const ds = await readProvisionedDataSource({ fileName: 'datasources.yaml' });
await panelEditPage.datasource.set(ds.name);
await panelEditPage.getQueryEditorRow('A').getByText('Query Text').fill('SELECT * FROM dataset');
await expect(panelEditPage.refreshPanel()).toBeOK();
});
创建面板数据断言
在许多情况下,断言数据查询响应是OK的并不能完全说明您的数据源插件正在正常工作。您还必须对面板中显示的数据进行断言。
Grafana附带了一套内置面板,您可以在Grafana插件目录中找到各种社区面板。每个面板都可以以不同的方式渲染数据,因此无法提供一种一致的方法来对所有面板的显示数据进行断言。因此,我们建议您使用Table
面板。
<page>.panel.data
属性返回一个Playwright定位器,它可以解析一个或多个包含当前在Table面板中显示的值的元素。这意味着您可以使用任何接受定位器作为接收类型的自动重试匹配器。
test('data query should return values 10 and 20', async ({ panelEditPage, readProvisionedDataSource }) => {
const ds = await readProvisionedDataSource({ fileName: 'datasources.yml' });
await panelEditPage.datasource.set(ds.name);
await panelEditPage.setVisualization('Table');
await expect(panelEditPage.refreshPanel()).toBeOK();
await expect(panelEditPage.panel.data).toContainText(['10', '20']);
});
如果您想断言在Table
面板中显示的列标题,可以使用<page>.panel.fieldNames
属性。
test('data query should return headers and 3', async ({ panelEditPage, readProvisionedDataSource }) => {
const ds = await readProvisionedDataSource({ fileName: 'datasources.yml' });
await panelEditPage.datasource.set(ds.name);
await panelEditPage.setVisualization('Table');
await expect(panelEditPage.refreshPanel()).toBeOK();
await expect(panelEditPage.panel.fieldNames).toHaveText(['Stockholm', 'Vienna']);
});
在已配置的仪表板上测试查询
有时您可能想打开现有面板的编辑页面并运行查询,以确保一切按预期工作。
test('query in provisioned dashboard should return temp and humidity data', async ({
readProvisionedDashboard,
gotoPanelEditPage,
}) => {
const dashboard = await readProvisionedDashboard({ fileName: 'dashboard.json' });
const panelEditPage = await gotoPanelEditPage({ dashboard, id: '3' });
await expect(panelEditPage.refreshPanel()).toBeOK();
await expect(panel.fieldNames).toContainText(['temperature', 'humidity']);
await expect(panel.data).toContainText(['25', '10']);
});
您还可以打开已存在的仪表板并验证表格面板是否已渲染您预期的数据。
test('getting panel by id', async ({ gotoDashboardPage, readProvisionedDashboard }) => {
const dashboard = await readProvisionedDashboard({ fileName: 'dashboard.json' });
const dashboardPage = await gotoDashboardPage(dashboard);
const panel1 = await dashboardPage.getPanelById('3');
await expect(panel1.data).toContainText(['25', '32', 'staging']);
const panel2 = await dashboardPage.getPanelByTitle('Basic table example');
await expect(dashboardPage.panel2.fieldNames).toContainText(['Tokyo', 'Berlin']);
});