Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2.1.5 breaks tests due to node.getAnimations #3468

Closed
razzeee opened this issue Sep 10, 2024 · 4 comments · Fixed by #3473
Closed

2.1.5 breaks tests due to node.getAnimations #3468

razzeee opened this issue Sep 10, 2024 · 4 comments · Fixed by #3473

Comments

@razzeee
Copy link

razzeee commented Sep 10, 2024

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
Copy link

mattmbt commented Sep 10, 2024

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
Copy link
Member

Hey!

I also just saw your comment here (#3452 (comment)). 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
Copy link

benface commented Sep 10, 2024

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
Copy link
Member

RobinMalfait commented Sep 10, 2024

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

RobinMalfait added a commit that referenced this issue Sep 11, 2024
… is not available (#3473)

Recently we made improvements to the `Transition` component and internal
`useTransition` hook. We now use the `Element.prototype.getAnimations`
API to know whether or not all transitions are done.

This API has been available in browsers since 2020, however jsdom
doesn't have support for this. This results in a lot of failing tests
where users rely on jsdom (e.g. inside of Jest or Vitest).

In a perfect world, jsdom is not used because it's not a real browser
and there is a lot you need to workaround to even mimic a real browser.

I understand that just switching to real browser tests (using Playwright
for example) is not an easy task that can be done easily.

Even our tests still rely on jsdom…

So to make the development experience better, we polyfill the
`Element.prototype.getAnimations` API only in tests
(`process.env.NODE_ENV === 'test'`) and show a warning in the console on
how to proceed.

The polyfill we ship simply returns an empty array for
`node.getAnimations()`. This means that it will be _enough_ for most
tests to pass. The exception is if you are actually relying on
`transition-duration` and `transition-delay` CSS properties.


The warning you will get looks like this:
``````
Headless UI has polyfilled `Element.prototype.getAnimations` for your tests.
Please install a proper polyfill e.g. `jsdom-testing-mocks`, to silence these warnings.

Example usage:
```js
import { mockAnimationsApi } from 'jsdom-testing-mocks'
mockAnimationsApi()
```
``````

Fixes: #3470
Fixes: #3469
Fixes: #3468
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants