Skip to content

Commit

Permalink
base E2E test suite using playwright
Browse files Browse the repository at this point in the history
  • Loading branch information
yesoreyeram committed Jan 18, 2024
1 parent 381cdee commit 8a9417e
Show file tree
Hide file tree
Showing 10 changed files with 302 additions and 29 deletions.
73 changes: 73 additions & 0 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: E2E Tests
on:
pull_request:
path-ignore:
- 'docs/**'
branches:
- main
push:
path-ignore:
- 'docs/**'
branches:
- main
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
jobs:
test:
timeout-minutes: 60
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Go environment
uses: actions/setup-go@v4
with:
go-version: '1.21.6'
- name: Test backend
uses: magefile/mage-action@v2
with:
version: latest
args: coverage
- name: Build backend
uses: magefile/mage-action@v2
with:
version: latest
args: buildAll
- name: Setup Node
uses: actions/setup-node@v3
with:
node-version: 20
- name: Install dependencies
run: npm install -g yarn && yarn install --frozen-lockfile;
- name: Spellcheck
run: |
yarn spellcheck;
- name: Build Frontend
run: |
yarn build;
- name: Start the docker container for E2E
run: |
docker-compose pull
docker-compose up -d
- name: Wait for grafana to start
uses: nev7n/wait_for_response@v1
with:
url: 'http://localhost:3000/'
responseCode: 200
timeout: 20000
interval: 500
- name: Install Playwright Browsers
run: yarn playwright install --with-deps
- name: Run E2E tests
run: yarn test:e2e
- name: Run E2E artifacts
uses: actions/upload-artifact@v3
if: always()
with:
name: playwright-report
path: playwright-report/
retention-days: 30
- name: Stop the docker container
if: always()
run: docker-compose down
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,9 @@ website/next-env.d.ts
work/
yarn-debug.log*
yarn-error.log*
docker/blocks/tempo/tempo-data
docker/blocks/tempo/tempo-data
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
/playwright/.auth/
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
18
20
4 changes: 2 additions & 2 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ services:
- GF_DEFAULT_APP_MODE=development
- GF_AUTH_ANONYMOUS_ENABLED=true
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
- GF_SECURITY_ADMIN_USER=infinity
- GF_SECURITY_ADMIN_PASSWORD=infinity
# - GF_SECURITY_ADMIN_USER=infinity
# - GF_SECURITY_ADMIN_PASSWORD=infinity
- GF_SECURITY_ANGULAR_SUPPORT_ENABLED=false
- GF_SECURITY_CSRF_ALWAYS_CHECK=true
- GF_ENTERPRISE_LICENSE_TEXT=$GF_ENTERPRISE_LICENSE_TEXT
5 changes: 5 additions & 0 deletions e2e/auth.setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { test as setup } from '@grafana/plugin-e2e';

setup('authenticate', async ({ login }) => {
await login();
});
80 changes: 80 additions & 0 deletions e2e/query.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { test, expect } from '@grafana/plugin-e2e';
import { runQuery } from './query';

test('test type:json source:url', async ({ page, panelEditPage }) => {
await panelEditPage.datasource.set('Infinity');
await panelEditPage.setVisualization('Table');
const queryEditorRow = await panelEditPage.getQueryEditorRow('A');

let frames = await runQuery(page, panelEditPage, queryEditorRow, {});
expect(frames.results['A'].frames[0].schema.name).toBe('A');
expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe(''); // Ensure the parser type passed correctly
expect(frames.results['A'].frames[0].schema.meta.custom.data[0].country).toBe('USA'); // Ensure schema meta have actual data to be passed to the frontend
await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered

frames = await runQuery(page, panelEditPage, queryEditorRow, { parser: 'backend' });
expect(frames.results['A'].frames[0].schema.name).toBe('A');
expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe('backend'); // Ensure the parser type passed correctly
expect(frames.results['A'].frames[0].data.values[1][0]).toBe('USA'); // Ensure actual data frames being returned
await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered

frames = await runQuery(page, panelEditPage, queryEditorRow, { parser: 'uql' });
expect(frames.results['A'].frames[0].schema.name).toBe('A');
expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe('uql'); // Ensure the parser type passed correctly
expect(frames.results['A'].frames[0].schema.meta.custom.data[0].country).toBe('USA'); // Ensure schema meta have actual data to be passed to the frontend
await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered

frames = await runQuery(page, panelEditPage, queryEditorRow, { parser: 'groq' });
expect(frames.results['A'].frames[0].schema.name).toBe('A');
expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe('groq'); // Ensure the parser type passed correctly
expect(frames.results['A'].frames[0].schema.meta.custom.data[0].country).toBe('USA'); // Ensure schema meta have actual data to be passed to the frontend
await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered
});

test('test type:csv source:url', async ({ page, panelEditPage }) => {
await panelEditPage.datasource.set('Infinity');
await panelEditPage.setVisualization('Table');
const queryEditorRow = await panelEditPage.getQueryEditorRow('A');

let frames = await runQuery(page, panelEditPage, queryEditorRow, { type: 'csv', url: 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.csv' });
expect(frames.results['A'].frames[0].schema.name).toBe('A');
expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe(''); // Ensure the parser type passed correctly
expect((frames.results['A'].frames[0].schema.meta.custom.data || '').startsWith('name,age,country,occupation,salary')).toBeTruthy(); // Ensure schema meta have actual data to be passed to the frontend
await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered

frames = await runQuery(page, panelEditPage, queryEditorRow, { type: 'csv', url: 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.csv', parser: 'backend' });
expect(frames.results['A'].frames[0].schema.name).toBe('A');
expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe('backend'); // Ensure the parser type passed correctly
expect(frames.results['A'].frames[0].data.values[1][0]).toBe('USA'); // Ensure actual data frames being returned
await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered

frames = await runQuery(page, panelEditPage, queryEditorRow, { type: 'csv', url: 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.csv', parser: 'uql' });
expect(frames.results['A'].frames[0].schema.name).toBe('A');
expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe('uql'); // Ensure the parser type passed correctly
expect((frames.results['A'].frames[0].schema.meta.custom.data || '').startsWith('name,age,country,occupation,salary')).toBeTruthy(); // Ensure schema meta have actual data to be passed to the frontend
await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered
});

test('test type:xml source:url', async ({ page, panelEditPage }) => {
await panelEditPage.datasource.set('Infinity');
await panelEditPage.setVisualization('Table');
const queryEditorRow = await panelEditPage.getQueryEditorRow('A');

let frames = await runQuery(page, panelEditPage, queryEditorRow, { type: 'xml', url: 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.xml' });
expect(frames.results['A'].frames[0].schema.name).toBe('A');
expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe(''); // Ensure the parser type passed correctly
expect((frames.results['A'].frames[0].schema.meta.custom.data || '').includes('<name>Leanne Graham</name')).toBeTruthy(); // Ensure schema meta have actual data to be passed to the frontend
// await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered

frames = await runQuery(page, panelEditPage, queryEditorRow, { type: 'xml', url: 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.xml', parser: 'backend' });
expect(frames.results['A'].frames[0].schema.name).toBe('A');
expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe('backend'); // Ensure the parser type passed correctly
expect(frames.results['A'].frames[0].data.values[0][0].includes('Leanne Graham')).toBeTruthy(); // Ensure actual data frames being returned
// await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered

frames = await runQuery(page, panelEditPage, queryEditorRow, { type: 'xml', url: 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.xml', parser: 'uql' });
expect(frames.results['A'].frames[0].schema.name).toBe('A');
expect(frames.results['A'].frames[0].schema.meta.custom.query.parser).toBe('uql'); // Ensure the parser type passed correctly
expect((frames.results['A'].frames[0].schema.meta.custom.data || '').includes('<name>Leanne Graham</name')).toBeTruthy(); // Ensure schema meta have actual data to be passed to the frontend
// await expect(page.getByText('Patricia Lebsack')).toBeVisible(); // Ensure actual data rendered
});
33 changes: 33 additions & 0 deletions e2e/query.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { Page, Locator } from '@playwright/test';
import { PanelEditPage, expect } from '@grafana/plugin-e2e';

export const runQuery = async (page: Page, panelEditPage: PanelEditPage, locator: Locator, query: Record<string, any>) => {
if (query.type) {
const typeDropdown = await locator.locator(`[data-testid='infinity-query-field-wrapper-type'] input`);
await typeDropdown.clear();
await typeDropdown.fill(query.type || 'json');
await page.keyboard.press('Enter');
}
if (query.source) {
const sourceDropdown = await locator.locator(`[data-testid='infinity-query-field-wrapper-source'] input`);
await sourceDropdown.clear();
await sourceDropdown.fill(query.source || 'url');
await page.keyboard.press('Enter');
}
if (query.parser) {
const parserDropdown = await locator.locator(`[data-testid='infinity-query-field-wrapper-parser'] input`);
await parserDropdown.clear();
await parserDropdown.fill(query.parser || 'simple');
await page.keyboard.press('Enter');
}
if (query.url) {
const urlTextBox = await locator.locator(`[data-testid='infinity-query-field-wrapper-url'] input`);
await urlTextBox.clear();
await urlTextBox.fill(query.url || 'https://github.com/grafana/grafana-infinity-datasource/blob/main/testdata/users.json');
await page.keyboard.press('Enter');
}
const res = await panelEditPage.refreshPanel();
await expect(panelEditPage).not.toHavePanelError();
const frames = await res.json();
return frames;
};
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"spellcheck": "cspell -c cspell.config.json \"**/*.{ts,tsx,js,go,md,mdx,yml,yaml,json,scss,css}\"",
"test": "jest --watch --onlyChanged",
"test:ci": "jest --passWithNoTests --maxWorkers 4",
"test:e2e": "yarn playwright test",
"build": "webpack -c ./webpack.config.ts --env production",
"dev": "webpack -w -c ./webpack.config.ts --env development",
"watch": "yarn dev",
Expand Down Expand Up @@ -67,7 +68,9 @@
"@changesets/cli": "^2.26.1",
"@changesets/types": "^5.2.1",
"@grafana/eslint-config": "^6.0.1",
"@grafana/plugin-e2e": "^0.9.0",
"@grafana/tsconfig": "^1.2.0-rc1",
"@playwright/test": "^1.41.0",
"@swc/core": "1.3.75",
"@swc/helpers": "^0.4.12",
"@swc/jest": "^0.2.23",
Expand All @@ -87,7 +90,7 @@
"eslint": "8.18.0",
"eslint-config-airbnb": "^19.0.4",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-jsdoc": "^39.3.3",
"eslint-plugin-jsdoc": "^48.0.2",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-react": "^7.28.0",
"eslint-plugin-react-hooks": "^4.3.0",
Expand Down
25 changes: 25 additions & 0 deletions playwright.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
testDir: './e2e',
fullyParallel: true,
forbidOnly: !!process.env.CI, // eslint-disable-line no-undef
retries: process.env.CI ? 2 : 0, // eslint-disable-line no-undef
workers: process.env.CI ? 1 : undefined, // eslint-disable-line no-undef
reporter: 'list',
use: {
baseURL: 'http://localhost:3000',
trace: 'on-first-retry',
},
projects: [
{
name: 'authenticate',
testMatch: [/.*auth\.setup\.ts/],
},
{
name: 'query',
use: { ...devices['Desktop Chrome'], storageState: 'playwright/.auth/user.json' },
dependencies: ['authenticate'],
},
],
});
Loading

0 comments on commit 8a9417e

Please sign in to comment.