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

Testing with Jest fireEvent.press() #243

Open
charlestbell opened this issue Apr 27, 2022 · 2 comments
Open

Testing with Jest fireEvent.press() #243

charlestbell opened this issue Apr 27, 2022 · 2 comments

Comments

@charlestbell
Copy link

charlestbell commented Apr 27, 2022

I mentioned this in #197 but that one is closed, so it neede a new issue.

Has anyone gotten Jest fireEvent.press() working?

In the testing example, they suggest mocking all the components like this:

jest.mock('react-native-popup-menu', () => ({
Menu: 'Menu',
MenuProvider: 'MenuProvider',
MenuOptions: 'MenuOptions',
MenuOption: 'MenuOption',
MenuTrigger: 'MenuTrigger',
}));
See Example: https://github.com/instea/react-native-popup-menu/blob/master/examples/__tests__/Basic-test.js

However, mocking all the components makes them no longer function. So trying to use fireEvent.press() on them to test actual functionality doesn't work at all.

I tried not mocking the components, but then Jest cannot find them at all, and the tests fail there, so I'm back to square one.

@charlestbell
Copy link
Author

charlestbell commented Apr 27, 2022

Update:
I found a kind of workaround. Basically, I just copied the same logic from the MenuOption's onSelect, to a Text or icon component child of MenuOption, in the form of an onPress. I also moved the testID tag to the child component.

Before:

<MenuOption
                     testID={`sharedScreen.${itemData.item.id}.removeButton`}
                      customStyles={optionShareStyles}
                      onSelect={() => {
                        removeShareHandler({
                          dispatch,
                          setIsRefreshing,
                          logbookId: itemData.item.id,
                        });
                      }}
                    >
                      <FontAwesomeIcon
                        icon={faEyeSlash}
                        color={Colors.neutral[1]}
                        size={20}
                        style={styles.menuIcon}
                      />
                      <Text
                        customStyles={optionsStyles}
                        style={styles.menuText}
                      >
                        Remove
                      </Text>
                    </MenuOption>

After:

 <MenuOption
                      customStyles={optionShareStyles}
                      onSelect={() => {
                        removeShareHandler({
                          dispatch,
                          setIsRefreshing,
                          logbookId: itemData.item.id,
                        });
                      }}
                    >
                      <FontAwesomeIcon
                        testID={`sharedScreen.${itemData.item.id}.removeButton`} // Moved the testId here
                        onPress={() => { // Copied the onSelect logic to this onPress to make testing work
                          removeShareHandler({
                            dispatch,
                            setIsRefreshing,
                            logbookId: itemData.item.id,
                          });
                        }}
                        icon={faEyeSlash}
                        color={Colors.neutral[1]}
                        size={20}
                        style={styles.menuIcon}
                      />
                      <Text
                        customStyles={optionsStyles}
                        style={styles.menuText}
                      >
                        Remove
                      </Text>
                    </MenuOption>

So now there are two copies of the onPress logic and it looks like hell, but it works!

A snippet from the test:

  const removeButton = await findByTestId(
    `sharedScreen.${mockLogbookKey}.removeButton`
  );
  fireEvent.press(removeButton);

Note: I am using the jest.mock from my previous comment to make this work.

If anybody comes up with a better way, I'm all ears.

@KhushPatel2003
Copy link

KhushPatel2003 commented Aug 9, 2022

I struggled with this for a while, but I think I found an excellent way to test this out. The only issue with your method is that when you put onPress logic onto a child component, sometimes the MenuOption will not be called and in turn won't close the pop-up menu, it will perform the task because the onPress was clicked on but won't close the menu for the user. To test this on jest you can do something like this to mock the component:

const mockedOnPress = jest.fn();
const mockedMenuOption = (
  <TouchableOpacity
    testID="menuOption"
    onPress={mockedOnPress}
  ></TouchableOpacity>
);
jest.mock("react-native-popup-menu", () => ({
  Menu: "Menu",
  MenuContext: "MenuContext",
  MenuOptions: "MenuOptions",
  MenuOption: () => mockedMenuOption,
  MenuTrigger: "MenuTrigger",
  renderers: "renderers",
}));

then to test this you can try something like this

it("tests the onPress of MenuOption", async () => {
    const { getAllByTestId } = render(
      <YourComponentHere />
    );
    const button = getAllByTestId("menuOption");
    fireEvent.press(button[0]);
    expect(mockedOnPress).toHaveBeenCalled();
  });

You can see that I used getAllByTestId this is because if we render multiple MenuOptions for the user, they will all have the same testId so this will allow us to get a specific one depending on the order starting from the 0 index.

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

2 participants