diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 9e86707ac0c..df35c592896 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -412,6 +412,39 @@ /e2e/cloud-plugins-suite/ @grafana/partner-datasources /e2e-playwright/ @grafana/grafana-frontend-platform /e2e-playwright/dashboard-new-layouts @grafana/dashboards-squad +/e2e-playwright/dashboards-suite/dashboard-browse-nested.spec.ts @grafana/grafana-search-navigate-organise +/e2e-playwright/dashboards-suite/dashboard-browse.spec.ts @grafana/grafana-search-navigate-organise +/e2e-playwright/dashboards-suite/dashboard-export-image.spec.ts @grafana/sharing-squad +/e2e-playwright/dashboards-suite/dashboard-export-json.spec.ts @grafana/sharing-squad +/e2e-playwright/dashboards-suite/dashboard-keybindings.spec.ts @grafana/dashboards-squad +/e2e-playwright/dashboards-suite/dashboard-links-without-slug.spec.ts @grafana/dashboards-squad +/e2e-playwright/dashboards-suite/dashboard-live-streaming.spec.ts @grafana/dashboards-squad +/e2e-playwright/dashboards-suite/dashboard-public-create.spec.ts @grafana/grafana-operator-experience-squad +/e2e-playwright/dashboards-suite/dashboard-public-templating.spec.ts @grafana/grafana-operator-experience-squad +/e2e-playwright/dashboards-suite/dashboard-share-externally-create.spec.ts @grafana/sharing-squad +/e2e-playwright/dashboards-suite/dashboard-share-internally.spec.ts @grafana/sharing-squad +/e2e-playwright/dashboards-suite/dashboard-share-snapshot-create.spec.ts @grafana/sharing-squad +/e2e-playwright/dashboards-suite/dashboard-templating.spec.ts @grafana/dashboards-squad +/e2e-playwright/dashboards-suite/dashboard-time-zone.spec.ts @grafana/dashboards-squad +/e2e-playwright/dashboards-suite/dashboard-timepicker.spec.ts @grafana/grafana-frontend-platform +/e2e-playwright/dashboards-suite/embedded-dashboard.spec.ts @grafana/dashboards-squad +/e2e-playwright/dashboards-suite/general-dashboards.spec.ts @grafana/dashboards-squad +/e2e-playwright/dashboards-suite/import-dashboard.spec.ts @grafana/dashboards-squad +/e2e-playwright/dashboards-suite/load-options-from-url.spec.ts @grafana/dashboards-squad +/e2e-playwright/dashboards-suite/new-constant-variable.spec.ts @grafana/dashboards-squad +/e2e-playwright/dashboards-suite/new-custom-variable.spec.ts @grafana/dashboards-squad +/e2e-playwright/dashboards-suite/new-datasource-variable.spec.ts @grafana/dashboards-squad +/e2e-playwright/dashboards-suite/new-interval-variable.spec.ts @grafana/dashboards-squad +/e2e-playwright/dashboards-suite/new-query-variable.spec.ts @grafana/dashboards-squad +/e2e-playwright/dashboards-suite/new-text-box-variable.spec.ts @grafana/dashboards-squad +/e2e-playwright/dashboards-suite/repeating-a-panel-horizontally.spec.ts @grafana/dashboards-squad +/e2e-playwright/dashboards-suite/repeating-a-panel-vertically.spec.ts @grafana/dashboards-squad +/e2e-playwright/dashboards-suite/repeating-an-empty-row.spec.ts @grafana/dashboards-squad +/e2e-playwright/dashboards-suite/set-options-from-ui.spec.ts @grafana/dashboards-squad +/e2e-playwright/dashboards-suite/snapshot-create.spec.ts @grafana/sharing-squad +/e2e-playwright/dashboards-suite/templating-dashboard-links-and-variables.spec.ts @grafana/dashboards-squad +/e2e-playwright/dashboards-suite/textbox-variables.spec.ts @grafana/dashboards-squad +/e2e-playwright/dashboards-suite/utils/makeDashboard.ts @grafana/grafana-search-navigate-organise /e2e-playwright/panels-suite/dashlist.spec.ts @grafana/grafana-search-navigate-organise /e2e-playwright/panels-suite/datagrid-data-change.spec.ts @grafana/dataviz-squad /e2e-playwright/panels-suite/datagrid-editing-features.spec.ts @grafana/dataviz-squad diff --git a/.github/workflows/pr-e2e-tests.yml b/.github/workflows/pr-e2e-tests.yml index 5c9ad0e71d4..824b621d198 100644 --- a/.github/workflows/pr-e2e-tests.yml +++ b/.github/workflows/pr-e2e-tests.yml @@ -206,8 +206,6 @@ jobs: include: - suite: various-suite path: e2e/various-suite - - suite: dashboards-suite - path: e2e/dashboards-suite - suite: various-suite (old arch) path: e2e/old-arch/various-suite flags: --flags="--env dashboardScene=false" diff --git a/.github/workflows/run-schema-v2-e2e.yml b/.github/workflows/run-schema-v2-e2e.yml index 2430da2f905..30b4e47efc7 100644 --- a/.github/workflows/run-schema-v2-e2e.yml +++ b/.github/workflows/run-schema-v2-e2e.yml @@ -13,7 +13,7 @@ env: jobs: dashboard-schema-v2-e2e: - runs-on: ubuntu-latest + runs-on: ubuntu-latest-8-cores continue-on-error: true if: github.event.pull_request.draft == false steps: @@ -32,12 +32,10 @@ jobs: cache: 'yarn' - name: Install dependencies run: yarn install --immutable + - name: Install Playwright browsers + run: yarn playwright install --with-deps chromium - name: Build grafana run: make build - - name: Install Cypress dependencies - uses: cypress-io/github-action@b8ba51a856ba5f4c15cf39007636d4ab04f23e3c - with: - runTests: false - name: Run dashboard scenes e2e run: yarn e2e:schema-v2 || echo "Test failed but marking as success since schema V2 is behind a feature flag and should not block PRs" diff --git a/e2e-playwright/dashboards-suite/dashboard-browse-nested.spec.ts b/e2e-playwright/dashboards-suite/dashboard-browse-nested.spec.ts index 7dfbf455176..48a3c00359f 100644 --- a/e2e-playwright/dashboards-suite/dashboard-browse-nested.spec.ts +++ b/e2e-playwright/dashboards-suite/dashboard-browse-nested.spec.ts @@ -9,13 +9,13 @@ const NUM_NESTED_DASHBOARDS = 60; test.use({ featureToggles: { - tableNextGen: true, + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', }, }); // TODO change this test so it doesn't conflict with the existing dashboard browse test // probably needs a separate user -test.describe.skip( +test.describe.fixme( 'Dashboard browse (nested)', { tag: ['@dashboards'], @@ -107,7 +107,7 @@ test.describe.skip( await expect(page.getByText('Nested folder 00')).toBeVisible(); // Get the table body container for scrolling - const tableBody = page.getByRole('grid'); + const tableBody = page.getByTestId(selectors.pages.BrowseDashboards.table.body).locator('> div'); // Scroll the page and check visibility of next set of items await tableBody.evaluate((el) => el.scrollTo(0, 2100)); diff --git a/e2e-playwright/dashboards-suite/dashboard-browse.spec.ts b/e2e-playwright/dashboards-suite/dashboard-browse.spec.ts index 98106773c2d..af0d65adc29 100644 --- a/e2e-playwright/dashboards-suite/dashboard-browse.spec.ts +++ b/e2e-playwright/dashboards-suite/dashboard-browse.spec.ts @@ -2,6 +2,12 @@ import { test, expect } from '@grafana/plugin-e2e'; import testDashboard from '../dashboards/TestDashboard.json'; +test.use({ + featureToggles: { + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', + }, +}); + test.describe( 'Dashboard browse', { diff --git a/e2e-playwright/dashboards-suite/dashboard-export-image.spec.ts b/e2e-playwright/dashboards-suite/dashboard-export-image.spec.ts index 5a72d94f9d6..855b1a47c92 100644 --- a/e2e-playwright/dashboards-suite/dashboard-export-image.spec.ts +++ b/e2e-playwright/dashboards-suite/dashboard-export-image.spec.ts @@ -7,6 +7,7 @@ test.use({ scenes: true, newDashboardSharingComponent: true, sharingDashboardImage: true, // Enable the export image feature + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', }, }); diff --git a/e2e-playwright/dashboards-suite/dashboard-export-json.spec.ts b/e2e-playwright/dashboards-suite/dashboard-export-json.spec.ts index d5a3f4ecac3..18145a6c739 100644 --- a/e2e-playwright/dashboards-suite/dashboard-export-json.spec.ts +++ b/e2e-playwright/dashboards-suite/dashboard-export-json.spec.ts @@ -1,5 +1,11 @@ import { test, expect } from '@grafana/plugin-e2e'; +test.use({ + featureToggles: { + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', + }, +}); + test.describe( 'Export as JSON', { diff --git a/e2e-playwright/dashboards-suite/dashboard-keybindings.spec.ts b/e2e-playwright/dashboards-suite/dashboard-keybindings.spec.ts index 893afe13f09..dd420093696 100644 --- a/e2e-playwright/dashboards-suite/dashboard-keybindings.spec.ts +++ b/e2e-playwright/dashboards-suite/dashboard-keybindings.spec.ts @@ -1,5 +1,11 @@ import { test, expect } from '@grafana/plugin-e2e'; +test.use({ + featureToggles: { + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', + }, +}); + test.describe( 'Dashboard keybindings', { diff --git a/e2e-playwright/dashboards-suite/dashboard-links-without-slug.spec.ts b/e2e-playwright/dashboards-suite/dashboard-links-without-slug.spec.ts index 89a03671f5a..530c74c2485 100644 --- a/e2e-playwright/dashboards-suite/dashboard-links-without-slug.spec.ts +++ b/e2e-playwright/dashboards-suite/dashboard-links-without-slug.spec.ts @@ -2,6 +2,12 @@ import { test, expect } from '@grafana/plugin-e2e'; import testDashboard from '../dashboards/DataLinkWithoutSlugTest.json'; +test.use({ + featureToggles: { + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', + }, +}); + test.describe( 'Dashboard with data links that have no slug', { diff --git a/e2e-playwright/dashboards-suite/dashboard-live-streaming.spec.ts b/e2e-playwright/dashboards-suite/dashboard-live-streaming.spec.ts index dcebf98884d..c8917dfae47 100644 --- a/e2e-playwright/dashboards-suite/dashboard-live-streaming.spec.ts +++ b/e2e-playwright/dashboards-suite/dashboard-live-streaming.spec.ts @@ -5,6 +5,7 @@ import testDashboard from '../dashboards/DashboardLiveTest.json'; test.use({ featureToggles: { tableNextGen: true, + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', }, }); diff --git a/e2e-playwright/dashboards-suite/dashboard-public-create.spec.ts b/e2e-playwright/dashboards-suite/dashboard-public-create.spec.ts index 3263b4f3011..874209513bc 100644 --- a/e2e-playwright/dashboards-suite/dashboard-public-create.spec.ts +++ b/e2e-playwright/dashboards-suite/dashboard-public-create.spec.ts @@ -3,6 +3,7 @@ import { test, expect } from '@grafana/plugin-e2e'; test.use({ featureToggles: { newDashboardSharingComponent: false, + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', }, }); diff --git a/e2e-playwright/dashboards-suite/dashboard-public-templating.spec.ts b/e2e-playwright/dashboards-suite/dashboard-public-templating.spec.ts index 60b928c1301..a9bc269427f 100644 --- a/e2e-playwright/dashboards-suite/dashboard-public-templating.spec.ts +++ b/e2e-playwright/dashboards-suite/dashboard-public-templating.spec.ts @@ -3,6 +3,7 @@ import { test, expect } from '@grafana/plugin-e2e'; test.use({ featureToggles: { newDashboardSharingComponent: false, + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', }, }); diff --git a/e2e-playwright/dashboards-suite/dashboard-share-externally-create.spec.ts b/e2e-playwright/dashboards-suite/dashboard-share-externally-create.spec.ts index 0d991c100e1..b7a0eb5f35e 100644 --- a/e2e-playwright/dashboards-suite/dashboard-share-externally-create.spec.ts +++ b/e2e-playwright/dashboards-suite/dashboard-share-externally-create.spec.ts @@ -4,6 +4,7 @@ test.use({ featureToggles: { scenes: true, newDashboardSharingComponent: true, + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', }, }); diff --git a/e2e-playwright/dashboards-suite/dashboard-share-internally.spec.ts b/e2e-playwright/dashboards-suite/dashboard-share-internally.spec.ts index d250bb73464..82c9f4a8c17 100644 --- a/e2e-playwright/dashboards-suite/dashboard-share-internally.spec.ts +++ b/e2e-playwright/dashboards-suite/dashboard-share-internally.spec.ts @@ -4,6 +4,7 @@ test.use({ featureToggles: { scenes: true, newDashboardSharingComponent: true, + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', }, }); diff --git a/e2e-playwright/dashboards-suite/dashboard-share-snapshot-create.spec.ts b/e2e-playwright/dashboards-suite/dashboard-share-snapshot-create.spec.ts index a3390122e92..b60cee55733 100644 --- a/e2e-playwright/dashboards-suite/dashboard-share-snapshot-create.spec.ts +++ b/e2e-playwright/dashboards-suite/dashboard-share-snapshot-create.spec.ts @@ -6,6 +6,7 @@ test.use({ featureToggles: { scenes: true, newDashboardSharingComponent: true, + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', }, }); diff --git a/e2e-playwright/dashboards-suite/dashboard-templating.spec.ts b/e2e-playwright/dashboards-suite/dashboard-templating.spec.ts index b31fecf230f..1b3f8a326fa 100644 --- a/e2e-playwright/dashboards-suite/dashboard-templating.spec.ts +++ b/e2e-playwright/dashboards-suite/dashboard-templating.spec.ts @@ -4,6 +4,9 @@ const DASHBOARD_UID = 'HYaGDGIMk'; test.use({ timezoneId: 'Pacific/Easter', + featureToggles: { + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', + }, }); test.describe( diff --git a/e2e-playwright/dashboards-suite/dashboard-time-zone.spec.ts b/e2e-playwright/dashboards-suite/dashboard-time-zone.spec.ts new file mode 100644 index 00000000000..2d21b0b6af5 --- /dev/null +++ b/e2e-playwright/dashboards-suite/dashboard-time-zone.spec.ts @@ -0,0 +1,289 @@ +import { addDays, addHours, differenceInCalendarDays, differenceInMinutes, isBefore, parseISO, toDate } from 'date-fns'; +import { Page } from 'playwright-core'; + +import { test, expect, DashboardPage, E2ESelectorGroups } from '@grafana/plugin-e2e'; + +const TIMEZONE_DASHBOARD_UID = 'd41dbaa2-a39e-4536-ab2b-caca52f1a9c8'; + +test.use({ + featureToggles: { + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', + }, +}); + +test.describe( + 'Dashboard time zone support', + { + tag: ['@dashboards'], + }, + () => { + test('Tests dashboard time zone scenarios', async ({ page, gotoDashboardPage, selectors }) => { + const dashboardPage = await gotoDashboardPage({ uid: TIMEZONE_DASHBOARD_UID }); + + const fromTimeZone = 'UTC'; + const toTimeZone = 'America/Chicago'; + const offset = offsetBetweenTimeZones(toTimeZone, fromTimeZone); + + // Enter edit mode + await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click(); + + // Open dashboard settings + await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.settingsButton).click(); + + // Change timezone to UTC + await page.getByTestId(selectors.components.TimeZonePicker.containerV2).click(); + await page.getByRole('option', { name: 'Coordinated Universal Time ' }).click(); + + // Close settings and refresh + await dashboardPage + .getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.backToDashboardButton) + .click(); + await dashboardPage.getByGrafanaSelector(selectors.components.RefreshPicker.runButtonV2).click(); + + const panelsToCheck = ['Panel in timezone']; + + const timesInUtc: Record = {}; + + // Verify all panels are visible + for (const title of panelsToCheck) { + await expect(dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title(title))).toBeVisible(); + const timeCell = dashboardPage + .getByGrafanaSelector(selectors.components.Panels.Panel.title(title)) + .getByRole('row') + .nth(1) + .getByRole('cell') + .first(); + const time = await timeCell.textContent(); + if (time) { + timesInUtc[title] = time; + } + } + + // Open dashboard settings + await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.settingsButton).click(); + + // Change timezone to America/Chicago + await page.getByTestId(selectors.components.TimeZonePicker.containerV2).click(); + await page.getByRole('option', { name: toTimeZone }).click(); + + // Close settings and refresh + await dashboardPage + .getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.backToDashboardButton) + .click(); + await dashboardPage.getByGrafanaSelector(selectors.components.RefreshPicker.runButtonV2).click(); + + // Verify panels are still visible after timezone change + for (const title of panelsToCheck) { + await expect(dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title(title))).toBeVisible(); + const timeCell = dashboardPage + .getByGrafanaSelector(selectors.components.Panels.Panel.title(title)) + .getByRole('row') + .nth(1) + .getByRole('cell') + .first(); + await expect(async () => { + const inUtc = timesInUtc[title]; + const inTz = await timeCell.textContent(); + expect(inTz).not.toBeNull(); + if (inTz) { + const isCorrect = isTimeCorrect(inUtc, inTz, offset); + expect(isCorrect).toEqual(true); + } + }).toPass(); + } + }); + + test('Tests relative timezone support and overrides', async ({ page, gotoDashboardPage, selectors }) => { + // Open dashboard + const dashboardPage = await gotoDashboardPage({ + uid: TIMEZONE_DASHBOARD_UID, + }); + + // Switch to Browser timezone + await setTimeRange(page, dashboardPage, selectors, { + from: 'now-6h', + to: 'now', + zone: 'Browser', + }); + + await expect( + dashboardPage + .getByGrafanaSelector(selectors.components.Panels.Panel.title('Panel with relative time override')) + .locator('[role="row"]') + .filter({ hasText: '00:00:00' }) + ).toBeVisible(); + + // Today so far, still in Browser timezone + await setTimeRange(page, dashboardPage, selectors, { + from: 'now/d', + to: 'now', + }); + + await expect( + dashboardPage + .getByGrafanaSelector(selectors.components.Panels.Panel.title('Panel with relative time override')) + .locator('[role="row"]') + .filter({ hasText: '00:00:00' }) + ).toBeVisible(); + + await expect( + dashboardPage + .getByGrafanaSelector(selectors.components.Panels.Panel.title('Panel in timezone')) + .locator('[role="row"]') + .filter({ hasText: '00:00:00' }) + ).toBeVisible(); + + // Test UTC timezone + await setTimeRange(page, dashboardPage, selectors, { + from: 'now-6h', + to: 'now', + zone: 'Coordinated Universal Time', + }); + + await expect( + dashboardPage + .getByGrafanaSelector(selectors.components.Panels.Panel.title('Panel with relative time override')) + .locator('[role="row"]') + .filter({ hasText: '00:00:00' }) + ).toBeVisible(); + + // Today so far, still in UTC timezone + await setTimeRange(page, dashboardPage, selectors, { + from: 'now/d', + to: 'now', + }); + + await expect( + dashboardPage + .getByGrafanaSelector(selectors.components.Panels.Panel.title('Panel with relative time override')) + .locator('[role="row"]') + .filter({ hasText: '00:00:00' }) + ).toBeVisible(); + + await expect( + dashboardPage + .getByGrafanaSelector(selectors.components.Panels.Panel.title('Panel in timezone')) + .locator('[role="row"]') + .filter({ hasText: '00:00:00' }) + ).toBeVisible(); + + // Test Tokyo timezone + await setTimeRange(page, dashboardPage, selectors, { + from: 'now-6h', + to: 'now', + zone: 'Asia/Tokyo', + }); + + await expect( + dashboardPage + .getByGrafanaSelector(selectors.components.Panels.Panel.title('Panel with relative time override')) + .locator('[role="row"]') + .filter({ hasText: '00:00:00' }) + ).toBeVisible(); + + // Today so far, still in Tokyo timezone + await setTimeRange(page, dashboardPage, selectors, { + from: 'now/d', + to: 'now', + }); + + await expect( + dashboardPage + .getByGrafanaSelector(selectors.components.Panels.Panel.title('Panel with relative time override')) + .locator('[role="row"]') + .filter({ hasText: '00:00:00' }) + ).toBeVisible(); + + await expect( + dashboardPage + .getByGrafanaSelector(selectors.components.Panels.Panel.title('Panel in timezone')) + .locator('[role="row"]') + .filter({ hasText: '00:00:00' }) + ).toBeVisible(); + + // Test LA timezone + await setTimeRange(page, dashboardPage, selectors, { + from: 'now-6h', + to: 'now', + zone: 'America/Los Angeles', + }); + + await expect( + dashboardPage + .getByGrafanaSelector(selectors.components.Panels.Panel.title('Panel with relative time override')) + .locator('[role="row"]') + .filter({ hasText: '00:00:00' }) + ).toBeVisible(); + + // Today so far, still in LA timezone + await setTimeRange(page, dashboardPage, selectors, { + from: 'now/d', + to: 'now', + }); + + await expect( + dashboardPage + .getByGrafanaSelector(selectors.components.Panels.Panel.title('Panel with relative time override')) + .locator('[role="row"]') + .filter({ hasText: '00:00:00' }) + ).toBeVisible(); + + await expect( + dashboardPage + .getByGrafanaSelector(selectors.components.Panels.Panel.title('Panel in timezone')) + .locator('[role="row"]') + .filter({ hasText: '00:00:00' }) + ).toBeVisible(); + }); + } +); + +// Helper function to set time range with optional timezone +async function setTimeRange( + page: Page, + dashboardPage: DashboardPage, + selectors: E2ESelectorGroups, + options: { from: string; to: string; zone?: string } +) { + await dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.openButton).click(); + + await dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.fromField).fill(options.from); + await dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.toField).fill(options.to); + + if (options.zone) { + await page.getByRole('button', { name: 'Change time settings' }).click(); + await page.getByTestId(selectors.components.TimeZonePicker.containerV2).click(); + await page.getByRole('option', { name: options.zone }).click(); + } + + await dashboardPage.getByGrafanaSelector(selectors.components.TimePicker.applyTimeRange).click(); +} + +const isTimeCorrect = (inUtc: string, inTz: string, offset: number): boolean => { + if (inUtc === inTz) { + // we need to catch issues when timezone isn't changed for some reason like https://github.com/grafana/grafana/issues/35504 + return false; + } + + const utcDate = toDate(parseISO(inUtc)); + const utcDateWithOffset = addHours(toDate(parseISO(inUtc)), offset); + const dayDifference = differenceInCalendarDays(utcDate, utcDateWithOffset); // if the utcDate +/- offset is the day before/after then we need to adjust reference + const dayOffset = isBefore(utcDateWithOffset, utcDate) ? dayDifference * -1 : dayDifference; + const tzDate = addDays(toDate(parseISO(inTz)), dayOffset); // adjust tzDate with any dayOffset + const diff = Math.abs(differenceInMinutes(utcDate, tzDate)); // use Math.abs if tzDate is in future + + return diff <= Math.abs(offset * 60); +}; + +const offsetBetweenTimeZones = (timeZone1: string, timeZone2: string, when: Date = new Date()): number => { + const t1 = convertDateToAnotherTimeZone(when, timeZone1); + const t2 = convertDateToAnotherTimeZone(when, timeZone2); + return (t1.getTime() - t2.getTime()) / (1000 * 60 * 60); +}; + +const convertDateToAnotherTimeZone = (date: Date, timeZone: string): Date => { + const dateString = date.toLocaleString('en-US', { + timeZone: timeZone, + }); + return new Date(dateString); +}; diff --git a/e2e-playwright/dashboards-suite/dashboard-timepicker.spec.ts b/e2e-playwright/dashboards-suite/dashboard-timepicker.spec.ts index e57c56b5afe..f7a5c4b9dec 100644 --- a/e2e-playwright/dashboards-suite/dashboard-timepicker.spec.ts +++ b/e2e-playwright/dashboards-suite/dashboard-timepicker.spec.ts @@ -15,6 +15,9 @@ test.use({ cookies: [], origins: [], }, + featureToggles: { + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', + }, }); test.describe( diff --git a/e2e-playwright/dashboards-suite/embedded-dashboard.spec.ts b/e2e-playwright/dashboards-suite/embedded-dashboard.spec.ts index b6479d8007c..342b912a48a 100644 --- a/e2e-playwright/dashboards-suite/embedded-dashboard.spec.ts +++ b/e2e-playwright/dashboards-suite/embedded-dashboard.spec.ts @@ -1,5 +1,11 @@ import { test, expect } from '@grafana/plugin-e2e'; +test.use({ + featureToggles: { + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', + }, +}); + test.describe( 'Embedded dashboard', { diff --git a/e2e-playwright/dashboards-suite/general-dashboards.spec.ts b/e2e-playwright/dashboards-suite/general-dashboards.spec.ts index 0a1978f3d69..3cdd27ed954 100644 --- a/e2e-playwright/dashboards-suite/general-dashboards.spec.ts +++ b/e2e-playwright/dashboards-suite/general-dashboards.spec.ts @@ -2,6 +2,12 @@ import { test, expect } from '@grafana/plugin-e2e'; const PAGE_UNDER_TEST = 'edediimbjhdz4b/a-tall-dashboard'; +test.use({ + featureToggles: { + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', + }, +}); + test.describe( 'Dashboards', { diff --git a/e2e-playwright/dashboards-suite/import-dashboard.spec.ts b/e2e-playwright/dashboards-suite/import-dashboard.spec.ts index cd905ac56b8..7ec014c728b 100644 --- a/e2e-playwright/dashboards-suite/import-dashboard.spec.ts +++ b/e2e-playwright/dashboards-suite/import-dashboard.spec.ts @@ -2,6 +2,12 @@ import { test, expect } from '@grafana/plugin-e2e'; import testDashboard from '../dashboards/TestDashboard.json'; +test.use({ + featureToggles: { + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', + }, +}); + test.describe( 'Import Dashboards Test', { diff --git a/e2e-playwright/dashboards-suite/load-options-from-url.spec.ts b/e2e-playwright/dashboards-suite/load-options-from-url.spec.ts index ce1293acc2c..c2f45459431 100644 --- a/e2e-playwright/dashboards-suite/load-options-from-url.spec.ts +++ b/e2e-playwright/dashboards-suite/load-options-from-url.spec.ts @@ -2,6 +2,12 @@ import { test, expect } from '@grafana/plugin-e2e'; const PAGE_UNDER_TEST = '-Y-tnEDWk/templating-nested-template-variables'; +test.use({ + featureToggles: { + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', + }, +}); + test.describe( 'Variables - Load options from Url', { diff --git a/e2e-playwright/dashboards-suite/new-constant-variable.spec.ts b/e2e-playwright/dashboards-suite/new-constant-variable.spec.ts index 99fa52b3a5c..3e28a6f49bc 100644 --- a/e2e-playwright/dashboards-suite/new-constant-variable.spec.ts +++ b/e2e-playwright/dashboards-suite/new-constant-variable.spec.ts @@ -3,6 +3,12 @@ import { test, expect } from '@grafana/plugin-e2e'; const PAGE_UNDER_TEST = 'kVi2Gex7z/test-variable-output'; const DASHBOARD_NAME = 'Test variable output'; +test.use({ + featureToggles: { + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', + }, +}); + test.describe( 'Variables - Constant', { diff --git a/e2e-playwright/dashboards-suite/new-custom-variable.spec.ts b/e2e-playwright/dashboards-suite/new-custom-variable.spec.ts index 30a16a7dae0..cc3bda551d9 100644 --- a/e2e-playwright/dashboards-suite/new-custom-variable.spec.ts +++ b/e2e-playwright/dashboards-suite/new-custom-variable.spec.ts @@ -50,6 +50,12 @@ async function assertPreviewValues( } } +test.use({ + featureToggles: { + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', + }, +}); + test.describe( 'Variables - Custom', { diff --git a/e2e-playwright/dashboards-suite/new-datasource-variable.spec.ts b/e2e-playwright/dashboards-suite/new-datasource-variable.spec.ts index a769f8438cb..988d79f78ca 100644 --- a/e2e-playwright/dashboards-suite/new-datasource-variable.spec.ts +++ b/e2e-playwright/dashboards-suite/new-datasource-variable.spec.ts @@ -3,6 +3,12 @@ import { test, expect } from '@grafana/plugin-e2e'; const PAGE_UNDER_TEST = 'kVi2Gex7z/test-variable-output'; const DASHBOARD_NAME = 'Test variable output'; +test.use({ + featureToggles: { + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', + }, +}); + test.describe( 'Variables - Datasource', { diff --git a/e2e-playwright/dashboards-suite/new-interval-variable.spec.ts b/e2e-playwright/dashboards-suite/new-interval-variable.spec.ts index dbb670c739e..0310f6c3500 100644 --- a/e2e-playwright/dashboards-suite/new-interval-variable.spec.ts +++ b/e2e-playwright/dashboards-suite/new-interval-variable.spec.ts @@ -16,6 +16,12 @@ async function assertPreviewValues( } } +test.use({ + featureToggles: { + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', + }, +}); + test.describe( 'Variables - Interval', { diff --git a/e2e-playwright/dashboards-suite/new-query-variable.spec.ts b/e2e-playwright/dashboards-suite/new-query-variable.spec.ts index d289142a097..212f0ecd018 100644 --- a/e2e-playwright/dashboards-suite/new-query-variable.spec.ts +++ b/e2e-playwright/dashboards-suite/new-query-variable.spec.ts @@ -3,6 +3,12 @@ import { test, expect } from '@grafana/plugin-e2e'; const PAGE_UNDER_TEST = '-Y-tnEDWk/templating-nested-template-variables'; const DASHBOARD_NAME = 'Templating - Nested Template Variables'; +test.use({ + featureToggles: { + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', + }, +}); + test.describe( 'Variables - Query - Add variable', { diff --git a/e2e-playwright/dashboards-suite/new-text-box-variable.spec.ts b/e2e-playwright/dashboards-suite/new-text-box-variable.spec.ts index 4f5a856c5de..5c49254284f 100644 --- a/e2e-playwright/dashboards-suite/new-text-box-variable.spec.ts +++ b/e2e-playwright/dashboards-suite/new-text-box-variable.spec.ts @@ -3,6 +3,12 @@ import { test, expect } from '@grafana/plugin-e2e'; const PAGE_UNDER_TEST = 'kVi2Gex7z/test-variable-output'; const DASHBOARD_NAME = 'Test variable output'; +test.use({ + featureToggles: { + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', + }, +}); + test.describe( 'Variables - Text box', { diff --git a/e2e-playwright/dashboards-suite/repeating-a-panel-horizontally.spec.ts b/e2e-playwright/dashboards-suite/repeating-a-panel-horizontally.spec.ts index 22aacc41c88..920bc343275 100644 --- a/e2e-playwright/dashboards-suite/repeating-a-panel-horizontally.spec.ts +++ b/e2e-playwright/dashboards-suite/repeating-a-panel-horizontally.spec.ts @@ -2,6 +2,12 @@ import { test, expect } from '@grafana/plugin-e2e'; const PAGE_UNDER_TEST = 'WVpf2jp7z/repeating-a-panel-horizontally'; +test.use({ + featureToggles: { + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', + }, +}); + test.describe( 'Repeating a panel horizontally', { diff --git a/e2e-playwright/dashboards-suite/repeating-a-panel-vertically.spec.ts b/e2e-playwright/dashboards-suite/repeating-a-panel-vertically.spec.ts index 0e6755c05e5..3dc9cfcbcc1 100644 --- a/e2e-playwright/dashboards-suite/repeating-a-panel-vertically.spec.ts +++ b/e2e-playwright/dashboards-suite/repeating-a-panel-vertically.spec.ts @@ -2,6 +2,12 @@ import { test, expect } from '@grafana/plugin-e2e'; const PAGE_UNDER_TEST = 'OY8Ghjt7k/repeating-a-panel-vertically'; +test.use({ + featureToggles: { + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', + }, +}); + test.describe( 'Repeating a panel vertically', { diff --git a/e2e-playwright/dashboards-suite/repeating-an-empty-row.spec.ts b/e2e-playwright/dashboards-suite/repeating-an-empty-row.spec.ts index c326f55552d..31a60079444 100644 --- a/e2e-playwright/dashboards-suite/repeating-an-empty-row.spec.ts +++ b/e2e-playwright/dashboards-suite/repeating-an-empty-row.spec.ts @@ -2,6 +2,12 @@ import { test, expect } from '@grafana/plugin-e2e'; const PAGE_UNDER_TEST = 'dtpl2Ctnk/repeating-an-empty-row'; +test.use({ + featureToggles: { + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', + }, +}); + test.describe( 'Repeating empty rows', { diff --git a/e2e-playwright/dashboards-suite/set-options-from-ui.spec.ts b/e2e-playwright/dashboards-suite/set-options-from-ui.spec.ts index ccf6056d695..556ec524713 100644 --- a/e2e-playwright/dashboards-suite/set-options-from-ui.spec.ts +++ b/e2e-playwright/dashboards-suite/set-options-from-ui.spec.ts @@ -2,6 +2,12 @@ import { test, expect } from '@grafana/plugin-e2e'; const PAGE_UNDER_TEST = '-Y-tnEDWk/templating-nested-template-variables'; +test.use({ + featureToggles: { + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', + }, +}); + test.describe( 'Variables - Set options from ui', { diff --git a/e2e-playwright/dashboards-suite/snapshot-create.spec.ts b/e2e-playwright/dashboards-suite/snapshot-create.spec.ts index a2ae416d84b..0a37d134b2b 100644 --- a/e2e-playwright/dashboards-suite/snapshot-create.spec.ts +++ b/e2e-playwright/dashboards-suite/snapshot-create.spec.ts @@ -5,6 +5,7 @@ const DASHBOARD_UID = 'ZqZnVvFZz'; test.use({ featureToggles: { newDashboardSharingComponent: false, // Use legacy sharing component for this test + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', }, }); diff --git a/e2e-playwright/dashboards-suite/templating-dashboard-links-and-variables.spec.ts b/e2e-playwright/dashboards-suite/templating-dashboard-links-and-variables.spec.ts index 54bfdb771ba..813815f7f39 100644 --- a/e2e-playwright/dashboards-suite/templating-dashboard-links-and-variables.spec.ts +++ b/e2e-playwright/dashboards-suite/templating-dashboard-links-and-variables.spec.ts @@ -2,6 +2,12 @@ import { test, expect } from '@grafana/plugin-e2e'; const DASHBOARD_UID = 'yBCC3aKGk'; +test.use({ + featureToggles: { + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', + }, +}); + test.describe( 'Templating dashboard links and variables', { diff --git a/e2e-playwright/dashboards-suite/textbox-variables.spec.ts b/e2e-playwright/dashboards-suite/textbox-variables.spec.ts index 20815446223..c992456a1bc 100644 --- a/e2e-playwright/dashboards-suite/textbox-variables.spec.ts +++ b/e2e-playwright/dashboards-suite/textbox-variables.spec.ts @@ -4,6 +4,12 @@ import { test, expect, E2ESelectorGroups, DashboardPage } from '@grafana/plugin- const PAGE_UNDER_TEST = 'AejrN1AMz'; +test.use({ + featureToggles: { + kubernetesDashboards: process.env.KUBERNETES_DASHBOARDS === 'true', + }, +}); + test.describe( 'TextBox - load options scenarios', { diff --git a/e2e/dashboards-suite/Repeating_a_panel_horizontally.spec.ts b/e2e/dashboards-suite/Repeating_a_panel_horizontally.spec.ts deleted file mode 100644 index 9b3ec4806e0..00000000000 --- a/e2e/dashboards-suite/Repeating_a_panel_horizontally.spec.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { e2e } from '../utils'; -const PAGE_UNDER_TEST = 'WVpf2jp7z/repeating-a-panel-horizontally'; - -describe('Repeating a panel horizontally', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('should be able to repeat a panel horizontally', () => { - e2e.flows.openDashboard({ uid: PAGE_UNDER_TEST }); - let prevLeft = Number.NEGATIVE_INFINITY; - let prevTop: number | null = null; - const panelTitles = ['Panel Title 1', 'Panel Title 2', 'Panel Title 3']; - panelTitles.forEach((title) => { - e2e.components.Panels.Panel.title(title) - .should('be.visible') - .then(($el) => { - const { left, top } = $el[0].getBoundingClientRect(); - expect(left).to.be.greaterThan(prevLeft); - if (prevTop !== null) { - expect(top).to.be.equal(prevTop); - } - - prevLeft = left; - prevTop = top; - }); - }); - }); - - it('responds to changes to the variables', () => { - e2e.flows.openDashboard({ uid: PAGE_UNDER_TEST }); - let prevLeft = Number.NEGATIVE_INFINITY; - let prevTop: number | null = null; - const panelTitles = ['Panel Title 1', 'Panel Title 2', 'Panel Title 3']; - panelTitles.forEach((title) => { - e2e.components.Panels.Panel.title(title).should('be.visible'); - }); - - // Change to only show panels 1 + 3 - e2e.pages.Dashboard.SubMenu.submenuItemLabels('horizontal') - .parent() - .within(() => { - cy.get('input').click(); - }); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('1').click(); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('3').click(); - - // blur the dropdown - cy.get('body').click(); - - const panelsShown = ['Panel Title 1', 'Panel Title 3']; - const panelsNotShown = ['Panel Title 2']; - panelsShown.forEach((title) => { - e2e.components.Panels.Panel.title(title) - .should('be.visible') - .then(($el) => { - const { left, top } = $el[0].getBoundingClientRect(); - expect(left).to.be.greaterThan(prevLeft); - if (prevTop !== null) { - expect(top).to.be.equal(prevTop); - } - - prevLeft = left; - prevTop = top; - }); - }); - panelsNotShown.forEach((title) => { - e2e.components.Panels.Panel.title(title).should('not.exist'); - }); - }); - - it('loads a dashboard based on the query params correctly', () => { - // Have to manually add the queryParams to the url because they have the same name - e2e.flows.openDashboard({ uid: `${PAGE_UNDER_TEST}?var-horizontal=1&var-horizontal=3` }); - let prevLeft = Number.NEGATIVE_INFINITY; - let prevTop: number | null = null; - const panelsShown = ['Panel Title 1', 'Panel Title 3']; - const panelsNotShown = ['Panel Title 2']; - // Check correct panels are displayed - panelsShown.forEach((title) => { - e2e.components.Panels.Panel.title(title) - .should('be.visible') - .then(($el) => { - const { left, top } = $el[0].getBoundingClientRect(); - expect(left).to.be.greaterThan(prevLeft); - if (prevTop !== null) { - expect(top).to.be.equal(prevTop); - } - - prevLeft = left; - prevTop = top; - }); - }); - panelsNotShown.forEach((title) => { - e2e.components.Panels.Panel.title(title).should('not.exist'); - }); - }); -}); diff --git a/e2e/dashboards-suite/Repeating_a_panel_vertically.spec.ts b/e2e/dashboards-suite/Repeating_a_panel_vertically.spec.ts deleted file mode 100644 index fbf0f5bf9d2..00000000000 --- a/e2e/dashboards-suite/Repeating_a_panel_vertically.spec.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { e2e } from '../utils'; -const PAGE_UNDER_TEST = 'OY8Ghjt7k/repeating-a-panel-vertically'; - -describe('Repeating a panel vertically', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('should be able to repeat a panel vertically', () => { - e2e.flows.openDashboard({ uid: PAGE_UNDER_TEST }); - - let prevTop = Number.NEGATIVE_INFINITY; - let prevLeft: number | null = null; - const panelTitles = ['Panel Title 1', 'Panel Title 2', 'Panel Title 3']; - panelTitles.forEach((title) => { - e2e.components.Panels.Panel.title(title) - .should('be.visible') - .then(($el) => { - const { left, top } = $el[0].getBoundingClientRect(); - expect(top).to.be.greaterThan(prevTop); - if (prevLeft !== null) { - expect(left).to.be.equal(prevLeft); - } - prevLeft = left; - prevTop = top; - }); - }); - }); - - it('responds to changes to the variables', () => { - e2e.flows.openDashboard({ uid: PAGE_UNDER_TEST }); - - let prevTop = Number.NEGATIVE_INFINITY; - let prevLeft: number | null = null; - const panelTitles = ['Panel Title 1', 'Panel Title 2', 'Panel Title 3']; - panelTitles.forEach((title) => { - e2e.components.Panels.Panel.title(title).should('be.visible'); - }); - - // Change to only show panels 1 + 3 - e2e.pages.Dashboard.SubMenu.submenuItemLabels('vertical') - .parent() - .within(() => { - cy.get('input').click(); - }); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('1').click(); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('3').click(); - - // blur the dropdown - cy.get('body').click(); - - const panelsShown = ['Panel Title 1', 'Panel Title 3']; - const panelsNotShown = ['Panel Title 2']; - panelsShown.forEach((title) => { - e2e.components.Panels.Panel.title(title) - .should('be.visible') - .then(($el) => { - const { left, top } = $el[0].getBoundingClientRect(); - expect(top).to.be.greaterThan(prevTop); - if (prevLeft !== null) { - expect(left).to.be.equal(prevLeft); - } - prevLeft = left; - prevTop = top; - }); - }); - panelsNotShown.forEach((title) => { - e2e.components.Panels.Panel.title(title).should('not.exist'); - }); - }); - - it('loads a dashboard based on the query params correctly', () => { - // Have to manually add the queryParams to the url because they have the same name - e2e.flows.openDashboard({ uid: `${PAGE_UNDER_TEST}?var-vertical=1&var-vertical=3` }); - - let prevTop = Number.NEGATIVE_INFINITY; - let prevLeft: number | null = null; - const panelsShown = ['Panel Title 1', 'Panel Title 3']; - const panelsNotShown = ['Panel Title 2']; - panelsShown.forEach((title) => { - e2e.components.Panels.Panel.title(title) - .should('be.visible') - .then(($el) => { - const { left, top } = $el[0].getBoundingClientRect(); - expect(top).to.be.greaterThan(prevTop); - if (prevLeft !== null) { - expect(left).to.be.equal(prevLeft); - } - prevLeft = left; - prevTop = top; - }); - }); - panelsNotShown.forEach((title) => { - e2e.components.Panels.Panel.title(title).should('not.exist'); - }); - }); -}); diff --git a/e2e/dashboards-suite/Repeating_an_empty_row.spec.ts b/e2e/dashboards-suite/Repeating_an_empty_row.spec.ts deleted file mode 100644 index 2bf52250bad..00000000000 --- a/e2e/dashboards-suite/Repeating_an_empty_row.spec.ts +++ /dev/null @@ -1,85 +0,0 @@ -import { e2e } from '../utils'; -const PAGE_UNDER_TEST = 'dtpl2Ctnk/repeating-an-empty-row'; - -describe('Repeating empty rows', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('should be able to repeat empty rows vertically', () => { - e2e.flows.openDashboard({ uid: PAGE_UNDER_TEST }); - - let prevTop = Number.NEGATIVE_INFINITY; - const rowTitles = ['Row title 1', 'Row title 2', 'Row title 3']; - rowTitles.forEach((title) => { - e2e.components.DashboardRow.title(title) - .should('be.visible') - .then(($el) => { - const { top } = $el[0].getBoundingClientRect(); - expect(top).to.be.greaterThan(prevTop); - prevTop = top; - }); - }); - }); - - it('responds to changes to the variables', () => { - e2e.flows.openDashboard({ uid: PAGE_UNDER_TEST }); - - let prevTop = Number.NEGATIVE_INFINITY; - const rowTitles = ['Row title 1', 'Row title 2', 'Row title 3']; - - rowTitles.forEach((title) => { - e2e.components.DashboardRow.title(title).should('be.visible'); - }); - - e2e.pages.Dashboard.SubMenu.submenuItemLabels('row') - .parent() - .within(() => { - cy.get('input').click(); - }); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('1').click(); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('3').click(); - - // blur the dropdown - cy.get('body').click(); - - const rowsShown = ['Row title 1', 'Row title 3']; - const rowsNotShown = ['Row title 2']; - rowsShown.forEach((title) => { - e2e.components.DashboardRow.title(title) - .should('be.visible') - .then(($el) => { - const { top } = $el[0].getBoundingClientRect(); - expect(top).to.be.greaterThan(prevTop); - prevTop = top; - }); - }); - - rowsNotShown.forEach((title) => { - e2e.components.DashboardRow.title(title).should('not.exist'); - }); - }); - - it('loads a dashboard based on the query params correctly', () => { - // Have to manually add the queryParams to the url because they have the same name - e2e.flows.openDashboard({ uid: `${PAGE_UNDER_TEST}?var-row=1&var-row=3` }); - - let prevTop = Number.NEGATIVE_INFINITY; - const rowsShown = ['Row title 1', 'Row title 3']; - const rowsNotShown = ['Row title 2']; - rowsShown.forEach((title) => { - e2e.components.DashboardRow.title(title) - .should('be.visible') - .then(($el) => { - const { top } = $el[0].getBoundingClientRect(); - expect(top).to.be.greaterThan(prevTop); - prevTop = top; - }); - }); - - rowsNotShown.forEach((title) => { - e2e.components.DashboardRow.title(title).should('not.exist'); - }); - }); -}); diff --git a/e2e/dashboards-suite/dashboard-browse-nested.spec.ts b/e2e/dashboards-suite/dashboard-browse-nested.spec.ts deleted file mode 100644 index a18c4108e4e..00000000000 --- a/e2e/dashboards-suite/dashboard-browse-nested.spec.ts +++ /dev/null @@ -1,140 +0,0 @@ -import { e2e } from '../utils'; - -import { makeNewDashboardRequestBody } from './utils/makeDashboard'; - -const NUM_ROOT_FOLDERS = 60; -const NUM_ROOT_DASHBOARDS = 60; -const NUM_NESTED_FOLDERS = 60; -const NUM_NESTED_DASHBOARDS = 60; - -// TODO enable this test when nested folders goes live -describe.skip('Dashboard browse (nested)', () => { - const dashboardUIDsToCleanUp: string[] = []; - const folderUIDsToCleanUp: string[] = []; - - // Add nested folder structure - before(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD'), false); - - // Add root folders - for (let i = 0; i < NUM_ROOT_FOLDERS; i++) { - cy.request({ - method: 'POST', - url: '/api/folders', - body: { - title: `Root folder ${i.toString().padStart(2, '0')}`, - }, - headers: { - 'Content-Type': 'application/json', - }, - }).then((response) => { - folderUIDsToCleanUp.push(response.body.uid); - }); - } - - // Add root dashboards - for (let i = 0; i < NUM_ROOT_DASHBOARDS; i++) { - cy.request({ - method: 'POST', - url: '/api/dashboards/db', - body: makeNewDashboardRequestBody(`Root dashboard ${i.toString().padStart(2, '0')}`), - headers: { - 'Content-Type': 'application/json', - }, - }).then((response) => { - dashboardUIDsToCleanUp.push(response.body.uid); - }); - } - - // Add folder with children - cy.request({ - method: 'POST', - url: '/api/folders', - body: { - title: 'A root folder with children', - }, - headers: { - 'Content-Type': 'application/json', - }, - }).then((response) => { - const folderUid = response.body.uid; - folderUIDsToCleanUp.push(folderUid); - // Add nested folders - for (let i = 0; i < NUM_NESTED_FOLDERS; i++) { - cy.request({ - method: 'POST', - url: '/api/folders', - body: { - title: `Nested folder ${i.toString().padStart(2, '0')}`, - parentUid: folderUid, - }, - headers: { - 'Content-Type': 'application/json', - }, - }); - } - // Add nested dashboards - for (let i = 0; i < NUM_NESTED_DASHBOARDS; i++) { - cy.request({ - method: 'POST', - url: '/api/dashboards/db', - body: makeNewDashboardRequestBody(`Nested dashboard ${i.toString().padStart(2, '0')}`, folderUid), - headers: { - 'Content-Type': 'application/json', - }, - }); - } - }); - }); - - // Remove nested folder structure - after(() => { - // Clean up root dashboards - for (const dashboardUID of dashboardUIDsToCleanUp) { - e2e.flows.deleteDashboard({ - uid: dashboardUID, - quick: true, - title: '', - }); - } - // Clean up root folders (cascading delete will remove any nested folders and dashboards) - for (const folderUID of folderUIDsToCleanUp) { - cy.request({ - method: 'DELETE', - url: `/api/folders/${folderUID}`, - qs: { - forceDeleteRules: false, - }, - }); - } - }); - - it('pagination works correctly for folders and root', () => { - e2e.pages.Dashboards.visit(); - - cy.contains('A root folder with children').should('be.visible'); - - // Expand A root folder with children - cy.get('[aria-label="Expand folder A root folder with children"]').click(); - cy.contains('Nested folder 00').should('be.visible'); - - // Scroll the page and check visibility of next set of items - e2e.pages.BrowseDashboards.table.body().find('> div').scrollTo(0, 1700); - cy.contains('Nested folder 59').should('be.visible'); - cy.contains('Nested dashboard 00').should('be.visible'); - - // Scroll the page and check visibility of next set of items - e2e.pages.BrowseDashboards.table.body().find('> div').scrollTo(0, 3800); - cy.contains('Nested dashboard 59').should('be.visible'); - cy.contains('Root folder 00').should('be.visible'); - - // Scroll the page and check visibility of next set of items - e2e.pages.BrowseDashboards.table.body().find('> div').scrollTo(0, 5900); - cy.contains('Root folder 59').should('be.visible'); - cy.contains('Root dashboard 00').should('be.visible'); - - // Scroll the page and check visibility of next set of items - e2e.pages.BrowseDashboards.table.body().find('> div').scrollTo(0, 8000); - cy.contains('Root dashboard 59').should('be.visible'); - }); -}); diff --git a/e2e/dashboards-suite/dashboard-browse.spec.ts b/e2e/dashboards-suite/dashboard-browse.spec.ts deleted file mode 100644 index a5dc3cfc5ca..00000000000 --- a/e2e/dashboards-suite/dashboard-browse.spec.ts +++ /dev/null @@ -1,52 +0,0 @@ -import testDashboard from '../dashboards/TestDashboard.json'; -import { e2e } from '../utils'; -// Skipping due to race conditions with same old arch test e2e/dashboards-suite/dashboard-browse.spec.ts -describe.skip('Dashboard browse', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('Manage Dashboards tests', () => { - e2e.flows.importDashboard(testDashboard, 1000, true); - - e2e.pages.Dashboards.visit(); - - // Folders and dashboards should be visible - e2e.pages.BrowseDashboards.table.row('gdev dashboards').should('be.visible'); - e2e.pages.BrowseDashboards.table.row('E2E Test - Import Dashboard').should('be.visible'); - - // gdev dashboards folder is collapsed - its content should not be visible - e2e.pages.BrowseDashboards.table.row('Bar Gauge Demo').should('not.exist'); - - // should click a folder and see it's children - e2e.pages.BrowseDashboards.table.row('gdev dashboards').find('[aria-label^="Expand folder"]').click(); - e2e.pages.BrowseDashboards.table.row('Bar Gauge Demo').should('be.visible'); - - // Open the new folder drawer - cy.contains('button', 'New').click(); - cy.contains('button', 'New folder').click(); - - // And create a new folder - e2e.pages.BrowseDashboards.NewFolderForm.nameInput().type('My new folder'); - e2e.pages.BrowseDashboards.NewFolderForm.form().contains('button', 'Create').click(); - e2e.components.Alert.alertV2('success').find('button[aria-label="Close alert"]').click(); - cy.contains('h1', 'My new folder').should('be.visible'); - - // Delete the folder and expect to go back to the root - cy.contains('button', 'Folder actions').click(); - cy.contains('button', 'Delete').click(); - e2e.flows.confirmDelete(); - cy.contains('h1', 'Dashboards').should('be.visible'); - - // Can collapse the gdev folder and delete the dashboard we imported - e2e.pages.BrowseDashboards.table.row('gdev dashboards').find('[aria-label^="Collapse folder"]').click(); - e2e.pages.BrowseDashboards.table - .row('E2E Test - Import Dashboard') - .find('[type="checkbox"]') - .click({ force: true }); - - cy.contains('button', 'Delete').click(); - e2e.flows.confirmDelete(); - e2e.pages.BrowseDashboards.table.row('E2E Test - Import Dashboard').should('not.exist'); - }); -}); diff --git a/e2e/dashboards-suite/dashboard-export-json.spec.ts b/e2e/dashboards-suite/dashboard-export-json.spec.ts deleted file mode 100644 index 34abe6cec05..00000000000 --- a/e2e/dashboards-suite/dashboard-export-json.spec.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { e2e } from '../utils'; -import '../utils/support/clipboard'; - -describe('Export as JSON', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('Export for internal and external use', () => { - // Opening a dashboard - cy.intercept({ - pathname: '/api/ds/query', - }).as('query'); - e2e.flows.openDashboard({ - uid: 'ZqZnVvFZz', - queryParams: { '__feature.scenes': true, '__feature.newDashboardSharingComponent': true }, - }); - cy.wait('@query'); - - // cy.wrap( - // Cypress.automation('remote:debugger:protocol', { - // command: 'Browser.grantPermissions', - // params: { - // permissions: ['clipboardReadWrite', 'clipboardSanitizedWrite'], - // origin: window.location.origin, - // }, - // }) - // ); - - // Open the export drawer - e2e.pages.Dashboard.DashNav.NewExportButton.arrowMenu().click(); - e2e.pages.Dashboard.DashNav.NewExportButton.Menu.exportAsJson().click(); - - cy.url().should('include', 'shareView=export'); - - // Export as JSON - e2e.pages.ExportDashboardDrawer.ExportAsJson.container().should('be.visible'); - e2e.pages.ExportDashboardDrawer.ExportAsJson.exportExternallyToggle().should('not.be.checked'); - e2e.components.CodeEditor.container().should('exist'); - - e2e.pages.ExportDashboardDrawer.ExportAsJson.saveToFileButton().should('exist'); - e2e.pages.ExportDashboardDrawer.ExportAsJson.copyToClipboardButton().should('exist'); - e2e.pages.ExportDashboardDrawer.ExportAsJson.cancelButton().should('exist'); - - //TODO Failing in CI/CD. Fix it - // Copy link button should be visible - // e2e.pages.ExportDashboardDrawer.ExportAsJson.copyToClipboardButton() - // .click() - // .then(() => { - // cy.copyFromClipboard().then((url) => { - // cy.wrap(url).should('not.include', '__inputs'); - // }); - // }); - - e2e.pages.ExportDashboardDrawer.ExportAsJson.exportExternallyToggle().click({ force: true }); - - //TODO Failing in CI/CD. Fix it - // e2e.pages.ExportDashboardDrawer.ExportAsJson.copyToClipboardButton() - // .click() - // .then(() => { - // cy.copyFromClipboard().then((url) => { - // cy.wrap(url).should('include', '__inputs'); - // }); - // }); - - e2e.pages.ExportDashboardDrawer.ExportAsJson.cancelButton().click(); - - cy.url().should('not.include', 'shareView=export'); - }); -}); diff --git a/e2e/dashboards-suite/dashboard-keybindings.spec.ts b/e2e/dashboards-suite/dashboard-keybindings.spec.ts deleted file mode 100644 index 42070f1ebc4..00000000000 --- a/e2e/dashboards-suite/dashboard-keybindings.spec.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { e2e } from '../utils'; - -describe('Dashboard keybindings', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('should collapse and expand all rows', () => { - e2e.flows.openDashboard({ uid: 'Repeating-rows-uid/repeating-rows' }); - e2e.components.Panels.Panel.content().should('have.length', 5); - e2e.components.Panels.Panel.title('server = A, pod = Bob').should('be.visible'); - e2e.components.Panels.Panel.title('server = B, pod = Bob').should('be.visible'); - - cy.get('body').type('d').type('{shift}c'); - e2e.components.Panels.Panel.content().should('have.length', 0); - e2e.components.Panels.Panel.title('server = A, pod = Bob').should('not.exist'); - e2e.components.Panels.Panel.title('server = B, pod = Bob').should('not.exist'); - - cy.get('body').type('d').type('{shift}e'); - e2e.components.Panels.Panel.content().should('have.length', 6); - e2e.components.Panels.Panel.title('server = A, pod = Bob').should('be.visible'); - e2e.components.Panels.Panel.title('server = B, pod = Bob').should('be.visible'); - }); - - it('should open panel inspect', () => { - e2e.flows.openDashboard({ uid: 'edediimbjhdz4b/a-tall-dashboard' }); - e2e.components.Panels.Panel.title('Panel #1').type('i'); - e2e.components.PanelInspector.Json.content().should('be.visible'); - cy.get('body').type('{esc}'); - e2e.components.PanelInspector.Json.content().should('not.exist'); - }); -}); diff --git a/e2e/dashboards-suite/dashboard-links-without-slug.spec.ts b/e2e/dashboards-suite/dashboard-links-without-slug.spec.ts deleted file mode 100644 index defc7678d3b..00000000000 --- a/e2e/dashboards-suite/dashboard-links-without-slug.spec.ts +++ /dev/null @@ -1,47 +0,0 @@ -import testDashboard from '../dashboards/DataLinkWithoutSlugTest.json'; -import { e2e } from '../utils'; - -describe('Dashboard with data links that have no slug', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('Should not reload if linking to same dashboard', () => { - cy.intercept({ - pathname: '/api/ds/query', - }).as('query'); - - e2e.flows.importDashboard(testDashboard, 1000, true); - cy.wait('@query'); - - e2e.components.Panels.Panel.title('Data links without slug').should('exist'); - - e2e.components.DataLinksContextMenu.singleLink().contains('9yy21uzzxypg').click(); - cy.contains('Loading', { timeout: 500 }) - .should(() => {}) // prevent test from failing if it does not find loading - .then(throwIfLoadingFound); - cy.url().should('include', urlShouldContain); - - e2e.components.DataLinksContextMenu.singleLink().contains('dr199bpvpcru').click(); - cy.contains('Loading', { timeout: 500 }) - .should(() => {}) // prevent test from failing if it does not find loading - .then(throwIfLoadingFound); - cy.url().should('include', urlShouldContain); - - e2e.components.DataLinksContextMenu.singleLink().contains('dre33fzyxcrz').click(); - cy.contains('Loading', { timeout: 500 }) - .should(() => {}) // prevent test from failing if it does not find loading - .then(throwIfLoadingFound); - cy.url().should('include', urlShouldContain); - }); -}); - -const urlShouldContain = '/d/data-link-no-slug/data-link-without-slug-test'; - -const throwIfLoadingFound = (el: JQuery) => { - if (el.length) { - // This means dashboard refreshes when clicking self-referencing data link - // that has no slug in it - throw new Error('Should not contain Loading'); - } -}; diff --git a/e2e/dashboards-suite/dashboard-live-streaming.spec.ts b/e2e/dashboards-suite/dashboard-live-streaming.spec.ts deleted file mode 100644 index 0623c8c30c7..00000000000 --- a/e2e/dashboards-suite/dashboard-live-streaming.spec.ts +++ /dev/null @@ -1,17 +0,0 @@ -import testDashboard from '../dashboards/DashboardLiveTest.json'; -import { e2e } from '../utils'; - -// Skipping due to flakiness/race conditions with same old arch test e2e/dashboards-suite/dashboard-live-streaming.spec.ts -describe.skip('Dashboard Live streaming support', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - e2e.flows.importDashboard(testDashboard, 1000); - }); - - it('Should receive streaming data', () => { - e2e.flows.openDashboard({ uid: 'live-e2e-test', queryParams: { '__feature.tableNextGen': false } }); - cy.wait(1000); - e2e.components.Panels.Panel.title('Live').should('exist'); - e2e.components.Panels.Visualization.Table.body().find('[role="row"]').should('have.length.at.least', 5); - }); -}); diff --git a/e2e/dashboards-suite/dashboard-public-create.spec.ts b/e2e/dashboards-suite/dashboard-public-create.spec.ts deleted file mode 100644 index 993bb82c702..00000000000 --- a/e2e/dashboards-suite/dashboard-public-create.spec.ts +++ /dev/null @@ -1,153 +0,0 @@ -import { e2e } from '../utils'; -// Skipping due to race conditions with same old arch test e2e/dashboards-suite/dashboard-public-create.spec.ts -describe.skip('Public dashboards', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('Create a public dashboard', () => { - // Opening a dashboard without template variables - cy.intercept({ - pathname: '/api/ds/query', - }).as('query'); - e2e.flows.openDashboard({ uid: 'ZqZnVvFZz' }); - cy.wait('@query'); - - // Open sharing modal - e2e.components.NavToolbar.shareDashboard().click(); - - // Select public dashboards tab - e2e.components.Tab.title('Public dashboard').click(); - - // Create button should be disabled - e2e.pages.ShareDashboardModal.PublicDashboard.CreateButton().should('be.disabled'); - - // Create flow shouldn't show these elements - e2e.pages.ShareDashboardModal.PublicDashboard.CopyUrlInput().should('not.exist'); - e2e.pages.ShareDashboardModal.PublicDashboard.CopyUrlButton().should('not.exist'); - e2e.pages.ShareDashboardModal.PublicDashboard.EnableAnnotationsSwitch().should('not.exist'); - e2e.pages.ShareDashboardModal.PublicDashboard.EnableTimeRangeSwitch().should('not.exist'); - e2e.pages.ShareDashboardModal.PublicDashboard.PauseSwitch().should('not.exist'); - e2e.pages.ShareDashboardModal.PublicDashboard.DeleteButton().should('not.exist'); - - // Acknowledge checkboxes - e2e.pages.ShareDashboardModal.PublicDashboard.WillBePublicCheckbox().should('be.enabled').click({ force: true }); - e2e.pages.ShareDashboardModal.PublicDashboard.LimitedDSCheckbox().should('be.enabled').click({ force: true }); - e2e.pages.ShareDashboardModal.PublicDashboard.CostIncreaseCheckbox().should('be.enabled').click({ force: true }); - - e2e.pages.ShareDashboardModal.PublicDashboard.CreateButton().should('be.enabled'); - - // Create public dashboard - cy.intercept('POST', '/api/dashboards/uid/ZqZnVvFZz/public-dashboards').as('save'); - e2e.pages.ShareDashboardModal.PublicDashboard.CreateButton().click(); - cy.wait('@save'); - - // These elements shouldn't be rendered after creating public dashboard - e2e.pages.ShareDashboardModal.PublicDashboard.WillBePublicCheckbox().should('not.exist'); - e2e.pages.ShareDashboardModal.PublicDashboard.LimitedDSCheckbox().should('not.exist'); - e2e.pages.ShareDashboardModal.PublicDashboard.CostIncreaseCheckbox().should('not.exist'); - e2e.pages.ShareDashboardModal.PublicDashboard.CreateButton().should('not.exist'); - - // These elements should be rendered - e2e.pages.ShareDashboardModal.PublicDashboard.CopyUrlInput().should('exist'); - e2e.pages.ShareDashboardModal.PublicDashboard.CopyUrlButton().should('exist'); - e2e.pages.ShareDashboardModal.PublicDashboard.PauseSwitch().should('exist'); - e2e.pages.ShareDashboardModal.PublicDashboard.DeleteButton().should('exist'); - e2e.pages.ShareDashboardModal.PublicDashboard.SettingsDropdown().should('exist'); - - e2e.pages.ShareDashboardModal.PublicDashboard.SettingsDropdown().click(); - // There elements should be rendered once the Settings dropdown is opened - e2e.pages.ShareDashboardModal.PublicDashboard.EnableAnnotationsSwitch().should('exist'); - e2e.pages.ShareDashboardModal.PublicDashboard.EnableTimeRangeSwitch().should('exist'); - }); - - it('Open a public dashboard', () => { - // Opening a dashboard without template variables - cy.intercept({ - method: 'POST', - pathname: '/api/ds/query', - }).as('query'); - e2e.flows.openDashboard({ uid: 'ZqZnVvFZz' }); - cy.wait('@query'); - - // Tag indicating a dashboard is public - e2e.pages.Dashboard.DashNav.publicDashboardTag().should('exist'); - - // Open sharing modal - e2e.components.NavToolbar.shareDashboard().click(); - - // Select public dashboards tab - cy.intercept('GET', '/api/dashboards/uid/ZqZnVvFZz/public-dashboards').as('query-public-dashboard'); - e2e.components.Tab.title('Public dashboard').click(); - cy.wait('@query-public-dashboard'); - - e2e.pages.ShareDashboardModal.PublicDashboard.CopyUrlInput().should('exist'); - e2e.pages.ShareDashboardModal.PublicDashboard.CopyUrlButton().should('exist'); - e2e.pages.ShareDashboardModal.PublicDashboard.PauseSwitch().should('exist'); - e2e.pages.ShareDashboardModal.PublicDashboard.DeleteButton().should('exist'); - e2e.pages.ShareDashboardModal.PublicDashboard.SettingsDropdown().should('exist'); - - e2e.pages.ShareDashboardModal.PublicDashboard.SettingsDropdown().click(); - // There elements should be rendered once the Settings dropdown is opened - e2e.pages.ShareDashboardModal.PublicDashboard.EnableTimeRangeSwitch().should('exist'); - e2e.pages.ShareDashboardModal.PublicDashboard.EnableAnnotationsSwitch().should('exist'); - - // Make a request to public dashboards api endpoint without authentication - e2e.pages.ShareDashboardModal.PublicDashboard.CopyUrlInput() - .invoke('val') - .then((url) => { - cy.clearCookies() - .request(getPublicDashboardAPIUrl(String(url))) - .then((resp) => { - expect(resp.status).to.eq(200); - }); - }); - }); - - it('Disable a public dashboard', () => { - // Opening a dashboard without template variables - cy.intercept({ - method: 'POST', - pathname: '/api/ds/query', - }).as('query'); - e2e.flows.openDashboard({ uid: 'ZqZnVvFZz' }); - cy.wait('@query'); - - // Open sharing modal - e2e.components.NavToolbar.shareDashboard().click(); - - // Select public dashboards tab - cy.intercept('GET', '/api/dashboards/uid/ZqZnVvFZz/public-dashboards').as('query-public-dashboard'); - e2e.components.Tab.title('Public dashboard').click(); - cy.wait('@query-public-dashboard'); - - // save url before disabling public dashboard - e2e.pages.ShareDashboardModal.PublicDashboard.CopyUrlInput() - .invoke('val') - .then((text) => cy.wrap(text).as('url')); - - // Save public dashboard - cy.intercept('PATCH', '/api/dashboards/uid/ZqZnVvFZz/public-dashboards/*').as('update'); - // Switch off enabling toggle - e2e.pages.ShareDashboardModal.PublicDashboard.PauseSwitch().should('be.enabled').click({ force: true }); - cy.wait('@update'); - - // Url should be hidden - e2e.pages.ShareDashboardModal.PublicDashboard.CopyUrlInput().should('be.disabled'); - e2e.pages.ShareDashboardModal.PublicDashboard.CopyUrlButton().should('be.disabled'); - - // Make a request to public dashboards api endpoint without authentication - cy.get('@url').then((url) => { - cy.clearCookies() - .request({ url: getPublicDashboardAPIUrl(String(url)), failOnStatusCode: false }) - .then((resp) => { - expect(resp.status).to.eq(403); - }); - }); - }); -}); - -const getPublicDashboardAPIUrl = (url: string): string => { - let accessToken = url.split('/').pop(); - return `/api/public/dashboards/${accessToken}`; -}; diff --git a/e2e/dashboards-suite/dashboard-public-templating.spec.ts b/e2e/dashboards-suite/dashboard-public-templating.spec.ts deleted file mode 100644 index 8040f4ce56e..00000000000 --- a/e2e/dashboards-suite/dashboard-public-templating.spec.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { e2e } from '../utils'; - -describe('Create a public dashboard with template variables shows a template variable warning', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('Create a public dashboard with template variables shows a template variable warning', () => { - // Opening a dashboard with template variables - e2e.flows.openDashboard({ uid: 'HYaGDGIMk', queryParams: { '__feature.newDashboardSharingComponent': false } }); - - // Open sharing modal - e2e.components.NavToolbar.shareDashboard().click(); - - // Select public dashboards tab - e2e.components.Tab.title('Public Dashboard').click(); - - // Warning Alert dashboard cannot be made public because it has template variables - e2e.pages.ShareDashboardModal.PublicDashboard.TemplateVariablesWarningAlert().should('be.visible'); - - // Configuration elements for public dashboards should not exist - e2e.pages.ShareDashboardModal.PublicDashboard.WillBePublicCheckbox().should('exist'); - e2e.pages.ShareDashboardModal.PublicDashboard.LimitedDSCheckbox().should('exist'); - e2e.pages.ShareDashboardModal.PublicDashboard.CostIncreaseCheckbox().should('exist'); - e2e.pages.ShareDashboardModal.PublicDashboard.CreateButton().should('exist'); - - e2e.pages.ShareDashboardModal.PublicDashboard.PauseSwitch().should('not.exist'); - }); -}); diff --git a/e2e/dashboards-suite/dashboard-share-externally-create.spec.ts b/e2e/dashboards-suite/dashboard-share-externally-create.spec.ts deleted file mode 100644 index 6548198013d..00000000000 --- a/e2e/dashboards-suite/dashboard-share-externally-create.spec.ts +++ /dev/null @@ -1,182 +0,0 @@ -import { PublicDashboard } from '../../public/app/features/dashboard/components/ShareModal/SharePublicDashboard/SharePublicDashboardUtils'; -import { e2e } from '../utils'; -import '../utils/support/clipboard'; - -describe('Shared dashboards', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('Close share externally drawer', () => { - openDashboard(); - - // Open share externally drawer - e2e.pages.Dashboard.DashNav.newShareButton.arrowMenu().click(); - e2e.pages.Dashboard.DashNav.newShareButton.menu.shareExternally().click(); - - cy.url().should('include', 'shareView=public_dashboard'); - e2e.pages.ShareDashboardDrawer.ShareExternally.container().should('be.visible'); - e2e.pages.ShareDashboardDrawer.ShareExternally.Creation.PublicShare.cancelButton().click(); - - cy.url().should('not.include', 'shareView=public_dashboard'); - e2e.pages.ShareDashboardDrawer.ShareExternally.container().should('not.exist'); - }); - - // Skipping due to being a flaky test - // https://drone.grafana.net/grafana/grafana/201217/6/14 - it.skip('Create a shared dashboard and check API', () => { - openDashboard(); - - // Open share externally drawer - e2e.pages.Dashboard.DashNav.newShareButton.arrowMenu().click(); - e2e.pages.Dashboard.DashNav.newShareButton.menu.shareExternally().click(); - - // Create button should be disabled - e2e.pages.ShareDashboardDrawer.ShareExternally.Creation.PublicShare.createButton().should('be.disabled'); - - // Create flow shouldn't show these elements - e2e.pages.ShareDashboardDrawer.ShareExternally.Configuration.enableTimeRangeSwitch().should('not.exist'); - e2e.pages.ShareDashboardDrawer.ShareExternally.Configuration.enableAnnotationsSwitch().should('not.exist'); - e2e.pages.ShareDashboardDrawer.ShareExternally.Configuration.copyUrlButton().should('not.exist'); - - e2e.pages.ShareDashboardDrawer.ShareExternally.Configuration.revokeAccessButton().should('not.exist'); - e2e.pages.ShareDashboardDrawer.ShareExternally.Configuration.toggleAccessButton().should('not.exist'); - - // Acknowledge checkbox - e2e.pages.ShareDashboardDrawer.ShareExternally.Creation.willBePublicCheckbox() - .should('be.enabled') - .click({ force: true }); - - // Create shared dashboard - cy.intercept('POST', '/api/dashboards/uid/edediimbjhdz4b/public-dashboards').as('create'); - e2e.pages.ShareDashboardDrawer.ShareExternally.Creation.PublicShare.createButton().should('be.enabled').click(); - cy.wait('@create') - .its('response.body') - .then((body: PublicDashboard) => { - cy.log(JSON.stringify(body)); - cy.clearCookies() - .request(getPublicDashboardAPIUrl(body.accessToken)) - .then((resp) => { - expect(resp.status).to.eq(200); - }); - }); - - // These elements shouldn't be rendered after creating public dashboard - e2e.pages.ShareDashboardDrawer.ShareExternally.Creation.willBePublicCheckbox().should('not.exist'); - e2e.pages.ShareDashboardDrawer.ShareExternally.Creation.PublicShare.createButton().should('not.exist'); - - // These elements should be rendered - e2e.pages.ShareDashboardDrawer.ShareExternally.Configuration.enableTimeRangeSwitch().should('exist'); - e2e.pages.ShareDashboardDrawer.ShareExternally.Configuration.enableAnnotationsSwitch().should('exist'); - e2e.pages.ShareDashboardDrawer.ShareExternally.Configuration.copyUrlButton().should('exist'); - e2e.pages.ShareDashboardDrawer.ShareExternally.Configuration.revokeAccessButton().should('exist'); - e2e.pages.ShareDashboardDrawer.ShareExternally.Configuration.toggleAccessButton().should('exist'); - }); - - // Skipping as clipboard permissions are failing in CI. Public dashboard creation is checked in previous test on purpose - it.skip('Open a shared dashboard', () => { - openDashboard(); - - cy.wrap( - Cypress.automation('remote:debugger:protocol', { - command: 'Browser.grantPermissions', - params: { - permissions: ['clipboardReadWrite', 'clipboardSanitizedWrite'], - origin: window.location.origin, - }, - }) - ); - - // Tag indicating a dashboard is public - e2e.pages.Dashboard.DashNav.publicDashboardTag().should('exist'); - - // Open share externally drawer - e2e.pages.Dashboard.DashNav.newShareButton.arrowMenu().click(); - e2e.pages.Dashboard.DashNav.newShareButton.menu.shareExternally().click(); - - e2e.pages.ShareDashboardDrawer.ShareExternally.Configuration.enableTimeRangeSwitch().should('exist'); - e2e.pages.ShareDashboardDrawer.ShareExternally.Configuration.enableAnnotationsSwitch().should('exist'); - e2e.pages.ShareDashboardDrawer.ShareExternally.Configuration.copyUrlButton().should('exist'); - e2e.pages.ShareDashboardDrawer.ShareExternally.Configuration.revokeAccessButton().should('exist'); - e2e.pages.ShareDashboardDrawer.ShareExternally.Configuration.toggleAccessButton().should('exist'); - - e2e.pages.ShareDashboardDrawer.ShareExternally.Configuration.copyUrlButton() - .click() - .then(() => { - cy.copyFromClipboard().then((url) => { - cy.clearCookies() - .request(getPublicDashboardAPIUrl(String(url))) - .then((resp) => { - expect(resp.status).to.eq(200); - }); - }); - }); - }); - - it.skip('Disable a shared dashboard', () => { - openDashboard(); - - //TODO Failing in CI/CD. Fix it - // cy.wrap( - // Cypress.automation('remote:debugger:protocol', { - // command: 'Browser.grantPermissions', - // params: { - // permissions: ['clipboardReadWrite', 'clipboardSanitizedWrite'], - // origin: window.location.origin, - // }, - // }) - // ); - - // Open share externally drawer - e2e.pages.Dashboard.DashNav.newShareButton.arrowMenu().click(); - e2e.pages.Dashboard.DashNav.newShareButton.menu.shareExternally().click(); - - // Save public dashboard - cy.intercept('PATCH', '/api/dashboards/uid/edediimbjhdz4b/public-dashboards/*').as('update'); - - // Switch off enabling toggle - e2e.pages.ShareDashboardDrawer.ShareExternally.Configuration.toggleAccessButton() - .should('be.enabled') - .click({ force: true }); - - cy.wait('@update') - .its('response') - .then((rs) => { - expect(rs.statusCode).eq(200); - const publicDashboard: PublicDashboard = rs.body; - cy.clearCookies() - .request({ url: getPublicDashboardAPIUrl(publicDashboard.accessToken), failOnStatusCode: false }) - .then((resp) => { - expect(resp.status).to.eq(403); - }); - }); - // .then(() => { - // e2e.pages.ShareDashboardDrawer.ShareExternally.Configuration.toggleAccessButton().contains('Resume access'); - // e2e.pages.ShareDashboardDrawer.ShareExternally.Configuration.copyUrlButton().should('be.enabled'); - // }); - - //TODO Failing in CI/CD. Fix it - // e2e.pages.ShareDashboardDrawer.ShareExternally.Configuration.copyUrlButton() - // .click() - // .then(() => { - // cy.copyFromClipboard().then((url) => { - // cy.clearCookies() - // .request({ url: getPublicDashboardAPIUrl(String(url)), failOnStatusCode: false }) - // .then((resp) => { - // expect(resp.status).to.eq(403); - // }); - // }); - // }); - }); -}); - -const openDashboard = () => { - e2e.flows.openDashboard({ - uid: 'edediimbjhdz4b', - queryParams: { '__feature.scenes': true, '__feature.newDashboardSharingComponent': true }, - }); -}; - -const getPublicDashboardAPIUrl = (accessToken: string): string => { - return `/api/public/dashboards/${accessToken}`; -}; diff --git a/e2e/dashboards-suite/dashboard-share-internally.spec.ts b/e2e/dashboards-suite/dashboard-share-internally.spec.ts deleted file mode 100644 index 76773fa7f71..00000000000 --- a/e2e/dashboards-suite/dashboard-share-internally.spec.ts +++ /dev/null @@ -1,246 +0,0 @@ -import { ShareLinkConfiguration } from '../../public/app/features/dashboard-scene/sharing/ShareButton/utils'; -import { e2e } from '../utils'; -import '../utils/support/clipboard'; - -describe('Share internally', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - cy.window().then((win) => { - win.localStorage.removeItem('grafana.dashboard.link.shareConfiguration'); - }); - }); - - it('Create a locked time range short link', () => { - cy.intercept({ - pathname: '/api/ds/query', - }).as('query'); - openDashboard(); - cy.wait('@query'); - - //TODO Failing in CI/CD. Fix it - // cy.wrap( - // Cypress.automation('remote:debugger:protocol', { - // command: 'Browser.grantPermissions', - // params: { - // permissions: ['clipboardReadWrite', 'clipboardSanitizedWrite'], - // origin: window.location.origin, - // }, - // }) - // ); - - // Open share externally drawer - e2e.pages.Dashboard.DashNav.newShareButton.arrowMenu().click(); - - cy.intercept('POST', '/api/short-urls').as('create'); - e2e.pages.Dashboard.DashNav.newShareButton.menu.shareInternally().click(); - - cy.url().should('include', 'shareView=link'); - - e2e.pages.ShareDashboardDrawer.ShareInternally.lockTimeRangeSwitch().should('exist'); - e2e.pages.ShareDashboardDrawer.ShareInternally.shortenUrlSwitch().should('exist'); - e2e.pages.ShareDashboardDrawer.ShareInternally.copyUrlButton().should('exist'); - e2e.components.RadioButton.container().should('have.length', 3); - - cy.window().then((win) => { - const shareConfiguration = win.localStorage.getItem('grafana.dashboard.link.shareConfiguration'); - expect(shareConfiguration).equal(null); - }); - cy.wait('@create') - .its('response') - .then((rs) => { - expect(rs.statusCode).eq(200); - const body: { url: string; uid: string } = rs.body; - expect(body.url).contain('goto'); - - // const url = fromBaseUrl(getShortLinkUrl(body.uid)); - // cy.intercept('GET', url).as('get'); - // cy.visit(url, { retryOnNetworkFailure: true }); - // cy.wait('@get'); - // - // cy.url().should('not.include', 'from=now-6h&to=now'); - }); - }); - - it('Create a relative time range short link', () => { - cy.intercept({ - pathname: '/api/ds/query', - }).as('query'); - openDashboard(); - cy.wait('@query'); - - e2e.pages.Dashboard.DashNav.newShareButton.arrowMenu().click(); - - e2e.pages.Dashboard.DashNav.newShareButton.menu.shareInternally().click(); - - cy.intercept('POST', '/api/short-urls').as('update'); - e2e.pages.ShareDashboardDrawer.ShareInternally.lockTimeRangeSwitch().click({ force: true }); - - cy.window().then((win) => { - const shareConfiguration = win.localStorage.getItem('grafana.dashboard.link.shareConfiguration'); - const { useAbsoluteTimeRange, useShortUrl, theme }: ShareLinkConfiguration = JSON.parse(shareConfiguration); - expect(useAbsoluteTimeRange).eq(false); - expect(useShortUrl).eq(true); - expect(theme).eq('current'); - }); - - cy.wait('@update') - .its('response') - .then((rs) => { - expect(rs.statusCode).eq(200); - const body: { url: string; uid: string } = rs.body; - expect(body.url).contain('goto'); - - // const url = fromBaseUrl(getShortLinkUrl(body.uid)); - // cy.intercept('GET', url).as('get'); - // cy.visit(url, { retryOnNetworkFailure: true }); - // cy.wait('@get'); - // - // cy.url().should('include', 'from=now-6h&to=now'); - }); - - // - // e2e.pages.ShareDashboardDrawer.ShareInternally.shortenUrlSwitch().click({ force: true }); - // - // cy.window().then((win) => { - // const shareConfiguration = win.localStorage.getItem('grafana.dashboard.link.shareConfiguration'); - // const { useAbsoluteTimeRange, useShortUrl, theme }: ShareLinkConfiguration = JSON.parse(shareConfiguration); - // expect(useAbsoluteTimeRange).eq(true); - // expect(useShortUrl).eq(false); - // expect(theme).eq('current'); - // }); - - // e2e.pages.ShareDashboardDrawer.ShareInternally.copyUrlButton().should('exist'); - - // e2e.pages.ShareDashboardDrawer.ShareInternally.copyUrlButton() - // .click() - // .then(() => { - // cy.copyFromClipboard().then((url) => { - // cy.wrap(url).should('include', 'from=now-6h&to=now'); - // cy.wrap(url).should('not.include', 'goto'); - // }); - // }); - }); - - it('Create a relative time range short link', () => { - cy.intercept({ - pathname: '/api/ds/query', - }).as('query'); - openDashboard(); - cy.wait('@query'); - - e2e.pages.Dashboard.DashNav.newShareButton.arrowMenu().click(); - - e2e.pages.Dashboard.DashNav.newShareButton.menu.shareInternally().click(); - - cy.intercept('POST', '/api/short-urls').as('update'); - e2e.pages.ShareDashboardDrawer.ShareInternally.lockTimeRangeSwitch().click({ force: true }); - - cy.window().then((win) => { - const shareConfiguration = win.localStorage.getItem('grafana.dashboard.link.shareConfiguration'); - const { useAbsoluteTimeRange, useShortUrl, theme }: ShareLinkConfiguration = JSON.parse(shareConfiguration); - expect(useAbsoluteTimeRange).eq(false); - expect(useShortUrl).eq(true); - expect(theme).eq('current'); - }); - - cy.wait('@update') - .its('response') - .then((rs) => { - expect(rs.statusCode).eq(200); - const body: { url: string; uid: string } = rs.body; - expect(body.url).contain('goto'); - - // const url = fromBaseUrl(getShortLinkUrl(body.uid)); - // cy.intercept('GET', url).as('get'); - // cy.visit(url, { retryOnNetworkFailure: true }); - // cy.wait('@get'); - // - // cy.url().should('include', 'from=now-6h&to=now'); - }); - }); - - //TODO Failing in CI/CD. Fix it - it.skip('Share button gets configured link', () => { - cy.intercept({ - pathname: '/api/ds/query', - }).as('query'); - openDashboard(); - cy.wait('@query'); - - // cy.wrap( - // Cypress.automation('remote:debugger:protocol', { - // command: 'Browser.grantPermissions', - // params: { - // permissions: ['clipboardReadWrite', 'clipboardSanitizedWrite'], - // origin: window.location.origin, - // }, - // }) - // ); - - //TODO Failing in CI/CD. Fix it - // e2e.pages.Dashboard.DashNav.newShareButton - // .shareLink() - // .click() - // .then(() => { - // cy.window() - // .then((win) => { - // return win.navigator.clipboard.readText().then((url) => { - // cy.wrap(url).as('url'); - // }); - // }) - // .then(() => { - // cy.get('@url').then((url) => { - // cy.wrap(url).should('not.include', 'from=now-6h&to=now'); - // cy.wrap(url).should('include', 'goto'); - // }); - // }); - // }); - - // Open share externally drawer - e2e.pages.Dashboard.DashNav.newShareButton.arrowMenu().click(); - e2e.pages.Dashboard.DashNav.newShareButton.menu.shareInternally().click(); - - cy.window().then((win) => { - const shareConfiguration = win.localStorage.getItem('grafana.dashboard.link.shareConfiguration'); - expect(shareConfiguration).equal(null); - }); - - e2e.pages.ShareDashboardDrawer.ShareInternally.shortenUrlSwitch().click({ force: true }); - e2e.pages.ShareDashboardDrawer.ShareInternally.lockTimeRangeSwitch().click({ force: true }); - - e2e.components.Drawer.General.close().click(); - - cy.url().should('not.include', 'shareView=link'); - - //TODO Failing in CI/CD. Fix it - // e2e.pages.Dashboard.DashNav.newShareButton - // .shareLink() - // .click() - // .then(() => { - // cy.window() - // .then((win) => { - // return win.navigator.clipboard.readText().then((url) => { - // cy.wrap(url).as('url'); - // }); - // }) - // .then(() => { - // cy.get('@url').then((url) => { - // cy.wrap(url).should('include', 'from=now-6h&to=now'); - // cy.wrap(url).should('not.include', 'goto'); - // }); - // }); - // }); - }); -}); - -const openDashboard = () => { - e2e.flows.openDashboard({ - uid: 'ZqZnVvFZz', - queryParams: { '__feature.scenes': true, '__feature.newDashboardSharingComponent': true }, - timeRange: { from: 'now-6h', to: 'now' }, - }); -}; - -// const getShortLinkUrl = (uid: string): string => { -// return `/goto/${uid}`; -// }; diff --git a/e2e/dashboards-suite/dashboard-share-snapshot-create.spec.ts b/e2e/dashboards-suite/dashboard-share-snapshot-create.spec.ts deleted file mode 100644 index 6661750718e..00000000000 --- a/e2e/dashboards-suite/dashboard-share-snapshot-create.spec.ts +++ /dev/null @@ -1,98 +0,0 @@ -import { SnapshotCreateResponse } from '../../public/app/features/dashboard/services/SnapshotSrv'; -import { e2e } from '../utils'; -import { fromBaseUrl } from '../utils/support/url'; -import '../utils/support/clipboard'; - -describe('Snapshots', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('Create a snapshot dashboard', () => { - // Opening a dashboard - cy.intercept({ - pathname: '/api/ds/query', - }).as('query'); - e2e.flows.openDashboard({ - uid: 'ZqZnVvFZz', - queryParams: { '__feature.scenes': true, '__feature.newDashboardSharingComponent': true }, - }); - cy.wait('@query'); - - //TODO Failing in CI/CD. Fix it - // cy.wrap( - // Cypress.automation('remote:debugger:protocol', { - // command: 'Browser.grantPermissions', - // params: { - // permissions: ['clipboardReadWrite', 'clipboardSanitizedWrite'], - // origin: window.location.origin, - // }, - // }) - // ); - - const panelsToCheck = [ - 'Raw Data Graph', - 'Last non-null', - 'min', - 'Max', - 'The data from graph above with seriesToColumns transform', - ]; - - // Open the sharing drawer - e2e.pages.Dashboard.DashNav.newShareButton.arrowMenu().click(); - e2e.pages.Dashboard.DashNav.newShareButton.menu.shareSnapshot().click(); - - // Publish snapshot - cy.intercept('POST', '/api/snapshots').as('create'); - e2e.pages.ShareDashboardDrawer.ShareSnapshot.publishSnapshot().click(); - cy.wait('@create') - .its('response') - .then((rs) => { - expect(rs.statusCode).eq(200); - const body: SnapshotCreateResponse = rs.body; - cy.visit(fromBaseUrl(getSnapshotUrl(body.key))); - - // Validate the dashboard controls are rendered - e2e.pages.Dashboard.Controls().should('exist'); - - // Validate the panels are rendered - for (const title of panelsToCheck) { - e2e.components.Panels.Panel.title(title).should('be.visible'); - } - }); - - // Copy link button should be visible - // e2e.pages.ShareDashboardDrawer.ShareSnapshot.copyUrlButton().should('exist'); - - //TODO Failing in CI/CD. Fix it - // Copy the snapshot URL form the clipboard and open the snapshot - // e2e.pages.ShareDashboardDrawer.ShareSnapshot.copyUrlButton() - // .click() - // .then(() => { - // cy.copyFromClipboard().then((url) => { - // cy.wrap(url).as('url'); - // }); - // }) - // .then(() => { - // cy.get('@url').then((url) => { - // e2e.pages.ShareDashboardDrawer.ShareSnapshot.visit(getSnapshotKey(String(url))); - // }); - // - // // Validate the dashboard controls are rendered - // e2e.pages.Dashboard.Controls().should('exist'); - // - // // Validate the panels are rendered - // for (const title of panelsToCheck) { - // e2e.components.Panels.Panel.title(title).should('be.visible'); - // } - // }); - }); -}); - -const getSnapshotUrl = (uid: string): string => { - return `/dashboard/snapshot/${uid}`; -}; - -// const getSnapshotKey = (url: string): string => { -// return url.split('/').pop(); -// }; diff --git a/e2e/dashboards-suite/dashboard-templating.spec.ts b/e2e/dashboards-suite/dashboard-templating.spec.ts deleted file mode 100644 index 0449f408868..00000000000 --- a/e2e/dashboards-suite/dashboard-templating.spec.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { e2e } from '../utils'; - -describe('Dashboard templating', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - // Note: Only works in Chrome/Chromium-based browsers - Cypress.automation('remote:debugger:protocol', { - command: 'Emulation.setTimezoneOverride', - params: { - timezoneId: 'Pacific/Easter', // OR 'UTC' - }, - }); - }); - - it('Verify variable interpolation works', () => { - // Open dashboard global variables and interpolation - e2e.flows.openDashboard({ uid: 'HYaGDGIMk' }); - - const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone; - const example = `Example: from=now-6h&to=now&timezone=${encodeURIComponent(timeZone)}`; - - const items: string[] = []; - const expectedItems: string[] = [ - '__dashboard = Templating - Global variables and interpolation', - '__dashboard.name = Templating - Global variables and interpolation', - '__dashboard.uid = HYaGDGIMk', - '__org.name = Main Org.', - '__org.id = 1', - '__user.id = 1', - '__user.login = admin', - '__user.email = admin@localhost', - `Server:raw = A'A"A,BB\\B,CCC`, - `Server:regex = (A'A"A|BB\\\\B|CCC)`, - `Server:lucene = ("A'A\\"A" OR "BB\\\\B" OR "CCC")`, - `Server:glob = {A'A"A,BB\\B,CCC}`, - `Server:pipe = A'A"A|BB\\B|CCC`, - `Server:distributed = A'A"A,Server=BB\\B,Server=CCC`, - `Server:csv = A'A"A,BB\\B,CCC`, - `Server:html = A'A"A, BB\\B, CCC`, - `Server:json = ["A'A\\"A","BB\\\\B","CCC"]`, - `Server:percentencode = %7BA%27A%22A%2CBB%5CB%2CCCC%7D`, - `Server:singlequote = 'A\\'A"A','BB\\B','CCC'`, - `Server:doublequote = "A'A\\"A","BB\\B","CCC"`, - `Server:sqlstring = 'A''A\\"A','BB\\\B','CCC'`, - `Server:date = NaN`, - `Server:text = All`, - `Server:queryparam = var-Server=$__all`, - `1 < 2`, - example, - ]; - - cy.get('.markdown-html li') - .should('have.length', 26) - .each((element) => { - items.push(element.text()); - }) - .then(() => { - expectedItems.forEach((expected, index) => { - expect(items[index]).to.equal(expected); - }); - }); - - // Check link interpolation is working correctly - cy.contains('a', example).should( - 'have.attr', - 'href', - `https://example.com/?from=now-6h&to=now&timezone=${encodeURIComponent(timeZone)}` - ); - }); -}); diff --git a/e2e/dashboards-suite/dashboard-time-zone.spec.ts b/e2e/dashboards-suite/dashboard-time-zone.spec.ts deleted file mode 100644 index 0361e84a236..00000000000 --- a/e2e/dashboards-suite/dashboard-time-zone.spec.ts +++ /dev/null @@ -1,263 +0,0 @@ -import { - addDays, - addHours, - differenceInCalendarDays, - differenceInMinutes, - format, - isBefore, - parseISO, - toDate, -} from 'date-fns'; - -import { e2e } from '../utils'; - -describe('Dashboard time zone support', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it.skip('Tests dashboard time zone scenarios', () => { - e2e.flows.openDashboard({ uid: '5SdHCasdf' }); - - const fromTimeZone = 'UTC'; - const toTimeZone = 'America/Chicago'; - const offset = offsetBetweenTimeZones(toTimeZone, fromTimeZone); - - const panelsToCheck = [ - 'Random walk series', - 'Millisecond res x-axis and tooltip', - '2 yaxis and axis labels', - 'Stacking value ontop of nulls', - 'Null between points', - 'Legend Table No Scroll Visible', - ]; - - const timesInUtc: Record = {}; - - for (const title of panelsToCheck) { - e2e.components.Panels.Panel.title(title) - .should('be.visible') - .within(() => { - e2e.components.Panels.Visualization.Graph.xAxis.labels().should('be.visible'); - e2e.components.Panels.Visualization.Graph.xAxis - .labels() - .last() - .should((element) => { - timesInUtc[title] = element.text(); - }); - }); - } - - e2e.components.PageToolbar.item('Dashboard settings').click(); - - e2e.components.TimeZonePicker.containerV2() - .should('be.visible') - .within(() => { - e2e.components.Select.singleValue().should('have.text', 'Coordinated Universal Time'); - e2e.components.Select.input().should('be.visible').click(); - }); - - e2e.components.Select.option().should('be.visible').contains(toTimeZone).click(); - - // click to go back to the dashboard. - e2e.pages.Dashboard.Settings.Actions.close().click(); - e2e.components.RefreshPicker.runButtonV2().should('be.visible').click(); - - for (const title of panelsToCheck) { - e2e.components.Panels.Panel.title(title) - .should('be.visible') - .within(() => { - e2e.components.Panels.Visualization.Graph.xAxis.labels().should('be.visible'); - e2e.components.Panels.Visualization.Graph.xAxis - .labels() - .last() - .should((element) => { - const inUtc = timesInUtc[title]; - const inTz = element.text(); - const isCorrect = isTimeCorrect(inUtc, inTz, offset); - expect(isCorrect).to.be.equal(true); - }); - }); - } - }); - - // TODO: remove skip once https://github.com/grafana/grafana/issues/86420 is done - it.skip('Tests relative timezone support and overrides', () => { - // Open dashboard - e2e.flows.openDashboard({ - uid: 'd41dbaa2-a39e-4536-ab2b-caca52f1a9c8', - }); - - cy.intercept('/api/ds/query*').as('dataQuery'); - - // Switch to Browser timezone - e2e.flows.setTimeRange({ - from: 'now-6h', - to: 'now', - zone: 'Browser', - }); - // Need to wait for 2 calls as there's 2 panels - cy.wait(['@dataQuery', '@dataQuery']); - - e2e.components.Panels.Panel.title('Panel with relative time override') - .should('be.visible') - .within(() => { - cy.contains('[role="row"]', '00:00:00').should('be.visible'); - }); - - // Today so far, still in Browser timezone - e2e.flows.setTimeRange({ - from: 'now/d', - to: 'now', - }); - // Need to wait for 2 calls as there's 2 panels - cy.wait(['@dataQuery', '@dataQuery']); - - e2e.components.Panels.Panel.title('Panel with relative time override') - .should('be.visible') - .within(() => { - cy.contains('[role="row"]', '00:00:00').should('be.visible'); - }); - - e2e.components.Panels.Panel.title('Panel in timezone') - .should('be.visible') - .within(() => { - cy.contains('[role="row"]', '00:00:00').should('be.visible'); - }); - // Test UTC timezone - e2e.flows.setTimeRange({ - from: 'now-6h', - to: 'now', - zone: 'Coordinated Universal Time', - }); - // Need to wait for 2 calls as there's 2 panels - cy.wait(['@dataQuery', '@dataQuery']); - - e2e.components.Panels.Panel.title('Panel with relative time override') - .should('be.visible') - .within(() => { - cy.contains('[role="row"]', '00:00:00').should('be.visible'); - }); - - // Today so far, still in UTC timezone - e2e.flows.setTimeRange({ - from: 'now/d', - to: 'now', - }); - // Need to wait for 2 calls as there's 2 panels - cy.wait(['@dataQuery', '@dataQuery']); - - e2e.components.Panels.Panel.title('Panel with relative time override') - .should('be.visible') - .within(() => { - cy.contains('[role="row"]', '00:00:00').should('be.visible'); - }); - - e2e.components.Panels.Panel.title('Panel in timezone') - .should('be.visible') - .within(() => { - cy.contains('[role="row"]', '00:00:00').should('be.visible'); - }); - - // Test Tokyo timezone - e2e.flows.setTimeRange({ - from: 'now-6h', - to: 'now', - zone: 'Asia/Tokyo', - }); - // Need to wait for 2 calls as there's 2 panels - cy.wait(['@dataQuery', '@dataQuery']); - - e2e.components.Panels.Panel.title('Panel with relative time override') - .should('be.visible') - .within(() => { - cy.contains('[role="row"]', '00:00:00').should('be.visible'); - }); - - // Today so far, still in Tokyo timezone - e2e.flows.setTimeRange({ - from: 'now/d', - to: 'now', - }); - // Need to wait for 2 calls as there's 2 panels - cy.wait(['@dataQuery', '@dataQuery']); - - e2e.components.Panels.Panel.title('Panel with relative time override') - .should('be.visible') - .within(() => { - cy.contains('[role="row"]', '00:00:00').should('be.visible'); - }); - - e2e.components.Panels.Panel.title('Panel in timezone') - .should('be.visible') - .within(() => { - cy.contains('[role="row"]', '00:00:00').should('be.visible'); - }); - - // Test LA timezone - e2e.flows.setTimeRange({ - from: 'now-6h', - to: 'now', - zone: 'America/Los_Angeles', - }); - // Need to wait for 2 calls as there's 2 panels - cy.wait(['@dataQuery', '@dataQuery']); - - e2e.components.Panels.Panel.title('Panel with relative time override') - .should('be.visible') - .within(() => { - cy.contains('[role="row"]', '00:00:00').should('be.visible'); - }); - - // Today so far, still in LA timezone - e2e.flows.setTimeRange({ - from: 'now/d', - to: 'now', - }); - // Need to wait for 2 calls as there's 2 panels - cy.wait(['@dataQuery', '@dataQuery']); - - e2e.components.Panels.Panel.title('Panel with relative time override') - .should('be.visible') - .within(() => { - cy.contains('[role="row"]', '00:00:00').should('be.visible'); - }); - - e2e.components.Panels.Panel.title('Panel in timezone') - .should('be.visible') - .within(() => { - cy.contains('[role="row"]', '00:00:00').should('be.visible'); - }); - }); -}); - -const isTimeCorrect = (inUtc: string, inTz: string, offset: number): boolean => { - if (inUtc === inTz) { - // we need to catch issues when timezone isn't changed for some reason like https://github.com/grafana/grafana/issues/35504 - return false; - } - - const reference = format(new Date(), 'yyyy-LL-dd'); - - const utcDate = toDate(parseISO(`${reference} ${inUtc}`)); - const utcDateWithOffset = addHours(toDate(parseISO(`${reference} ${inUtc}`)), offset); - const dayDifference = differenceInCalendarDays(utcDate, utcDateWithOffset); // if the utcDate +/- offset is the day before/after then we need to adjust reference - const dayOffset = isBefore(utcDateWithOffset, utcDate) ? dayDifference * -1 : dayDifference; - const tzDate = addDays(toDate(parseISO(`${reference} ${inTz}`)), dayOffset); // adjust tzDate with any dayOffset - const diff = Math.abs(differenceInMinutes(utcDate, tzDate)); // use Math.abs if tzDate is in future - - return diff <= Math.abs(offset * 60); -}; - -const offsetBetweenTimeZones = (timeZone1: string, timeZone2: string, when: Date = new Date()): number => { - const t1 = convertDateToAnotherTimeZone(when, timeZone1); - const t2 = convertDateToAnotherTimeZone(when, timeZone2); - return (t1.getTime() - t2.getTime()) / (1000 * 60 * 60); -}; - -const convertDateToAnotherTimeZone = (date: Date, timeZone: string): Date => { - const dateString = date.toLocaleString('en-US', { - timeZone: timeZone, - }); - return new Date(dateString); -}; diff --git a/e2e/dashboards-suite/dashboard-timepicker.spec.ts b/e2e/dashboards-suite/dashboard-timepicker.spec.ts deleted file mode 100644 index e4ffbec6299..00000000000 --- a/e2e/dashboards-suite/dashboard-timepicker.spec.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { e2e } from '../utils'; - -describe('Dashboard timepicker', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('Shows the correct calendar days with custom timezone set via preferences', () => { - e2e.flows.setUserPreferences({ - timezone: 'Asia/Tokyo', - }); - - // Open dashboard with time range from 8th to end of 10th. - // Will be Tokyo time because of above preference - e2e.flows.openDashboard({ - uid: '5SdHCasdf', - timeRange: { - zone: 'Default', - from: '2022-06-08 00:00:00', - to: '2022-06-10 23:59:59', - }, - }); - - // Assert that the calendar shows 08 and 09 and 10 as selected days - e2e.components.TimePicker.openButton().click(); - e2e.components.TimePicker.calendar.openButton().first().click(); - cy.get('.react-calendar__tile--active, .react-calendar__tile--hasActive').should('have.length', 3); - }); - - it('Shows the correct calendar days with custom timezone set via time picker', () => { - // Open dashboard with time range from 2022-06-08 00:00:00 to 2022-06-10 23:59:59 in Tokyo time - e2e.flows.openDashboard({ - uid: '5SdHCasdf', - timeRange: { - zone: 'Asia/Tokyo', - from: '2022-06-08 00:00:00', - to: '2022-06-10 23:59:59', - }, - }); - - // Assert that the calendar shows 08 and 09 and 10 as selected days - e2e.components.TimePicker.openButton().click(); - e2e.components.TimePicker.calendar.openButton().first().click(); - cy.get('.react-calendar__tile--active, .react-calendar__tile--hasActive').should('have.length', 3); - }); -}); diff --git a/e2e/dashboards-suite/embedded-dashboard.spec.ts b/e2e/dashboards-suite/embedded-dashboard.spec.ts deleted file mode 100644 index 8c52271994c..00000000000 --- a/e2e/dashboards-suite/embedded-dashboard.spec.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { selectors } from '@grafana/e2e-selectors'; - -import { e2e } from '../utils'; -import { fromBaseUrl } from '../utils/support/url'; - -describe('Embedded dashboard', function () { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('open test page', function () { - cy.visit(fromBaseUrl('/dashboards/embedding-test')); - - // Verify pie charts are rendered - cy.get( - `[data-viz-panel-key="panel-11"] [data-testid^="${selectors.components.Panels.Visualization.PieChart.svgSlice}"]` - ).should('have.length', 5); - - // Verify no url sync - e2e.components.TimePicker.openButton().click(); - cy.get('label:contains("Last 1 hour")').click(); - cy.url().should('eq', fromBaseUrl('/dashboards/embedding-test')); - }); -}); diff --git a/e2e/dashboards-suite/general-dashboards.spec.ts b/e2e/dashboards-suite/general-dashboards.spec.ts deleted file mode 100644 index bc1b2a306be..00000000000 --- a/e2e/dashboards-suite/general-dashboards.spec.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { e2e } from '../utils'; - -const PAGE_UNDER_TEST = 'edediimbjhdz4b/a-tall-dashboard'; - -describe('Dashboards', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('should restore scroll position', () => { - e2e.flows.openDashboard({ uid: PAGE_UNDER_TEST }); - e2e.components.Panels.Panel.title('Panel #1').should('be.visible'); - - // scroll to the bottom - cy.scrollTo('bottom', { - timeout: 5 * 1000, - }); - - // The last panel should be visible... - e2e.components.Panels.Panel.title('Panel #50').should('be.visible'); - - // Then we open and close the panel editor - e2e.components.Panels.Panel.menu('Panel #50').click({ force: true }); // it only shows on hover - e2e.components.Panels.Panel.menuItems('Edit').click(); - e2e.components.NavToolbar.editDashboard.backToDashboardButton().click(); - - // The last panel should still be visible! - e2e.components.Panels.Panel.title('Panel #50').should('be.visible'); - }); -}); diff --git a/e2e/dashboards-suite/import-dashboard.spec.ts b/e2e/dashboards-suite/import-dashboard.spec.ts deleted file mode 100644 index 6d4bfed5e68..00000000000 --- a/e2e/dashboards-suite/import-dashboard.spec.ts +++ /dev/null @@ -1,12 +0,0 @@ -import testDashboard from '../dashboards/TestDashboard.json'; -import { e2e } from '../utils'; - -describe('Import Dashboards Test', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('Ensure you can import a number of json test dashboards from a specific test directory', () => { - e2e.flows.importDashboard(testDashboard, 1000); - }); -}); diff --git a/e2e/dashboards-suite/load-options-from-url.spec.ts b/e2e/dashboards-suite/load-options-from-url.spec.ts deleted file mode 100644 index d674ae2a385..00000000000 --- a/e2e/dashboards-suite/load-options-from-url.spec.ts +++ /dev/null @@ -1,169 +0,0 @@ -import { e2e } from '../utils'; - -const PAGE_UNDER_TEST = '-Y-tnEDWk/templating-nested-template-variables'; - -describe('Variables - Load options from Url', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('default options should be correct', () => { - e2e.flows.openDashboard({ uid: PAGE_UNDER_TEST }); - cy.intercept({ - method: 'POST', - pathname: '/api/ds/query*', - }).as('query'); - - cy.wait('@query'); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('A') - .should('be.visible') - .within(() => { - cy.get('input').click(); - }); - - e2e.components.Select.option().parent().should('have.length', 10); - - e2e.components.Select.toggleAllOptions().should('have.text', 'Selected (1)'); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('All').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('A').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('B').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('C').should('be.visible'); - - cy.get('body').click(0, 0); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('AA') - .should('be.visible') - .within(() => { - cy.get('input').click(); - }); - - e2e.components.Select.option().parent().should('have.length', 10); - - e2e.components.Select.toggleAllOptions().should('have.text', 'Selected (1)'); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('All').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AA').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AB').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AC').should('be.visible'); - - cy.get('body').click(0, 0); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('$__all') - .should('be.visible') - .within(() => { - cy.get('input').click(); - }); - - e2e.components.Select.option().parent().should('have.length', 10); - - e2e.components.Select.toggleAllOptions().should('have.text', 'Selected (1)'); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('All').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AAA').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AAB').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AAC').should('be.visible'); - }); - - it('options set in url should load correct options', () => { - e2e.flows.openDashboard({ uid: `${PAGE_UNDER_TEST}?orgId=1&var-datacenter=B&var-server=BB&var-pod=BBB` }); - cy.intercept({ - method: 'POST', - pathname: '/api/ds/query', - }).as('query'); - - cy.wait('@query'); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('B') - .should('be.visible') - .within(() => { - cy.get('input').click(); - }); - - e2e.components.Select.option().parent().should('have.length', 10); - - e2e.components.Select.toggleAllOptions().should('have.text', 'Selected (1)'); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('All').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('A').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('B').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('C').should('be.visible'); - - cy.get('body').click(0, 0); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('BB') - .should('be.visible') - .within(() => { - cy.get('input').click(); - }); - - e2e.components.Select.option().parent().should('have.length', 10); - - e2e.components.Select.toggleAllOptions().should('have.text', 'Selected (1)'); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('All').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BA').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BB').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BC').should('be.visible'); - - cy.get('body').click(0, 0); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('BBB') - .should('be.visible') - .within(() => { - cy.get('input').click(); - }); - - e2e.components.Select.option().parent().should('have.length', 10); - - e2e.components.Select.toggleAllOptions().should('have.text', 'Selected (1)'); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('All').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BBA').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BBB').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BBC').should('be.visible'); - }); - - it('options set in url that do not exist should load correct options', () => { - // @ts-ignore some typing issue - cy.on('uncaught:exception', (err) => { - if (err.stack?.indexOf("Couldn't find any field of type string in the results.") !== -1) { - // return false to prevent the error from - // failing this test - return false; - } - - return true; - }); - - e2e.flows.openDashboard({ uid: `${PAGE_UNDER_TEST}?orgId=1&var-datacenter=X` }); - cy.intercept({ - method: 'POST', - pathname: '/api/ds/query', - }).as('query'); - - cy.wait('@query'); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('X') - .should('be.visible') - .within(() => { - cy.get('input').click(); - }); - - e2e.components.Select.option().parent().should('have.length', 10); - - e2e.components.Select.toggleAllOptions().should('have.text', 'Selected (1)'); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('All').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('A').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('B').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('C').should('be.visible'); - - cy.get('body').click(); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('$__all') - .should('be.visible') - .should('have.length', 2); - }); -}); diff --git a/e2e/dashboards-suite/new-constant-variable.spec.ts b/e2e/dashboards-suite/new-constant-variable.spec.ts deleted file mode 100644 index 42693acb668..00000000000 --- a/e2e/dashboards-suite/new-constant-variable.spec.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { e2e } from '../utils'; - -const PAGE_UNDER_TEST = 'kVi2Gex7z/test-variable-output'; -const DASHBOARD_NAME = 'Test variable output'; - -describe('Variables - Constant', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('can add a new constant variable', () => { - e2e.flows.openDashboard({ uid: `${PAGE_UNDER_TEST}?orgId=1&editview=variables` }); - cy.contains(DASHBOARD_NAME).should('be.visible'); - - // Create a new "Constant" variable - e2e.components.CallToActionCard.buttonV2('Add variable').click(); - - e2e.pages.Dashboard.Settings.Variables.Edit.General.generalTypeSelectV2().within(() => { - cy.get('input').type('Constant{enter}'); - }); - e2e.pages.Dashboard.Settings.Variables.Edit.General.generalNameInputV2().clear().type('VariableUnderTest').blur(); - e2e.pages.Dashboard.Settings.Variables.Edit.ConstantVariable.constantOptionsQueryInputV2().type('pesto').blur(); - e2e.pages.Dashboard.Settings.Variables.Edit.General.generalLabelInputV2().type('Variable under test').blur(); - - // e2e.pages.Dashboard.Settings.Variables.Edit.General.previewOfValuesOption().eq(0).should('have.text', 'pesto'); - - // Navigate back to the homepage and change the selected variable value - e2e.pages.Dashboard.Settings.Variables.Edit.General.applyButton().click(); - e2e.components.NavToolbar.editDashboard.backToDashboardButton().click(); - e2e.components.RefreshPicker.runButtonV2().click(); - - // Assert it was rendered - cy.get('.markdown-html').should('include.text', 'VariableUnderTest: pesto'); - - // Assert the variable is not visible in the dashboard nav - e2e.pages.Dashboard.SubMenu.submenuItemLabels('Variable under test').should('not.exist'); - }); -}); diff --git a/e2e/dashboards-suite/new-custom-variable.spec.ts b/e2e/dashboards-suite/new-custom-variable.spec.ts deleted file mode 100644 index bda748fbdf2..00000000000 --- a/e2e/dashboards-suite/new-custom-variable.spec.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { e2e } from '../utils'; - -const PAGE_UNDER_TEST = 'kVi2Gex7z/test-variable-output'; -const DASHBOARD_NAME = 'Test variable output'; - -function fillInCustomVariable(name: string, label: string, value: string) { - e2e.pages.Dashboard.Settings.Variables.Edit.General.generalTypeSelectV2().within(() => { - cy.get('input').type('Custom{enter}'); - }); - e2e.pages.Dashboard.Settings.Variables.Edit.General.generalNameInputV2().clear().type(name).blur(); - e2e.pages.Dashboard.Settings.Variables.Edit.General.generalLabelInputV2().type(label).blur(); - e2e.pages.Dashboard.Settings.Variables.Edit.CustomVariable.customValueInput().type(value).blur(); -} - -function assertPreviewValues(expectedValues: string[]) { - for (const expected of expectedValues) { - const index = expectedValues.indexOf(expected); - e2e.pages.Dashboard.Settings.Variables.Edit.General.previewOfValuesOption().eq(index).should('have.text', expected); - } -} - -describe('Variables - Custom', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('can add a custom template variable', () => { - e2e.flows.openDashboard({ uid: `${PAGE_UNDER_TEST}?orgId=1&editview=variables` }); - cy.contains(DASHBOARD_NAME).should('be.visible'); - - // Create a new "Custom" variable - e2e.components.CallToActionCard.buttonV2('Add variable').click(); - fillInCustomVariable('VariableUnderTest', 'Variable under test', 'one,two,three'); - assertPreviewValues(['one', 'two', 'three']); - - // Navigate back to the homepage and change the selected variable value - e2e.pages.Dashboard.Settings.Variables.Edit.General.applyButton().click(); - e2e.components.NavToolbar.editDashboard.backToDashboardButton().click(); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('one').click(); - e2e.components.Select.option().contains('two').click(); - // Assert it was rendered - cy.get('.markdown-html').should('include.text', 'VariableUnderTest: two'); - }); - - it('can add a custom template variable with labels', () => { - e2e.flows.openDashboard({ uid: `${PAGE_UNDER_TEST}?orgId=1&editview=variables` }); - cy.contains(DASHBOARD_NAME).should('be.visible'); - - // Create a new "Custom" variable - e2e.components.CallToActionCard.buttonV2('Add variable').click(); - e2e.pages.Dashboard.Settings.Variables.Edit.General.generalTypeSelectV2().within(() => { - cy.get('input').type('Custom{enter}'); - }); - - // Set its name, label, and content - fillInCustomVariable('VariableUnderTest', 'Variable under test', 'One : 1,Two : 2, Three : 3'); - assertPreviewValues(['One', 'Two', 'Three']); - - // Navigate back to the homepage and change the selected variable value - e2e.pages.Dashboard.Settings.Variables.Edit.General.applyButton().click(); - e2e.components.NavToolbar.editDashboard.backToDashboardButton().click(); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('1').click(); - e2e.components.Select.option().contains('Two').click(); - - // Assert it was rendered - cy.get('.markdown-html').should('include.text', 'VariableUnderTest: 2'); - }); -}); diff --git a/e2e/dashboards-suite/new-datasource-variable.spec.ts b/e2e/dashboards-suite/new-datasource-variable.spec.ts deleted file mode 100644 index b56e458567c..00000000000 --- a/e2e/dashboards-suite/new-datasource-variable.spec.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { e2e } from '../utils'; - -const PAGE_UNDER_TEST = 'kVi2Gex7z/test-variable-output'; -const DASHBOARD_NAME = 'Test variable output'; - -// Skipping due to flakiness/race conditions with same old arch test e2e/dashboards-suite/new-datasource-variable.spec.ts -describe.skip('Variables - Datasource', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('can add a new datasource variable', () => { - e2e.flows.openDashboard({ uid: `${PAGE_UNDER_TEST}?orgId=1&editview=variables` }); - cy.contains(DASHBOARD_NAME).should('be.visible'); - - // Create a new "Datasource" variable - e2e.components.CallToActionCard.buttonV2('Add variable').click(); - e2e.pages.Dashboard.Settings.Variables.Edit.General.generalTypeSelectV2().within(() => { - cy.get('input').type('Data source{enter}'); - }); - e2e.pages.Dashboard.Settings.Variables.Edit.General.generalNameInputV2().clear().type('VariableUnderTest').blur(); - e2e.pages.Dashboard.Settings.Variables.Edit.General.generalLabelInputV2().type('Variable under test').blur(); - - // If this is failing, but sure to check there are Prometheus datasources named "gdev-prometheus" and "gdev-slow-prometheus" - // Or, just update is to match some gdev datasources to test with :) - e2e.pages.Dashboard.Settings.Variables.Edit.DatasourceVariable.datasourceSelect().within(() => { - cy.get('input').type('Prometheus{enter}'); - }); - e2e.pages.Dashboard.Settings.Variables.Edit.General.previewOfValuesOption().should( - 'contain.text', - 'gdev-prometheus' - ); - e2e.pages.Dashboard.Settings.Variables.Edit.General.previewOfValuesOption().should( - 'contain.text', - 'gdev-slow-prometheus' - ); - - // Navigate back to the homepage and change the selected variable value - e2e.pages.Dashboard.Settings.Variables.Edit.General.applyButton().click(); - e2e.components.NavToolbar.editDashboard.backToDashboardButton().click(); - e2e.components.RefreshPicker.runButtonV2().click(); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('gdev-prometheus').click(); - e2e.components.Select.option().contains('gdev-slow-prometheus').click(); - - // Assert it was rendered - cy.get('.markdown-html').should('include.text', 'VariableUnderTest: gdev-slow-prometheus-uid'); - cy.get('.markdown-html').should('include.text', 'VariableUnderTestText: gdev-slow-prometheus'); - }); -}); diff --git a/e2e/dashboards-suite/new-interval-variable.spec.ts b/e2e/dashboards-suite/new-interval-variable.spec.ts deleted file mode 100644 index 88e1052ce5e..00000000000 --- a/e2e/dashboards-suite/new-interval-variable.spec.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { e2e } from '../utils'; - -const PAGE_UNDER_TEST = 'kVi2Gex7z/test-variable-output'; -const DASHBOARD_NAME = 'Test variable output'; - -function assertPreviewValues(expectedValues: string[]) { - for (const expected of expectedValues) { - const index = expectedValues.indexOf(expected); - e2e.pages.Dashboard.Settings.Variables.Edit.General.previewOfValuesOption().eq(index).should('have.text', expected); - } -} - -describe('Variables - Interval', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('can add a new interval variable', () => { - e2e.flows.openDashboard({ uid: `${PAGE_UNDER_TEST}?orgId=1&editview=variables` }); - cy.contains(DASHBOARD_NAME).should('be.visible'); - - // Create a new "Interval" variable - e2e.components.CallToActionCard.buttonV2('Add variable').click(); - e2e.pages.Dashboard.Settings.Variables.Edit.General.generalTypeSelectV2().within(() => { - cy.get('input').type('Interval{enter}'); - }); - e2e.pages.Dashboard.Settings.Variables.Edit.General.generalNameInputV2().clear().type('VariableUnderTest').blur(); - e2e.pages.Dashboard.Settings.Variables.Edit.General.generalLabelInputV2().type('Variable under test').blur(); - - e2e.pages.Dashboard.Settings.Variables.Edit.IntervalVariable.intervalsValueInput() - .clear() - .type('10s,10m,60m,90m,1h30m') - .blur(); - - assertPreviewValues(['10s', '10m', '60m', '90m', '1h30m']); - - // Navigate back to the homepage and change the selected variable value - e2e.pages.Dashboard.Settings.Variables.Edit.General.applyButton().click(); - e2e.components.NavToolbar.editDashboard.backToDashboardButton().click(); - - e2e.components.RefreshPicker.runButtonV2().click(); - - e2e.pages.Dashboard.SubMenu.submenuItemLabels('Variable under test').next().should('have.text', `10s`).click(); - e2e.components.Select.option().contains('1h30m').click(); - - // Assert it was rendered - cy.get('.markdown-html').should('include.text', 'VariableUnderTest: 1h30m'); - }); -}); diff --git a/e2e/dashboards-suite/new-query-variable.spec.ts b/e2e/dashboards-suite/new-query-variable.spec.ts deleted file mode 100644 index 4b3c09a6eb0..00000000000 --- a/e2e/dashboards-suite/new-query-variable.spec.ts +++ /dev/null @@ -1,184 +0,0 @@ -import { selectors } from '@grafana/e2e-selectors'; - -import { e2e } from '../utils'; - -const PAGE_UNDER_TEST = '-Y-tnEDWk/templating-nested-template-variables'; -const DASHBOARD_NAME = 'Templating - Nested Template Variables'; - -describe('Variables - Query - Add variable', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('query variable should be default and default fields should be correct', () => { - e2e.flows.openDashboard({ uid: `${PAGE_UNDER_TEST}?orgId=1&editview=variables` }); - cy.contains(DASHBOARD_NAME).should('be.visible'); - - cy.get(`[data-testid="${selectors.pages.Dashboard.Settings.Variables.List.newButton}"]`) - .should('be.visible') - .click(); - - e2e.pages.Dashboard.Settings.Variables.Edit.General.generalNameInputV2() - .should('be.visible') - .within((input) => { - expect(input.attr('placeholder')).equals('Variable name'); - expect(input.val()).equals('query0'); - }); - e2e.pages.Dashboard.Settings.Variables.Edit.General.generalTypeSelectV2() - .should('be.visible') - .within((select) => { - e2e.components.Select.singleValue().should('have.text', 'Query'); - }); - e2e.pages.Dashboard.Settings.Variables.Edit.General.generalLabelInputV2() - .should('be.visible') - .within((input) => { - expect(input.attr('placeholder')).equals('Label name'); - expect(input.val()).equals(''); - }); - cy.get('[placeholder="Descriptive text"]') - .should('be.visible') - .within((input) => { - expect(input.attr('placeholder')).equals('Descriptive text'); - expect(input.val()).equals(''); - }); - cy.get('label').contains('Hide').should('be.visible'); - - e2e.pages.Dashboard.Settings.Variables.Edit.QueryVariable.queryOptionsDataSourceSelect() - .get('input[placeholder="gdev-testdata"]') - .scrollIntoView() - .should('be.visible'); - - cy.get('label').contains('Refresh').scrollIntoView().should('be.visible'); - cy.get('label').contains('On dashboard load').scrollIntoView().should('be.visible'); - - e2e.pages.Dashboard.Settings.Variables.Edit.QueryVariable.queryOptionsRegExInputV2() - .should('be.visible') - .within((input) => { - const placeholder = '/.*-(?.*)-(?.*)-.*/'; - expect(input.attr('placeholder')).equals(placeholder); - expect(input.val()).equals(''); - }); - e2e.pages.Dashboard.Settings.Variables.Edit.QueryVariable.queryOptionsSortSelectV2() - .should('be.visible') - .within((select) => { - e2e.components.Select.singleValue().should('have.text', 'Disabled'); - }); - - cy.contains('label', 'Multi-value').within(() => { - cy.get('input[type="checkbox"]').should('not.be.checked'); - }); - - cy.contains('label', 'Include All option').within(() => { - cy.get('input[type="checkbox"]').should('not.be.checked'); - }); - - e2e.pages.Dashboard.Settings.Variables.Edit.General.previewOfValuesOption().should('not.exist'); - e2e.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsCustomAllInput().should('not.exist'); - }); - - it('adding a single value query variable', () => { - e2e.flows.openDashboard({ uid: `${PAGE_UNDER_TEST}?orgId=1&editview=variables` }); - cy.contains(DASHBOARD_NAME).should('be.visible'); - - cy.get(`[data-testid="${selectors.pages.Dashboard.Settings.Variables.List.newButton}"]`) - .should('be.visible') - .click(); - - e2e.pages.Dashboard.Settings.Variables.Edit.General.generalLabelInputV2() - .should('be.visible') - .clear() - .type('a label'); - - cy.get('[placeholder="Descriptive text"]').should('be.visible').clear().type('a description'); - - e2e.components.DataSourcePicker.container().should('be.visible').type('gdev-testdata{enter}'); - - e2e.pages.Dashboard.Settings.Variables.Edit.QueryVariable.queryOptionsQueryInput() - .should('be.visible') - .type('*') - .blur(); - - e2e.pages.Dashboard.Settings.Variables.Edit.QueryVariable.queryOptionsRegExInputV2() - .should('be.visible') - .type('/.*C.*/') - .blur(); - - e2e.pages.Dashboard.Settings.Variables.Edit.General.previewOfValuesOption().should('exist'); - - e2e.pages.Dashboard.Settings.Variables.Edit.General.submitButton().scrollIntoView().should('be.visible').click(); - - e2e.components.NavToolbar.editDashboard.backToDashboardButton().click(); - - e2e.pages.Dashboard.SubMenu.submenuItemLabels('a label').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItem() - .should('have.length', 4) - .eq(3) - .within(() => { - cy.get('input').click(); - }); - - e2e.components.Select.option().should('have.length', 1); - e2e.components.Select.option().contains('C'); - }); - - it('adding a multi value query variable', () => { - e2e.flows.openDashboard({ uid: `${PAGE_UNDER_TEST}?orgId=1&editview=variables` }); - cy.contains(DASHBOARD_NAME).should('be.visible'); - - cy.get(`[data-testid="${selectors.pages.Dashboard.Settings.Variables.List.newButton}"]`) - .should('be.visible') - .click(); - - e2e.pages.Dashboard.Settings.Variables.Edit.General.generalLabelInputV2() - .should('be.visible') - .clear() - .type('a label'); - - cy.get('[placeholder="Descriptive text"]').should('be.visible').clear().type('a description'); - - e2e.components.DataSourcePicker.container().type('gdev-testdata{enter}'); - - e2e.pages.Dashboard.Settings.Variables.Edit.QueryVariable.queryOptionsQueryInput() - .should('be.visible') - .type('*') - .blur(); - - e2e.pages.Dashboard.Settings.Variables.Edit.QueryVariable.queryOptionsRegExInputV2() - .should('be.visible') - .type('/.*C.*/') - .blur(); - - cy.contains('label', 'Multi-value').within(() => { - cy.get('input[type="checkbox"]').click({ force: true }).should('be.checked'); - }); - - cy.contains('label', 'Include All option').within(() => { - cy.get('input[type="checkbox"]').click({ force: true }).should('be.checked'); - }); - - e2e.pages.Dashboard.Settings.Variables.Edit.General.selectionOptionsCustomAllInput().within((input) => { - expect(input.val()).equals(''); - }); - - e2e.pages.Dashboard.Settings.Variables.Edit.General.previewOfValuesOption().should('exist'); - - e2e.pages.Dashboard.Settings.Variables.Edit.General.submitButton().scrollIntoView().should('be.visible').click(); - - e2e.components.NavToolbar.editDashboard.backToDashboardButton().click(); - - e2e.pages.Dashboard.SubMenu.submenuItemLabels('a label').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItem() - .should('have.length', 4) - .eq(3) - .within(() => { - cy.get('input').click(); - }); - - e2e.components.Select.option().should('have.length', 3); - - e2e.components.Select.toggleAllOptions().should('have.text', 'Selected (1)'); - - e2e.components.Select.option().contains('All'); - e2e.components.Select.option().contains('C'); - }); -}); diff --git a/e2e/dashboards-suite/new-text-box-variable.spec.ts b/e2e/dashboards-suite/new-text-box-variable.spec.ts deleted file mode 100644 index 7da9afa32bf..00000000000 --- a/e2e/dashboards-suite/new-text-box-variable.spec.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { e2e } from '../utils'; - -const PAGE_UNDER_TEST = 'kVi2Gex7z/test-variable-output'; -const DASHBOARD_NAME = 'Test variable output'; - -describe('Variables - Text box', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('can add a new text box variable', () => { - e2e.flows.openDashboard({ uid: `${PAGE_UNDER_TEST}?orgId=1&editview=variables` }); - cy.contains(DASHBOARD_NAME).should('be.visible'); - - // Create a new "text box" variable - e2e.components.CallToActionCard.buttonV2('Add variable').click(); - - e2e.pages.Dashboard.Settings.Variables.Edit.General.generalTypeSelectV2().within(() => { - cy.get('input').type('Textbox{enter}'); - }); - e2e.pages.Dashboard.Settings.Variables.Edit.General.generalNameInputV2().clear().type('VariableUnderTest').blur(); - e2e.pages.Dashboard.Settings.Variables.Edit.General.generalLabelInputV2().type('Variable under test').blur(); - e2e.pages.Dashboard.Settings.Variables.Edit.TextBoxVariable.textBoxOptionsQueryInputV2().type('cat-dog').blur(); - - // Navigate back to the homepage and change the selected variable value - e2e.pages.Dashboard.Settings.Variables.Edit.General.applyButton().click(); - e2e.components.NavToolbar.editDashboard.backToDashboardButton().click(); - e2e.pages.Dashboard.SubMenu.submenuItem().within(() => { - cy.get('input').clear().type('dog-cat').blur(); - }); - // Assert it was rendered - cy.get('.markdown-html').should('include.text', 'VariableUnderTest: dog-cat'); - }); -}); diff --git a/e2e/dashboards-suite/set-options-from-ui.spec.ts b/e2e/dashboards-suite/set-options-from-ui.spec.ts deleted file mode 100644 index bdcc5c6b516..00000000000 --- a/e2e/dashboards-suite/set-options-from-ui.spec.ts +++ /dev/null @@ -1,171 +0,0 @@ -import { selectors } from '@grafana/e2e-selectors'; - -import { e2e } from '../utils'; - -const PAGE_UNDER_TEST = '-Y-tnEDWk/templating-nested-template-variables'; - -describe('Variables - Set options from ui', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('clicking a value that is not part of dependents options should change these to All', () => { - e2e.flows.openDashboard({ uid: `${PAGE_UNDER_TEST}?orgId=1&var-datacenter=A&var-server=AA&var-pod=AAA` }); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('A') - .should('be.visible') - .within(() => { - cy.get('input').click(); - }); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('A').should('be.visible').click(); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('B').should('be.visible').click(); - - cy.get('body').click(); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('B').scrollIntoView().should('be.visible'); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('$__all') - .should('have.length', 2) - .eq(0) - .should('be.visible') - .within(() => { - cy.get('input').click(); - }); - - e2e.components.Select.option().parent().should('have.length', 10); - - e2e.components.Select.toggleAllOptions().should('have.text', 'Selected (1)'); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('All').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BA').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BB').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BC').should('be.visible'); - - cy.get('body').click(); - - e2e.pages.Dashboard.SubMenu.submenuItemLabels('pod') - .parent() - .within(() => { - cy.get('input').click(); - }); - - // length is 11 because of virtualized select options - e2e.components.Select.option().parent().should('have.length', 11); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('All').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BAA').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BAB').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BAC').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BAD').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BAE').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BAF').should('be.visible'); - }); - - it('adding a value that is not part of dependents options should add the new values dependant options', () => { - e2e.flows.openDashboard({ uid: `${PAGE_UNDER_TEST}?orgId=1&var-datacenter=A&var-server=AA&var-pod=AAA` }); - cy.intercept({ - pathname: '/api/ds/query', - }).as('query'); - - cy.wait('@query'); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('A') - .should('be.visible') - .within(() => { - cy.get('input').click(); - }); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('B').should('be.visible').click(); - - e2e.components.Select.toggleAllOptions().should('have.text', 'Selected (2)'); - - cy.get('body').click(); - - cy.wait('@query'); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('A,B').scrollIntoView().should('be.visible'); - - cy.get(`[aria-label="${selectors.components.LoadingIndicator.icon}"]`).should('not.exist'); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('AA') - .should('be.visible') - .within(() => { - cy.get('input').click(); - }); - - e2e.components.Select.option().should('have.length', 11); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('All').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AA').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AB').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AC').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AD').should('be.visible'); - - cy.get('body').click(); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('AAA') - .should('be.visible') - .within(() => { - cy.get('input').click(); - }); - - e2e.components.Select.option().should('have.length', 10); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('All').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AAA').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AAB').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('AAC').should('be.visible'); - }); - - it('removing a value that is part of dependents options should remove the new values dependant options', () => { - e2e.flows.openDashboard({ - uid: `${PAGE_UNDER_TEST}?orgId=1&var-datacenter=A&var-datacenter=B&var-server=AA&var-server=BB&var-pod=AAA&var-pod=BBB`, - }); - cy.intercept({ pathname: '/api/ds/query' }).as('query'); - - cy.wait('@query'); - cy.get(`[aria-label="${selectors.components.LoadingIndicator.icon}"]`).should('not.exist'); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('A,B') - .should('be.visible') - .within(() => { - cy.get('input').click(); - }); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('A').should('be.visible').click(); - - cy.get('body').click(); - - cy.wait('@query'); - cy.get(`[aria-label="${selectors.components.LoadingIndicator.icon}"]`).should('not.exist'); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('B').should('be.visible'); - - cy.get(`[aria-label="${selectors.components.LoadingIndicator.icon}"]`).should('not.exist'); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('BB') - .should('be.visible') - .within(() => { - cy.get('input').click(); - }); - - e2e.components.Select.option().should('have.length', 10); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('All').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BA').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BB').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BC').should('be.visible'); - - cy.get('body').click(0, 0); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('BBB') - .should('be.visible') - .within(() => { - cy.get('input').click(); - }); - e2e.components.Select.option().should('have.length', 10); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BBA').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BBB').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('BBC').should('be.visible'); - }); -}); diff --git a/e2e/dashboards-suite/snapshot-create.spec.ts b/e2e/dashboards-suite/snapshot-create.spec.ts deleted file mode 100644 index ee07081bfd0..00000000000 --- a/e2e/dashboards-suite/snapshot-create.spec.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { e2e } from '../utils'; - -describe('Snapshots', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('Create a snapshot dashboard', () => { - // Opening a dashboard - cy.intercept({ - pathname: '/api/ds/query', - }).as('query'); - e2e.flows.openDashboard({ uid: 'ZqZnVvFZz', queryParams: { '__feature.newDashboardSharingComponent': false } }); - cy.wait('@query'); - - const panelsToCheck = [ - 'Raw Data Graph', - 'Last non-null', - 'min', - 'Max', - 'The data from graph above with seriesToColumns transform', - ]; - - // Open the sharing modal - e2e.components.NavToolbar.shareDashboard().click(); - - // Select the snapshot tab - e2e.components.Tab.title('Snapshot').click(); - - // Publish snapshot - cy.intercept('POST', '/api/snapshots').as('save'); - e2e.pages.ShareDashboardModal.SnapshotScene.PublishSnapshot().click(); - cy.wait('@save'); - - // Copy link button should be visible - e2e.pages.ShareDashboardModal.SnapshotScene.CopyUrlButton().should('exist'); - - // Copy the snapshot URL form the input and open the snapshot - e2e.pages.ShareDashboardModal.SnapshotScene.CopyUrlInput() - .invoke('val') - .then((text) => cy.wrap(text).as('url')); - - // Open the snapshot using the new URL - cy.get('@url').then((url) => { - e2e.pages.ShareDashboardModal.SnapshotScene.visit(getSnapshotKey(String(url))); - }); - - // Validate the dashboard controls are rendered - e2e.pages.Dashboard.Controls().should('exist'); - - // Validate the panels are rendered - for (const title of panelsToCheck) { - e2e.components.Panels.Panel.title(title).should('be.visible'); - } - }); -}); -// -const getSnapshotKey = (url: string): string => { - return url.split('/').pop(); -}; diff --git a/e2e/dashboards-suite/templating-dashboard-links-and-variables.spec.ts b/e2e/dashboards-suite/templating-dashboard-links-and-variables.spec.ts deleted file mode 100644 index 03fa10a4b2d..00000000000 --- a/e2e/dashboards-suite/templating-dashboard-links-and-variables.spec.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { e2e } from '../utils'; - -describe('Templating', () => { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('Tests dashboard links and variables in links', () => { - cy.intercept({ - method: 'GET', - url: '/api/search?tag=templating&limit=100', - }).as('tagsTemplatingSearch'); - cy.intercept({ - method: 'GET', - url: '/api/search?tag=demo&limit=100', - }).as('tagsDemoSearch'); - - e2e.flows.openDashboard({ uid: 'yBCC3aKGk' }); - - // waiting for network requests first - cy.wait(['@tagsTemplatingSearch', '@tagsDemoSearch']); - - const verifyLinks = (variableValue: string) => { - e2e.components.DashboardLinks.link() - .should('be.visible') - .should((links) => { - expect(links).to.have.length.greaterThan(13); - - for (let index = 0; index < links.length; index++) { - expect(Cypress.$(links[index]).attr('href')).contains(variableValue); - } - }); - }; - - e2e.components.DashboardLinks.dropDown().should('be.visible').click().wait('@tagsTemplatingSearch'); - - verifyLinks('var-custom=$__all'); - - cy.get('body').click(); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts('$__all') - .should('be.visible') - .within(() => { - cy.get('input').click(); - }); - - e2e.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts('p2').should('be.visible').click(); - - cy.get('body').click(); - - e2e.components.DashboardLinks.dropDown() - .scrollIntoView() - .should('be.visible') - .click() - .wait('@tagsTemplatingSearch'); - - // verify all links, should have p2 value - verifyLinks('p2'); - }); -}); diff --git a/e2e/dashboards-suite/textbox-variables.spec.ts b/e2e/dashboards-suite/textbox-variables.spec.ts deleted file mode 100644 index 4b5790a7f76..00000000000 --- a/e2e/dashboards-suite/textbox-variables.spec.ts +++ /dev/null @@ -1,236 +0,0 @@ -import { e2e } from '../utils'; - -const PAGE_UNDER_TEST = 'AejrN1AMz'; - -describe('TextBox - load options scenarios', function () { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('default options should be correct', function () { - e2e.flows.openDashboard({ uid: `${PAGE_UNDER_TEST}/templating-textbox-e2e-scenarios?orgId=1` }); - - validateTextboxAndMarkup('default value'); - }); - - it('loading variable from url should be correct', function () { - e2e.flows.openDashboard({ - uid: `${PAGE_UNDER_TEST}/templating-textbox-e2e-scenarios?orgId=1&var-text=not default value`, - }); - - validateTextboxAndMarkup('not default value'); - }); -}); - -describe.skip('TextBox - change query scenarios', function () { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('when changing the query value and not saving current as default should revert query value', function () { - copyExistingDashboard(); - - changeQueryInput(); - - e2e.components.BackButton.backArrow().should('be.visible').click({ force: true }); - - validateTextboxAndMarkup('changed value'); - - saveDashboard(false); - - cy.get('@dashuid').then((dashuid) => { - expect(dashuid).not.to.eq(PAGE_UNDER_TEST); - - e2e.flows.openDashboard({ uid: dashuid }); - - cy.wait('@load-dash'); - - validateTextboxAndMarkup('default value'); - - validateVariable('changed value'); - }); - }); - - it('when changing the query value and saving current as default should change query value', function () { - copyExistingDashboard(); - - changeQueryInput(); - - e2e.components.BackButton.backArrow().should('be.visible').click({ force: true }); - - validateTextboxAndMarkup('changed value'); - - saveDashboard(true); - - cy.get('@dashuid').then((dashuid) => { - expect(dashuid).not.to.eq(PAGE_UNDER_TEST); - - e2e.flows.openDashboard({ uid: dashuid }); - - cy.wait('@load-dash'); - - validateTextboxAndMarkup('changed value'); - - validateVariable('changed value'); - }); - }); -}); - -describe.skip('TextBox - change picker value scenarios', function () { - beforeEach(() => { - e2e.flows.login(Cypress.env('USERNAME'), Cypress.env('PASSWORD')); - }); - - it('when changing the input value and not saving current as default should revert query value', function () { - copyExistingDashboard(); - - changeTextBoxInput(); - - validateTextboxAndMarkup('changed value'); - - saveDashboard(false); - - cy.get('@dashuid').then((dashuid) => { - expect(dashuid).not.to.eq(PAGE_UNDER_TEST); - - e2e.flows.openDashboard({ uid: dashuid }); - - cy.wait('@load-dash'); - - validateTextboxAndMarkup('default value'); - validateVariable('default value'); - }); - }); - - it('when changing the input value and saving current as default should change query value', function () { - copyExistingDashboard(); - - changeTextBoxInput(); - - validateTextboxAndMarkup('changed value'); - - saveDashboard(true); - - cy.get('@dashuid').then((dashuid) => { - expect(dashuid).not.to.eq(PAGE_UNDER_TEST); - - e2e.flows.openDashboard({ uid: dashuid }); - - cy.wait('@load-dash'); - - validateTextboxAndMarkup('changed value'); - validateVariable('changed value'); - }); - }); -}); - -function copyExistingDashboard() { - cy.intercept({ - method: 'GET', - url: '/api/search?query=&type=dash-folder&permission=Edit', - }).as('dash-settings'); - cy.intercept({ - method: 'POST', - url: '/api/dashboards/db/', - }).as('save-dash'); - cy.intercept({ - method: 'GET', - url: /\/api\/dashboards\/uid\/(?!AejrN1AMz)\w+/, - }).as('load-dash'); - e2e.flows.openDashboard({ uid: `${PAGE_UNDER_TEST}/templating-textbox-e2e-scenarios?orgId=1&editview=settings` }); - - cy.wait('@dash-settings'); - - e2e.pages.Dashboard.Settings.General.saveAsDashBoard().should('be.visible').click(); - - e2e.pages.SaveDashboardAsModal.newName().should('be.visible').type(`${Date.now()}`); - - e2e.pages.SaveDashboardAsModal.save().should('be.visible').click(); - - cy.wait('@save-dash'); - cy.wait('@load-dash'); - - e2e.pages.Dashboard.SubMenu.submenuItem().should('be.visible'); - - cy.location().then((loc) => { - const dashuid = /\/d\/(\w+)\//.exec(loc.href)![1]; - cy.wrap(dashuid).as('dashuid'); - }); - - cy.wait(500); -} - -function saveDashboard(saveVariables: boolean) { - e2e.components.PageToolbar.item('Save dashboard').should('be.visible').click(); - - if (saveVariables) { - e2e.pages.SaveDashboardModal.saveVariables().should('exist').click({ force: true }); - } - - e2e.pages.SaveDashboardModal.save().should('be.visible').click(); - - cy.wait('@save-dash'); -} - -function validateTextboxAndMarkup(value: string) { - e2e.pages.Dashboard.SubMenu.submenuItem() - .should('be.visible') - .within(() => { - e2e.pages.Dashboard.SubMenu.submenuItemLabels('text').should('be.visible'); - cy.get('input').should('be.visible').should('have.value', value); - }); - - e2e.components.Panels.Visualization.Text.container() - .should('be.visible') - .within(() => { - cy.get('h1').should('be.visible').should('have.text', `variable: ${value}`); - }); -} - -function validateVariable(value: string) { - e2e.components.PageToolbar.item('Dashboard settings').should('be.visible').click(); - - e2e.pages.Dashboard.Settings.General.sectionItems('Variables').should('be.visible').click(); - - e2e.pages.Dashboard.Settings.Variables.List.tableRowNameFields('text').should('be.visible').click(); - - e2e.pages.Dashboard.Settings.Variables.Edit.TextBoxVariable.textBoxOptionsQueryInputV2() - .should('be.visible') - .should('have.value', value); -} - -function changeTextBoxInput() { - e2e.pages.Dashboard.SubMenu.submenuItemLabels('text').should('be.visible'); - e2e.pages.Dashboard.SubMenu.submenuItem() - .should('be.visible') - .within(() => { - cy.get('input') - .should('be.visible') - .should('have.value', 'default value') - .clear() - .type('changed value') - .type('{enter}'); - }); - - cy.location().should((loc) => { - expect(loc.search).to.contain('var-text=changed%20value'); - }); -} - -function changeQueryInput() { - e2e.components.PageToolbar.item('Dashboard settings').should('be.visible').click(); - - e2e.pages.Dashboard.Settings.General.sectionItems('Variables').should('be.visible').click(); - - e2e.pages.Dashboard.Settings.Variables.List.tableRowNameFields('text').should('be.visible').click(); - - e2e.pages.Dashboard.Settings.Variables.Edit.TextBoxVariable.textBoxOptionsQueryInputV2() - .should('be.visible') - .clear() - .type('changed value') - .blur(); - - e2e.pages.Dashboard.Settings.Variables.Edit.General.previewOfValuesOption() - .should('have.length', 1) - .should('have.text', 'changed value'); -} diff --git a/e2e/dashboards-suite/utils/makeDashboard.ts b/e2e/dashboards-suite/utils/makeDashboard.ts deleted file mode 100644 index 2ada48db7a9..00000000000 --- a/e2e/dashboards-suite/utils/makeDashboard.ts +++ /dev/null @@ -1,58 +0,0 @@ -export function makeNewDashboardRequestBody(dashboardName: string, folderUid?: string) { - return { - dashboard: { - 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, - links: [], - liveNow: false, - panels: [ - { - datasource: { type: 'testdata', uid: '89_jzlT4k' }, - gridPos: { h: 9, w: 12, x: 0, y: 0 }, - id: 2, - options: { - code: { - language: 'plaintext', - showLineNumbers: false, - showMiniMap: false, - }, - content: '***A nice little happy empty dashboard***', - mode: 'markdown', - }, - pluginVersion: '9.4.0-pre', - title: 'Nothing to see here', - type: 'text', - }, - ], - refresh: '', - revision: 1, - schemaVersion: 38, - tags: [], - templating: { list: [] }, - time: { from: 'now-6h', to: 'now' }, - timepicker: {}, - timezone: '', - title: dashboardName, - version: 0, - uid: '', - weekStart: '', - }, - message: '', - overwrite: false, - folderUid, - } as const; -} diff --git a/e2e/run-suite b/e2e/run-suite index 3303918e1fd..f0b9fdd6712 100755 --- a/e2e/run-suite +++ b/e2e/run-suite @@ -28,7 +28,6 @@ declare -A env=( testFilesForSingleSuite="*.spec.ts" rootForEnterpriseSuite="./e2e/extensions" rootForOldArch="./e2e/old-arch" -rootForKubernetesDashboards="./e2e/dashboards-suite" rootForSearchDashboards="./e2e/dashboards-search-suite" declare -A cypressConfig=( @@ -111,24 +110,6 @@ case "$1" in cypressConfig[video]=${args[1]} env[dashboardScene]=false ;; - "dashboards-schema-v2") - env[kubernetesDashboards]=true - cypressConfig[specPattern]=$rootForKubernetesDashboards/$testFilesForSingleSuite - cypressConfig[video]=false - case "$2" in - "debug") - echo -e "Debug mode" - env[SLOWMO]=1 - PARAMS="--no-exit" - enterpriseSuite=$(basename "${args[2]}") - ;; - "dev") - echo "Dev mode" - CMD="cypress open" - enterpriseSuite=$(basename "${args[2]}") - ;; - esac - ;; "dashboards-search") env[kubernetesDashboards]=true cypressConfig[specPattern]=$rootForSearchDashboards/$testFilesForSingleSuite diff --git a/package.json b/package.json index 8c48e83a01c..71c62b5c442 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "dev": "NODE_ENV=dev nx exec -- webpack --config scripts/webpack/webpack.dev.js", "e2e": "./e2e/start-and-run-suite", "e2e:old-arch": "./e2e/start-and-run-suite old-arch", - "e2e:schema-v2": "./e2e/start-and-run-suite dashboards-schema-v2", + "e2e:schema-v2": "KUBERNETES_DASHBOARDS=true yarn playwright test --project dashboards", "e2e:dashboards-search": "./e2e/start-and-run-suite dashboards-search", "e2e:debug": "./e2e/start-and-run-suite debug", "e2e:dev": "./e2e/start-and-run-suite dev", diff --git a/scripts/grafana-server/start-server b/scripts/grafana-server/start-server index 71b6f929510..d9581910b83 100755 --- a/scripts/grafana-server/start-server +++ b/scripts/grafana-server/start-server @@ -25,7 +25,7 @@ echo starting server # air now deletes the binary, so we check if we need to build it before trying to start the server # see https://github.com/air-verse/air/issues/525 # if this gets resolved, we could remove the go build and rely on the binary being present as before -if [[ ! -f ./bin/grafana ]]; then +if [[ ! -f ./bin/"$ARCH"grafana ]]; then make GO_BUILD_DEV=1 build-go-fast fi