Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs: Plugin E2E - Add Setup Resources article #748

Merged
merged 16 commits into from
Feb 20, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions docusaurus/docs/e2e-test-a-plugin/setup-resources.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
id: setup-resources
title: Configure the resources you need
sunker marked this conversation as resolved.
Show resolved Hide resolved
description: Configure any dashboards, data sources or other Grafana resources necessary for end-to-end testing your plugin, through provisioning.
keywords:
- grafana
- plugins
- plugin
- testing
- e2e
- end-to-end
- data-source
- preparation
sunker marked this conversation as resolved.
Show resolved Hide resolved
- provisioning
sidebar_position: 60
---

## Introduction

In many cases, you'll need certain resources to be configured in Grafana before you can run your end-to-end tests. For example, to test how a panel plugin displays data, you'll need a data source configured to query and return that data. This guide covers how to setup the resources that you need through [provisioning](https://grafana.com/docs/grafana/latest/administration/provisioning/).

### Test isolation

[Test isolation](https://playwright.dev/docs/browser-contexts#what-is-test-isolation) is a central part of Playwright testing. On this subject, we recommend testing plugin features independently and not run through advanced flows where certain steps have dependencies to the previous steps.

#### A concrete example

Let's say you want to test template variable interpolation in your data source plugin. For any interpolation to take place in the DataSource file, there needs to be a template variable defined. Since the goal is to test variable interpolation, we don't want to create the template variable within the test code. A better approach is to open a provisioned dashboard that has a template variable defined already and use that in our test.

In the following example, we navigate to a provisioned dashboard. The dashboard has a multi-valued template variable `env` with the values `test` and `prod`. We add a new panel and set a SQL query that refers to the `env` variable. We then spy on the query data request, asserting that it was called with the expanded values associated with the template variable.

```ts
test('should expand multi-valued variable before calling backend', async ({
readProvision,
request,
page,
selectors,
grafanaVersion,
}) => {
const dashboard = await readProvisionDashboard({ fileName: 'variable.json' });
const dashboardPage = new DashboardPage({ request, page, selectors, grafanaVersion }, dashboard);
await dashboardPage.goto();
const panelEditPage = await dashboardPage.addPanel();
const queryDataSpy = panelEditPage.waitForQueryDataRequest((request) =>
(request.postData() ?? '').includes(`select * from dataset where env in ('test', 'prod')"`)
);
await page.getByLabel('Query').fill('select * from dataset where env in (${env:singlequote})');
await panelEditPage.refreshPanel();
await expect(await queryDataSpy).toBeTruthy();
});
```

### Provision any required resources

You can use [provisioning](https://grafana.com/docs/grafana/latest/administration/provisioning/) to configure resources such as dashboards and data sources.

:::note
If running end-to-end tests in CI requires provisioning, you may need to remove the `provisioning` folder from your plugin's `.gitignore` file.
:::

:::danger Be careful not to commit secrets to public repositories. Use [environment variable](https://grafana.com/docs/grafana/latest/administration/provisioning/#using-environment-variables) interpolation for sensitive data.
:::

### Read provisioned files

`@grafana/plugin-e2e` provides fixtures that enables you to read files that you have placed in the `provisioning` folder.
sympatheticmoose marked this conversation as resolved.
Show resolved Hide resolved

#### `readProvisionedDataSource` fixture

The `readProvisionedDataSource` fixture allows you to read a file from your plugin's `provisioning/datasources` folder. This gives you typings and it also allows you to keep data source configuration in one place.

```ts title="configEditor.spec.ts"
const datasource = readProvisionedDataSource<JsonData, SecureJsonData>({ fileName: 'datasources.yml' });
await page.getByLabel('API Key').fill(datasource.secureJsonData.apiKey);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Above we claim it's dangerous to commit secrets to public repos and to use env vars for sensitive data but here we grab an API key from a datasources.yml file. Am I wrong or is this example contradicting the advice above?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As long as secrets are being defined with environment variables in the provisioned file it should be fine. Look at this example for the google-sheets datasource:

datasources:
  - editable: true
    enabled: true
    jsonData:
      authType: jwt
    name: Google Sheets Service Account
    secureJsonData:
      jwt: ${GOOGLE_JWT_FILE}
    type: grafana-googlesheets-datasource
    version: 1

```

```ts title="queryEditor.spec.ts"
const datasource = readProvisionedDataSource({ fileName: 'datasources.yml' });
await panelEditPage.datasource.set(datasource.name);
```

#### `readProvisionedDashboard` fixture

The `readProvisionedDashboard` fixture allows you to read the content of a dashboard JSON file from your `provisioning/dashboards` folder. It can be useful when navigating to a provisioned dashboard and you don't want to hard code the dashboard UID.

```ts title="variableEditPage.spec.ts"
const dashboard = await readProvisionedDashboard({ fileName: 'dashboard.json' });
const variableEditPage = new VariableEditPage({ request, page, selectors, grafanaVersion }, { dashboard, id: '2' });
await variableEditPage.goto();
```
Loading