import { expect, type Locator, type Page, test } from "@playwright/test"; import { captureScreenshot, completeOnboarding, createNamedBot, openMainBotThread, signup, } from "./helpers"; test.use({ hasTouch: true }); /** Hold a finger on the element the way iOS does: touch down, wait, lift without moving. */ async function longPress(page: Page, target: Locator) { const box = await target.boundingBox(); if (!box) throw new Error("long-press target is not visible"); const point = { x: box.x + box.width / 2, y: box.y + box.height / 2 }; const cdp = await page.context().newCDPSession(page); await cdp.send("Input.dispatchTouchEvent", { type: "touchStart", touchPoints: [point] }); await page.waitForTimeout(700); await cdp.send("Input.dispatchTouchEvent", { type: "touchEnd", touchPoints: [] }); } test("holding a conversation on a phone opens its actions", async ({ page }, testInfo) => { const stamp = Date.now(); await signup(page, `long-press-${stamp}@rakazo.test`, "password12", "Phone"); await completeOnboarding(page); const botId = await createNamedBot(page, "Scout"); await openMainBotThread(page); await page.setViewportSize({ width: 390, height: 844 }); await page.getByRole("button", { name: "Open navigation" }).click(); const scout = page .locator("aside") .first() .getByRole("button", { name: /^Scout/ }) .first(); await expect(scout).toBeVisible(); await longPress(page, scout); await expect(page.getByRole("menu", { name: "Actions for Scout" })).toBeVisible(); await expect(page.getByRole("menuitem", { name: "Pin", exact: true })).toBeVisible(); // The lift that ends the hold must not also open the conversation behind the menu. await expect(page).not.toHaveURL(new RegExp(`/app/${botId}$`)); await page.emulateMedia({ colorScheme: "dark" }); await captureScreenshot(page, testInfo, "phone-long-press-menu-dark"); await page.emulateMedia({ colorScheme: "light" }); await captureScreenshot(page, testInfo, "phone-long-press-menu-light"); await page.getByRole("menuitem", { name: "Pin", exact: true }).click(); await expect( page .locator("aside") .first() .getByRole("button", { name: /Pinned/ }), ).toBeVisible(); });