diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index c640a1525..a644904d8 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -71,16 +71,16 @@ jobs: run: | cd packages/plugin-e2e docker compose pull - AWS_SECRET_ACCESS_KEY=${{secrets.AWS_SECRET_ACCESS_KEY}} AWS_ACCESS_KEY_ID=${{secrets.AWS_ACCESS_KEY_ID}} GOOGLE_JWT_FILE=${{secrets.GOOGLE_JWT_FILE}} GRAFANA_IMAGE=${{ matrix.GRAFANA_IMAGE.NAME }} GRAFANA_VERSION=${{ matrix.GRAFANA_IMAGE.VERSION }} docker compose up -d + ANONYMOUS_AUTH_ENABLED=false GRAFANA_IMAGE=${{ matrix.GRAFANA_IMAGE.NAME }} GRAFANA_VERSION=${{ matrix.GRAFANA_IMAGE.VERSION }} docker compose up -d - name: Wait for grafana server uses: grafana/plugin-actions/wait-for-grafana@main + with: + url: http://localhost:3000/login - name: Run Playwright tests id: run-tests run: npm run playwright:test --w @grafana/plugin-e2e - env: - GOOGLE_JWT_FILE: ${{ secrets.GOOGLE_JWT_FILE }} - name: Publish report to GCS if: ${{ github.repository_owner == 'grafana' && (failure() && steps.run-tests.outcome == 'failure') }} diff --git a/package-lock.json b/package-lock.json index bdbbfb291..431b0dd05 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5587,6 +5587,24 @@ "resolved": "packages/create-plugin", "link": true }, + "node_modules/@grafana/e2e-selectors": { + "version": "11.5.0-216908", + "resolved": "https://registry.npmjs.org/@grafana/e2e-selectors/-/e2e-selectors-11.5.0-216908.tgz", + "integrity": "sha512-UnA+8xpw0Ib1jwgpl0aovOG7F+DXgTlrDGj/I2ekapLizHqzQYsObx71t/d64wBEk8Y5ILrfk4h5DkC2r83x1A==", + "license": "Apache-2.0", + "dependencies": { + "@grafana/tsconfig": "^2.0.0", + "semver": "7.6.3", + "tslib": "2.8.1", + "typescript": "5.7.3" + } + }, + "node_modules/@grafana/e2e-selectors/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, "node_modules/@grafana/eslint-config": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/@grafana/eslint-config/-/eslint-config-8.0.0.tgz", @@ -6207,7 +6225,8 @@ "node_modules/@grafana/tsconfig": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@grafana/tsconfig/-/tsconfig-2.0.0.tgz", - "integrity": "sha512-cxC3Htv/GidI5FeVGAzj/lYZTMMz/Cfsc8VOQFO3Ichjx3hUjyjeoBUIpVSVMnIjKUdA5ycdxtMYPHIuIrk8+A==" + "integrity": "sha512-cxC3Htv/GidI5FeVGAzj/lYZTMMz/Cfsc8VOQFO3Ichjx3hUjyjeoBUIpVSVMnIjKUdA5ycdxtMYPHIuIrk8+A==", + "license": "Apache-2.0" }, "node_modules/@hapi/hoek": { "version": "9.3.0", @@ -35103,29 +35122,6 @@ "@playwright/test": "^1.41.2" } }, - "packages/plugin-e2e/node_modules/@grafana/e2e-selectors": { - "version": "11.5.0-216287", - "license": "Apache-2.0", - "dependencies": { - "@grafana/tsconfig": "^2.0.0", - "semver": "7.6.3", - "tslib": "2.7.0", - "typescript": "5.5.4" - } - }, - "packages/plugin-e2e/node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, "packages/plugin-meta-extractor": { "name": "@grafana/plugin-meta-extractor", "version": "0.0.12", diff --git a/packages/plugin-e2e/CONTRIBUTING.md b/packages/plugin-e2e/CONTRIBUTING.md index 48c8172df..bcb6eaa89 100644 --- a/packages/plugin-e2e/CONTRIBUTING.md +++ b/packages/plugin-e2e/CONTRIBUTING.md @@ -52,39 +52,30 @@ npm run build # used to build @grafana/plugin-e2e npm run dev # watches for changes to files and rebuilds @grafana/plugin-e2e automatically ``` -#### Running e2e tests locally +### Tests -There are two types of Playwright tests - those that require data source credentials (only available to members of the Grafana team) and those that don't. +The [tests](./tests/) folder contains a suite of Playwright tests designed to validate that the plugin-e2e APIs work as expected. These tests run continuously for every PR in the plugin-tools repository to identify potential breakages in the plugin-e2e package. Since all plugin-e2e APIs must remain compatible with Grafana 9.5 and later, the tests are executed against a matrix of Grafana versions. The test environment is configured using the docker-compose file in this workspace, which installs a set of plugins to ensure comprehensive coverage of the plugin-e2e APIs throughout the test suite. -To run the Playwright tests that don't require credentials. +To run the tests locally: -1. Start the e2e test server: +1. Start the Grafana e2e instance: ```shell +# starts the test server using the main branch of Grafana npm run server - -``` - -2. Run the Playwright tests - -```shell -npm run playwright:test # runs all the playwright tests that don't require credentials +# if you want to test a specific version of Grafana +GRAFANA_VERSION=11.2.1 npm run server ``` -To run the e2e tests that require data source credentials, you need to add a `/packages/plugin-e2e/.env` file and provide the necessary credentials (see `/packages/plugin-e2e/.env.example` to get an understanding of what variables you need to provide). You'll find all the necessary credentials in the [plugin-provisioning](https://github.com/grafana/plugin-provisioning) repo. - -1. Start the e2e test server: +2. Run the tests ```shell -npm run server - +npm run playwright:test # runs all the playwright ``` -2. Run the Playwright integration tests +### The [Test DataSource](https://github.com/grafana/grafana-test-datasource) -```shell -npm run playwright:test:integration #runs all the playwright tests that integrates with third-party services -``` +Many of the Playwright tests in the [test suite](./tests/) use a custom made data source plugin. This data source it not published to the catalog - its only purpose is to verify that the plugin-e2e APIs work as expected. If you need to change the functionality of this plugin, refer to the [plugin readme](https://github.com/grafana/grafana-test-datasource?tab=readme-ov-file#distributing-changes-in-the-plugin). ### VS Code Playwright extension diff --git a/packages/plugin-e2e/docker-compose.yaml b/packages/plugin-e2e/docker-compose.yaml index f4bf6b77a..e0076838c 100644 --- a/packages/plugin-e2e/docker-compose.yaml +++ b/packages/plugin-e2e/docker-compose.yaml @@ -2,15 +2,13 @@ services: grafana: image: grafana/${GRAFANA_IMAGE:-grafana-enterprise}:${GRAFANA_VERSION:-11.4.0} environment: - - GF_INSTALL_PLUGINS=grafana-clock-panel 2.1.3,grafana-googlesheets-datasource 1.2.4,grafana-redshift-datasource 1.13.0,marcusolsson-json-datasource 1.3.12,redis-app 2.2.1 - - GF_AUTH_ANONYMOUS_ENABLED=true + - GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=grafana-test-datasource + - GF_INSTALL_PLUGINS=https://github.com/grafana/grafana-test-datasource/releases/download/v0.0.7/grafana-test-datasource-0.0.7.zip;grafana-test-datasource,grafana-clock-panel 2.1.3,marcusolsson-json-datasource 1.3.12,redis-app 2.2.1 + - GF_AUTH_ANONYMOUS_ENABLED=${ANONYMOUS_AUTH_ENABLED:-true} - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin - GF_AUTH_ANONYMOUS_ORG_NAME=Main Org. - GF_AUTH_ANONYMOUS_ORG_ID=1 - GF_PANELS_ENABLE_ALPHA=true - - GOOGLE_JWT_FILE=${GOOGLE_JWT_FILE} - - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} - - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} ports: - 3000:3000/tcp volumes: diff --git a/packages/plugin-e2e/package.json b/packages/plugin-e2e/package.json index 4c522a7ae..564fc4158 100644 --- a/packages/plugin-e2e/package.json +++ b/packages/plugin-e2e/package.json @@ -27,9 +27,7 @@ "server": "docker compose up --build", "typecheck": "tsc --emitDeclarationOnly false --noEmit", "test": "vitest --passWithNoTests", - "playwright:test": "npx playwright test --grep-invert @integration", - "playwright:test:integration": "npx playwright test --grep @integration", - "playwright:all": "npx playwright test" + "playwright:test": "npx playwright test" }, "engines": { "node": ">=18 <=22" diff --git a/packages/plugin-e2e/playwright.config.ts b/packages/plugin-e2e/playwright.config.ts index 1e0032c7f..667c74014 100644 --- a/packages/plugin-e2e/playwright.config.ts +++ b/packages/plugin-e2e/playwright.config.ts @@ -3,6 +3,7 @@ import { defineConfig, devices } from '@playwright/test'; import { PluginOptions } from './src'; import dotenv from 'dotenv'; +import path from 'path'; dotenv.config(); @@ -14,12 +15,12 @@ export default defineConfig({ 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: { + // provisioningRootDir: './packages/plugin-e2e/provisioning', + provisioningRootDir: process.env.PROVISIONING_ROOT_DIR || path.join(process.cwd(), 'provisioning'), /* Base URL to use in actions like `await page.goto('/')`. */ baseURL: 'http://localhost:3000', @@ -75,6 +76,21 @@ export default defineConfig({ }, dependencies: ['authenticate'], }, + + // Run all tests in parallel using user with admin role but with wide screen + { + name: 'admin-wide-screen', + testDir: './tests/as-admin-user', + use: { + ...devices['Desktop Chrome'], + storageState: 'playwright/.auth/admin.json', + viewport: { + width: 1920, + height: 1080, + }, + }, + dependencies: ['authenticate'], + }, // Run all tests in parallel using user with viewer role { name: 'viewer', diff --git a/packages/plugin-e2e/provisioning/alerting/alerts.yml b/packages/plugin-e2e/provisioning/alerting/testdatasource.yml similarity index 78% rename from packages/plugin-e2e/provisioning/alerting/alerts.yml rename to packages/plugin-e2e/provisioning/alerting/testdatasource.yml index ac987bc48..f573a6097 100644 --- a/packages/plugin-e2e/provisioning/alerting/alerts.yml +++ b/packages/plugin-e2e/provisioning/alerting/testdatasource.yml @@ -1,37 +1,31 @@ apiVersion: 1 - - -deleteRules: - - name: working_rule - - name: broken_rule - groups: - orgId: 1 - name: test_group - folder: redshift - interval: 5m + name: test-datasource + folder: testdatasource + interval: 1m rules: - - uid: uid1 - title: working_rule + - uid: ee6sapq2x30u8a + title: successful-alert condition: C data: - refId: A relativeTimeRange: from: 600 to: 0 - datasourceUid: P7DC3E4760CFAC4AH + datasourceUid: P6E498B96656A7F9B model: + constant: 6.5 datasource: - type: grafana-redshift-datasource - uid: P7DC3E4760CFAC4AH + type: grafana-test-datasource + uid: P6E498B96656A7F9B + hide: false intervalMs: 1000 maxDataPoints: 43200 - rawSQL: select * from long_format_example + project: project-2 + queryText: test refId: A - refId: B - relativeTimeRange: - from: 600 - to: 0 datasourceUid: __expr__ model: conditions: @@ -57,9 +51,6 @@ groups: refId: B type: reduce - refId: C - relativeTimeRange: - from: 600 - to: 0 datasourceUid: __expr__ model: conditions: @@ -86,31 +77,28 @@ groups: type: threshold noDataState: NoData execErrState: Error - for: 5m - annotations: {} - labels: {} + for: 1m isPaused: false - - uid: uid2 - title: broken_rule - condition: A + - uid: ce6say4zyst1ce + title: broken-alert + condition: C data: - refId: A relativeTimeRange: from: 600 to: 0 - datasourceUid: P7DC3E4760CFAC4AH + datasourceUid: P6E498B96656A7F9B model: + constant: 6.5 datasource: - type: grafana-redshift-datasource - uid: P7DC3E4760CFAC4AH + type: grafana-test-datasource + uid: P6E498B96656A7F9B intervalMs: 1000 maxDataPoints: 43200 - rawSQL: \!select + project: project-2 + queryText: error refId: A - refId: B - relativeTimeRange: - from: 600 - to: 0 datasourceUid: __expr__ model: conditions: @@ -136,9 +124,6 @@ groups: refId: B type: reduce - refId: C - relativeTimeRange: - from: 600 - to: 0 datasourceUid: __expr__ model: conditions: @@ -165,8 +150,6 @@ groups: type: threshold noDataState: NoData execErrState: Error - for: 5m - annotations: {} - labels: {} + for: 1m isPaused: false - + \ No newline at end of file diff --git a/packages/plugin-e2e/provisioning/dashboards/redshift.json b/packages/plugin-e2e/provisioning/dashboards/redshift.json deleted file mode 100644 index 78cc67bab..000000000 --- a/packages/plugin-e2e/provisioning/dashboards/redshift.json +++ /dev/null @@ -1,926 +0,0 @@ -{ - "annotations": { - "list": [ - { - "builtIn": 1, - "datasource": { - "type": "datasource", - "uid": "grafana" - }, - "enable": true, - "hide": true, - "iconColor": "rgba(0, 211, 255, 1)", - "limit": 100, - "name": "Annotations & Alerts", - "target": { - "limit": 100, - "matchAny": false, - "tags": [], - "type": "dashboard" - }, - "type": "dashboard" - }, - { - "datasource": { - "type": "grafana-redshift-datasource", - "uid": "P7DC3E4760CFAC4AH" - }, - "enable": false, - "iconColor": "red", - "mappings": { - "time": { - "source": "field", - "value": "time" - }, - "timeEnd": { - "source": "field", - "value": "time" - } - }, - "name": "High Humidity", - "target": { - "format": 1, - "rawSQL": "select\n time as time,\n environment as tags,\n humidity as text\nfrom $__table\nwhere $__timeFilter(time) and humidity > 95", - "refId": "Anno", - "table": "long_format_example" - } - } - ] - }, - "editable": true, - "fiscalYearStartMonth": 0, - "graphTooltip": 0, - "id": 729, - "links": [], - "liveNow": false, - "panels": [ - { - "datasource": { - "type": "grafana-redshift-datasource", - "uid": "P7DC3E4760CFAC4AH" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 0 - }, - "id": 2, - "options": { - "cellHeight": "sm", - "footer": { - "countRows": false, - "fields": "", - "reducer": ["sum"], - "show": false - }, - "showHeader": true - }, - "pluginVersion": "10.3.0-pre", - "targets": [ - { - "datasource": { - "type": "grafana-redshift-datasource", - "uid": "P7DC3E4760CFAC4AH" - }, - "fillMode": { - "mode": 0 - }, - "format": 1, - "rawSQL": "select * from long_format_example where environment in (${environment:singlequote}) limit 100", - "refId": "A" - } - ], - "title": "Basic table example", - "type": "table" - }, - { - "datasource": { - "type": "grafana-redshift-datasource", - "uid": "P7DC3E4760CFAC4AH" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 0 - }, - "id": 3, - "options": { - "cellHeight": "sm", - "footer": { - "countRows": false, - "fields": "", - "reducer": ["sum"], - "show": false - }, - "showHeader": true - }, - "pluginVersion": "10.3.0-pre", - "targets": [ - { - "datasource": { - "type": "grafana-redshift-datasource", - "uid": "P7DC3E4760CFAC4AH" - }, - "format": 1, - "rawSQL": "select * from long_format_example where environment = ${env:singlequote} limit 100", - "refId": "A" - } - ], - "title": "Basic table example with templating", - "type": "table" - }, - { - "datasource": { - "type": "grafana-redshift-datasource", - "uid": "P7DC3E4760CFAC4AH" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 9 - }, - "id": 4, - "options": { - "cellHeight": "sm", - "footer": { - "countRows": false, - "fields": "", - "reducer": ["sum"], - "show": false - }, - "showHeader": true - }, - "pluginVersion": "10.3.0-pre", - "targets": [ - { - "datasource": { - "type": "grafana-redshift-datasource", - "uid": "P7DC3E4760CFAC4AH" - }, - "format": 1, - "rawSQL": "select * from long_format_example where environment = ${env:singlequote} limit 100", - "refId": "A" - } - ], - "title": "Basic table example with templating query", - "type": "table" - }, - { - "datasource": { - "type": "grafana-redshift-datasource", - "uid": "P7DC3E4760CFAC4AH" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 9 - }, - "id": 5, - "options": { - "cellHeight": "sm", - "footer": { - "countRows": false, - "fields": "", - "reducer": ["sum"], - "show": false - }, - "showHeader": true - }, - "pluginVersion": "10.3.0-pre", - "targets": [ - { - "datasource": { - "type": "grafana-redshift-datasource", - "uid": "P7DC3E4760CFAC4AH" - }, - "format": 1, - "rawSQL": "select * from long_format_example where environment in ($multi_valued_env_query) limit 100", - "refId": "A" - } - ], - "title": "Basic table example with multi-valued templating query", - "type": "table" - }, - { - "datasource": { - "type": "grafana-redshift-datasource", - "uid": "P7DC3E4760CFAC4AH" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 18 - }, - "id": 6, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.1.0-pre", - "targets": [ - { - "datasource": { - "type": "grafana-redshift-datasource", - "uid": "P7DC3E4760CFAC4AH" - }, - "format": 0, - "rawSQL": "-- One metric is created per combination timestamp (time index) - number column (metric value) - varchar column (metric label)\nselect * from long_format_example where $__timeFilter(time)", - "refId": "A" - } - ], - "title": "Long to wide formatted time series", - "type": "timeseries" - }, - { - "datasource": { - "type": "grafana-redshift-datasource", - "uid": "P7DC3E4760CFAC4AH" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 18 - }, - "id": 7, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.1.0-pre", - "targets": [ - { - "datasource": { - "type": "grafana-redshift-datasource", - "uid": "P7DC3E4760CFAC4AH" - }, - "format": 0, - "rawSQL": "select time as time, temperature as tmp from long_format_example ", - "refId": "A" - } - ], - "title": "Picked column", - "type": "timeseries" - }, - { - "datasource": { - "type": "grafana-redshift-datasource", - "uid": "P7DC3E4760CFAC4AH" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "custom": { - "align": "auto", - "cellOptions": { - "type": "auto" - }, - "inspect": false - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 27 - }, - "id": 8, - "options": { - "cellHeight": "sm", - "footer": { - "countRows": false, - "fields": "", - "reducer": ["sum"], - "show": false - }, - "showHeader": true - }, - "pluginVersion": "10.3.0-pre", - "targets": [ - { - "datasource": { - "type": "grafana-redshift-datasource", - "uid": "P7DC3E4760CFAC4AH" - }, - "format": 0, - "rawSQL": "select * from long_format_example limit 500\n-- where $__timeFilter(time)", - "refId": "A" - } - ], - "title": "Time filter macro", - "type": "table" - }, - { - "alert": { - "alertRuleTags": {}, - "conditions": [ - { - "evaluator": { - "params": [30], - "type": "gt" - }, - "operator": { - "type": "and" - }, - "query": { - "params": ["A", "5m", "now"] - }, - "reducer": { - "params": [], - "type": "avg" - }, - "type": "query" - } - ], - "executionErrorState": "alerting", - "for": "5m", - "frequency": "1m", - "handler": 1, - "name": "Alerting alert", - "noDataState": "no_data", - "notifications": [] - }, - "datasource": { - "type": "grafana-redshift-datasource", - "uid": "P7DC3E4760CFAC4AH" - }, - "fieldConfig": { - "defaults": { - "color": { - "mode": "palette-classic" - }, - "custom": { - "axisBorderShow": false, - "axisCenteredZero": false, - "axisColorMode": "text", - "axisLabel": "", - "axisPlacement": "auto", - "barAlignment": 0, - "drawStyle": "line", - "fillOpacity": 0, - "gradientMode": "none", - "hideFrom": { - "legend": false, - "tooltip": false, - "viz": false - }, - "insertNulls": false, - "lineInterpolation": "linear", - "lineWidth": 1, - "pointSize": 5, - "scaleDistribution": { - "type": "linear" - }, - "showPoints": "auto", - "spanNulls": false, - "stacking": { - "group": "A", - "mode": "none" - }, - "thresholdsStyle": { - "mode": "off" - } - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 27 - }, - "id": 9, - "options": { - "legend": { - "calcs": [], - "displayMode": "list", - "placement": "bottom", - "showLegend": true - }, - "tooltip": { - "mode": "single", - "sort": "none" - } - }, - "pluginVersion": "8.1.0-pre", - "targets": [ - { - "datasource": { - "type": "grafana-redshift-datasource", - "uid": "P7DC3E4760CFAC4AH" - }, - "format": 0, - "rawSQL": "select time as time, temperature as tmp from long_format_example", - "refId": "A" - } - ], - "thresholds": [ - { - "colorMode": "critical", - "op": "gt", - "value": 30, - "visible": true - } - ], - "title": "Alerting", - "type": "timeseries" - }, - { - "datasource": { - "type": "grafana-redshift-datasource", - "uid": "P7DC3E4760CFAC4AH" - }, - "gridPos": { - "h": 9, - "w": 12, - "x": 0, - "y": 36 - }, - "id": 10, - "options": { - "dedupStrategy": "none", - "enableLogDetails": true, - "prettifyLogMessage": false, - "showCommonLabels": false, - "showLabels": false, - "showTime": true, - "sortOrder": "Descending", - "wrapLogMessage": false - }, - "pluginVersion": "8.0.0-beta3", - "targets": [ - { - "datasource": { - "type": "grafana-redshift-datasource", - "uid": "P7DC3E4760CFAC4AH" - }, - "format": 0, - "rawSQL": "select * from cloudfront_logs limit 100", - "refId": "A" - } - ], - "title": "Logging example - picked fields", - "type": "logs" - }, - { - "datasource": { - "type": "grafana-redshift-datasource", - "uid": "P7DC3E4760CFAC4AH" - }, - "description": "", - "gridPos": { - "h": 9, - "w": 12, - "x": 12, - "y": 36 - }, - "id": 11, - "options": { - "dedupStrategy": "none", - "enableLogDetails": true, - "prettifyLogMessage": false, - "showCommonLabels": false, - "showLabels": false, - "showTime": false, - "sortOrder": "Descending", - "wrapLogMessage": false - }, - "pluginVersion": "8.0.0-beta3", - "targets": [ - { - "datasource": { - "type": "grafana-redshift-datasource", - "uid": "P7DC3E4760CFAC4AH" - }, - "format": 1, - "rawSQL": "select * from cloudfront_logs limit 100", - "refId": "A" - } - ], - "title": "Logging example - Organize fields transformation", - "transformations": [ - { - "id": "organize", - "options": { - "excludeByName": {}, - "indexByName": { - "bytes": 4, - "clientinfo": 1, - "date": 0, - "host": 7, - "location": 3, - "method": 6, - "referrer": 10, - "requestip": 5, - "status": 9, - "time": 2, - "uri": 8 - }, - "renameByName": {} - } - } - ], - "type": "logs" - } - ], - "refresh": "", - "schemaVersion": 39, - "tags": [], - "templating": { - "list": [ - { - "current": { - "selected": false, - "text": "staging", - "value": "staging" - }, - "description": "", - "hide": 0, - "includeAll": false, - "multi": false, - "name": "env", - "options": [ - { - "selected": false, - "text": "test", - "value": "test" - }, - { - "selected": true, - "text": "staging", - "value": "staging" - } - ], - "query": "test,staging", - "queryValue": "", - "skipUrlSync": false, - "type": "custom" - }, - { - "current": { - "selected": false, - "text": "staging", - "value": "staging" - }, - "datasource": { - "type": "grafana-redshift-datasource", - "uid": "P7DC3E4760CFAC4AH" - }, - "definition": "", - "description": "", - "hide": 0, - "includeAll": false, - "multi": false, - "name": "env_query", - "options": [], - "query": { - "rawSQL": "select distinct environment from long_format_example " - }, - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "type": "query" - }, - { - "current": { - "selected": true, - "text": ["staging"], - "value": ["staging"] - }, - "datasource": { - "type": "grafana-redshift-datasource", - "uid": "P7DC3E4760CFAC4AH" - }, - "definition": "", - "description": "", - "hide": 0, - "includeAll": false, - "multi": true, - "name": "multi_valued_env_query", - "options": [], - "query": { - "rawSQL": "select distinct environment from long_format_example " - }, - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "type": "query" - }, - { - "current": { - "selected": false, - "text": "staging", - "value": "staging" - }, - "datasource": { - "type": "grafana-redshift-datasource", - "uid": "P7DC3E4760CFAC4AH" - }, - "definition": "", - "hide": 0, - "includeAll": false, - "multi": true, - "name": "environment", - "options": [], - "query": { - "rawSQL": "select distinct environment from long_format_example " - }, - "refresh": 1, - "regex": "", - "skipUrlSync": false, - "sort": 0, - "type": "query" - } - ] - }, - "time": { - "from": "now-30d", - "to": "now" - }, - "timepicker": {}, - "timezone": "", - "title": "Redshift Demo", - "uid": "7M8fNhz7k", - "version": 22, - "weekStart": "" -} diff --git a/packages/plugin-e2e/provisioning/dashboards/google-sheets.json b/packages/plugin-e2e/provisioning/dashboards/testdatasource-annotations.json similarity index 56% rename from packages/plugin-e2e/provisioning/dashboards/google-sheets.json rename to packages/plugin-e2e/provisioning/dashboards/testdatasource-annotations.json index ee7a6db74..fa0ba6c7f 100644 --- a/packages/plugin-e2e/provisioning/dashboards/google-sheets.json +++ b/packages/plugin-e2e/provisioning/dashboards/testdatasource-annotations.json @@ -12,22 +12,45 @@ "iconColor": "rgba(0, 211, 255, 1)", "name": "Annotations & Alerts", "type": "dashboard" + }, + { + "datasource": { + "type": "grafana-test-datasource", + "uid": "P6E498B96656A7F9B" + }, + "enable": true, + "hide": false, + "iconColor": "red", + "name": "anno", + "target": { + "constant": 6.5, + "datasource": { + "type": "grafana-test-datasource", + "uid": "P6E498B96656A7F9B" + }, + "enable": true, + "iconColor": "red", + "name": "New annotation", + "queryMode": "Annotations", + "queryText": "annotationQuery", + "refId": "annotationQuery", + "region": "default", + "statistic": "Average" + } } ] }, "editable": true, "fiscalYearStartMonth": 0, "graphTooltip": 0, - "id": 1, + "id": 10, "links": [], - "liveNow": false, "panels": [ { "datasource": { - "type": "grafana-googlesheets-datasource", - "uid": "PB0CCE99F8730D01D" + "type": "grafana-test-datasource", + "uid": "P6E498B96656A7F9B" }, - "description": "", "fieldConfig": { "defaults": { "color": { @@ -40,6 +63,7 @@ "axisLabel": "", "axisPlacement": "auto", "barAlignment": 0, + "barWidthFactor": 0.6, "drawStyle": "line", "fillOpacity": 0, "gradientMode": "none", @@ -101,98 +125,37 @@ "sort": "none" } }, + "pluginVersion": "11.5.0-213591", "targets": [ { - "cacheDurationSeconds": 300, + "constant": 6.5, "datasource": { - "type": "grafana-googlesheets-datasource", - "uid": "PB0CCE99F8730D01D" + "type": "grafana-test-datasource", + "uid": "P6E498B96656A7F9B" }, - "refId": "A", - "spreadsheet": "1TZlZX67Y0s4CvRro_3pCYqRCKuXer81oFp_xcsjPpe8" + "queryText": "annotationQuesdf", + "refId": "A" } ], - "title": "Monthly average", + "title": "With annotation", "type": "timeseries" - }, - { - "datasource": { - "type": "grafana-googlesheets-datasource", - "uid": "PB0CCE99F8730D01D" - }, - "description": "", - "fieldConfig": { - "defaults": { - "color": { - "mode": "thresholds" - }, - "mappings": [], - "thresholds": { - "mode": "absolute", - "steps": [ - { - "color": "green", - "value": null - }, - { - "color": "red", - "value": 80 - } - ] - } - }, - "overrides": [] - }, - "gridPos": { - "h": 8, - "w": 12, - "x": 12, - "y": 0 - }, - "id": 2, - "options": { - "colorMode": "value", - "graphMode": "area", - "justifyMode": "auto", - "orientation": "auto", - "reduceOptions": { - "calcs": ["mean"], - "fields": "", - "values": false - }, - "textMode": "auto", - "wideLayout": true - }, - "pluginVersion": "10.2.1", - "targets": [ - { - "cacheDurationSeconds": 300, - "datasource": { - "type": "grafana-googlesheets-datasource", - "uid": "PB0CCE99F8730D01D" - }, - "refId": "A", - "spreadsheet": "1TZlZX67Y0s4CvRro_3pCYqRCKuXer81oFp_xcsjPpe8" - } - ], - "title": "Yearly average", - "type": "stat" } ], + "preload": false, "refresh": "", - "schemaVersion": 38, + "schemaVersion": 40, "tags": [], "templating": { "list": [] }, "time": { - "from": "2019-01-10T23:00:00.000Z", - "to": "2019-12-14T23:00:00.000Z" + "from": "2024-12-15T23:00:00.000Z", + "to": "2024-12-17T23:00:00.000Z" }, "timepicker": {}, - "timezone": "", - "title": "Google Sheets", - "uid": "eda84f4d-0b3c-4e4d-815d-7fcb9aa702c2", - "version": 3, + "timezone": "browser", + "title": "Test dashboard with annotations", + "uid": "ae766j91d6xhcf", + "version": 5, "weekStart": "" } diff --git a/packages/plugin-e2e/provisioning/dashboards/testdatasource.json b/packages/plugin-e2e/provisioning/dashboards/testdatasource.json new file mode 100644 index 000000000..e324c7654 --- /dev/null +++ b/packages/plugin-e2e/provisioning/dashboards/testdatasource.json @@ -0,0 +1,395 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 8, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "default": false, + "type": "grafana-test-datasource", + "uid": "P6E498B96656A7F9B" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "constant": 6.5, + "datasource": { + "type": "grafana-test-datasource", + "uid": "P6E498B96656A7F9B" + }, + "project": "project-1", + "queryText": "test", + "refId": "A" + } + ], + "title": "Panel Title", + "type": "timeseries" + }, + { + "datasource": { + "default": false, + "type": "grafana-test-datasource", + "uid": "P6E498B96656A7F9B" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 0 + }, + "id": 2, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": ["sum"], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "9.5.21", + "targets": [ + { + "constant": 6.5, + "datasource": { + "type": "grafana-test-datasource", + "uid": "P6E498B96656A7F9B" + }, + "project": "project-1", + "queryText": "singleTableRow", + "refId": "A" + } + ], + "title": "Single row", + "type": "table" + }, + { + "datasource": { + "default": false, + "type": "grafana-test-datasource", + "uid": "P6E498B96656A7F9B" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 3, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": ["sum"], + "show": false + }, + "showHeader": true + }, + "pluginVersion": "9.5.21", + "targets": [ + { + "constant": 6.5, + "datasource": { + "type": "grafana-test-datasource", + "uid": "P6E498B96656A7F9B" + }, + "project": "project-1", + "queryText": "tableData", + "refId": "A" + } + ], + "title": "Table data", + "type": "table" + }, + { + "datasource": { + "default": false, + "type": "grafana-test-datasource", + "uid": "P6E498B96656A7F9B" + }, + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 8 + }, + "id": 4, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "pluginVersion": "11.2.2", + "targets": [ + { + "constant": 6.5, + "datasource": { + "type": "grafana-test-datasource", + "uid": "P6E498B96656A7F9B" + }, + "project": "project-1", + "queryText": "tableData", + "refId": "A" + } + ], + "title": "Time series data", + "type": "timeseries" + } + ], + "refresh": false, + "schemaVersion": 38, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": true, + "text": "A", + "value": "A" + }, + "datasource": { + "type": "grafana-test-datasource", + "uid": "P6E498B96656A7F9B" + }, + "definition": "", + "hide": 0, + "includeAll": false, + "multi": false, + "name": "var1", + "options": [], + "query": { + "constant": 6.5, + "project": "project-1", + "queryText": "annotationQuery" + }, + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "type": "query" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": {}, + "timezone": "browser", + "title": "Test datasource dashboard", + "uid": "be6sir7o1iccgb", + "version": 1, + "weekStart": "" +} diff --git a/packages/plugin-e2e/provisioning/datasources/google-sheets-datasource-jwt.yaml b/packages/plugin-e2e/provisioning/datasources/google-sheets-datasource-jwt.yaml deleted file mode 100644 index 31669c906..000000000 --- a/packages/plugin-e2e/provisioning/datasources/google-sheets-datasource-jwt.yaml +++ /dev/null @@ -1,18 +0,0 @@ -# config file version -apiVersion: 1 - -deleteDatasources: - - name: Google Sheets Service Account - orgId: 1 - -datasources: - - editable: true - enabled: true - uid: PB0CCE99F8730D01D - jsonData: - authType: jwt - name: Google Sheets Service Account - secureJsonData: - jwt: ${GOOGLE_JWT_FILE} - type: grafana-googlesheets-datasource - version: 1 diff --git a/packages/plugin-e2e/provisioning/datasources/redshift.yaml b/packages/plugin-e2e/provisioning/datasources/redshift.yaml deleted file mode 100644 index 37ca060f3..000000000 --- a/packages/plugin-e2e/provisioning/datasources/redshift.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: 1 - -deleteDatasources: - - name: AWS Redshift - orgId: 1 - -datasources: - - name: AWS Redshift - type: grafana-redshift-datasource - uid: P7DC3E4760CFAC4AH - jsonData: - authType: keys - defaultRegion: us-east-2 - useManagedSecret: false - database: dev - dbUser: cloud-datasources - clusterIdentifier: redshift-cluster-grafana - secureJsonData: - accessKey: $AWS_ACCESS_KEY_ID - secretKey: $AWS_SECRET_ACCESS_KEY - version: 1 diff --git a/packages/plugin-e2e/provisioning/datasources/testdatasource.yaml b/packages/plugin-e2e/provisioning/datasources/testdatasource.yaml new file mode 100644 index 000000000..bb1f2de7b --- /dev/null +++ b/packages/plugin-e2e/provisioning/datasources/testdatasource.yaml @@ -0,0 +1,14 @@ +apiVersion: 1 + +datasources: + - name: 'test-datasource' + type: 'grafana-test-datasource' + access: proxy + isDefault: false + orgId: 1 + version: 1 + editable: true + jsonData: + path: '/resources' + secureJsonData: + apiKey: 'api-key' diff --git a/packages/plugin-e2e/src/fixtures/isFeatureToggleEnabled.ts b/packages/plugin-e2e/src/fixtures/isFeatureToggleEnabled.ts index 27e125770..4de75c2ba 100644 --- a/packages/plugin-e2e/src/fixtures/isFeatureToggleEnabled.ts +++ b/packages/plugin-e2e/src/fixtures/isFeatureToggleEnabled.ts @@ -1,4 +1,4 @@ -import { TestFixture } from '@playwright/test'; +import { Page, TestFixture } from '@playwright/test'; import { PlaywrightArgs } from '../types'; type FeatureToggleFixture = TestFixture<(featureToggle: keyof T) => Promise, PlaywrightArgs>; @@ -9,3 +9,8 @@ export const isFeatureToggleEnabled: FeatureToggleFixture = async ({ page }, use return Boolean(featureToggles[featureToggle]); }); }; + +export const isFeatureEnabled = async (page: Page, featureToggle: string) => { + const featureToggles: Record = await page.evaluate('window.grafanaBootData.settings.featureToggles'); + return Boolean(featureToggles[featureToggle]); +}; diff --git a/packages/plugin-e2e/src/models/pages/DashboardPage.ts b/packages/plugin-e2e/src/models/pages/DashboardPage.ts index cabdc9fe7..3446d67a2 100644 --- a/packages/plugin-e2e/src/models/pages/DashboardPage.ts +++ b/packages/plugin-e2e/src/models/pages/DashboardPage.ts @@ -5,6 +5,7 @@ import { GrafanaPage } from './GrafanaPage'; import { PanelEditPage } from './PanelEditPage'; import { TimeRange } from '../components/TimeRange'; import { Panel } from '../components/Panel'; +import { isFeatureEnabled } from '../../fixtures/isFeatureToggleEnabled'; export class DashboardPage extends GrafanaPage { dataSourcePicker: any; @@ -86,17 +87,28 @@ export class DashboardPage extends GrafanaPage { async addPanel(): Promise { const { components, pages, constants } = this.ctx.selectors; - // From Grafana 11.3.0, one needs to click the edit button before adding a new panel in already existing dashboards - if (semver.gte(this.ctx.grafanaVersion, '11.3.0') && this.dashboard?.uid) { + const scenesEnabled = await isFeatureEnabled(this.ctx.page, 'dashboardScene'); + + // In scenes powered dashboards, one needs to click the edit button before adding a new panel in already existing dashboards + if (scenesEnabled && this.dashboard?.uid) { await this.getByGrafanaSelector(components.NavToolbar.editDashboard.editButton).click(); } + // on small screens, the toolbar buttons are hidden behind a "Show more items" button + const toolbarButtonsHidden = !scenesEnabled && !!(await this.ctx.page.getByLabel('Show more items').count()); + if (toolbarButtonsHidden) { + await this.ctx.page.getByLabel('Show more items').click(); + } if (semver.gte(this.ctx.grafanaVersion, '9.5.0')) { - await this.getByGrafanaSelector(components.PageToolbar.itemButton(constants.PageToolBar.itemButtonTitle)).click(); + let addButton = this.getByGrafanaSelector( + components.PageToolbar.itemButton(constants.PageToolBar.itemButtonTitle) + ); + toolbarButtonsHidden ? await addButton.last().click() : await addButton.click(); await this.getByGrafanaSelector(pages.AddDashboard.itemButton(pages.AddDashboard.itemButtonAddViz)).click(); } else { if (this.dashboard?.uid) { - await this.getByGrafanaSelector(components.PageToolbar.item('Add panel')).click(); + const addPanelButton = this.getByGrafanaSelector(components.PageToolbar.item('Add panel')); + toolbarButtonsHidden ? await addPanelButton.last().click() : await addPanelButton.click(); } await this.getByGrafanaSelector(pages.AddDashboard.addNewPanel).click(); } diff --git a/packages/plugin-e2e/src/models/pages/PanelEditPage.ts b/packages/plugin-e2e/src/models/pages/PanelEditPage.ts index 3765e3eeb..e36a5c98a 100644 --- a/packages/plugin-e2e/src/models/pages/PanelEditPage.ts +++ b/packages/plugin-e2e/src/models/pages/PanelEditPage.ts @@ -176,7 +176,14 @@ export class PanelEditPage extends GrafanaPage { root: this.getByGrafanaSelector(this.ctx.selectors.components.PanelEditor.General.content), }); - await refreshPanelButton.click(); + try { + await refreshPanelButton.click({ timeout: 2000 }); + } catch (error) { + // refresh button may be hidden behind the visualization options + await this.getByGrafanaSelector(this.ctx.selectors.components.PanelEditor.toggleVizOptions).click(); + await refreshPanelButton.click(); + await this.getByGrafanaSelector(this.ctx.selectors.components.PanelEditor.toggleVizOptions).click(); + } return responsePromise; } diff --git a/packages/plugin-e2e/tests/as-admin-user/datasource/alerting/alerting.spec.ts b/packages/plugin-e2e/tests/as-admin-user/datasource/alerting/alerting.spec.ts index 9b5aa9249..756b1ee95 100644 --- a/packages/plugin-e2e/tests/as-admin-user/datasource/alerting/alerting.spec.ts +++ b/packages/plugin-e2e/tests/as-admin-user/datasource/alerting/alerting.spec.ts @@ -2,62 +2,79 @@ import * as semver from 'semver'; import { test, expect } from '../../../../src'; const skipMsg = 'Alerting rule test API are only compatible with Grafana 9.5.0 and later'; -test( - 'should evaluate to true if query is valid', - { tag: '@integration' }, - async ({ grafanaVersion, page, alertRuleEditPage, selectors }) => { + +test.describe('Test new alert rules', () => { + test('should evaluate to true if query is valid', async ({ + grafanaVersion, + page, + alertRuleEditPage, + selectors, + readProvisionedDataSource, + }) => { test.skip(semver.lt(grafanaVersion, '9.5.0'), skipMsg); + const ds = await readProvisionedDataSource({ fileName: 'testdatasource.yaml' }); const queryA = alertRuleEditPage.getAlertRuleQueryRow('A'); - await queryA.datasource.set('AWS Redshift'); - await alertRuleEditPage.alertRuleNameField.fill('Test Alert Rule'); - await page.waitForFunction(() => window.monaco); - await queryA.getByGrafanaSelector(selectors.components.CodeEditor.container).click(); - await page.keyboard.insertText('select * from long_format_example where $__timeFilter(time) '); + await queryA.datasource.set(ds.name); + await page.getByRole('textbox', { name: 'Query Text' }).fill('some query'); await expect(alertRuleEditPage.evaluate()).toBeOK(); - } -); + }); -test('should evaluate to false if query is invalid', async ({ grafanaVersion, page, alertRuleEditPage, selectors }) => { - test.skip(semver.lt(grafanaVersion, '9.5.0'), skipMsg); - const queryA = alertRuleEditPage.getAlertRuleQueryRow('A'); - await queryA.datasource.set('AWS Redshift'); - await page.waitForFunction(() => window.monaco); - await alertRuleEditPage.alertRuleNameField.fill('Test Alert Rule'); - await queryA.getByGrafanaSelector(selectors.components.CodeEditor.container).click(); - await page.keyboard.insertText('select !'); - await expect(alertRuleEditPage.evaluate()).not.toBeOK(); -}); + test('should evaluate to false if query is invalid', async ({ + grafanaVersion, + page, + alertRuleEditPage, + readProvisionedDataSource, + }) => { + test.skip(semver.lt(grafanaVersion, '9.5.0'), skipMsg); + const ds = await readProvisionedDataSource({ fileName: 'testdatasource.yaml' }); + const queryA = alertRuleEditPage.getAlertRuleQueryRow('A'); + await queryA.datasource.set(ds.name); + await page.getByRole('textbox', { name: 'Query Text' }).fill('error'); + await expect(alertRuleEditPage.evaluate()).not.toBeOK(); + }); -test('should be possible to add multiple rows', async ({ grafanaVersion, alertRuleEditPage, selectors }) => { - test.skip(semver.lt(grafanaVersion, '9.5.0'), skipMsg); - const { rows } = selectors.components.QueryEditorRows; - const queryA = alertRuleEditPage.getAlertRuleQueryRow('A'); - await queryA.datasource.set('AWS Redshift'); - const rowCount = await alertRuleEditPage.getByGrafanaSelector(rows).count(); - await alertRuleEditPage.clickAddQueryRow(); - await expect(alertRuleEditPage.getByGrafanaSelector(rows)).toHaveCount(rowCount + 1); - await alertRuleEditPage.clickAddQueryRow(); - await expect(alertRuleEditPage.getByGrafanaSelector(rows)).toHaveCount(rowCount + 2); + test('should be possible to add multiple rows', async ({ + grafanaVersion, + alertRuleEditPage, + selectors, + readProvisionedDataSource, + }) => { + test.skip(semver.lt(grafanaVersion, '9.5.0'), skipMsg); + const { rows } = selectors.components.QueryEditorRows; + const ds = await readProvisionedDataSource({ fileName: 'testdatasource.yaml' }); + const queryA = alertRuleEditPage.getAlertRuleQueryRow('A'); + await queryA.datasource.set(ds.name); + const rowCount = await alertRuleEditPage.getByGrafanaSelector(rows).count(); + await alertRuleEditPage.clickAddQueryRow(); + await expect(alertRuleEditPage.getByGrafanaSelector(rows)).toHaveCount(rowCount + 1); + await alertRuleEditPage.clickAddQueryRow(); + await expect(alertRuleEditPage.getByGrafanaSelector(rows)).toHaveCount(rowCount + 2); + }); }); -test( - 'should evaluate to true when loading a provisioned query that is valid', - { tag: '@integration' }, - async ({ grafanaVersion, gotoAlertRuleEditPage, readProvisionedAlertRule }) => { +test.describe('Tests existing alert rules', () => { + test('should evaluate to true when loading a provisioned query that is valid', async ({ + grafanaVersion, + gotoAlertRuleEditPage, + readProvisionedAlertRule, + }) => { test.skip(semver.lt(grafanaVersion, '9.5.0'), skipMsg); - const alertRule = await readProvisionedAlertRule({ fileName: 'alerts.yml' }); + const alertRule = await readProvisionedAlertRule({ + fileName: 'testdatasource.yml', + ruleTitle: 'successful-alert', + }); const alertRuleEditPage = await gotoAlertRuleEditPage(alertRule); await expect(alertRuleEditPage.evaluate()).toBeOK(); - } -); + }); -test('should evaluate to false when loading a provisioned query that is invalid', async ({ - grafanaVersion, - gotoAlertRuleEditPage, - readProvisionedAlertRule, -}) => { - test.skip(semver.lt(grafanaVersion, '9.5.0'), skipMsg); - const alertRule = await readProvisionedAlertRule({ fileName: 'alerts.yml', ruleTitle: 'broken_rule' }); - const alertRuleEditPage = await gotoAlertRuleEditPage(alertRule); - await expect(alertRuleEditPage.evaluate()).not.toBeOK(); + test('should evaluate to false when loading a provisioned query that is invalid', async ({ + grafanaVersion, + gotoAlertRuleEditPage, + readProvisionedAlertRule, + }) => { + test.skip(semver.lt(grafanaVersion, '9.5.0'), skipMsg); + const alertRule = await readProvisionedAlertRule({ fileName: 'testdatasource.yml', ruleTitle: 'broken-alert' }); + const alertRuleEditPage = await gotoAlertRuleEditPage(alertRule); + await expect(alertRuleEditPage.evaluate()).not.toBeOK(); + }); }); diff --git a/packages/plugin-e2e/tests/as-admin-user/datasource/annotations/annotationEditor.spec.ts b/packages/plugin-e2e/tests/as-admin-user/datasource/annotations/annotationEditor.spec.ts index f499e311a..83d07f72b 100644 --- a/packages/plugin-e2e/tests/as-admin-user/datasource/annotations/annotationEditor.spec.ts +++ b/packages/plugin-e2e/tests/as-admin-user/datasource/annotations/annotationEditor.spec.ts @@ -1,20 +1,10 @@ import * as semver from 'semver'; import { test, expect, AnnotationPage } from '../../../../src'; -import { REDSHIFT_SCHEMAS } from '../mocks/resource'; -test('should load resources and display them as options when clicking on an input', async ({ - annotationEditPage, - page, - selectors, - readProvisionedDataSource, -}) => { - await annotationEditPage.mockResourceResponse('schemas', REDSHIFT_SCHEMAS); - const ds = await readProvisionedDataSource({ fileName: 'redshift.yaml' }); +test('should render annotations editor', async ({ annotationEditPage, page, readProvisionedDataSource }) => { + const ds = await readProvisionedDataSource({ fileName: 'testdatasource.yaml' }); await annotationEditPage.datasource.set(ds.name); - await page.getByLabel('Schema').click(); - await expect(annotationEditPage.getByGrafanaSelector(selectors.components.Select.option)).toContainText( - REDSHIFT_SCHEMAS - ); + await expect(page.getByRole('textbox', { name: 'Query Text' })).toBeVisible(); }); test('should be able to add a new annotation when annotations already exist', async ({ @@ -24,7 +14,7 @@ test('should be able to add a new annotation when annotations already exist', as request, readProvisionedDashboard, }, testInfo) => { - const dashboard = await readProvisionedDashboard({ fileName: 'redshift.json' }); + const dashboard = await readProvisionedDashboard({ fileName: 'testdatasource-annotations.json' }); const annotationPage = new AnnotationPage({ page, selectors, grafanaVersion, request, testInfo }, dashboard); await annotationPage.goto(); await annotationPage.clickAddNew(); diff --git a/packages/plugin-e2e/tests/as-admin-user/datasource/annotations/annotationQueryRunner.integration.spec.ts b/packages/plugin-e2e/tests/as-admin-user/datasource/annotations/annotationQueryRunner.integration.spec.ts deleted file mode 100644 index 5a9b3536e..000000000 --- a/packages/plugin-e2e/tests/as-admin-user/datasource/annotations/annotationQueryRunner.integration.spec.ts +++ /dev/null @@ -1,48 +0,0 @@ -import * as semver from 'semver'; -import semverLt from 'semver/functions/lt'; -import { test, expect } from '../../../../src'; - -test.describe('annotation edit page', { tag: '@integration' }, () => { - test('should run successfully if valid Redshift query was provided', async ({ - annotationEditPage, - page, - selectors, - readProvisionedDataSource, - grafanaVersion, - }, testInfo) => { - testInfo.skip(semverLt(grafanaVersion, '9.2.0'), 'Code editor seems to trigger one query per character typed'); - const ds = await readProvisionedDataSource({ fileName: 'redshift.yaml' }); - await annotationEditPage.datasource.set(ds.name); - await page.waitForFunction(() => (window as any).monaco); - await annotationEditPage.getByGrafanaSelector(selectors.components.CodeEditor.container).click(); - await page.keyboard.insertText('SELECT starttime, eventname FROM event ORDER BY eventname ASC LIMIT 5 '); - await expect(annotationEditPage.runQuery()).toBeOK(); - await expect(page.getByText('.38 Special')).toBeTruthy(); - }); - - test('should run successfully if valid Google Sheets query was provided', async ({ - annotationEditPage, - page, - readProvisionedDataSource, - }) => { - const ds = await readProvisionedDataSource({ fileName: 'google-sheets-datasource-jwt.yaml' }); - await annotationEditPage.datasource.set(ds.name); - await page.getByText('Enter SpreadsheetID').click(); - await page.keyboard.insertText('1TZlZX67Y0s4CvRro_3pCYqRCKuXer81oFp_xcsjPpe8'); - await page.keyboard.press('Enter'); - await expect(annotationEditPage.runQuery()).toBeOK(); - }); - - test('should run successfully if valid Redshift query was provided in provisioned dashboard', async ({ - gotoAnnotationEditPage, - readProvisionedDashboard, - grafanaVersion, - }) => { - const dashboard = await readProvisionedDashboard({ fileName: 'redshift.json' }); - const annotationEditPage = await gotoAnnotationEditPage({ dashboard, id: '1' }); - await expect(annotationEditPage.runQuery()).toBeOK(); - if (semver.gte(grafanaVersion, '11.0.0')) { - await expect(annotationEditPage).toHaveAlert('warning', { hasText: 'No events found' }); - } - }); -}); diff --git a/packages/plugin-e2e/tests/as-admin-user/datasource/annotations/annotationQueryRunner.spec.ts b/packages/plugin-e2e/tests/as-admin-user/datasource/annotations/annotationQueryRunner.spec.ts new file mode 100644 index 000000000..fc0e8cb3a --- /dev/null +++ b/packages/plugin-e2e/tests/as-admin-user/datasource/annotations/annotationQueryRunner.spec.ts @@ -0,0 +1,46 @@ +import * as semver from 'semver'; +import semverLt from 'semver/functions/lt'; +import { test, expect } from '../../../../src'; + +test('create new, successful annotation query', async ({ + grafanaVersion, + annotationEditPage, + readProvisionedDataSource, + page, +}) => { + const ds = await readProvisionedDataSource({ fileName: 'testdatasource.yaml' }); + await annotationEditPage.datasource.set(ds.name); + await page.getByRole('textbox', { name: 'Query Text' }).fill('annotationQuery'); + await expect(annotationEditPage.runQuery()).toBeOK(); + if (semver.gte(grafanaVersion, '11.0.0')) { + await expect(annotationEditPage).toHaveAlert('success'); + } +}); + +test('create new, unsuccessful annotation query', async ({ + grafanaVersion, + annotationEditPage, + readProvisionedDataSource, + page, +}) => { + const ds = await readProvisionedDataSource({ fileName: 'testdatasource.yaml' }); + await annotationEditPage.datasource.set(ds.name); + await page.getByRole('textbox', { name: 'Query Text' }).fill('error'); + await expect(annotationEditPage.runQuery()).not.toBeOK(); + if (semver.gte(grafanaVersion, '11.0.0')) { + await expect(annotationEditPage).toHaveAlert('error'); + } +}); + +test('open provisioned, successful annotation query', async ({ + grafanaVersion, + gotoAnnotationEditPage, + readProvisionedDashboard, +}) => { + const dashboard = await readProvisionedDashboard({ fileName: 'testdatasource-annotations.json' }); + const annotationEditPage = await gotoAnnotationEditPage({ dashboard, id: '1' }); + await expect(annotationEditPage.runQuery()).toBeOK(); + if (semver.gte(grafanaVersion, '11.0.0')) { + await expect(annotationEditPage).toHaveAlert('success'); + } +}); diff --git a/packages/plugin-e2e/tests/as-admin-user/datasource/config-editor/configEditor.spec.ts b/packages/plugin-e2e/tests/as-admin-user/datasource/config-editor/configEditor.spec.ts index 2c0717566..82d2ebf3f 100644 --- a/packages/plugin-e2e/tests/as-admin-user/datasource/config-editor/configEditor.spec.ts +++ b/packages/plugin-e2e/tests/as-admin-user/datasource/config-editor/configEditor.spec.ts @@ -1,11 +1,34 @@ import { expect, test } from '../../../../src'; import { clickRadioButton } from '../../../utils'; -test('invalid credentials should return an error', async ({ createDataSourceConfigPage, page }) => { - const configPage = await createDataSourceConfigPage({ type: 'grafana-googlesheets-datasource' }); - await clickRadioButton(page, 'API Key', { exact: true }); - await page.getByPlaceholder('Enter API key').fill('xyz'); - await expect(configPage.saveAndTest()).not.toBeOK(); +test('should render config editor', async ({ createDataSourceConfigPage, readProvisionedDataSource, page }) => { + const ds = await readProvisionedDataSource({ fileName: 'testdatasource.yaml' }); + await createDataSourceConfigPage({ type: ds.type }); + await expect(page.getByLabel('Path')).toBeVisible(); +}); + +test('should be successful if config is valid', async ({ + createDataSourceConfigPage, + readProvisionedDataSource, + page, +}) => { + const ds = await readProvisionedDataSource({ fileName: 'testdatasource.yaml' }); + const datasourceConfigPage = await createDataSourceConfigPage({ type: ds.type }); + await page.getByLabel('Path').fill('example.com'); + await expect(datasourceConfigPage.saveAndTest()).toBeOK(); + await expect(datasourceConfigPage).toHaveAlert('success'); +}); + +test('should return error if API key is missing', async ({ + createDataSourceConfigPage, + readProvisionedDataSource, + page, +}) => { + const ds = await readProvisionedDataSource({ fileName: 'testdatasource.yaml' }); + const datasourceConfigPage = await createDataSourceConfigPage({ type: ds.type }); + await page.getByLabel('Path').fill(''); + await expect(datasourceConfigPage.saveAndTest()).not.toBeOK(); + await expect(datasourceConfigPage).toHaveAlert('error', { hasText: 'API key is missing' }); }); test('should call a custom health endpoint when healthCheckPath is provided', async ({ @@ -25,13 +48,3 @@ test('should call a custom health endpoint when healthCheckPath is provided', as await expect(configPage.saveAndTest({ path: healthCheckPath })).toBeOK(); await expect(configPage).toHaveAlert('success', { hasNotText: 'Datasource updated' }); }); - -test( - 'existing ds instance - valid credentials should return a 200 status code', - { tag: '@integration' }, - async ({ readProvisionedDataSource, gotoDataSourceConfigPage }) => { - const datasource = await readProvisionedDataSource({ fileName: 'google-sheets-datasource-jwt.yaml' }); - const configPage = await gotoDataSourceConfigPage(datasource.uid); - await expect(configPage.saveAndTest()).toBeOK(); - } -); diff --git a/packages/plugin-e2e/tests/as-admin-user/datasource/dashboards/dashboard.spec.ts b/packages/plugin-e2e/tests/as-admin-user/datasource/dashboards/dashboard.spec.ts index b16eb20f8..d7f64a310 100644 --- a/packages/plugin-e2e/tests/as-admin-user/datasource/dashboards/dashboard.spec.ts +++ b/packages/plugin-e2e/tests/as-admin-user/datasource/dashboards/dashboard.spec.ts @@ -1,7 +1,7 @@ import { expect, test } from '../../../../src'; test('add panel in already existing dashboard', async ({ gotoDashboardPage, readProvisionedDashboard, page }) => { - const dashboard = await readProvisionedDashboard({ fileName: 'redshift.json' }); + const dashboard = await readProvisionedDashboard({ fileName: 'testdatasource.json' }); const dashboardPage = await gotoDashboardPage(dashboard); await dashboardPage.addPanel(); await expect(page.url()).toContain('editPanel'); diff --git a/packages/plugin-e2e/tests/as-admin-user/datasource/data-assertions/dataAssertion.spec.ts b/packages/plugin-e2e/tests/as-admin-user/datasource/data-assertions/dataAssertion.spec.ts index c4e40f457..ce5bcc141 100644 --- a/packages/plugin-e2e/tests/as-admin-user/datasource/data-assertions/dataAssertion.spec.ts +++ b/packages/plugin-e2e/tests/as-admin-user/datasource/data-assertions/dataAssertion.spec.ts @@ -1,59 +1,49 @@ import * as semver from 'semver'; import { test, expect } from '../../../../src'; -test.describe( - 'panel edit page', - { - tag: '@integration', - }, - () => { - test('table panel data assertions', async ({ gotoPanelEditPage, readProvisionedDashboard }, testInfo) => { - const dashboard = await readProvisionedDashboard({ fileName: 'redshift.json' }); - const panelEditPage = await gotoPanelEditPage({ dashboard, id: '3' }); - await panelEditPage.setVisualization('Table'); - await expect(panelEditPage.panel.locator).toBeVisible(); - await expect(panelEditPage.panel.data).toContainText(['staging']); - await expect(panelEditPage.panel.fieldNames).toContainText(['time', 'temperature']); - }); +test.describe('panel edit page', () => { + test('table panel data assertions', async ({ gotoPanelEditPage, readProvisionedDashboard }, testInfo) => { + const dashboard = await readProvisionedDashboard({ fileName: 'testdatasource.json' }); + const panelEditPage = await gotoPanelEditPage({ dashboard, id: '2' }); + await expect(panelEditPage.panel.locator).toBeVisible(); + await expect(panelEditPage.panel.data).toContainText(['22.2', '70', 'Staging']); + await expect(panelEditPage.panel.fieldNames).toContainText(['time', 'temperature', 'humidity', 'environment']); + }); - test('timeseries panel - table view assertions', async ({ readProvisionedDashboard, gotoPanelEditPage }) => { - const dashboard = await readProvisionedDashboard({ fileName: 'google-sheets.json' }); - const panelEditPage = await gotoPanelEditPage({ dashboard, id: '1' }); - await panelEditPage.setVisualization('Time series'); - await panelEditPage.toggleTableView(); - await expect(panelEditPage.panel.fieldNames).toContainText(['Stockholm', 'Berlin']); - await expect(panelEditPage.panel.data).toContainText(['-1', '2.90']); - }); - } -); + test('timeseries panel - table view assertions', async ({ readProvisionedDashboard, gotoPanelEditPage }) => { + const dashboard = await readProvisionedDashboard({ fileName: 'testdatasource.json' }); + const panelEditPage = await gotoPanelEditPage({ dashboard, id: '4' }); + await panelEditPage.toggleTableView(); + await expect(panelEditPage.panel.fieldNames).toContainText(['time', 'temperature', 'humidity', 'environment']); + await expect(panelEditPage.panel.data).toContainText(['22.2', '70', 'Staging']); + }); +}); -test.describe('dashboard page', { tag: '@integration' }, () => { +test.describe('dashboard page', () => { test('getting panel by title', async ({ readProvisionedDashboard, gotoDashboardPage }) => { - const dashboard = await readProvisionedDashboard({ fileName: 'redshift.json' }); + const dashboard = await readProvisionedDashboard({ fileName: 'testdatasource.json' }); const dashboardPage = await gotoDashboardPage(dashboard); - const panel = await dashboardPage.getPanelByTitle('Basic table example'); + const panel = await dashboardPage.getPanelByTitle('Single row'); + await expect(panel.data).toContainText(['22.2', '70', 'Staging']); await expect(panel.fieldNames).toContainText(['time', 'temperature', 'humidity', 'environment']); - await expect(panel.data).toContainText(['25', '32', 'staging']); }); test('getting panel by id', async ({ gotoDashboardPage, readProvisionedDashboard }) => { - const dashboard = await readProvisionedDashboard({ fileName: 'redshift.json' }); + const dashboard = await readProvisionedDashboard({ fileName: 'testdatasource.json' }); const dashboardPage = await gotoDashboardPage(dashboard); - const panel = await dashboardPage.getPanelById('3'); + const panel = await dashboardPage.getPanelById('2'); + await expect(panel.data).toContainText(['22.2', '70', 'Staging']); await expect(panel.fieldNames).toContainText(['time', 'temperature', 'humidity', 'environment']); - await expect(panel.data).toContainText(['25', '32', 'staging']); }); }); test.describe('explore page', () => { test('table panel', async ({ grafanaVersion, explorePage }) => { - const url = semver.lt('10.0.0', grafanaVersion) - ? `panes=%7B"_t4":%7B"datasource":"grafana","queries":%5B%7B"queryType":"randomWalk","refId":"A","datasource":%7B"type":"datasource","uid":"grafana"%7D%7D%5D,"range":%7B"from":"now-6h","to":"now"%7D%7D%7D&orgId=1&left=%7B"datasource":"grafana","queries":%5B%7B"refId":"A","datasource":%7B"type":"datasource","uid":"grafana"%7D,"queryType":"randomWalk"%7D%5D,"range":%7B"from":"now-1h","to":"now"%7D%7D` - : 'left=%7B"datasource":"grafana","queries":%5B%7B"queryType":"randomWalk","refId":"A","datasource":%7B"type":"datasource","uid":"grafana"%7D%7D%5D,"range":%7B"from":"1547161200000","to":"1576364400000"%7D%7D&orgId=1'; + const params = semver.lt(grafanaVersion, '10.0.0') + ? 'left=%7B"datasource":"grafana","queries":%5B%7B"queryType":"randomWalk","refId":"A","datasource":%7B"type":"datasource","uid":"grafana"%7D%7D%5D,"range":%7B"from":"1547161200000","to":"1576364400000"%7D%7D&orgId=1' + : `panes=%7B"_t4":%7B"datasource":"grafana","queries":%5B%7B"queryType":"randomWalk","refId":"A","datasource":%7B"type":"datasource","uid":"grafana"%7D%7D%5D,"range":%7B"from":"now-6h","to":"now"%7D%7D%7D&orgId=1&left=%7B"datasource":"grafana","queries":%5B%7B"refId":"A","datasource":%7B"type":"datasource","uid":"grafana"%7D,"queryType":"randomWalk"%7D%5D,"range":%7B"from":"now-1h","to":"now"%7D%7D`; - await explorePage.goto({ - queryParams: new URLSearchParams(url), - }); + await explorePage.goto({ queryParams: new URLSearchParams(params) }); await expect(explorePage.tablePanel.fieldNames).toContainText(['time', 'A-series']); }); diff --git a/packages/plugin-e2e/tests/as-admin-user/datasource/explore/queryEditor.integration.spec.ts b/packages/plugin-e2e/tests/as-admin-user/datasource/explore/queryEditor.integration.spec.ts index 5be43ac10..d79c52596 100644 --- a/packages/plugin-e2e/tests/as-admin-user/datasource/explore/queryEditor.integration.spec.ts +++ b/packages/plugin-e2e/tests/as-admin-user/datasource/explore/queryEditor.integration.spec.ts @@ -1,37 +1,24 @@ const semver = require('semver'); import { expect, test } from '../../../../src'; -test( - 'should return data and not display panel error when a valid query is provided', - { tag: '@integration' }, - async ({ explorePage, page, readProvisionedDataSource }) => { - const ds = await readProvisionedDataSource({ fileName: 'google-sheets-datasource-jwt.yaml' }); - await explorePage.datasource.set(ds.name); - await explorePage.timeRange.set({ from: '2019-01-11', to: '2019-12-15' }); - await explorePage.getQueryEditorRow('A').getByText('Enter SpreadsheetID').click(); - await page.keyboard.insertText('1TZlZX67Y0s4CvRro_3pCYqRCKuXer81oFp_xcsjPpe8'); - const responsePromise = page.waitForResponse((resp) => resp.url().includes('/api/ds/query')); - await page.keyboard.press('Tab'); - await responsePromise; - await expect(explorePage.runQuery()).toBeOK(); - } -); - -test('should return an error and display panel error when an invalid query is provided', async ({ +test('should return data and not display panel error when a valid query is provided', async ({ + explorePage, + readProvisionedDataSource, +}) => { + const ds = await readProvisionedDataSource({ fileName: 'testdatasource.yaml' }); + await explorePage.datasource.set(ds.name); + const editorRow = await explorePage.getQueryEditorRow('A'); + await editorRow.getByRole('textbox', { name: 'Query Text' }).fill('query'); + await expect(explorePage.runQuery()).toBeOK(); +}); +test('should return an error and display panel error when query is invalid', async ({ explorePage, - page, readProvisionedDataSource, }) => { - const ds = await readProvisionedDataSource({ fileName: 'google-sheets-datasource-jwt.yaml' }); + const ds = await readProvisionedDataSource({ fileName: 'testdatasource.yaml' }); await explorePage.datasource.set(ds.name); - await explorePage.timeRange.set({ from: '2019-01-11', to: '2019-12-15' }); - await page.getByPlaceholder('Class Data!A2:E').fill('invalid range'); - await page.keyboard.press('Tab'); - await explorePage.getQueryEditorRow('A').getByText('Enter SpreadsheetID').click(); - await page.keyboard.insertText('1TZlZX67Y0s4CvRro_3pCYqRCKuXer81oFp_xcsjPpe8'); - const responsePromise = page.waitForResponse((resp) => resp.url().includes('/api/ds/query')); - await page.keyboard.press('Tab'); - await responsePromise; + const editorRow = await explorePage.getQueryEditorRow('A'); + await editorRow.getByRole('textbox', { name: 'Query Text' }).fill('error'); await expect(explorePage.runQuery()).not.toBeOK(); }); @@ -39,13 +26,11 @@ test('explore page should display table and time series panel only for certain q explorePage, grafanaVersion, }) => { - const url = semver.lt('10.0.0', grafanaVersion) - ? `panes=%7B"_t4":%7B"datasource":"grafana","queries":%5B%7B"queryType":"randomWalk","refId":"A","datasource":%7B"type":"datasource","uid":"grafana"%7D%7D%5D,"range":%7B"from":"now-6h","to":"now"%7D%7D%7D&orgId=1&left=%7B"datasource":"grafana","queries":%5B%7B"refId":"A","datasource":%7B"type":"datasource","uid":"grafana"%7D,"queryType":"randomWalk"%7D%5D,"range":%7B"from":"now-1h","to":"now"%7D%7D` - : 'left=%7B"datasource":"PB0CCE99F8730D01D","queries":%5B%7B"cacheDurationSeconds":300,"datasource":%7B"type":"grafana-googlesheets-datasource","uid":"PB0CCE99F8730D01D"%7D,"refId":"A","spreadsheet":"1TZlZX67Y0s4CvRro_3pCYqRCKuXer81oFp_xcsjPpe8","range":""%7D%5D,"range":%7B"from":"1547161200000","to":"1576364400000"%7D%7D&orgId=1'; + const params = semver.lt(grafanaVersion, '10.0.0') + ? 'left=%7B"datasource":"grafana","queries":%5B%7B"queryType":"randomWalk","refId":"A","datasource":%7B"type":"datasource","uid":"grafana"%7D%7D%5D,"range":%7B"from":"1547161200000","to":"1576364400000"%7D%7D&orgId=1' + : `panes=%7B"_t4":%7B"datasource":"grafana","queries":%5B%7B"queryType":"randomWalk","refId":"A","datasource":%7B"type":"datasource","uid":"grafana"%7D%7D%5D,"range":%7B"from":"now-6h","to":"now"%7D%7D%7D&orgId=1&left=%7B"datasource":"grafana","queries":%5B%7B"refId":"A","datasource":%7B"type":"datasource","uid":"grafana"%7D,"queryType":"randomWalk"%7D%5D,"range":%7B"from":"now-1h","to":"now"%7D%7D`; - await explorePage.goto({ - queryParams: new URLSearchParams(url), - }); + await explorePage.goto({ queryParams: new URLSearchParams(params) }); await expect(explorePage.timeSeriesPanel.locator).toBeVisible(); await expect(explorePage.tablePanel.locator).toBeVisible(); diff --git a/packages/plugin-e2e/tests/as-admin-user/datasource/explore/queryEditor.spec.ts b/packages/plugin-e2e/tests/as-admin-user/datasource/explore/queryEditor.spec.ts index 6e282dc35..a2abc06ab 100644 --- a/packages/plugin-e2e/tests/as-admin-user/datasource/explore/queryEditor.spec.ts +++ b/packages/plugin-e2e/tests/as-admin-user/datasource/explore/queryEditor.spec.ts @@ -1,11 +1,13 @@ +import * as semver from 'semver'; import { expect, test } from '../../../../src'; -test('editor populates query from url', async ({ explorePage }) => { - await explorePage.goto({ - queryParams: new URLSearchParams( - `panes=%7B%22xlX%22:%7B%22datasource%22:%22undefined%22,%22queries%22:%5B%7B%22refId%22:%22A%22,%22datasource%22:%7B%22type%22:%22grafana-redshift-datasource%22,%22uid%22:%22P7DC3E4760CFAC4AH%22%7D,%22rawSQL%22:%22SELECT%20%2A%20FROM%20public.average_temperature%22,%22format%22:0%7D%5D,%22range%22:%7B%22from%22:%221579046400000%22,%22to%22:%221607990400000%22%7D%7D%7D&schemaVersion=1&orgId=1&left=%7B%22datasource%22:%22P7DC3E4760CFAC4AH%22,%22queries%22:%5B%7B%22refId%22:%22A%22,%22datasource%22:%7B%22type%22:%22grafana-redshift-datasource%22,%22uid%22:%22P7DC3E4760CFAC4AH%22%7D,%22rawSQL%22:%22SELECT%20%2A%20FROM%20public.average_temperature%22,%22format%22:0%7D%5D,%22range%22:%7B%22from%22:%22now-1h%22,%22to%22:%22now%22%7D%7D` - ), - }); +test('editor populates query from url', async ({ explorePage, grafanaVersion }) => { + const params = semver.lt(grafanaVersion, '10.1.0') + ? 'orgId=1&left=%7B"datasource":"P6E498B96656A7F9B","queries":%5B%7B"refId":"A","datasource":%7B"type":"grafana-test-datasource","uid":"P6E498B96656A7F9B"%7D,"constant":9,"project":"project-2","queryText":"test%20query"%7D%5D,"range":%7B"from":"now-1h","to":"now"%7D%7D' + : `?schemaVersion=1&panes=%7B"9ye":%7B"datasource":"P6E498B96656A7F9B","queries":%5B%7B"constant":9,"refId":"A","datasource":%7B"type":"grafana-test-datasource","uid":"P6E498B96656A7F9B"%7D,"queryText":"test%20query"%7D%5D,"range":%7B"from":"now-1h","to":"now"%7D%7D%7D&orgId=1`; + + await explorePage.goto({ queryParams: new URLSearchParams(params) }); const queryEditorRowLocator = explorePage.getQueryEditorRow('A'); - await expect(queryEditorRowLocator).toContainText('SELECT * FROM public.average_temperature'); + await expect(queryEditorRowLocator.getByRole('textbox', { name: 'Query Text' })).toHaveValue('test query'); + await expect(queryEditorRowLocator.getByRole('spinbutton', { name: 'Constant' })).toHaveValue('9'); }); diff --git a/packages/plugin-e2e/tests/as-admin-user/datasource/feature-toggles/queryEditor.async.spec.ts b/packages/plugin-e2e/tests/as-admin-user/datasource/feature-toggles/queryEditor.async.spec.ts deleted file mode 100644 index b6bcee99c..000000000 --- a/packages/plugin-e2e/tests/as-admin-user/datasource/feature-toggles/queryEditor.async.spec.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { expect, test } from '../../../../src'; - -const TRUTHY_CUSTOM_TOGGLE = 'custom_toggle1'; -const FALSY_CUSTOM_TOGGLE = 'custom_toggle2'; - -// override the feature toggles defined in playwright.config.ts only for tests in this file -test.use({ - featureToggles: { - redshiftAsyncQueryDataSupport: true, - [TRUTHY_CUSTOM_TOGGLE]: true, - [FALSY_CUSTOM_TOGGLE]: false, - }, -}); - -test('should set feature toggles correctly', async ({ isFeatureToggleEnabled }) => { - expect(await isFeatureToggleEnabled(TRUTHY_CUSTOM_TOGGLE)).toBeTruthy(); - expect(await isFeatureToggleEnabled(FALSY_CUSTOM_TOGGLE)).toBeFalsy(); -}); - -test( - 'async query data handler should return a `finished` status', - { tag: '@integration' }, - async ({ selectors, panelEditPage, page, readProvisionedDataSource }) => { - const ds = await readProvisionedDataSource({ fileName: 'redshift.yaml' }); - await panelEditPage.datasource.set(ds.name); - await panelEditPage.timeRange.set({ from: '2020-01-31', to: '2020-02-20' }); - await page.waitForFunction(() => (window as any).monaco); - await panelEditPage.getByGrafanaSelector(selectors.components.CodeEditor.container).click(); - await page.keyboard.insertText('select * from long_format_example limit 100'); - await expect( - panelEditPage.refreshPanel({ - waitForResponsePredicateCallback: (r) => - r.url().includes(selectors.apis.DataSource.query) && - r.body().then((body) => body.includes(`"status":"finished"`)), - }) - ).toBeOK(); - } -); diff --git a/packages/plugin-e2e/tests/as-admin-user/datasource/feature-toggles/queryEditor.sync.spec.ts b/packages/plugin-e2e/tests/as-admin-user/datasource/feature-toggles/queryEditor.sync.spec.ts deleted file mode 100644 index ee70feef1..000000000 --- a/packages/plugin-e2e/tests/as-admin-user/datasource/feature-toggles/queryEditor.sync.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { expect, test } from '../../../../src'; - -test('standard query data handler should only be called once', async ({ - panelEditPage, - page, - selectors, - readProvisionedDataSource, -}) => { - const requestListener = (request) => request.url().includes(selectors.apis.DataSource.query) && calledTimes++; - - const ds = await readProvisionedDataSource({ fileName: 'redshift.yaml' }); - await panelEditPage.datasource.set(ds.name); - await panelEditPage.timeRange.set({ from: '2020-01-31', to: '2020-02-20' }); - await page.waitForFunction(() => (window as any).monaco); - await panelEditPage.getByGrafanaSelector(selectors.components.CodeEditor.container).click(); - - await page.keyboard.insertText('select * from long_format_example limit 100'); - let calledTimes = 0; - page.on('request', requestListener); - await expect(panelEditPage.refreshPanel()).toBeOK(); - await page.waitForTimeout(2000); - await expect(calledTimes).toBe(1); - page.off('request', requestListener); -}); diff --git a/packages/plugin-e2e/tests/as-admin-user/datasource/feature-toggles/queryEditor.tlsEnabled.spec.ts b/packages/plugin-e2e/tests/as-admin-user/datasource/feature-toggles/queryEditor.tlsEnabled.spec.ts new file mode 100644 index 000000000..29835919b --- /dev/null +++ b/packages/plugin-e2e/tests/as-admin-user/datasource/feature-toggles/queryEditor.tlsEnabled.spec.ts @@ -0,0 +1,33 @@ +import * as semver from 'semver'; +import { expect, test } from '../../../../src'; + +const TRUTHY_CUSTOM_TOGGLE = 'custom_toggle1'; +const FALSY_CUSTOM_TOGGLE = 'custom_toggle2'; + +// override the feature toggles defined in playwright.config.ts only for tests in this file +test.use({ + featureToggles: { + tlsEnabled: true, + [TRUTHY_CUSTOM_TOGGLE]: true, + [FALSY_CUSTOM_TOGGLE]: false, + }, +}); + +test('should set feature toggles correctly', async ({ isFeatureToggleEnabled }) => { + expect(await isFeatureToggleEnabled(TRUTHY_CUSTOM_TOGGLE)).toBeTruthy(); + expect(await isFeatureToggleEnabled(FALSY_CUSTOM_TOGGLE)).toBeFalsy(); +}); + +test('should display TLS enabled field when tlsEnabled feature toggle is set to true', async ({ + gotoPanelEditPage, + readProvisionedDashboard, + grafanaVersion, +}) => { + const dashboard = await readProvisionedDashboard({ fileName: 'testdatasource.json' }); + const panelEditPage = await gotoPanelEditPage({ dashboard, id: '1' }); + const row = panelEditPage.getQueryEditorRow('A'); + const locator = semver.lt(grafanaVersion, '9.3.0') + ? row.locator(`[label="TLS Enabled"]`).locator('../label') + : row.getByLabel('TLS Enabled'); + await expect(locator).toBeVisible(); +}); diff --git a/packages/plugin-e2e/tests/as-admin-user/datasource/feature-toggles/queryEditor.tlsNotEnabled.spec.ts b/packages/plugin-e2e/tests/as-admin-user/datasource/feature-toggles/queryEditor.tlsNotEnabled.spec.ts new file mode 100644 index 000000000..de0a90022 --- /dev/null +++ b/packages/plugin-e2e/tests/as-admin-user/datasource/feature-toggles/queryEditor.tlsNotEnabled.spec.ts @@ -0,0 +1,23 @@ +import * as semver from 'semver'; +import { expect, test } from '../../../../src'; + +// override the feature toggles defined in playwright.config.ts only for tests in this file +test.use({ + featureToggles: { + tlsEnabled: false, + }, +}); + +test('should not display TLS enabled field when tlsEnabled feature toggle is set to false', async ({ + gotoPanelEditPage, + readProvisionedDashboard, + grafanaVersion, +}) => { + const dashboard = await readProvisionedDashboard({ fileName: 'testdatasource.json' }); + const panelEditPage = await gotoPanelEditPage({ dashboard, id: '1' }); + const editorRow = panelEditPage.getQueryEditorRow('A'); + const locator = semver.lt(grafanaVersion, '9.3.0') + ? editorRow.locator(`[label="TLS Enabled"]`).locator('../label') + : editorRow.getByLabel('TLS Enabled'); + await expect(locator).not.toBeVisible(); +}); diff --git a/packages/plugin-e2e/tests/as-admin-user/datasource/mocks/resource.ts b/packages/plugin-e2e/tests/as-admin-user/datasource/mocks/resource.ts deleted file mode 100644 index dc037c49e..000000000 --- a/packages/plugin-e2e/tests/as-admin-user/datasource/mocks/resource.ts +++ /dev/null @@ -1,9 +0,0 @@ -export const GOOGLE_SHEETS_SPREADSHEETS = { - spreadsheets: { - sheet1: 'Datasource test spreadsheet', - sheet2: 'Google Sheets Datasource - Average Temperature', - }, -}; - -export const REDSHIFT_SCHEMAS = ['public', 'test']; -export const REDSHIFT_TABLES = ['custom-namespace1', 'custom-namespace2']; diff --git a/packages/plugin-e2e/tests/as-admin-user/datasource/query-editor/queryEditor.integration.spec.ts b/packages/plugin-e2e/tests/as-admin-user/datasource/query-editor/queryEditor.integration.spec.ts index 40d6df9d0..0a7d77e6d 100644 --- a/packages/plugin-e2e/tests/as-admin-user/datasource/query-editor/queryEditor.integration.spec.ts +++ b/packages/plugin-e2e/tests/as-admin-user/datasource/query-editor/queryEditor.integration.spec.ts @@ -5,32 +5,32 @@ test('should return data and not display panel error when a valid query is provi page, readProvisionedDataSource, }) => { - const ds = await readProvisionedDataSource({ - fileName: 'google-sheets-datasource-jwt.yaml', - }); + const ds = await readProvisionedDataSource({ fileName: 'testdatasource.yaml' }); await panelEditPage.datasource.set(ds.name); - await panelEditPage.timeRange.set({ from: '2019-01-11', to: '2019-12-15' }); - await panelEditPage.getQueryEditorRow('A').getByText('Enter SpreadsheetID').click(); - await page.keyboard.insertText('1TZlZX67Y0s4CvRro_3pCYqRCKuXer81oFp_xcsjPpe8'); - await page.keyboard.press('Enter'); + const editorRow = await panelEditPage.getQueryEditorRow('A'); + await editorRow.getByRole('textbox', { name: 'Query Text' }).fill('query'); await expect(panelEditPage.refreshPanel()).toBeOK(); await expect(panelEditPage.panel.getErrorIcon()).not.toBeVisible(); }); -test('should return an error and display panel error when an invalid query is provided', async ({ +test('should return an error and display panel error when query is invalid', async ({ panelEditPage, - page, readProvisionedDataSource, }) => { - const ds = await readProvisionedDataSource({ - fileName: 'google-sheets-datasource-jwt.yaml', - }); + const ds = await readProvisionedDataSource({ fileName: 'testdatasource.yaml' }); await panelEditPage.datasource.set(ds.name); - await panelEditPage.timeRange.set({ from: '2019-01-11', to: '2019-12-15' }); - await panelEditPage.getQueryEditorRow('A').getByText('Enter SpreadsheetID').click(); - await page.keyboard.insertText('1TZlZX67Y0s4CvRro_3pCYqRCKuXer81oFp_xcsjPpe8'); - await page.keyboard.press('Enter'); - await page.getByPlaceholder('Class Data!A2:E').fill('invalid range'); + const editorRow = await panelEditPage.getQueryEditorRow('A'); + await editorRow.getByRole('textbox', { name: 'Query Text' }).fill('error'); await expect(panelEditPage.refreshPanel()).not.toBeOK(); await expect(panelEditPage.panel.getErrorIcon()).toBeVisible(); }); + +test('should be possible to load and execute an existing valid query', async ({ + gotoPanelEditPage, + readProvisionedDashboard, +}) => { + const dashboard = await readProvisionedDashboard({ fileName: 'testdatasource.json' }); + const panelEditPage = await gotoPanelEditPage({ dashboard, id: '1' }); + await expect(panelEditPage.refreshPanel()).toBeOK(); + await expect(panelEditPage.panel.getErrorIcon()).not.toBeVisible(); +}); diff --git a/packages/plugin-e2e/tests/as-admin-user/datasource/query-editor/queryEditor.spec.ts b/packages/plugin-e2e/tests/as-admin-user/datasource/query-editor/queryEditor.spec.ts index 60daff97f..fbad41d41 100644 --- a/packages/plugin-e2e/tests/as-admin-user/datasource/query-editor/queryEditor.spec.ts +++ b/packages/plugin-e2e/tests/as-admin-user/datasource/query-editor/queryEditor.spec.ts @@ -1,60 +1,33 @@ import { expect, test } from '../../../../src'; -import { GOOGLE_SHEETS_SPREADSHEETS } from '../mocks/resource'; -export interface SheetsJsonData { - authenticationType: string; - tokenUri?: string; - clientEmail?: string; - defaultProject?: string; - privateKeyPath?: string; -} - -export interface SheetsSecureJsonData { - privateKey?: string; -} - -test('should list spreadsheets when clicking on spreadsheet segment', async ({ - panelEditPage, - page, - readProvisionedDataSource, -}) => { - const ds = await readProvisionedDataSource({ - fileName: 'google-sheets-datasource-jwt.yaml', - }); +test('should render query editor', async ({ panelEditPage, readProvisionedDataSource }) => { + const ds = await readProvisionedDataSource({ fileName: 'testdatasource.yaml' }); await panelEditPage.datasource.set(ds.name); - await panelEditPage.mockResourceResponse('spreadsheets', GOOGLE_SHEETS_SPREADSHEETS); - await panelEditPage.getQueryEditorRow('A').getByText('Enter SpreadsheetID').click(); - await expect(page.getByText(GOOGLE_SHEETS_SPREADSHEETS.spreadsheets.sheet1, { exact: true })).toHaveCount(1); - await expect(page.getByText(GOOGLE_SHEETS_SPREADSHEETS.spreadsheets.sheet2, { exact: true })).toHaveCount(1); + await expect(panelEditPage.getQueryEditorRow('A').getByRole('textbox', { name: 'Query Text' })).toBeVisible(); }); -test('should set correct cache time on query passed to the backend', async ({ +test('should list projects when clicking the projects drowndown', async ({ panelEditPage, - page, + selectors, readProvisionedDataSource, }) => { - const ds = await readProvisionedDataSource({ fileName: 'google-sheets-datasource-jwt.yaml' }); + const ds = await readProvisionedDataSource({ fileName: 'testdatasource.yaml' }); await panelEditPage.datasource.set(ds.name); - await panelEditPage.mockResourceResponse('spreadsheets', GOOGLE_SHEETS_SPREADSHEETS); - await panelEditPage.getQueryEditorRow('A').getByText('5m', { exact: true }).click(); - await page.keyboard.insertText('1h'); - await page.keyboard.press('Enter'); - - const queryReq = panelEditPage.waitForQueryDataRequest((request) => - (request.postData() ?? '').includes('"cacheDurationSeconds":3600') - ); - - await panelEditPage.refreshPanel(); - await expect(await queryReq).toBeTruthy(); + await panelEditPage.getQueryEditorRow('A').getByRole('combobox', { name: 'Projects' }).click(); + await expect(panelEditPage.getByGrafanaSelector(selectors.components.Select.option)).toHaveText([ + 'project-1', + 'project-2', + ]); }); test('backToDashboard method should be backwards compatible and navigate to dashboard page', async ({ - gotoPanelEditPage, + gotoDashboardPage, readProvisionedDashboard, page, }) => { - const dashboard = await readProvisionedDashboard({ fileName: 'redshift.json' }); - const panelEditPage = await gotoPanelEditPage({ dashboard, id: '3' }); + const dashboard = await readProvisionedDashboard({ fileName: 'testdatasource.json' }); + const dashboardPage = await gotoDashboardPage(dashboard); + const panelEditPage = await dashboardPage.addPanel(); await panelEditPage.backToDashboard(); await expect(page.url()).not.toContain('editPanel'); }); diff --git a/packages/plugin-e2e/tests/as-admin-user/datasource/variables/customVariableEditor.spec.ts b/packages/plugin-e2e/tests/as-admin-user/datasource/variables/customVariableEditor.spec.ts deleted file mode 100644 index ae9541dcb..000000000 --- a/packages/plugin-e2e/tests/as-admin-user/datasource/variables/customVariableEditor.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { expect, test } from '../../../../src'; -import { REDSHIFT_SCHEMAS, REDSHIFT_TABLES } from '../mocks/resource'; - -test('should load resources and display them as options when clicking on an input', async ({ - variableEditPage, - page, - selectors, - readProvisionedDataSource, -}) => { - await variableEditPage.mockResourceResponse('schemas', REDSHIFT_SCHEMAS); - await variableEditPage.mockResourceResponse('tables', REDSHIFT_TABLES); - const ds = await readProvisionedDataSource({ fileName: 'redshift.yaml' }); - await variableEditPage.setVariableType('Query'); - await variableEditPage.datasource.set(ds.name); - await page.getByLabel('Schema').click(); - await expect(variableEditPage.getByGrafanaSelector(selectors.components.Select.option)).toContainText( - REDSHIFT_SCHEMAS - ); - await page.keyboard.press('Enter'); - await page.getByLabel('Table').click(); - await expect(variableEditPage.getByGrafanaSelector(selectors.components.Select.option)).toContainText( - REDSHIFT_TABLES - ); -}); diff --git a/packages/plugin-e2e/tests/as-admin-user/datasource/variables/customVariableQueryRunner.integration.spec.ts b/packages/plugin-e2e/tests/as-admin-user/datasource/variables/customVariableQueryRunner.integration.spec.ts deleted file mode 100644 index 2c598c72b..000000000 --- a/packages/plugin-e2e/tests/as-admin-user/datasource/variables/customVariableQueryRunner.integration.spec.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { expect, test } from '../../../../src'; - -test.describe('custom variable editor query runner', { tag: '@integration' }, () => { - test('custom variable editor query runner should return data when query is valid', async ({ - variableEditPage, - page, - readProvisionedDataSource, - selectors, - }) => { - const ds = await readProvisionedDataSource({ fileName: 'redshift.yaml' }); - await variableEditPage.setVariableType('Query'); - await variableEditPage.datasource.set(ds.name); - await page.waitForFunction(() => (window as any).monaco); - await variableEditPage.getByGrafanaSelector(selectors.components.CodeEditor.container).click(); - await page.keyboard.insertText('select distinct(environment) from long_format_example'); - const queryDataRequest = variableEditPage.waitForQueryDataRequest(); - await variableEditPage.runQuery(); - await queryDataRequest; - await expect(variableEditPage).toDisplayPreviews([/stag.*/, 'test']); - }); - - test('custom variable editor query runner should return data when valid query from provisioned dashboard is used', async ({ - readProvisionedDashboard, - gotoVariableEditPage, - }) => { - const dashboard = await readProvisionedDashboard({ fileName: 'redshift.json' }); - const variableEditPage = await gotoVariableEditPage({ dashboard, id: '2' }); - const queryDataRequest = variableEditPage.waitForQueryDataRequest(); - await variableEditPage.runQuery(); - await queryDataRequest; - await expect(variableEditPage).toDisplayPreviews(['staging', 'test']); - }); -}); diff --git a/packages/plugin-e2e/tests/as-admin-user/datasource/variables/variableEditor.spec.ts b/packages/plugin-e2e/tests/as-admin-user/datasource/variables/variableEditor.spec.ts new file mode 100644 index 000000000..76b16a3e4 --- /dev/null +++ b/packages/plugin-e2e/tests/as-admin-user/datasource/variables/variableEditor.spec.ts @@ -0,0 +1,33 @@ +import { expect, test } from '../../../../src'; + +test('should render variable editor', async ({ variableEditPage, page, readProvisionedDataSource }) => { + const ds = await readProvisionedDataSource({ fileName: 'testdatasource.yaml' }); + await variableEditPage.datasource.set(ds.name); + await expect(page.getByRole('textbox', { name: 'Query Text' })).toBeVisible(); +}); + +test('create new variable and execute successful query', async ({ + variableEditPage, + readProvisionedDataSource, + page, +}) => { + const ds = await readProvisionedDataSource({ fileName: 'testdatasource.yaml' }); + await variableEditPage.datasource.set(ds.name); + await page.getByRole('textbox', { name: 'Query Text' }).fill('annotationQuery'); + const queryDataRequest = variableEditPage.waitForQueryDataRequest(); + await variableEditPage.runQuery(); + await queryDataRequest; + await expect(variableEditPage).toDisplayPreviews(['A', 'B']); +}); + +test('open existing variable and execute successful query', async ({ + gotoVariableEditPage, + readProvisionedDashboard, +}) => { + const dashboard = await readProvisionedDashboard({ fileName: 'testdatasource.json' }); + const variableEditPage = await gotoVariableEditPage({ dashboard, id: '0' }); + const queryDataRequest = variableEditPage.waitForQueryDataRequest(); + await variableEditPage.runQuery(); + await queryDataRequest; + await expect(variableEditPage).toDisplayPreviews(['A', 'B']); +}); diff --git a/packages/plugin-e2e/tests/as-admin-user/datasource/variables/variableInterpolation.spec.ts b/packages/plugin-e2e/tests/as-admin-user/datasource/variables/variableInterpolation.spec.ts index 05d4b1c82..c6f1f3756 100644 --- a/packages/plugin-e2e/tests/as-admin-user/datasource/variables/variableInterpolation.spec.ts +++ b/packages/plugin-e2e/tests/as-admin-user/datasource/variables/variableInterpolation.spec.ts @@ -1,49 +1,15 @@ import { test, expect, PanelEditPage } from '../../../../src'; -test('variable interpolation', async ({ - readProvisionedDashboard, - request, - page, - selectors, - grafanaVersion, -}, testInfo) => { - const dashboard = await readProvisionedDashboard({ fileName: 'redshift.json' }); - const panelEditPage = new PanelEditPage( - { request, page, selectors, grafanaVersion, testInfo }, - { - id: '5', - dashboard, - } - ); - const queryReq = panelEditPage.waitForQueryDataRequest((request) => - (request.postData() ?? '').includes( - `"rawSQL":"select * from long_format_example where environment in ('staging') limit 100"` - ) - ); - await panelEditPage.goto(); - await expect(await queryReq).toBeTruthy(); -}); - -test('variable interpolation (navigate to panel from dashboard)', async ({ - readProvisionedDashboard, - request, - page, - selectors, - grafanaVersion, -}, testInfo) => { - const dashboard = await readProvisionedDashboard({ fileName: 'redshift.json' }); - const panelEditPage = new PanelEditPage( - { request, page, selectors, grafanaVersion, testInfo }, - { - id: '5', - dashboard, - } - ); +test('variable interpolation', async ({ readProvisionedDashboard, gotoDashboardPage }) => { + const dashboard = await readProvisionedDashboard({ fileName: 'testdatasource.json' }); + const dashboardPage = await gotoDashboardPage(dashboard); + const panelEditPage = await dashboardPage.addPanel(); + await panelEditPage.datasource.set('test-datasource'); + const editorRow = await panelEditPage.getQueryEditorRow('A'); + await editorRow.getByRole('textbox', { name: 'Query Text' }).fill('$var1'); const queryReq = panelEditPage.waitForQueryDataRequest((request) => - (request.postData() ?? '').includes( - `"rawSQL":"select * from long_format_example where environment in ('staging') limit 100"` - ) + (request.postData() ?? '').includes(`"queryText":"A"`) ); - await panelEditPage.goto(); + await panelEditPage.refreshPanel(); await expect(await queryReq).toBeTruthy(); }); diff --git a/packages/plugin-e2e/tests/as-admin-user/page-loading/goto.spec.ts b/packages/plugin-e2e/tests/as-admin-user/page-loading/goto.spec.ts index d8a7074f7..164ad43da 100644 --- a/packages/plugin-e2e/tests/as-admin-user/page-loading/goto.spec.ts +++ b/packages/plugin-e2e/tests/as-admin-user/page-loading/goto.spec.ts @@ -6,18 +6,18 @@ test.describe('gotoDashboardPage', () => { gotoDashboardPage, readProvisionedDashboard, }) => { - const dashboard = await readProvisionedDashboard({ fileName: 'redshift.json' }); + const dashboard = await readProvisionedDashboard({ fileName: 'testdatasource.json' }); const dashboardPage = await gotoDashboardPage({ ...dashboard, waitUntil: 'load' }); - await expect(dashboardPage.getPanelByTitle('Basic table example').locator).toHaveCount(0); + await expect(dashboardPage.getPanelByTitle('Table data').locator).toHaveCount(0); }); test('should not display elements when waitUntil `networkidle` (default) is used', async ({ gotoDashboardPage, readProvisionedDashboard, }) => { - const dashboard = await readProvisionedDashboard({ fileName: 'redshift.json' }); + const dashboard = await readProvisionedDashboard({ fileName: 'testdatasource.json' }); const dashboardPage = await gotoDashboardPage(dashboard); - await expect(dashboardPage.getPanelByTitle('Basic table example').locator).toBeVisible(); + await expect(dashboardPage.getPanelByTitle('Table data').locator).toBeVisible(); }); }); @@ -26,7 +26,7 @@ test.describe('gotoPanelEditPage', () => { gotoPanelEditPage, readProvisionedDashboard, }) => { - const dashboard = await readProvisionedDashboard({ fileName: 'redshift.json' }); + const dashboard = await readProvisionedDashboard({ fileName: 'testdatasource.json' }); const panelEditPage = await gotoPanelEditPage({ dashboard, id: '3', waitUntil: 'load' }); await expect(panelEditPage.panel.locator).toHaveCount(0); }); @@ -35,7 +35,7 @@ test.describe('gotoPanelEditPage', () => { gotoPanelEditPage, readProvisionedDashboard, }) => { - const dashboard = await readProvisionedDashboard({ fileName: 'redshift.json' }); + const dashboard = await readProvisionedDashboard({ fileName: 'testdatasource.json' }); const panelEditPage = await gotoPanelEditPage({ dashboard, id: '3' }); await expect(panelEditPage.panel.locator).toBeVisible(); }); diff --git a/packages/plugin-e2e/tests/as-admin-user/panel/panelEdit.spec.ts b/packages/plugin-e2e/tests/as-admin-user/panel/panelEdit.spec.ts index 0d1dddc68..e1b225946 100644 --- a/packages/plugin-e2e/tests/as-admin-user/panel/panelEdit.spec.ts +++ b/packages/plugin-e2e/tests/as-admin-user/panel/panelEdit.spec.ts @@ -88,7 +88,7 @@ test('select value in single value select', async ({ gotoPanelEditPage }) => { }); test('enter value in slider', async ({ gotoPanelEditPage }) => { - const panelEdit = await gotoPanelEditPage({ dashboard: { uid: 'eda84f4d-0b3c-4e4d-815d-7fcb9aa702c2' }, id: '1' }); + const panelEdit = await gotoPanelEditPage({ dashboard: { uid: 'be6sir7o1iccgb' }, id: '1' }); const graphOptions = panelEdit.getCustomOptions('Graph styles'); const lineWith = graphOptions.getSliderInput('Line width'); @@ -98,7 +98,7 @@ test('enter value in slider', async ({ gotoPanelEditPage }) => { }); test('enter value in number input', async ({ gotoPanelEditPage }) => { - const panelEdit = await gotoPanelEditPage({ dashboard: { uid: 'eda84f4d-0b3c-4e4d-815d-7fcb9aa702c2' }, id: '1' }); + const panelEdit = await gotoPanelEditPage({ dashboard: { uid: 'be6sir7o1iccgb' }, id: '1' }); const graphOptions = panelEdit.getCustomOptions('Axis'); const lineWith = graphOptions.getNumberInput('Soft min'); @@ -121,7 +121,7 @@ test('select color in color picker', async ({ gotoPanelEditPage, grafanaVersion, }); test('select unit in unit picker', async ({ gotoPanelEditPage }) => { - const panelEdit = await gotoPanelEditPage({ dashboard: { uid: 'eda84f4d-0b3c-4e4d-815d-7fcb9aa702c2' }, id: '1' }); + const panelEdit = await gotoPanelEditPage({ dashboard: { uid: 'be6sir7o1iccgb' }, id: '1' }); const standardOptions = panelEdit.getStandardOptions(); const unitPicker = standardOptions.getUnitPicker('Unit'); @@ -133,7 +133,7 @@ test('select unit in unit picker', async ({ gotoPanelEditPage }) => { test('select timezone in timezone picker', async ({ gotoPanelEditPage, grafanaVersion }) => { test.skip(lte(grafanaVersion, '9.1.0'), 'This feature is only available starting from Grafana 9.1.0'); - const panelEdit = await gotoPanelEditPage({ dashboard: { uid: 'eda84f4d-0b3c-4e4d-815d-7fcb9aa702c2' }, id: '1' }); + const panelEdit = await gotoPanelEditPage({ dashboard: { uid: 'be6sir7o1iccgb' }, id: '1' }); const axisOptions = panelEdit.getCustomOptions('Axis'); const timeZonePicker = axisOptions.getSelect('Time zone'); diff --git a/packages/plugin-e2e/tests/as-admin-user/panel/panelMenu.spec.ts b/packages/plugin-e2e/tests/as-admin-user/panel/panelMenu.spec.ts index 6c72211a8..8a64ba929 100644 --- a/packages/plugin-e2e/tests/as-admin-user/panel/panelMenu.spec.ts +++ b/packages/plugin-e2e/tests/as-admin-user/panel/panelMenu.spec.ts @@ -1,17 +1,17 @@ import { test, expect } from '../../../src'; test('click on menu item', async ({ readProvisionedDashboard, gotoDashboardPage, page }) => { - const dashboard = await readProvisionedDashboard({ fileName: 'redshift.json' }); + const dashboard = await readProvisionedDashboard({ fileName: 'testdatasource.json' }); const dashboardPage = await gotoDashboardPage(dashboard); - const panel = await dashboardPage.getPanelByTitle('Basic table example'); + const panel = await dashboardPage.getPanelByTitle('Table data'); await panel.clickOnMenuItem('Edit'); await expect(page).toHaveURL(/.*editPanel=.*/); }); test('click on sub menu item', async ({ readProvisionedDashboard, gotoDashboardPage, page, selectors }) => { - const dashboard = await readProvisionedDashboard({ fileName: 'redshift.json' }); + const dashboard = await readProvisionedDashboard({ fileName: 'testdatasource.json' }); const dashboardPage = await gotoDashboardPage(dashboard); - const panel = await dashboardPage.getPanelByTitle('Basic table example'); + const panel = await dashboardPage.getPanelByTitle('Table data'); await panel.clickOnMenuItem('Query', { parentItem: 'Inspect' }); await expect( dashboardPage.getByGrafanaSelector(selectors.components.Drawer.General.title(''), { startsWith: true })