From 9e4b7670a194ef391e3b08e1f05be6988d8ed94b Mon Sep 17 00:00:00 2001 From: Victor Giers Date: Fri, 3 Apr 2026 00:24:16 +0200 Subject: [PATCH] Add viewport test helpers --- tests/e2e/viewport-test-helpers.ts | 152 +++++++++++++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 tests/e2e/viewport-test-helpers.ts diff --git a/tests/e2e/viewport-test-helpers.ts b/tests/e2e/viewport-test-helpers.ts new file mode 100644 index 00000000..98d91f07 --- /dev/null +++ b/tests/e2e/viewport-test-helpers.ts @@ -0,0 +1,152 @@ +import type { Page } from "@playwright/test"; + +import type { CreationTarget, ViewportToolPreview } from "../../src/viewport-three/viewport-transient-state"; + +export const DEFAULT_VIEWPORT_PANEL_ID = "topLeft"; + +export function getViewportPanel(page: Page, panelId: string = DEFAULT_VIEWPORT_PANEL_ID) { + return page.getByTestId(`viewport-panel-${panelId}`); +} + +export function getViewportCanvas(page: Page, panelId: string = DEFAULT_VIEWPORT_PANEL_ID) { + return getViewportPanel(page, panelId).locator("canvas"); +} + +export function getViewportOverlay(page: Page, panelId: string = DEFAULT_VIEWPORT_PANEL_ID) { + return page.getByTestId(`viewport-overlay-${panelId}`); +} + +interface EditorStoreSnapshot { + selection: { + kind: string; + ids?: string[]; + }; + document: { + assets: Record; + modelInstances: Record; + entities: Record; + }; + viewportTransientState: { + toolPreview: ViewportToolPreview; + }; +} + +export async function getEditorStoreSnapshot(page: Page): Promise { + return page.evaluate(() => { + const store = (window as Window & { + __webeditor3dEditorStore?: { + getState(): EditorStoreSnapshot; + }; + }).__webeditor3dEditorStore; + + if (store === undefined) { + throw new Error("Editor store debug hook is unavailable."); + } + + return store.getState(); + }); +} + +export async function getViewportToolPreview(page: Page): Promise { + const snapshot = await getEditorStoreSnapshot(page); + return snapshot.viewportTransientState.toolPreview; +} + +export async function setViewportCreationPreview( + page: Page, + panelId: string, + target: CreationTarget, + center: { x: number; y: number; z: number } | null +) { + await page.evaluate( + ({ sourcePanelId, nextTarget, nextCenter }) => { + const store = (window as Window & { + __webeditor3dEditorStore?: { + setViewportToolPreview(preview: ViewportToolPreview): void; + }; + }).__webeditor3dEditorStore; + + if (store === undefined) { + throw new Error("Editor store debug hook is unavailable."); + } + + store.setViewportToolPreview({ + kind: "create", + sourcePanelId, + target: nextTarget, + center: nextCenter + }); + }, + { + sourcePanelId: panelId, + nextTarget: target, + nextCenter: center + } + ); +} + +export async function setViewportPlacementPreview( + page: Page, + panelId: string, + target: CreationTarget, + center: { x: number; y: number; z: number } | null +) { + return setViewportCreationPreview(page, panelId, target, center); +} + +export async function clearViewportCreationPreview(page: Page) { + await page.evaluate(() => { + const store = (window as Window & { + __webeditor3dEditorStore?: { + setViewportToolPreview(preview: ViewportToolPreview): void; + }; + }).__webeditor3dEditorStore; + + if (store === undefined) { + throw new Error("Editor store debug hook is unavailable."); + } + + store.setViewportToolPreview({ + kind: "none" + }); + }); +} + +export async function clickViewport(page: Page, panelId: string = DEFAULT_VIEWPORT_PANEL_ID) { + const viewportPanel = getViewportPanel(page, panelId); + await viewportPanel.click({ position: { x: 16, y: 16 }, force: true }); + + const viewportCanvas = getViewportCanvas(page, panelId); + + if ((await viewportCanvas.count()) > 0) { + await viewportCanvas.click(); + return; + } + + const fallbackButton = viewportPanel.getByTestId(`viewport-fallback-create-${panelId}`); + await fallbackButton.waitFor({ state: "visible" }); + await fallbackButton.click(); +} + +export async function setSharedBoxCreationPreview( + page: Page, + panelId: string, + center: { x: number; y: number; z: number } | null +) { + return setViewportCreationPreview( + page, + panelId, + { + kind: "box-brush" + }, + center + ); +} + +export async function setSharedBoxCreatePreview( + page: Page, + panelId: string, + center: { x: number; y: number; z: number } | null +) { + return setSharedBoxCreationPreview(page, panelId, center); +}