跳到主要内容

测试面板插件

面板插件允许您以不同的方式可视化数据。 本指南向您展示如何使用 @grafana/plugin-e2e 来测试您的面板插件在多个 Grafana 版本中正确呈现数据。

测试数据

为了能够测试您的面板插件,您需要为其提供测试数据。 Grafana 附带 TestData 数据源,该数据源可用于模拟格式化为时间序列、日志、跟踪、注释等的 数据帧

在您开始之前

要编写类似于本指南中的端到端测试,您需要使用配置来配置 TestData 数据源。 如果您尚未阅读我们关于如何 设置资源 的指南,请先阅读该指南。

测试面板选项

为了测试面板的行为,我们建议配置一个仪表板,其中包含多个面板,展示面板的不同状态。 这确保您的面板在各种配置下都能正常运行。 通过避免依赖 Grafana 面板编辑 UI,此方法减少了由 UI 更改引起的测试失败,使您的测试更加稳定可靠。

在需要与面板编辑选项交互的情况下,我们提供了一组 API 来简化编写测试。 这些 API 确保您的测试在不同版本的 Grafana 中一致运行,而无需进行更改。

要与任何 Grafana 提供的选项组交互,请使用以下任何函数

函数名称返回的选项组
getPanelOptions()面板选项
getStandardOptions()标准选项
getValueMappingOptions()值映射
getDataLinksOptions()数据链接
getThresholdsOptions()阈值

要与面板添加的自定义选项组交互,请使用 getCustomOptions('选项组名称') API。

调用这些 API 中的任何一个都会返回一个选项组对象,该对象提供用于与该组内选项交互的 API。

函数名称返回选项类型
getRadioGroup(label)RadioGroup
getSwitch(label)Switch
getTextInput(label)Locator
getNumberInput(label)Locator
getSliderInput(label)Locator
getSelect(label)Select
getMultiSelect(label)MultiSelect
getColorPicker(label)ColorPicker
getUnitPicker(label)UnitPicker

示例

此测试确保当用户从标准选项中选择不同的单位时,UI 中显示的单位会正确更新。

test('should change the unit when standard option is changed', async ({ panelEditPage }) => {
const standardOptions = panelEditPage.getStandardOptions();
const unitPicker = standardOptions.getUnitPicker('Unit');
const unit = page.getByTestId('unit-container');

await unitPicker.selectOption('Misc > Pixels');

await expect(unit).toContainText('px');
});

此测试验证在面板设置中选择不同的时区会更新时钟面板中显示的时区。

test('should change time zone when option is selected', async ({ panelEditPage, page }) => {
const timeFormatOptions = panelEditPage.getCustomOptions('Timezone');
const timeZoneSelect = timeFormatOptions.getSelect('Timezone');
const timeZone = page.getByTestId('clock-panel').getByTestId('time-zone');

await timeZoneSelect.selectOption('Europe/Stockholm');
await expect(timeZone).toContainText('Europe/Stockholm');
});

此测试验证在 Clock 面板中启用等宽字体选项是否正确地将面板的字体系列更新为“monospace”。

test('should change the font family when enabling monospace', async ({ panelEditPage, page }) => {
const clockOptions = panelEditPage.getCustomOptions('Clock');
const monospaceFont = clockOptions.getSwitch('Font monospace');
const panel = page.getByTestId('clock-panel');

await monospaceFont.check();
await expect(panel).toHaveCSS('font-family', 'monospace');
});

此测试确保当在时钟面板的选项中选择“倒计时”模式时,时钟以倒计时模式运行。

test('should count down time when option is selected', async ({ panelEditPage, page }) => {
const clockOptions = panelEditPage.getCustomOptions('Clock');
const clockMode = clockOptions.getRadioGroup('Mode');
const panel = page.getByTestId('clock-panel-countdown');

await clockMode.check('Countdown');
await expect(panel).toBeVisible();
});

此测试验证当从面板选项中的颜色选择器中选择新颜色时,面板的背景颜色会发生变化。

test('should update background color based on selected option', async ({ panelEditPage, page }) => {
const color = { hex: '#73bf69', rgb: 'rgb(115, 191, 105)' };
const clockOptions = panelEditPage.getCustomOptions('Clock');
const backgroundColor = clockOptions.getColorPicker('Background color');
const panel = page.getByTestId('clock-panel');

await backgroundColor.selectOption(color.hex);
await expect(panel).toHaveCSS('background-color', color.rgb);
});

表格面板默认定义一个名为 Show table header 的自定义面板选项。 如果禁用该开关,表格面板应从表格中删除标题。

以下测试验证默认情况下显示字段名称(标题),并且在未选择 Show table header 选项时将其删除

test('should hide headers when "Show table header" is unchecked', async ({ panelEditPage, selectors }) => {
await panelEditPage.datasource.set('gdev-testdata');
await panelEditPage.setVisualization('Table');
await expect(await panelEditPage.panel.fieldNames.count()).toBeGreaterThan(0);
const showTableHeaderSwitch = panelEditPage
.getByGrafanaSelector(selectors.components.PanelEditor.OptionsPane.fieldLabel('Table Show table header'))
.getByLabel('Toggle switch');
await panelEditPage.collapseSection('Table');
await showTableHeaderSwitch.uncheck();
await expect(panelEditPage.panel.fieldNames).not.toBeVisible();
});

测试面板如何处理不同的数据类型

数据帧模型在设计上是灵活的。 其目的是允许数据源根据各种不同的 数据类型 返回查询响应。 Grafana 框架中的数据类型定义或声明包括种类和格式。

面板不必支持每种数据类型。 但是,如果您的面板应该支持某种数据类型,我们建议您编写端到端测试来验证它是否按预期工作。

“无数据”场景

如果数据源返回 No Data,那么最好向用户指示这一点。 在以下代码片段中,我们测试表格面板如何处理 No Data 场景

test('should display "No data" in case no data response was passed to the panel', async ({ panelEditPage, page }) => {
await panelEditPage.datasource.set('gdev-testdata');
await panelEditPage.setVisualization('Table');
await page.getByLabel('Scenario').last().click();
await page.getByText('No Data Points').click();
await panelEditPage.refreshPanel();
await expect(panelEditPage.panel.locator).toContainText('No data');
});

多个帧

表格面板一次只能显示一个帧。 如果将多个帧传递到面板,无论是来自同一查询还是来自不同查询,面板都只显示第一个帧。

此外,面板中还会有一个下拉菜单,允许用户在不同的帧之间切换。 此行为是表格面板特有的。

以下代码片段测试插件在将两个帧传递到面板的情况下显示具有两个值的下拉菜单

test('should display dropdown with two values when two frames are passed to the panel', async ({
panelEditPage,
page,
selectors,
}) => {
await panelEditPage.datasource.set('gdev-testdata');
await panelEditPage.setVisualization('Table');
await panelEditPage.getQueryEditorRow('A').getByLabel('Alias').fill('a');
await page.getByText('Add query').click();
await panelEditPage.getQueryEditorRow('B').getByLabel('Alias').fill('b');
await panelEditPage.refreshPanel();
await panelEditPage.panel.locator.getByRole('combobox').click();
await expect(panelEditPage.getByTestIdOrAriaLabel(selectors.components.Select.option)).toHaveText(['a', 'b']);
});