Skip to content

Commit

Permalink
Add e2e smoke tests (#336)
Browse files Browse the repository at this point in the history
  • Loading branch information
kevinwcyu authored Dec 20, 2024
1 parent 7908a32 commit 28c8601
Show file tree
Hide file tree
Showing 12 changed files with 260 additions and 24 deletions.
78 changes: 78 additions & 0 deletions .github/workflows/e2e-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
name: E2E tests
on:
pull_request:
schedule:
- cron: '0 11 * * *' #once a day at 11 UTC

permissions:
contents: read
id-token: write

jobs:
resolve-versions:
name: Resolve Grafana images
runs-on: ubuntu-latest
timeout-minutes: 3
outputs:
matrix: ${{ steps.resolve-versions.outputs.matrix }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Resolve Grafana E2E versions
id: resolve-versions
uses: grafana/plugin-actions/e2e-version@main
with:
version-resolver-type: version-support-policy

playwright-tests:
needs: resolve-versions
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
GRAFANA_IMAGE: ${{fromJson(needs.resolve-versions.outputs.matrix)}}
name: e2e ${{ matrix.GRAFANA_IMAGE.name }}@${{ matrix.GRAFANA_IMAGE.VERSION }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Node.js environment
uses: actions/setup-node@v4
with:
node-version-file: .nvmrc

- name: Install yarn dependencies
run: yarn install

- name: Install Mage
uses: magefile/mage-action@v3
with:
install-only: true

- name: Build binaries
run: mage -v build:linux

- name: Build frontend
run: yarn build

- name: Install Playwright Browsers
run: yarn playwright install --with-deps

- name: Start Grafana
run: |
docker compose pull
GRAFANA_VERSION=${{ matrix.GRAFANA_IMAGE.VERSION }} GRAFANA_IMAGE=${{ matrix.GRAFANA_IMAGE.NAME }} docker compose up -d --wait --wait-timeout 60
- name: Run Playwright tests
id: run-tests
run: yarn playwright test

# Uncomment this step to upload the Playwright report to Github artifacts.
# If your repository is public, the report will be public on the Internet so beware not to expose sensitive information.
# - name: Upload artifacts
# uses: actions/upload-artifact@v4
# if: ${{ (always() && steps.run-tests.outcome == 'success') || (failure() && steps.run-tests.outcome == 'failure') }}
# with:
# name: playwright-report-${{ matrix.GRAFANA_IMAGE.NAME }}-v${{ matrix.GRAFANA_IMAGE.VERSION }}-${{github.run_id}}
# path: playwright-report/
# retention-days: 30
10 changes: 6 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,12 @@ build/
# nodenv
.node-version

#e2e testing
cypress/videos
cypress/report.json
cypress/screenshots/actual
# End to end tests
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
/playwright/.auth/

# Editor
.idea
Expand Down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ You need to have commit rights to the GitHub repository to publish a release.
1. Update the version number in the `package.json` file.
2. Update the `CHANGELOG.md` by copy and pasting the relevant PRs from [Github's Release drafter interface](https://github.com/grafana/grafana-iot-twinmaker-app/releases/new) or by running `npm run generate-release-notes`.
3. PR the changes.
4. Let the AWS TwinMaker team know that you are planning a release so they can test it first. You can do this by tagging them in the release PR.
4. Let the AWS TwinMaker team know that you are planning a release so they can test it first. You can do this by tagging them in the release PR.
5. 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)

## Install
Expand All @@ -59,3 +59,9 @@ a. This container will mount the volume `~/.aws:/usr/share/grafana/.aws` with th
By default, the webpack mode is set to `production` to work with the released Grafana production build.

To build the plugin with `development` mode, change the mode in [webpack.config.js](https://github.com/grafana/grafana-iot-twinmaker-app/blob/main/webpack.config.js) file to be `development`, and start the development mode local Grafana server following [Grafana Developer Guide](https://github.com/grafana/grafana/blob/main/contribute/developer-guide.md#build-grafana)

## E2E tests

1. `yarn playwright install --with-deps`
1. `yarn server`
1. `yarn e2e`
5 changes: 5 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,12 @@ services:
build:
context: ./.config
args:
grafana_image: ${GRAFANA_IMAGE:-grafana-enterprise}
grafana_version: ${GRAFANA_VERSION:-8.4.0}
healthcheck:
test: curl -f http://localhost:3000 || exit 1
start_period: 30s
start_interval: 500ms
ports:
- 3000:3000/tcp
volumes:
Expand Down
7 changes: 7 additions & 0 deletions e2e/configEditor.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { test, expect } from '@grafana/plugin-e2e';

test('should render config editor', async ({ createDataSourceConfigPage, readProvisionedDataSource, page }) => {
const ds = await readProvisionedDataSource({ fileName: 'aws-iot-twinmaker.yaml', name: 'AWS IoT TwinMaker' });
await createDataSourceConfigPage({ type: ds.type });
await expect(page.getByTestId('connection-config')).toBeVisible();
});
6 changes: 6 additions & 0 deletions e2e/queryEditor.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { test, expect } from '@grafana/plugin-e2e';

test('should render query editor', async ({ panelEditPage, selectors }) => {
await panelEditPage.datasource.set('AWS IoT TwinMaker');
await expect(panelEditPage.getQueryEditorRow('A').getByLabel('Query Type')).toBeVisible();
});
6 changes: 6 additions & 0 deletions e2e/variableEditor.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { expect, test } from '@grafana/plugin-e2e';

test('should render variable editor', async ({ variableEditPage, page }) => {
await variableEditPage.datasource.set('AWS IoT TwinMaker');
await expect(page.getByLabel('Query Type')).toBeVisible();
});
25 changes: 14 additions & 11 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"build": "NODE_OPTIONS='--max-old-space-size=4096' webpack -c ./webpack.config.ts --env production",
"clean": "rm -rf dist/ build/*",
"dev": "webpack -w -c ./webpack.config.ts --env development",
"e2e": "playwright test",
"generate-release-notes": "PREV_TAG=$(git tag | tail -n 1) && gh api --method POST /repos/grafana/grafana-iot-twinmaker-app/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 @@ -23,7 +24,10 @@
"devDependencies": {
"@babel/core": "^7.26.0",
"@grafana/eslint-config": "^8.0.0",
"@grafana/plugin-e2e": "^1.14.0",
"@grafana/tsconfig": "^2.0.0",
"@playwright/test": "^1.49.1",
"@stylistic/eslint-plugin-ts": "^2.9.0",
"@swc/core": "^1.10.1",
"@swc/helpers": "^0.5.15",
"@swc/jest": "^0.2.37",
Expand All @@ -39,11 +43,18 @@
"@types/testing-library__jest-dom": "6.0.0",
"@types/three": "0.170.0",
"@types/uuid": "^10.0.0",
"@typescript-eslint/eslint-plugin": "^6.18.0",
"@typescript-eslint/parser": "^6.18.0",
"copy-webpack-plugin": "^12.0.2",
"cspell": "^8.16.1",
"css-loader": "^7.1.2",
"eslint": "^8.0.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-deprecation": "^3.0.0",
"eslint-plugin-jsdoc": "^46.8.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react": "^7.33.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-webpack-plugin": "^4.0.1",
"file-loader": "^6.2.0",
"fork-ts-checker-webpack-plugin": "^9.0.2",
Expand All @@ -60,22 +71,14 @@
"sass-loader": "16.0.4",
"style-loader": "4.0.0",
"swc-loader": "^0.2.6",
"terser-webpack-plugin": "^5.3.10",
"ts-node": "^10.9.2",
"tsconfig-paths": "^4.2.0",
"typescript": "5.7.2",
"webpack": "^5.97.1",
"webpack-cli": "^5.1.4",
"webpack-livereload-plugin": "^3.0.2",
"webpack-shell-plugin-next": "^2.3.2",
"@stylistic/eslint-plugin-ts": "^2.9.0",
"@typescript-eslint/eslint-plugin": "^6.18.0",
"@typescript-eslint/parser": "^6.18.0",
"eslint": "^8.0.0",
"eslint-config-prettier": "^8.8.0",
"eslint-plugin-jsdoc": "^46.8.0",
"eslint-plugin-react": "^7.33.0",
"eslint-plugin-react-hooks": "^4.6.0",
"terser-webpack-plugin": "^5.3.10",
"webpack-subresource-integrity": "^5.1.0",
"webpack-virtual-modules": "^0.6.2"
},
Expand Down Expand Up @@ -107,9 +110,9 @@
"react-dom": "18.2.0",
"react-router-dom": "^7.0.2",
"react-use": "^17.5.1",
"rxjs": "7.8.1",
"tslib": "2.8.1",
"uuid": "^11.0.3",
"rxjs": "7.8.1"
"uuid": "^11.0.3"
},
"engines": {
"node": ">=20"
Expand Down
57 changes: 57 additions & 0 deletions playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { dirname } from 'path';
import { defineConfig, devices } from '@playwright/test';
import type { PluginOptions } from '@grafana/plugin-e2e';

const pluginE2eAuth = `${dirname(require.resolve('@grafana/plugin-e2e'))}/auth`;

/**
* Read environment variables from file.
* https://github.com/motdotla/dotenv
*/
// import dotenv from 'dotenv';
// import path from 'path';
// dotenv.config({ path: path.resolve(__dirname, '.env') });

/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig<PluginOptions>({
testDir: './e2e',
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: 'html',
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: 'http://localhost:3000',

/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: 'on-first-retry',
},

/* Configure projects for major browsers */
projects: [
{
name: 'auth',
testDir: pluginE2eAuth,
testMatch: [/.*\.js/],
},
{
name: 'run-tests',
use: {
...devices['Desktop Chrome'],
// @grafana/plugin-e2e writes the auth state to this file,
// the path should not be modified
storageState: 'playwright/.auth/admin.json',
},
dependencies: ['auth'],
},
],
});
19 changes: 19 additions & 0 deletions provisioning/datasources/aws-iot-twinmaker.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
apiVersion: 1

deleteDatasources:
- name: AWS IoT TwinMaker
orgId: 1

datasources:
- name: AWS IoT TwinMaker
type: grafana-iot-twinmaker-datasource
enabled: true
jsonData:
authType: keys
defaultRegion: us-east-1
assumeRoleArn: $ASSUME_ROLE_ARN
workspaceId: $WORKSPACE_ID
secureJsonData:
accessKey: $ACCESS_KEY
secretKey: $SECRET_KEY
version: 1
3 changes: 2 additions & 1 deletion src/datasource/components/VariableQueryEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,9 @@ export default function VariableQueryEditor(props: Props) {
return (
<>
<InlineFieldRow>
<InlineField label="Query Type" labelWidth={20} grow={true}>
<InlineField htmlFor="query-type" label="Query Type" labelWidth={20} grow={true}>
<Select
inputId="query-type"
menuShouldPortal={true}
options={variableQueryTypes}
value={variableQueryTypes.find((v) => v.value === query.queryType) ?? variableQueryTypes[0]}
Expand Down
Loading

0 comments on commit 28c8601

Please sign in to comment.