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

Sarahzinger/config editor e2e 2 #299

Merged
merged 2 commits into from
Apr 5, 2024
Merged
Show file tree
Hide file tree
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
19 changes: 11 additions & 8 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ jobs:
run: |
docker-compose pull
GRAFANA_VERSION=${{ matrix.GRAFANA_IMAGE.VERSION }} GRAFANA_IMAGE=${{ matrix.GRAFANA_IMAGE.NAME }} docker-compose up -d

- name: Wait for Grafana to start
uses: nev7n/wait_for_response@v1
with:
Expand All @@ -67,12 +68,14 @@ jobs:
timeout: 60000
interval: 500

- name: Run Playwright tests
id: run-tests
run: yarn playwright test

- name: Publish report to GCS
if: ${{ github.repository_owner == 'grafana' && (always() && steps.run-tests.outcome == 'success') || (failure() && steps.run-tests.outcome == 'failure') }}
uses: grafana/plugin-actions/publish-report@main
- name: Get secrets for e2e tests and set in env
id: get-secrets
uses: grafana/shared-workflows/actions/get-vault-secrets@main
with:
grafana-version: ${{ matrix.GRAFANA_IMAGE.VERSION }}
repo_secrets: |
AWS_ACCESS_KEY=e2e:AWS_ACCESS_KEY
AWS_SECRET_KEY=e2e:AWS_SECRET_KEY

- name: Run E2E tests
id: run-tests
run: yarn run e2e
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
node_modules/
coverage/
ci/
cypress/report.json
cypress/screenshots/actual
cypress/videos/
dist/
.idea/
.DS_Store
Expand Down
41 changes: 41 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,44 @@ You need to have commit rights to the GitHub repository to publish a release.
2. Update the `CHANGELOG.md` by copy and pasting the relevant PRs from [Github's Release drafter interface](https://github.com/grafana/iot-sitewise-datasource/releases/new) or by running `yarn generate-release-notes` (you'll need to install the [gh cli](https://cli.github.com/) and [jq](https://jqlang.github.io/jq/) to run this command).
3. PR the changes.
4. Once merged, follow the Drone release process that you can find [here](https://github.com/grafana/integrations-team/wiki/Plugin-Release-Process#drone-release-process)

## E2E Tests

This plugin uses [playwright](https://playwright.dev/) and [@grafana/plugin-e2e](https://github.com/grafana/plugin-tools/tree/main/packages/plugin-e2e) for e2e end tests.

To get the best fidelity, we make live requests to AWS for many of our e2e tests. In order to run them you will need to create an AWS User and secret/access keys and add them in either as env variables (`AWS_ACCESS_KEY` and `AWS_SECRET_KEY`) which is how we run our tests in CI or add a yaml file to the provisioning repo like so:

```
apiVersion: 1

deleteDatasources:
- name: sitewise
orgId: 1

datasources:
- name: sitewise
type: grafana-iot-sitewise-datasource
editable: true
jsonData:
authType: keys
defaultRegion: us-east-1
secureJsonData:
accessKey: {your access key here}
secretKey: {your secret key here}
```

### Running e2e tests locally

To run e2e tests locally:

```
yarn run e2e
```

This will then print out a report that can be viewed. Or To run e2e tests locally with [UI mode](https://playwright.dev/docs/test-ui-mode) for easier debugging:

```
yarn run e2e:debug
```

You may also wish to enable "traces" in the playwright.config.ts file which will show screenshots of failures and network requests.
1 change: 0 additions & 1 deletion cspell.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"language": "en",
"ignorePaths": [
"coverage/**",
"cypress/**",
"dist/**",
"go.sum",
"mage_output_file.go",
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
"scripts": {
"build": "webpack -c ./.config/webpack/webpack.config.ts --env production",
"dev": "webpack -w -c ./.config/webpack/webpack.config.ts --env development",
"e2e": "yarn exec cypress install && yarn exec grafana-e2e run",
"e2e:update": "yarn exec cypress install && yarn exec grafana-e2e run --update-screenshots",
"generate-release-notes": "PREV_TAG=$(git tag | tail -n 1) && gh api --method POST /repos/grafana/iot-sitewise-datasource/releases/generate-notes -f tag_name=v${npm_package_version} -f target_commitish=main -f previous_tag_name=${PREV_TAG} | jq -r .body",
"lint": "eslint --cache --ignore-path ./.gitignore --ext .js,.jsx,.ts,.tsx .",
"lint:fix": "yarn run lint --fix",
Expand All @@ -18,6 +16,8 @@
"typecheck": "tsc --noEmit",
"test:coverage": "jest --coverage",
"test:coverage:changes": "jest --coverage --changedSince=origin/main",
"e2e:debug": "npx playwright test --ui",
"e2e": "npx playwright test",
"watch": "webpack -w -c ./.config/webpack/webpack.config.ts --env development"
},
"repository": "github:grafana/iot-sitewise-datasource",
Expand Down
87 changes: 87 additions & 0 deletions tests/configEditor.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { test, expect, ReadProvisionedDataSourceArgs, DataSourceSettings } from '@grafana/plugin-e2e';
import { SitewiseOptions, SitewiseSecureJsonData } from '../src/types';

test.describe('ConfigEditor', () => {
test('invalid credentials should return a 400 status code', async ({ createDataSourceConfigPage, page }) => {
// create a new datasource and navigate to config page
const configPage = await createDataSourceConfigPage({ type: 'grafana-iot-sitewise-datasource' });

// fill in the config form
await page.getByLabel(/^Authentication Provider/).fill('Access & secret key');
await page.keyboard.press('Enter');
await page.getByLabel('Access Key ID').fill('bad1credentials');
await page.getByLabel('Secret Access Key').fill('very-bad-credentials');
await page.getByLabel('Default Region').fill('us-east-1');
await page.keyboard.press('Enter');

// click save and test
const response = await configPage.saveAndTest();

// expect network response have error
const body = await response.json();
expect(body).toHaveProperty('status', 'ERROR');
expect(body.message).toContain('invalid');

// expect error to be shown in the UI
const errorMessage = page.getByText('The security token included in the request is invalid');
expect(errorMessage).toBeVisible();
});

test('valid credentials should return a 200 status code', async ({
createDataSourceConfigPage,
readProvisionedDataSource,
page,
}) => {
const { accessKey, secretKey } = await getTestCredentials(readProvisionedDataSource);

// create a new datasource and navigate to config page
const configPage = await createDataSourceConfigPage({ type: 'grafana-iot-sitewise-datasource' });

// fill in the config form
await page.getByLabel(/^Authentication Provider/).fill('Access & secret key');
await page.keyboard.press('Enter');
await page.getByLabel('Access Key ID').fill(accessKey);
await page.getByLabel('Secret Access Key').fill(secretKey);
await page.getByLabel('Default Region').fill('us-east-1');
await page.keyboard.press('Enter');

// click save and test
const response = await configPage.saveAndTest();

// expect network response have success message
const body = await response.json();
expect(body).toHaveProperty('status', 'OK');

// expect success message to be shown in the UI
const successMessage = page.getByText('OK');
expect(successMessage).toBeVisible();
});
});

async function getTestCredentials(
readProvisionedDataSource: <T = {}, S = {}>(args: ReadProvisionedDataSourceArgs) => Promise<DataSourceSettings<T, S>>
) {
// get access key from env (in ci) or from provisioning repo (if running e2e test locally)
let accessKey = '';
let secretKey = '';
if (process.env.AWS_ACCESS_KEY && process.env.AWS_SECRET_KEY) {
accessKey = process.env.AWS_ACCESS_KEY;
secretKey = process.env.AWS_SECRET_KEY;
} else {
try {
const ds = await readProvisionedDataSource<SitewiseOptions, SitewiseSecureJsonData>({
fileName: 'iot-sitewise.yaml',
});
if (!ds.secureJsonData || !ds.secureJsonData.accessKey || !ds.secureJsonData.secretKey) {
throw new Error('Provisioned datasource does not have valid credentials');
}
accessKey = ds.secureJsonData.accessKey;
secretKey = ds.secureJsonData.secretKey;
} catch (err) {
throw new Error(
'Missing valid credentials for e2e tests. Please provide AWS_ACCESS_KEY and AWS_SECRET_KEY in the environment variables or provision a datasource with valid credentials in the provisioning repo.'
);
}
}
return { accessKey, secretKey };
}
Loading