Files
grafana/e2e/plugin-e2e/canvas/canvas-scene.spec.ts
Ihor Yeromin 66b01e49a1 Canvas: Pan and zoom improvement (#86879)
* fix(canvas): style linter issue

* feat(canvas): update infinite viewer root element

* fix(canvas): resize element on moving

* fix(canvas): global element position

* fix(canvas): connection anchor position

* fix(canvas): connection position

* fix(canvas): connection coordinates calculation

* cleaning

* fix(canvas): calculation connection coordinates

* fix(canvas): initial connections svg position

* fix(canvas): align connection with new coordinates system

* fix(canvas): temporary element position fix

* comment

* Canvas: Fix canvas selecto (#104621)

* fix(canvas): get context back

* fix(canvas): selecto containers

* clean up

* Canvas: Fix jumpy elements behaviour on select and drag (#104641)

fix(canvas): jumpy elements behaviour on select and drag

* fix(canvas): connection regression (#104682)

* Canvas pan + zoom:  Updated mouse interactions (#104648)

* feat: canvas panel pan + zoom key binds

* feat: panning when right click + ctrl

* chore: some cleanup

* chore: adjust mouse move delta by canvas scale

* Canvas: Zoom to content (#104950)

feat(canvas): zoom to content

* Canvas pan + zoom: Unique key for canvas panel elements (#104947)

fix: unique keys

* Canvas: Placement adjustment (#105117)

* feat(canvas): top/left placement migration

* feat(canvas): adjust constraint system for pan and zoom usage

* feat(canvas): support other constraints

* Canvas: Align connection anchors and element rotation (#106002)

* feat(canvas): align connection anchors and element rotation

* clean up

* clean-up math

* Canvas: Disable pan when pan+zoom toggle is false (#106224)

chore: no pan when pan+zoom toggle is disabled

* Canvas: Fix desync between scene and InfiniteViewer zoom/position on element addition (#106655)

feat(canvas): keep pan and zoom state to re-apply

* Canvas: Clicking on metricValue dropdown does not work; right-click triggers context menu instead (#106701)

fix(canvas): metricValue left click dropdown

* Canvas: Double-click on canvas should reset scale and position (#106709)

fix(canvas): dblclick to reset zoom

* Canvas: Put new canvas pan and zoom under feature toggle (#107001)

* feat(canvas): put pan and zoom under FF

* clean-up

* clean-up

* fix(canvas): clear selection on scene manipulation

* fix(canvas): any types

* Canvas: Fix canvas apply styles (#107404)

* fix(canvas): apply styles

* remove deps

* Canvas: E2E test coverage (#107474)

* betterer

* feat(canvas): sceneAbleManagement tests

* feat(canvas): playwright tests

* chore(canvas): add draft e2e tests

* chore(canvas): clean draft e2e tests

* chore(canvas): fix draft e2e tests

* chore(canvas): todo comments

* chore(canvas): update e2e tests

* chore(canvas): delete scene unit tests

* chore(canvas): delete sceneAbleManagement unit tests

* chore(canvas): delete sceneAbleManagement unit tests

* chore(canvas): linter

* chore(canvas): locales

* chore(canvas): remove flag checking

* Fix canvas connection point z-indexing bug (#107223)

fix(canvas): hoist connect points one level higher in DOM to fix z-index

* Revert "Fix canvas connection point z-indexing bug" (#108146)

Revert "Fix canvas connection point z-indexing bug (#107223)"

This reverts commit e419cb164a.

* Canvas: Set canvas zoom range (#108318)

* chore(canvas): set zoom range

* chore(canvas): naming

* Canvas: Fix infinite-viewer connections viewport values (#108315)

chore(canvas): infinite-viewer connections viewport values

* Canvas: Fix z-indices order and explicit pointer events (#108284)

* fix(canvas-connection-points): z-indices order, explicit pointer events

* chore(canvas): remove user select

* chore(canvas): naming

* chore(canvas): create ConnectionAnchor2 component

---------

Co-authored-by: Ihor Yeromin <yeryomin.igor@gmail.com>

* Canvas: Hide anchors on panel resize (#108588)

chore(canvas): hide anchors on panel resize

* Canvas: Center & scale select, resize, zoom bugs (#108749)

* Canvas: Fix center and scale constraint with zoom

* Remove unused resize flag

* Consolidate and clean up

* fix(canvas): re-size scale and center elements

---------

Co-authored-by: Ihor Yeromin <yeryomin.igor@gmail.com>

* Canvas: Fix on constraint change during zoom (#108947)

* Canvas: Ensure correct panel size during edit (#108953)

* chore(canvas): re-gen cue

---------

Co-authored-by: drew08t <drew08@gmail.com>
Co-authored-by: Sven Grossmann <svennergr@gmail.com>
Co-authored-by: Alex Spencer <52186778+alexjonspencer1@users.noreply.github.com>
Co-authored-by: Jesse David Peterson <jesdavpet@users.noreply.github.com>
Co-authored-by: Drew Slobodnjak <60050885+drew08t@users.noreply.github.com>
2025-07-31 19:34:48 +02:00

88 lines
3.7 KiB
TypeScript

import { Locator } from '@playwright/test';
import { test, expect } from '@grafana/plugin-e2e';
test.use({
featureToggles: {
canvasPanelPanZoom: true,
},
});
test.describe('Canvas Panel - Scene Tests', () => {
test.beforeEach(async ({ page, gotoDashboardPage }) => {
const dashboardPage = await gotoDashboardPage({});
const panelEditPage = await dashboardPage.addPanel();
await panelEditPage.setVisualization('Canvas');
// Wait for canvas panel to load
await page.waitForSelector('[data-testid="canvas-scene-pan-zoom"]', { timeout: 10000 });
});
test('should create and render canvas panel with scene elements', async ({ page }) => {
const canvasElement = await page.getByRole('button', { name: 'Double click to set field' });
await expect(canvasElement).toBeVisible();
});
test('should handle scene pan and zoom when enabled', async ({ page }) => {
// Feature toggle is enabled, pan/zoom functionality should be available
const panZoomCheckbox = await page.getByLabel('Canvas Pan and zoom field').locator('label').nth(1);
await panZoomCheckbox.setChecked(true);
await expect(panZoomCheckbox).toBeChecked({ checked: true });
const canvasElement = await page.getByRole('button', { name: 'Double click to set field' });
const canvasSceneWrapper = await page.getByTestId('canvas-scene-wrapper');
// Check if infinite viewer is present (pan/zoom feature)
await page.waitForSelector('[data-testid="canvas-scene-pan-zoom"]', { timeout: 10000 });
const infiniteViewer = page.locator('[data-testid="canvas-scene-pan-zoom"]');
await infiniteViewer.waitFor({ state: 'visible', timeout: 5000 });
await expect(await infiniteViewer.isVisible()).toBe(true);
await infiniteViewer.hover();
const viewerBounds = await infiniteViewer.boundingBox();
await expect(viewerBounds).toBeDefined();
// Test pan functionality
const startX = viewerBounds.x + 50;
const startY = viewerBounds.y + 50;
const endX = viewerBounds.x + 250;
const endY = viewerBounds.y + 250;
await page.getByTestId('canvas-scene-pan-zoom');
await page.mouse.move(startX, startY);
await page.mouse.down({ button: 'middle' });
await page.mouse.move(endX, endY);
await page.mouse.up({ button: 'middle' });
await expect(await isOutsideViewport(canvasElement, canvasSceneWrapper)).toBe(true);
// Test zoom reset with double-click
await page.mouse.dblclick(startX, startY);
// Verify canvas element is visible after pan/zoom operations
await expect(await isOutsideViewport(canvasElement, canvasSceneWrapper)).toBe(false);
// Test zoom functionality
await page.mouse.move(startX, startY);
await page.keyboard.down('Control');
await page.mouse.wheel(0, -400); // Zoom in
await page.keyboard.up('Control');
// Check if canvas element is not visible after zoom operations
await expect(await isOutsideViewport(canvasElement, canvasSceneWrapper)).toBe(true);
// Test zoom reset with double-click
await page.mouse.dblclick(startX, startY);
// Verify canvas element is visible after pan/zoom operations
await expect(await isOutsideViewport(canvasElement, canvasSceneWrapper)).toBe(false);
});
});
// TODO: this function is workaround for .toBeVisible()
async function isOutsideViewport(element: Locator, viewPort: Locator): Promise<boolean> {
const elementBounds = await element.boundingBox();
const viewportBounds = await viewPort.boundingBox();
return (
elementBounds.x + elementBounds.width < viewportBounds.x ||
elementBounds.x > viewportBounds.x + viewportBounds.width ||
elementBounds.y + elementBounds.height < viewportBounds.y ||
elementBounds.y > viewportBounds.y + viewportBounds.height
);
}