diff --git a/e2e/keyboard.spec.ts b/e2e/keyboard.spec.ts index 134108b1..4cdbe32a 100644 --- a/e2e/keyboard.spec.ts +++ b/e2e/keyboard.spec.ts @@ -80,18 +80,14 @@ test.describe("Keyboard Shortcuts", () => { test("Ctrl+S triggers save", async ({ page }) => { // Set up download listener - const downloadPromise = page - .waitForEvent("download", { timeout: 5000 }) - .catch(() => null); + const downloadPromise = page.waitForEvent("download", { timeout: 5000 }); // Press Ctrl+S await page.keyboard.press("Control+s"); // Should trigger download const download = await downloadPromise; - if (download) { - expect(download.suggestedFilename()).toContain(".Rackula.zip"); - } + expect(download.suggestedFilename()).toMatch(/\.zip$/); }); test("Escape closes dialogs", async ({ page }) => { @@ -107,19 +103,27 @@ test.describe("Keyboard Shortcuts", () => { }); test("Arrow keys move device in rack", async ({ page }) => { - // Add a device to the rack - await dragDeviceToRack(page); + // Add a device lower in the rack so ArrowUp can move it. + await dragDeviceToRack(page, { yOffsetPercent: 70 }); - // Wait for device - await expect(page.locator(".rack-device").first()).toBeVisible(); + const device = page.locator(".rack-front .rack-device").first(); + await expect(device).toBeVisible(); - // Select the device (first one in dual-view) - await page.locator(".rack-device").first().click(); + await device.click(); + const beforePosition = await device.boundingBox(); + expect(beforePosition).not.toBeNull(); + if (!beforePosition) { + throw new Error("Could not determine device position before ArrowUp"); + } // Press Arrow Up await page.keyboard.press("ArrowUp"); - // Note: This test verifies the key is handled, actual movement depends on implementation - await expect(page.locator(".rack-device").first()).toBeVisible(); + await expect + .poll(async () => { + const afterPosition = await device.boundingBox(); + return afterPosition?.y ?? beforePosition.y; + }) + .not.toBe(beforePosition.y); }); }); diff --git a/e2e/rack-context-menu-focus.spec.ts b/e2e/rack-context-menu-focus.spec.ts index 194d00a6..b14d5780 100644 --- a/e2e/rack-context-menu-focus.spec.ts +++ b/e2e/rack-context-menu-focus.spec.ts @@ -17,6 +17,15 @@ async function getPanzoomTransform(page: Page) { }); } +async function setPanzoomTransform(page: Page, transform: string) { + await page.evaluate((nextTransform) => { + const panzoomContainer = document.querySelector(".panzoom-container"); + if (panzoomContainer) { + (panzoomContainer as HTMLElement).style.transform = nextTransform; + } + }, transform); +} + test.describe("Rack Context Menu Focus", () => { test.beforeEach(async ({ page }) => { await gotoWithRack(page); @@ -28,12 +37,23 @@ test.describe("Rack Context Menu Focus", () => { // Rack should be visible await expect(page.locator(".rack-container").first()).toBeVisible(); - // Get the initial transform + // Force a non-focused transform so Focus must change it. + await setPanzoomTransform(page, "matrix(0.4, 0, 0, 0.4, 0, 0)"); const transformBefore = await getPanzoomTransform(page); expect(transformBefore).toBeTruthy(); + expect(transformBefore?.scale).toBe(0.4); - // Right-click on the rack-svg (inside the dual view) - await page.locator(".rack-svg").first().click({ button: "right" }); + // Open the canvas context menu directly on the rack element. + await page.evaluate(() => { + const rack = document.querySelector(".rack-svg"); + if (!rack) throw new Error("Could not find rack svg"); + rack.dispatchEvent( + new MouseEvent("contextmenu", { + bubbles: true, + cancelable: true, + }), + ); + }); // Wait for context menu to appear await expect(page.locator(".context-menu-content")).toBeVisible(); @@ -43,22 +63,30 @@ test.describe("Rack Context Menu Focus", () => { await expect(focusItem).toBeVisible(); await focusItem.click(); - // Focus recalculates and applies optimal zoom/pan for the rack. - // Even from the initial position, Focus will center the rack. - // Wait for transform to potentially change (animation may take time) - await expect(async () => { - const transformAfter = await getPanzoomTransform(page); - expect(transformAfter).toBeTruthy(); - expect(transformAfter?.scale).toBeDefined(); - expect(transformAfter?.x).toBeDefined(); - expect(transformAfter?.y).toBeDefined(); - }).toPass({ timeout: 1000 }); + await expect + .poll(async () => { + const transformAfter = await getPanzoomTransform(page); + if (!transformBefore || !transformAfter) return false; + + return ( + transformAfter.scale !== transformBefore.scale || + transformAfter.x !== transformBefore.x || + transformAfter.y !== transformBefore.y + ); + }) + .toBe(true); }); test("Focus option in Racks panel context menu works", async ({ page }) => { // Rack should be visible await expect(page.locator(".rack-container").first()).toBeVisible(); + // Force a non-focused transform so Focus must change it. + await setPanzoomTransform(page, "matrix(0.4, 0, 0, 0.4, 0, 0)"); + const transformBefore = await getPanzoomTransform(page); + expect(transformBefore).toBeTruthy(); + expect(transformBefore?.scale).toBe(0.4); + // Switch to the Racks tab in the sidebar // This test requires the sidebar to be visible (desktop viewport) const racksTab = page.locator('button[role="tab"]:has-text("Racks")'); @@ -81,13 +109,17 @@ test.describe("Rack Context Menu Focus", () => { // Click Focus - this triggers the focusRack function via callback chain await focusItem.click(); - // Verify the transform exists (Focus was applied) - await expect(async () => { - const transformAfter = await getPanzoomTransform(page); - expect(transformAfter).toBeTruthy(); - expect(transformAfter?.scale).toBeDefined(); - expect(transformAfter?.x).toBeDefined(); - expect(transformAfter?.y).toBeDefined(); - }).toPass({ timeout: 1000 }); + await expect + .poll(async () => { + const transformAfter = await getPanzoomTransform(page); + if (!transformBefore || !transformAfter) return false; + + return ( + transformAfter.scale !== transformBefore.scale || + transformAfter.x !== transformBefore.x || + transformAfter.y !== transformBefore.y + ); + }) + .toBe(true); }); });