tailwindlabs / headlessui

Completely unstyled, fully accessible UI components, designed to integrate beautifully with Tailwind CSS.
https://headlessui.com
MIT License
25.81k stars 1.07k forks source link

2.1.5 breaks tests due to node.getAnimations #3468

Closed razzeee closed 3 weeks ago

razzeee commented 3 weeks ago

What package within Headless UI are you using?

@headlessui/react

What version of that package are you using?

2.1.5

What browser are you using?

This concernes a jest test, I'm not sure, if it also happens in a browser

Reproduction URL

A trimmed down menu plus a test seem to be enought to trigger this

                      <Menu>
                        <MenuButton>
                          <img alt="Avatar" />
                        </MenuButton>
                      </Menu>
    // User menu
    const button = screen.getByAltText('Avatar')
    await waitFor(async () => await userEvent.click(button))

Describe your issue

Tests fail with

    TypeError: node.getAnimations is not a function

      at waitForTransition (node_modules/@headlessui/react/dist/headlessui.dev.cjs:3752:26)
      at node_modules/@headlessui/react/dist/headlessui.dev.cjs:3739:13
      at invokeTheCallbackFunction (node_modules/jsdom/lib/jsdom/living/generated/Function.js:19:26)
      at runAnimationFrameCallbacks (node_modules/jsdom/lib/jsdom/browser/Window.js:603:13)
      at Timeout._onTimeout (node_modules/jsdom/lib/jsdom/browser/Window.js:581:11)

It seems to be happening, when we want to access a menu via it's menubutton

mattmbt commented 3 weeks ago

Jsdom doesnt support the Web Animations API yet, which this new version seems to use.

I opted to install jsdom-testing-mocks as an additional dev dependency which has polyfills for some browser API's.

Just place this in your initial test setup code or so.

import { mockAnimationsApi } from 'jsdom-testing-mocks';
mockAnimationsApi()
RobinMalfait commented 3 weeks ago

Hey!

I also just saw your comment here (https://github.com/tailwindlabs/headlessui/pull/3452#issuecomment-2338126766). Unfortunately, as @mattmbt mentioned jsdom doesn't have support for the getAnimations API (even though it has been in browsers since 2020).

You can use the mock packages that was mentioned above or use a custom implementation that is just enough to make the tests pass.

This is also just a bandaid solution, and instead I would recommend to move away from jsdom based tests because we rely on more modern features that are available in the browser but not in jsdom.

Hope this helps!

benface commented 3 weeks ago

I would recommend to move away from jsdom based tests because we rely on more modern features that are available in the browser but not in jsdom.

Amen. Even basic CSS features like the cascade and inheritance are not properly supported in jsdom. It's a mystery to me how so many projects are able to rely on it for their tests.

RobinMalfait commented 2 weeks ago

@benface I'm exploring browsers tests for the Headless UI codebase instead of jsdom just because of this.