adobe / react-spectrum

A collection of libraries and tools that help you build adaptive, accessible, and robust user experiences.
https://react-spectrum.adobe.com
Apache License 2.0
13.1k stars 1.14k forks source link

useLongPress cannot be easily tested with browser automation tools (playwright) #7306

Open Georgegriff opened 4 weeks ago

Georgegriff commented 4 weeks ago

Provide a general summary of the issue here

You cannot long press with playwright and useLongPress from react-aria. This happens because the pointerType is coming through as "virtual" usePress works but of course click type comes in as virtual

This issue also happens in jsdom too because of virtual events but other hacks required in that environment too.

πŸ€” Expected Behavior?

Long press works with automation tools

😯 Current Behavior

Long press does not work because virtual clicks are not supported.

image

πŸ’ Possible Solution

It fails due to this line: https://github.com/adobe/react-spectrum/blob/e37ad74f5677475f36bab2998bc3285a10a8549b/packages/%40react-aria/interactions/src/useLongPress.ts#L73C1-L74C1 and this line https://github.com/adobe/react-spectrum/blob/e37ad74f5677475f36bab2998bc3285a10a8549b/packages/%40react-aria/interactions/src/useLongPress.ts#L115

And caused by isVirtualPointerEvent in your code detecting this as a virtual ponter

πŸ”¦ Context

Important functionality cannot be integrated or end to end tested without using keyboard instead

πŸ–₯️ Steps to Reproduce

Install playwright and use this test with npx playwright test

import { expect, test } from "@playwright/test";

  test.describe("long press", () => {
    test("long press test", async ({ page }) => {
      await page.goto(
        "https://react-spectrum.adobe.com/react-aria/useLongPress.html"
      );
      const button = await page
        .getByRole("button")
        .filter({ hasText: "Activate" });
      await button.hover();
     /// delay should work as a long press as it delays time between mouse down and mouse up
      await button.click({
        delay: 2000,
      });
      await expect(page.getByText("long press with mouse")).toBeInViewport();
    });
});

see that i am using your docs site

Version

latest

What browsers are you seeing the problem on?

Chrome

If other, please specify.

Chromium in playwright

What operating system are you using?

Mac OS

🧒 Your Company/Team

No response

πŸ•· Tracking Issue

No response

Georgegriff commented 4 weeks ago

Update:

I did some digging in your code around how you might be determining this and i came across some code referencing pressure, so i tried manually firing the events and it works to "trick" this library into doing long presses, but it's kinda horrible and i had to look at your isVirtualPointerEvent implementation to trick it

You need presure or width/height to trick the method into working

 await button.dispatchEvent("pointerdown", {
        pressure: 1,
        width: 5,
        height: 5,
        pointerType: "mouse",
      });

      await page.waitForTimeout(1000);
      await button.dispatchEvent("pointerup", {
        pressure: 1,
        width: 5,
        height: 5,
        pointerType: "mouse",
      });

adding force:1 is the key difference here, but this code is horrible and doesn't feel like an acceptable work around