mmazzarolo / react-native-modal-datetime-picker

A React-Native datetime-picker for Android and iOS
MIT License
2.98k stars 400 forks source link

Issue Testing the DateTimePickerModal with Jest & React Native Testing Library #372

Closed ghost closed 4 years ago

ghost commented 4 years ago

I am trying to write unit tests (React Native Testing Library) for this DateTimePickerModal. I've passed in 3 (what I believe are) standard RN props:

accessible: true,
accessibilityLabel: testLabel,
testID: testLabel,

Here are my tests:

fireEvent(dobField, 'handleCalendarPress');
const calendarPicker = wrapper.getByTestId('BDD--ThirdPartyComp--DateTimePickerModal');
fireEvent(calendarPicker, 'onConfirm', ageOver18);

The dobField is my custom input field that I've created, and when it is "pressed", I can find the modal by the testID that I've added. However, that 3rd condition that fires the event to onConfirm, I am getting this error:

Error: Uncaught [TypeError: this._picker.current.setNativeProps is not a function]

I've read the RN docs (link) on "direct manipulation" that talk about setting/using the native props. However, it seems like that's something that should be implemented on the modal/lib itself, not from my side?

So my question is, is there a better way to write unit tests for this modal? Are there props/pieces that I'm missing to be able to properly interact with the component via Jest?

If the solution is to go the route that the docs recommend, and thread down the nativeProps, I could make a PR for that.

Please let me know what you think or if you have any questions. Thanks!

mmazzarolo commented 4 years ago

Hey @metal-gabe , thanks for the detailed description :)

Honestly, I've not been actively using and testing this library for years now, so I'm not sure what testing strategy is the best here.

A couple of things worth noticing are:

  1. Under the hood this library is using @react-native-community/datetimepicker. Do you mind checking if that library itself is testable or if the issue is happening just on this component?
  2. This component is cross-platform and shows two completely different versions on the UI based on the platform. What platform are you on in your unit tests?
  3. AFAIK The native props setting shouldn't matter in this case, but I'm open to any PR!
olie-chan commented 2 years ago

In case it helps anyone else, you can test this picker by following this thread for @react-native-community/datetimepicker.

The rough steps as follows

Pass a testID to your component using the Picker

export function SomeComponent({
  onChange,
}: {
  onChange: (date: Date) => void;
}) {
  return (
    <DateTimePickerModal
      isVisible={true}
      testID='dateTimePicker'
      date={new Date()}
      onConfirm={onChange}
      onCancel={() => {}}
    />
  );
}

Testing file

import { fireEvent, render, act } from '@testing-library/react-native';
import { SomeComponent} from './somewhere';

it('tests something', async () => {
  const onChange = jest.fn();
  const { getByTestId, getByA11yLabel } = render(
    <SomeComponent onChange={onChange} />,
  );

  await act(async () => {
    fireEvent(getByTestId('dateTimePicker'), 'onChange', {
      nativeEvent: { timestamp: '01/01/1976' },
    });
  });

  await act(async () => {
    fireEvent.press(getByA11yLabel(/confirm/i));
  });

  expect(onChange).toHaveBeenCalledWith(new Date('1976-01-01T00:00:00.000Z'));
});