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.11k stars 1.14k forks source link

userEvent.keyboard('{arrowdown}') no longer opens combobox in playwright tests since 12-20 release #5790

Open ashleyryan opened 10 months ago

ashleyryan commented 10 months ago

Provide a general summary of the issue here

We use Storybook interaction tests and storybook test-runner to run interaction/unit tests against our components. When I updated to the 12.20 release, I noticed that in the test-runner (but not in the browser interaction tests tab, which I don't believe uses Playwright) all of our combobox tests that use userEvent.keyboard('{arrowdown}') or user.type(await canvas.findByRole('combobox'), '{arrowdown}') on the text input to open the popover no longer fire the open event.

Interestingly, the tests where I type letters seem to work fine, it's simulating other keys that doesn't appear to. Are you aware of any changes to key press behavior for overlays that may have broken this?

๐Ÿค” Expected Behavior?

The combobox opens when simulating an arrowdown

๐Ÿ˜ฏ Current Behavior

the combobox does not open simulating an arrow down

๐Ÿ’ Possible Solution

No response

๐Ÿ”ฆ Context

This is a long shot. I looked at the commits in the react-aria/overlays folder in code and didn't see anything obvious that stuck out to me, so hoping you all have an idea of a change that may have caused this between the November and December release. These are the packages we use:

 "@react-aria/button": "3.9.1",
 "@react-aria/combobox": "3.8.1",
 "@react-aria/dialog": "3.5.9",
 "@react-aria/i18n": "3.10.0",
 "@react-aria/interactions": "3.20.1",
 "@react-aria/listbox": "3.11.3",
 "@react-aria/menu": "3.12.0",
 "@react-aria/overlays": "3.20.0", // downgrading yo 3.19.0 will fix the issue
 "@react-aria/separator": "3.3.9",
 "@react-aria/ssr": "3.9.1",
 "@react-stately/collections": "3.10.4",
 "@react-stately/combobox": "3.8.1",
 "@react-stately/data": "3.11.0",
 "@react-stately/list": "3.10.2",
 "@react-stately/menu": "3.6.0",
    "@react-stately/overlays": "3.6.4",

๐Ÿ–ฅ๏ธ Steps to Reproduce

-

Version

2023-12-20

What browsers are you seeing the problem on?

Other

If other, please specify.

Jest + Playwright

What operating system are you using?

MacOS & Windows

๐Ÿงข Your Company/Team

No response

๐Ÿ•ท Tracking Issue

No response

LFDanLu commented 10 months ago

all of our combobox tests that use userEvent.keyboard('{arrowdown}') or user.type(await canvas.findByRole('combobox'), '{arrowdown}') on the text input to open the popover no longer fire the open event

By the above, do you mean you confirmed onOpenChange doesn't fire at all? There was this change to close combobox dropdowns on scroll, wondering if a scroll event could be instantly closing the drop down. Other than that nothing else immediately jumps out to me, would have to dive into the code with a reproduction

ashleyryan commented 2 weeks ago

Coming back to this again (because I really want to upgrade our react-aria/overlays dependency). I'm able to track this down to a useLayoutEffect hook we call that attempts to resize the popover width to match the input width (if there's a better way to make the popover width match the triggerwidth, let me know!)

useLayoutEffect(() => {
    if (isOpen) {
      const popoverEl = popoverRef.current
      const triggerEl = inputRef.current
      if (isOpen && triggerEl && popoverEl) {
        const { width } = triggerEl.getBoundingClientRect()
        popoverEl.style.width = `${width}px`
        popoverEl.style.minWidth = `${width}px`
        popoverEl.style.maxWidth = `${width}px`
      }
    }
  }, [isOpen])

Your RA Combobox component is fine, this doesn't seem to happen there, I can resize just fine, it's something in our implementation of the hooks. When I track the overlayState.isOpen variable, it seems like it's opening and then immediately closing before await screen.findByRole('listbox') can detect anything.

If I add a scroll event listener, I can see the document scroll event being fired after the resize happens. So it does seem related to that issue. Again, it's only in our storybook playwright tests, not in the browser.

I'll try and work on a repro - our hook implementation is so convoluted that ripping something out is going to be tricky, which is why I haven't provided one yet

ashleyryan commented 2 weeks ago

Oh actually, I can reproduce this in my storybook interaction tests in the browser, if I make the iframe window in storybook small enough. So resizing the popover, in my case, does seem to be doing something to cause the page to scroll.

And that happens with the React Aria combobox component too, not just our hook implementation.

LFDanLu commented 1 week ago

Interesting, I see the issue now when I make the docs page for RAC combobox small enough that the input is partially out of view, thus causing the page to scroll when opening the combobox. Not sure how we can differentiate this scroll event from a user scroll event, maybe we could freeze that close on scroll logic until after initial open.