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

Having issues testing DropdownMenu with React testing library #856

Closed
nirbenya opened this issue Sep 10, 2021 · 6 comments
Closed

Having issues testing DropdownMenu with React testing library #856

nirbenya opened this issue Sep 10, 2021 · 6 comments

Comments

@nirbenya
Copy link

Bug report

Current Behavior

When I want to open the menu via test (jest, react testing library) I cannot, radix looks amazing to me but before I refacttor my menus to use it I need it to be testable :)

Expected behavior

it should behave on jsdom the same as on the browser

Reproducible example

https://codesandbox.io/s/radix-dropdown-tests-forked-829re

Suggested solution

Tried looking at the code and wrote this test, the problem is that onPointerDown expects button: 0 and ctrlKey=false properites on the event, which apparently does not exist on jsdom.

import React from 'react';
import { fireEvent, render, screen } from '@testing-library/react';
import * as Menu from './DropdownMenu';


const OPEN_TEXT = 'Open';

const MenuTest = (props: any) => (
  <Menu.Root {...props}>
    <Menu.Trigger>{OPEN_TEXT}</Menu.Trigger>
    <Menu.Content>
      content I want to be shown on this test
    </Menu.Content>
  </Menu.Root>
);

window.DOMRect = {

  // @ts-ignore
  fromRect: () => undefined
};
describe('given a default Dialog', () => {

  it('should open the content', () => {
    render(<MenuTest />);
    fireEvent.pointerDown(screen.getByRole('button'), { ctrlKey: false });

// no content is shown on debug
    screen.debug();
  });


});

Additional context

Upgraded rtl to latest version but its not enough apparently

I will dig more into this but I wondered if you had any thoughts on this, I saw there are no tests for dropdown-menu in the package.

Thanks!

Your environment

Software Name(s) Version
Radix Package(s) 0.5.0
React 16.8.0
Node 14
npm/yarn 1.2.1
Operating System: mac OS
@andy-hook
Copy link
Contributor

Hey @nirbenya as you say this appears to be a limitation in jsdom. We favour testing in a real browser environment for reasons such as this and to better match what a user experiences (see cypress tests for this component)

In terms of RTL though, I did some brief searching to see if anything had changed lately and the proposed solution suggested in this issue worked for me when combined with pointerdown.

I also recommend checking out the user-event library if you haven't already.

@norman-ags
Copy link
Contributor

I made this work by combining @benoitgrelard #420 and @andy-hook answers:

// setupTest.ts

window.PointerEvent = PointerEvent;

// https://github.com/radix-ui/primitives/issues/420#issuecomment-771615182
window.ResizeObserver = class ResizeObserver {
  constructor(cb) {
    this.cb = cb;
  }
  observe() {
    this.cb([{ borderBoxSize: { inlineSize: 0, blockSize: 0 } }]);
  }
  unobserve() {}
};

window.DOMRect = {
  fromRect: () => ({
    top: 0,
    left: 0,
    bottom: 0,
    right: 0,
    width: 0,
    height: 0,
  }),
};


// test/helpers.ts
export class PointerEvent extends Event {
  button: number;
  ctrlKey: boolean;

  constructor(type, props) {
    super(type, props);
    if (props.button != null) {
      this.button = props.button;
    }
    if (props.ctrlKey != null) {
      this.ctrlKey = props.ctrlKey;
    }
  }
}

// dropdownMenu.test.tsx
fireEvent.pointerDown(
  button,
  new PointerEvent('pointerdown', {
    ctrlKey: false,
    button: 0,
  })
);

@misha-erm
Copy link

Hello 👋🏻

Sorry for bringing up closed issue, but @andy-hook was you able to make it work with user-event library?

Currently I'm migrating from antd menu to radix-ui dropdown and a lot of my tests are falling now )

The solution provided by #856 (comment) works but don't really want to replace all my userEvent.click with fireEvent.pointerDown thing if there's another working solution

Thanks in advance

@andy-hook
Copy link
Contributor

was you able to make it work with user-event library?

@MikeYermolayev Supplying your custom implementation to window.PointerEvent should work as userEvent.click does fire pointer events for you. You'll need to provide properties to that class per the solution posted in this thread. Should then be able to pass those props userEvent.click(elem, {ctrlKey: true, ...}).

@jaorsh
Copy link

jaorsh commented May 14, 2024

Replacing window.PointerEvent with MouseEvent works too and is less cumbersome. This can happen either globally in a jest setup file setupFilesAfterEnv, or in beforeAll. To appease typescript I'm casting as typeof PointerEvent;

// jestSetup.ts
window.PointerEvent = MouseEvent as typeof PointerEvent;

// Alternatively, Dropdown.spec.tsx
beforeAll(() => {
  window.PointerEvent = MouseEvent as typeof PointerEvent;
});

// Dropdown.spec.tsx
fireEvent.pointerDown(screen.getByTestId("dropdown-trigger"));

@chris-mcdonald-dev
Copy link

Since userEvent v14, this behaves a bit differently, and luckily seems to have a more simple solution.
For some reason, the Radix DropdownMenu.Item doesn't seem to register a click if the selectable option is hovered over first with React Testing Library before being clicked.
This feels like either something that needs to be fixed in RTL or Radix eventually. But for now, fortunately there's an option to disable the hover before clicking during RTL's userEvent.setup()

const user = userEvent.setup({ skipHover: true })
const user.click(myDropdownItemElement)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants