From dac20761e7f40e3af096c99b8fcbe85edf931c0f Mon Sep 17 00:00:00 2001 From: Vitor George Date: Tue, 14 Oct 2025 20:26:45 +0100 Subject: [PATCH] test: add bbox selection overlay mode e2e test - Add bbox-select-overlay.spec.ts with overlay render mode test - Add maplibre.ts helper for MapLibre-specific bbox drawing - Increase wait time for overlay mode initialization (2s -> 5s) --- tests/e2e/bbox-select-overlay.spec.ts | 47 +++++++++++++++++++++++++++ tests/e2e/helpers/maplibre.ts | 28 ++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 tests/e2e/bbox-select-overlay.spec.ts create mode 100644 tests/e2e/helpers/maplibre.ts diff --git a/tests/e2e/bbox-select-overlay.spec.ts b/tests/e2e/bbox-select-overlay.spec.ts new file mode 100644 index 00000000..de6bedd1 --- /dev/null +++ b/tests/e2e/bbox-select-overlay.spec.ts @@ -0,0 +1,47 @@ +import { test, expect } from "@playwright/test"; +import { + openNotebookFresh, + runFirstNCells, + executeCellAndWaitForOutput, +} from "./helpers/notebook"; +import { validateBounds } from "./helpers/assertions"; +import { drawBboxOnMapLibre } from "./helpers/maplibre"; + +test.describe("BBox selection - Overlay render mode", () => { + test("draws bbox and syncs selected_bounds to Python with overlay render_mode", async ({ + page, + }) => { + const { notebookRoot } = await openNotebookFresh( + page, + "simple-map-overlay.ipynb", + { + workspaceId: `bbox-overlay-${Date.now()}`, + }, + ); + await runFirstNCells(page, notebookRoot, 2); + await page.waitForTimeout(5000); + + // Start bbox selection mode + const bboxButton = page.getByRole("button", { name: "Select BBox" }); + await expect(bboxButton).toBeVisible({ timeout: 10000 }); + await bboxButton.click(); + + // Verify drawing mode is active + const cancelButton = page.getByRole("button", { name: "Cancel drawing" }); + await expect(cancelButton).toBeVisible({ timeout: 5000 }); + + // Draw bbox using simple mouse events + await drawBboxOnMapLibre(page, { x: 200, y: 200 }, { x: 400, y: 400 }); + + // Verify bbox was drawn successfully + const finalClearButton = page.getByRole("button", { + name: "Clear bounding box", + }); + await expect(finalClearButton).toBeVisible({ timeout: 5000 }); + + // Execute cell to check selected bounds + const output = await executeCellAndWaitForOutput(notebookRoot, 2); + const outputText = await output.textContent(); + validateBounds(outputText); + }); +}); diff --git a/tests/e2e/helpers/maplibre.ts b/tests/e2e/helpers/maplibre.ts new file mode 100644 index 00000000..9e789b27 --- /dev/null +++ b/tests/e2e/helpers/maplibre.ts @@ -0,0 +1,28 @@ +import type { Page } from "@playwright/test"; + +/** + * Draws a bounding box on the MapLibre map using click-click pattern. + * In overlay mode, MapLibre handles events and forwards them to deck.gl via MapboxOverlay. + * + * The bbox selection pattern matches deck-first mode: click at start, hover at end, click at end. + */ +export async function drawBboxOnMapLibre( + page: Page, + start: { x: number; y: number }, + end: { x: number; y: number }, +): Promise { + // Find the map canvas (MapLibre renders the map canvas directly) + const canvas = page.locator("canvas").first(); + await canvas.waitFor({ state: "visible", timeout: 10000 }); + + // Bbox selection pattern: click at start, hover at end, click at end + // Use locator-based actions which are more robust than page.mouse + await canvas.click({ position: { x: start.x, y: start.y } }); + await page.waitForTimeout(500); + + await canvas.hover({ position: { x: end.x, y: end.y } }); + await page.waitForTimeout(500); + + await canvas.click({ position: { x: end.x, y: end.y } }); + await page.waitForTimeout(1000); +}