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

DateRangePicker onChange not triggering during testing #426

Closed
mnemanja opened this issue Aug 7, 2020 · 4 comments
Closed

DateRangePicker onChange not triggering during testing #426

mnemanja opened this issue Aug 7, 2020 · 4 comments

Comments

@mnemanja
Copy link

mnemanja commented Aug 7, 2020

  • @testing-library/user-event version: v12.0.11
  • Testing Framework and version:
  • jest version: v24.9.0
  • DOM Environment:
  • @testing-library/jest-dom version: v5.11.0

node version: v13.8.0

What you did:
Writing test for DateRangePicker from Material-UI to assert the changes to the component which needs the date range information.

What happened:
The onChange of the DateRangePicker doesn't get triggered.
However, it works in the browser.
This simply does nothing:

await userEvent.type(screen.getByLabelText(/start date/i), '05082020');

However:
Using the delay option throws an unexpected error:

await userEvent.type(screen.getByLabelText(/start date/i), '05082020', {delay: 1});

TypeError: the current element is of type DIV and doesn't have a valid value

This error is not very clear, since when debugging the element returned by the query it returns the correct one.

screen.debug(screen.getByLabelText(/start date/i));
...
<input
      aria-invalid="false"
      class="MuiInputBase-input MuiInput-input"
      id="startDate"
      placeholder="dd/mm/yyyy"
      type="tel"
      value="06/08/2020"
    />

Reproduction repository:
I've created a reproduction in a sandbox, but couldn't get the tests feedback. Not sure why.
https://codesandbox.io/s/daterangepicker-onchange-not-triggering-022cl

Problem description:
The behaviour should be as expected when running tests or testing manually in a browser. Meaning, the onChange event should be triggered disregarding if the method of triggering it was userEvent.type() or manually via browser.

Suggested solution:
I'm actually not sure if this is a fault of the DateRangePicker library, or userEvents library, and because of that I've created a bug ticket there as well.
mui/material-ui-pickers#2073

@kentcdodds kentcdodds added help wanted needs investigation Someone has to do research on this labels Aug 7, 2020
@marcosvega91
Copy link
Member

marcosvega91 commented Aug 7, 2020

Hi @mnajdova thanks for opening the issue :).

I suggest you to use getByRole (https://testing-playground.com/gist/e5bf2f963c4be4ebe69e08e9563e08f9/b288e31dbfab91329ed0e6828dbaa59037780f3f).

The problem here is that clicking on the input field only this events are fired

  1. pointerdown
  2. mousedown
  3. focus
  4. focusin

while on user-event are fired

  1. pointerdown
  2. mousedown
  3. focus
  4. focusin
  5. pointerup
  6. mouseup
  7. click

This is causing a change of the focus from the input to the calendar div. This is wired 🤔

@mnemanja
Copy link
Author

mnemanja commented Aug 11, 2020

@marcosvega91, thanks for your feedback.
We are currently investigating the bug and will come back with more info soon, hopefully.

@Lukas-Kullmann
Copy link

Lukas-Kullmann commented Aug 11, 2020

So the problem in our (i.e. @mnemanja and mine) tests was that the date range picker is rendered in mobile mode by default.

The picker library (@material-ui/pickers) uses media queries to determine if you are using a desktop environment. We were running our tests with jest and jsdom 16. It does not implement window.matchMedia. Defining matchMedia made our tests work:

import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

beforeEach(() => {
  // add window.matchMedia
  // this is necessary for the date picker to be rendered in desktop mode.
  // if this is not provided, the mobile mode is rendered, which might lead to unexpected behavior
  Object.defineProperty(window, 'matchMedia', {
    writable: true,
    value: (query: string): MediaQueryList => ({
      media: query,
      // this is the media query that @material-ui/pickers uses to determine if a device is a desktop device
      matches: query === '(pointer: fine)',
      onchange: () => {},
      addEventListener: () => {},
      removeEventListener: () => {},
      addListener: () => {},
      removeListener: () => {},
      dispatchEvent: () => false,
    }),
  });
});

afterEach(() => {
  delete window.matchMedia;
});

it('should be possible to set a start and end date', async () => {
  render(<MyComponent />);

  const startDateInput = await screen.findByRole('textbox', { name: /start date/i });
  const endDateInput = screen.getByRole('textbox', { name: /end date/i });

  userEvent.clear(startDateInput);
  // this has to be typed one number at a time for the formatting to work
  await userEvent.type(startDateInput, '20200106', { delay: 1 });

  userEvent.clear(endDateInput);
  await userEvent.type(endDateInput, '20200109', { delay: 1 });

  expect(screen.getByRole('textbox', { name: /start date/i })).toHaveValue('2020-01-06');
  expect(screen.getByRole('textbox', { name: /end date/i })).toHaveValue('2020-01-09');
});

So this was more a documentation issue for @material-ui/pickers.

@kentcdodds
Copy link
Member

Glad you worked that out! I think we're safe to close this here.

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

5 participants