diff --git a/e2e-playwright/dashboard-new-layouts/dashboards-repeats-auto-grid.spec.ts b/e2e-playwright/dashboard-new-layouts/dashboards-repeats-auto-grid.spec.ts new file mode 100644 index 00000000000..28ca51e3b28 --- /dev/null +++ b/e2e-playwright/dashboard-new-layouts/dashboards-repeats-auto-grid.spec.ts @@ -0,0 +1,457 @@ +import { Page } from 'playwright-core'; + +import { test, expect } from '@grafana/plugin-e2e'; + +import testV2DashWithRepeats from '../dashboards/V2DashWithRepeats.json'; + +import { + checkRepeatedPanelTitles, + saveDashboard, + verifyChanges, + movePanel, + getPanelPosition, + importTestDashboard, + goToEmbeddedPanel, +} from './utils'; + +const repeatTitleBase = 'repeat - '; +const newTitleBase = 'edited rep - '; +const repeatOptions = [1, 2, 3, 4]; + +test.use({ + featureToggles: { + kubernetesDashboards: true, + dashboardNewLayouts: true, + groupByVariable: true, + }, +}); + +test.use({ + viewport: { width: 1920, height: 1080 }, +}); + +test.describe( + 'Repeats - Dashboard auto grid', + { + tag: ['@dashboards'], + }, + () => { + test('can enable repeats', async ({ dashboardPage, selectors, page }) => { + await importTestDashboard(page, selectors, 'Auto grid repeats - add repeats'); + + await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click(); + + await switchToAutoGrid(page); + + await dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title('New panel')).first().click(); + + await dashboardPage + .getByGrafanaSelector(selectors.components.PanelEditor.OptionsPane.fieldInput('Title')) + .fill(`${repeatTitleBase}$c1`); + + const repeatOptionsGroup = dashboardPage.getByGrafanaSelector( + selectors.components.OptionsGroup.group('repeat-options') + ); + // expand repeat options dropdown + await repeatOptionsGroup.getByRole('button').first().click(); + // find repeat variable dropdown + await repeatOptionsGroup.getByRole('combobox').click(); + await page.getByRole('option', { name: 'c1' }).click(); + + await checkRepeatedPanelTitles(dashboardPage, selectors, repeatTitleBase, repeatOptions); + + await saveDashboard(dashboardPage, page, selectors); + await page.reload(); + + await checkRepeatedPanelTitles(dashboardPage, selectors, repeatTitleBase, repeatOptions); + }); + + test('can update repeats with variable change', async ({ dashboardPage, selectors, page }) => { + await importTestDashboard( + page, + selectors, + 'Auto grid repeats - update on variable change', + JSON.stringify(testV2DashWithRepeats) + ); + + await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click(); + + await switchToAutoGrid(page); + await saveDashboard(dashboardPage, page, selectors); + await page.reload(); + + await dashboardPage + .getByGrafanaSelector( + selectors.pages.Dashboard.SubMenu.submenuItemValueDropDownValueLinkTexts(repeatOptions.join(',')) + ) + .click(); + + // deselect last variable option + await dashboardPage + .getByGrafanaSelector( + selectors.pages.Dashboard.SubMenu.submenuItemValueDropDownOptionTexts(`${repeatOptions.at(-1)}`) + ) + .click(); + await page.locator('body').click({ position: { x: 0, y: 0 } }); // blur select + + // verify that repeats are present for first 3 values + await checkRepeatedPanelTitles(dashboardPage, selectors, repeatTitleBase, repeatOptions.slice(0, -1)); + + // verify there is no repeat with last value + await expect( + dashboardPage.getByGrafanaSelector( + selectors.components.Panels.Panel.title(`${repeatTitleBase}${repeatOptions.at(-1)}`) + ) + ).toBeHidden(); + }); + test('can update repeats in edit pane', async ({ dashboardPage, selectors, page }) => { + await importTestDashboard( + page, + selectors, + 'Auto grid repeats - update through edit pane', + JSON.stringify(testV2DashWithRepeats) + ); + + await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click(); + + await switchToAutoGrid(page); + + // select first/original repeat panel to activate edit pane + await dashboardPage + .getByGrafanaSelector(selectors.components.Panels.Panel.title(`${repeatTitleBase}${repeatOptions.at(0)}`)) + .click(); + + await dashboardPage + .getByGrafanaSelector(selectors.components.PanelEditor.OptionsPane.fieldInput('Title')) + .fill(`${newTitleBase}$c1`); + await dashboardPage.getByGrafanaSelector(selectors.components.PanelEditor.OptionsPane.fieldInput('Title')).blur(); + + await checkRepeatedPanelTitles(dashboardPage, selectors, newTitleBase, repeatOptions); + + await saveDashboard(dashboardPage, page, selectors); + await page.reload(); + + await checkRepeatedPanelTitles(dashboardPage, selectors, newTitleBase, repeatOptions); + }); + + test('can update repeats in panel editor', async ({ dashboardPage, selectors, page }) => { + await importTestDashboard( + page, + selectors, + 'Auto grid repeats - update through panel editor', + JSON.stringify(testV2DashWithRepeats) + ); + + await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click(); + await switchToAutoGrid(page); + await saveDashboard(dashboardPage, page, selectors); + await page.reload(); + + await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click(); + + // selecting last repeat + const panel = dashboardPage.getByGrafanaSelector( + selectors.components.Panels.Panel.title(`${repeatTitleBase}${repeatOptions.at(-1)}`) + ); + await panel.hover(); + await page.keyboard.press('e'); + + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.DashboardEditPaneSplitter.primaryBody) + ).toBeHidden(); // verifying that panel editor loaded + + // verify original repeat panel is loaded + await expect( + dashboardPage.getByGrafanaSelector( + selectors.components.Panels.Panel.title(`${repeatTitleBase}${repeatOptions.at(0)}`) + ) + ).toBeVisible(); + + await dashboardPage + .getByGrafanaSelector(selectors.components.PanelEditor.OptionsPane.fieldInput('Title')) + .fill(`${newTitleBase}$c1`); + await dashboardPage.getByGrafanaSelector(selectors.components.PanelEditor.OptionsPane.fieldInput('Title')).blur(); + + // playwright too fast, verifying JSON diff that changes landed + await verifyChanges(dashboardPage, page, selectors, newTitleBase); + + // verify panel title change in panel editor UI + await expect( + dashboardPage.getByGrafanaSelector( + selectors.components.Panels.Panel.title(`${newTitleBase}${repeatOptions.at(0)}`) + ) + ).toBeVisible(); + + await dashboardPage + .getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.backToDashboardButton) + .click(); + + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.DashboardEditPaneSplitter.primaryBody) + ).toBeVisible(); // verifying that dashboard loaded + + await checkRepeatedPanelTitles(dashboardPage, selectors, newTitleBase, repeatOptions); + + await saveDashboard(dashboardPage, page, selectors); + await page.reload(); + + await checkRepeatedPanelTitles(dashboardPage, selectors, newTitleBase, repeatOptions); + }); + + test('can update repeats in panel editor when loaded directly', async ({ dashboardPage, selectors, page }) => { + await importTestDashboard( + page, + selectors, + 'Auto grid repeats - update through directly loaded panel editor', + JSON.stringify(testV2DashWithRepeats) + ); + + await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click(); + await switchToAutoGrid(page); + await saveDashboard(dashboardPage, page, selectors); + + // loading directly into panel editor + await page.goto(`${page.url()}&editPanel=1`); + + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.DashboardEditPaneSplitter.primaryBody) + ).toBeHidden(); // verifying that panel editor loaded + + await expect( + dashboardPage.getByGrafanaSelector( + selectors.components.Panels.Panel.title(`${repeatTitleBase}${repeatOptions.at(0)}`) + ) + ).toBeVisible(); + + await dashboardPage + .getByGrafanaSelector(selectors.components.PanelEditor.OptionsPane.fieldInput('Title')) + .fill(`${newTitleBase}$c1`); + + await dashboardPage.getByGrafanaSelector(selectors.components.PanelEditor.OptionsPane.fieldInput('Title')).blur(); + + // playwright too fast, verifying JSON diff that changes landed + await verifyChanges(dashboardPage, page, selectors, newTitleBase); + + await expect( + dashboardPage.getByGrafanaSelector( + selectors.components.Panels.Panel.title(`${newTitleBase}${repeatOptions.at(0)}`) + ) + ).toBeVisible(); + + await dashboardPage + .getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.backToDashboardButton) + .click(); + + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.DashboardEditPaneSplitter.primaryBody) + ).toBeVisible(); // verifying that dashboard loaded + + await checkRepeatedPanelTitles(dashboardPage, selectors, newTitleBase, repeatOptions); + + await saveDashboard(dashboardPage, page, selectors); + await page.reload(); + + await checkRepeatedPanelTitles(dashboardPage, selectors, newTitleBase, repeatOptions); + }); + test('can move repeated panels', async ({ dashboardPage, selectors, page }) => { + await importTestDashboard( + page, + selectors, + 'Auto grid repeats - move repeated panels', + JSON.stringify(testV2DashWithRepeats) + ); + + await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click(); + + await switchToAutoGrid(page); + + // this moving repeated panel between two normal panels + await movePanel(dashboardPage, selectors, `${repeatTitleBase}${repeatOptions.at(0)}`, 'New panel'); + + // verify move by panel title order + expect(dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.headerContainer).first()).toHaveText( + 'New panel' + ); + expect(dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.headerContainer).last()).toHaveText( + 'New panel' + ); + + // verify move by panel position + let repeatedPanel = await getPanelPosition(dashboardPage, selectors, `${repeatTitleBase}${repeatOptions.at(0)}`); + let normalPanel = await getPanelPosition(dashboardPage, selectors, 'New panel'); + expect(normalPanel?.x).toBeLessThan(repeatedPanel?.x || 0); + + await saveDashboard(dashboardPage, page, selectors); + await page.reload(); + + const repeatedPanel2 = await getPanelPosition( + dashboardPage, + selectors, + `${repeatTitleBase}${repeatOptions.at(0)}` + ); + + const normalPanel2 = await getPanelPosition(dashboardPage, selectors, 'New panel'); + + expect(normalPanel2?.x).toBeLessThan(repeatedPanel2?.x || 0); + expect(dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.headerContainer).first()).toHaveText( + 'New panel' + ); + expect(dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.headerContainer).last()).toHaveText( + 'New panel' + ); + }); + test('can view repeated panel', async ({ dashboardPage, selectors, page }) => { + await importTestDashboard( + page, + selectors, + 'Auto grid repeats - move repeated panels', + JSON.stringify(testV2DashWithRepeats) + ); + + await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click(); + await switchToAutoGrid(page); + await saveDashboard(dashboardPage, page, selectors); + await page.reload(); + + await dashboardPage + .getByGrafanaSelector(selectors.components.Panels.Panel.title(`${repeatTitleBase}${repeatOptions.at(-1)}`)) + .hover(); + await page.keyboard.press('v'); + + await expect( + dashboardPage.getByGrafanaSelector( + selectors.components.Panels.Panel.title(`${repeatTitleBase}${repeatOptions.at(0)}`) + ) + ).toBeHidden(); + + await expect( + dashboardPage.getByGrafanaSelector( + selectors.components.Panels.Panel.title(`${repeatTitleBase}${repeatOptions.at(-1)}`) + ) + ).toBeVisible(); + + const repeatedPanelUrl = page.url(); + + await dashboardPage + .getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.backToDashboardButton) + .click(); + + await dashboardPage + .getByGrafanaSelector(selectors.components.Panels.Panel.title(`${repeatTitleBase}${repeatOptions.at(0)}`)) + .hover(); + await page.keyboard.press('v'); + + await expect( + dashboardPage.getByGrafanaSelector( + selectors.components.Panels.Panel.title(`${repeatTitleBase}${repeatOptions.at(-1)}`) + ) + ).toBeHidden(); + + await expect( + dashboardPage.getByGrafanaSelector( + selectors.components.Panels.Panel.title(`${repeatTitleBase}${repeatOptions.at(0)}`) + ) + ).toBeVisible(); + + // load view panel directly + await page.goto(repeatedPanelUrl); + + await expect( + dashboardPage.getByGrafanaSelector( + selectors.components.Panels.Panel.title(`${repeatTitleBase}${repeatOptions.at(-1)}`) + ) + ).toBeVisible(); + }); + + test('can view embedded repeated panel', async ({ dashboardPage, selectors, page }) => { + await importTestDashboard( + page, + selectors, + 'Auto grid repeats - view embedded repeated panel', + JSON.stringify(testV2DashWithRepeats) + ); + + await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click(); + await switchToAutoGrid(page); + await saveDashboard(dashboardPage, page, selectors); + await page.reload(); + + await dashboardPage + .getByGrafanaSelector(selectors.components.Panels.Panel.title(`${repeatTitleBase}${repeatOptions.at(-1)}`)) + .hover(); + await page.keyboard.press('p+e'); + + await goToEmbeddedPanel(page); + + await expect( + dashboardPage.getByGrafanaSelector( + selectors.components.Panels.Panel.title(`${repeatTitleBase}${repeatOptions.at(-1)}`) + ) + ).toBeVisible(); + }); + test('can remove repeats', async ({ dashboardPage, selectors, page }) => { + await importTestDashboard( + page, + selectors, + 'Auto grid repeats - remove repeats', + JSON.stringify(testV2DashWithRepeats) + ); + + await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click(); + await switchToAutoGrid(page); + await saveDashboard(dashboardPage, page, selectors); + await page.reload(); + + await expect(page.locator('[data-testid="uplot-main-div"]').first()).toBeVisible(); + + // verify 6 panels are present (4 repeats and 2 normal) + expect( + await dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.headerContainer).all() + ).toHaveLength(6); + + await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.editButton).click(); + + await dashboardPage + .getByGrafanaSelector(selectors.components.Panels.Panel.title(`${repeatTitleBase}${repeatOptions.at(0)}`)) + .click(); + + const repeatOptionsGroup = dashboardPage.getByGrafanaSelector( + selectors.components.OptionsGroup.group('repeat-options') + ); + // expand repeat options dropdown + await repeatOptionsGroup.getByRole('button').first().click(); + // find repeat variable dropdown + await repeatOptionsGroup.getByRole('combobox').first().click(); + await page.getByRole('option', { name: 'Disable repeating' }).click(); + + await expect( + dashboardPage.getByGrafanaSelector( + selectors.components.Panels.Panel.title(`${repeatTitleBase}${repeatOptions.join(' + ')}`) + ) + ).toBeVisible(); + + // verify only 3 panels are present + expect( + await dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.headerContainer).all() + ).toHaveLength(3); + + await saveDashboard(dashboardPage, page, selectors); + await page.reload(); + + await expect( + dashboardPage.getByGrafanaSelector( + selectors.components.Panels.Panel.title(`${repeatTitleBase}${repeatOptions.join(' + ')}`) + ) + ).toBeVisible(); + + expect( + await dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.headerContainer).all() + ).toHaveLength(3); + }); + } +); + +async function switchToAutoGrid(page: Page) { + await page.getByLabel('Expand Panel layout category').click(); + await page.getByLabel('Auto grid').click(); +} diff --git a/e2e-playwright/dashboard-new-layouts/dashboards-repeats-custom-grid.spec.ts b/e2e-playwright/dashboard-new-layouts/dashboards-repeats-custom-grid.spec.ts index 4e12c03bc34..0a349df5728 100644 --- a/e2e-playwright/dashboard-new-layouts/dashboards-repeats-custom-grid.spec.ts +++ b/e2e-playwright/dashboard-new-layouts/dashboards-repeats-custom-grid.spec.ts @@ -1,10 +1,18 @@ -import { Page } from 'playwright-core'; - -import { test, expect, E2ESelectorGroups, DashboardPage } from '@grafana/plugin-e2e'; +import { test, expect } from '@grafana/plugin-e2e'; import testV2Dashboard from '../dashboards/TestV2Dashboard.json'; import testV2DashWithRepeats from '../dashboards/V2DashWithRepeats.json'; +import { + checkRepeatedPanelTitles, + verifyChanges, + movePanel, + getPanelPosition, + saveDashboard, + importTestDashboard, + goToEmbeddedPanel, +} from './utils'; + const repeatTitleBase = 'repeat - '; const newTitleBase = 'edited rep - '; const repeatOptions = [1, 2, 3, 4]; @@ -49,7 +57,7 @@ test.describe( await checkRepeatedPanelTitles(dashboardPage, selectors, repeatTitleBase, repeatOptions); - await saveDashboard(dashboardPage, selectors); + await saveDashboard(dashboardPage, page, selectors); await page.reload(); await checkRepeatedPanelTitles(dashboardPage, selectors, repeatTitleBase, repeatOptions); @@ -109,7 +117,7 @@ test.describe( await checkRepeatedPanelTitles(dashboardPage, selectors, newTitleBase, repeatOptions); - await saveDashboard(dashboardPage, selectors); + await saveDashboard(dashboardPage, page, selectors); await page.reload(); await checkRepeatedPanelTitles(dashboardPage, selectors, newTitleBase, repeatOptions); @@ -168,7 +176,7 @@ test.describe( await checkRepeatedPanelTitles(dashboardPage, selectors, newTitleBase, repeatOptions); - await saveDashboard(dashboardPage, selectors); + await saveDashboard(dashboardPage, page, selectors); await page.reload(); await checkRepeatedPanelTitles(dashboardPage, selectors, newTitleBase, repeatOptions); @@ -220,7 +228,7 @@ test.describe( await checkRepeatedPanelTitles(dashboardPage, selectors, newTitleBase, repeatOptions); - await saveDashboard(dashboardPage, selectors); + await saveDashboard(dashboardPage, page, selectors); await page.reload(); await checkRepeatedPanelTitles(dashboardPage, selectors, newTitleBase, repeatOptions); @@ -250,7 +258,7 @@ test.describe( let normalPanel = await getPanelPosition(dashboardPage, selectors, 'New panel'); expect(normalPanel?.y).toBeLessThan(repeatedPanel?.y || 0); - await saveDashboard(dashboardPage, selectors); + await saveDashboard(dashboardPage, page, selectors); await page.reload(); const repeatedPanel2 = await getPanelPosition( @@ -340,20 +348,7 @@ test.describe( .hover(); await page.keyboard.press('p+e'); - // extracting embedded panel url from UI - const textAreaValue = await page.getByTestId('share-embed-html').evaluate((el) => el.textContent); - const srcRegex = /src="([^"]*)"/; - let soloPanelUrl = textAreaValue.match(srcRegex)?.[1]; - - expect(soloPanelUrl).toBeDefined(); - - // adjust base url (different each time in CI) - const currentUrl = page.url(); - const baseUrlRegex = /^http:\/\/[^/:]+:3001\//; - const baseUrl = currentUrl.match(baseUrlRegex)?.[0]; - soloPanelUrl = soloPanelUrl!.replace(baseUrlRegex, baseUrl!); - - page.goto(soloPanelUrl!); + await goToEmbeddedPanel(page); await expect( dashboardPage.getByGrafanaSelector( @@ -400,7 +395,7 @@ test.describe( await dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.headerContainer).all() ).toHaveLength(3); - await saveDashboard(dashboardPage, selectors); + await saveDashboard(dashboardPage, page, selectors); await page.reload(); await expect( @@ -415,86 +410,3 @@ test.describe( }); } ); - -async function importTestDashboard(page: Page, selectors: E2ESelectorGroups, title: string, dashInput?: string) { - await page.goto(selectors.pages.ImportDashboard.url); - await page - .getByTestId(selectors.components.DashboardImportPage.textarea) - .fill(dashInput || JSON.stringify(testV2Dashboard)); - await page.getByTestId(selectors.components.DashboardImportPage.submit).click(); - await page.getByTestId(selectors.components.ImportDashboardForm.name).fill(title); - await page.getByTestId(selectors.components.DataSourcePicker.inputV2).click(); - await page.locator('div[data-testid="data-source-card"]').first().click(); - await page.getByTestId(selectors.components.ImportDashboardForm.submit).click(); - const undockMenuButton = page.locator('[aria-label="Undock menu"]'); - const undockMenuVisible = await undockMenuButton.isVisible(); - if (undockMenuVisible) { - undockMenuButton.click(); - } - - await expect(page.locator('[data-testid="uplot-main-div"]').first()).toBeVisible(); -} - -async function saveDashboard(dashboardPage: DashboardPage, selectors: E2ESelectorGroups) { - await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.saveButton).click(); - await dashboardPage.getByGrafanaSelector(selectors.components.Drawer.DashboardSaveDrawer.saveButton).click(); -} - -async function checkRepeatedPanelTitles( - dashboardPage: DashboardPage, - selectors: E2ESelectorGroups, - title: string, - options: Array -) { - for (const option of options) { - await expect( - dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title(`${title}${option}`)) - ).toBeVisible(); - } -} - -async function movePanel( - dashboardPage: DashboardPage, - selectors: E2ESelectorGroups, - sourcePanel: string | RegExp, - targetPanel: string | RegExp -) { - // Get target panel position - const targetPanelElement = dashboardPage - .getByGrafanaSelector(selectors.components.Panels.Panel.headerContainer) - .filter({ hasText: targetPanel }) - .first(); - - // Get source panel element - const sourcePanelElement = dashboardPage - .getByGrafanaSelector(selectors.components.Panels.Panel.headerContainer) - .filter({ hasText: sourcePanel }); - - // Perform drag and drop - await sourcePanelElement.dragTo(targetPanelElement); -} - -async function getPanelPosition( - dashboardPage: DashboardPage, - selectors: E2ESelectorGroups, - panelTitle: string | RegExp -) { - const panel = dashboardPage - .getByGrafanaSelector(selectors.components.Panels.Panel.headerContainer) - .filter({ hasText: panelTitle }) - .first(); - const boundingBox = await panel.boundingBox(); - return boundingBox; -} - -async function verifyChanges( - dashboardPage: DashboardPage, - page: Page, - selectors: E2ESelectorGroups, - changeText: string -) { - await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.saveButton).click(); - await dashboardPage.getByGrafanaSelector(selectors.components.Tab.title('Changes')).click(); - await expect(page.getByText('Full JSON diff').locator('..')).toContainText(changeText); - await dashboardPage.getByGrafanaSelector(selectors.components.Drawer.General.close).click(); -} diff --git a/e2e-playwright/dashboard-new-layouts/utils.ts b/e2e-playwright/dashboard-new-layouts/utils.ts index 1ef85b85261..2d279b0545a 100644 --- a/e2e-playwright/dashboard-new-layouts/utils.ts +++ b/e2e-playwright/dashboard-new-layouts/utils.ts @@ -1,4 +1,8 @@ -import { DashboardPage, E2ESelectorGroups } from '@grafana/plugin-e2e'; +import { Page } from '@playwright/test'; + +import { DashboardPage, E2ESelectorGroups, expect } from '@grafana/plugin-e2e'; + +import testV2Dashboard from '../dashboards/TestV2Dashboard.json'; const deselectPanels = async (dashboardPage: DashboardPage, selectors: E2ESelectorGroups) => { await dashboardPage.getByGrafanaSelector(selectors.pages.Dashboard.Controls).click({ @@ -82,3 +86,104 @@ export type Variable = { description?: string; value: string; }; + +export async function saveDashboard(dashboardPage: DashboardPage, page: Page, selectors: E2ESelectorGroups) { + await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.saveButton).click(); + await dashboardPage.getByGrafanaSelector(selectors.components.Drawer.DashboardSaveDrawer.saveButton).click(); + await expect(page.getByText('Dashboard saved')).toBeVisible(); +} + +export async function checkRepeatedPanelTitles( + dashboardPage: DashboardPage, + selectors: E2ESelectorGroups, + title: string, + options: Array +) { + for (const option of options) { + await expect( + dashboardPage.getByGrafanaSelector(selectors.components.Panels.Panel.title(`${title}${option}`)) + ).toBeVisible(); + } +} + +export async function movePanel( + dashboardPage: DashboardPage, + selectors: E2ESelectorGroups, + sourcePanel: string | RegExp, + targetPanel: string | RegExp +) { + // Get target panel position + const targetPanelElement = dashboardPage + .getByGrafanaSelector(selectors.components.Panels.Panel.headerContainer) + .filter({ hasText: targetPanel }) + .first(); + + // Get source panel element + const sourcePanelElement = dashboardPage + .getByGrafanaSelector(selectors.components.Panels.Panel.headerContainer) + .filter({ hasText: sourcePanel }); + + // Perform drag and drop + await sourcePanelElement.dragTo(targetPanelElement); +} + +export async function getPanelPosition( + dashboardPage: DashboardPage, + selectors: E2ESelectorGroups, + panelTitle: string | RegExp +) { + const panel = dashboardPage + .getByGrafanaSelector(selectors.components.Panels.Panel.headerContainer) + .filter({ hasText: panelTitle }) + .first(); + const boundingBox = await panel.boundingBox(); + return boundingBox; +} + +export async function verifyChanges( + dashboardPage: DashboardPage, + page: Page, + selectors: E2ESelectorGroups, + changeText: string +) { + await dashboardPage.getByGrafanaSelector(selectors.components.NavToolbar.editDashboard.saveButton).click(); + await dashboardPage.getByGrafanaSelector(selectors.components.Tab.title('Changes')).click(); + await expect(page.getByText('Full JSON diff').locator('..')).toContainText(changeText); + await dashboardPage.getByGrafanaSelector(selectors.components.Drawer.General.close).click(); +} + +export async function importTestDashboard(page: Page, selectors: E2ESelectorGroups, title: string, dashInput?: string) { + await page.goto(selectors.pages.ImportDashboard.url); + await page + .getByTestId(selectors.components.DashboardImportPage.textarea) + .fill(dashInput || JSON.stringify(testV2Dashboard)); + await page.getByTestId(selectors.components.DashboardImportPage.submit).click(); + await page.getByTestId(selectors.components.ImportDashboardForm.name).fill(title); + await page.getByTestId(selectors.components.DataSourcePicker.inputV2).click(); + await page.locator('div[data-testid="data-source-card"]').first().click(); + await page.getByTestId(selectors.components.ImportDashboardForm.submit).click(); + const undockMenuButton = page.locator('[aria-label="Undock menu"]'); + const undockMenuVisible = await undockMenuButton.isVisible(); + if (undockMenuVisible) { + undockMenuButton.click(); + } + + await expect(page.locator('[data-testid="uplot-main-div"]').first()).toBeVisible(); +} + +export async function goToEmbeddedPanel(page: Page) { + // extracting embedded panel url from UI + const textAreaValue = await page.getByTestId('share-embed-html').evaluate((el) => el.textContent); + const srcRegex = /src="([^"]*)"/; + let soloPanelUrl = textAreaValue.match(srcRegex)?.[1]; + + expect(soloPanelUrl).toBeDefined(); + + // adjust base url (different each time in CI) + const currentUrl = page.url(); + const baseUrlRegex = /^http:\/\/[^/:]+:3001\//; + const baseUrl = currentUrl.match(baseUrlRegex)?.[0]; + soloPanelUrl = soloPanelUrl!.replace(baseUrlRegex, baseUrl!); + + page.goto(soloPanelUrl!); +}