J. Hesters
J. Hesters

Reputation: 14768

Unit testing in React with TypeScript, Jest and Enzyme: Cannot invoke an object which is possibly 'undefined'

I'm building a React Native app with TypeScript. I'm doing my component tests using Jest and Enzyme. I'm also using React Navigation

In my last question Brian explained to me how to correctly test the press of a button. My problem is that the buttons onPress prop may be undefined. Let me show you the code:

export class HomeScreen extends Component<Props, object> {
  // ... navigationOptions and stuff

  handlePress = () => {
    this.props.navigation.navigate("QuestionsScreen");
  };

  render() {
    return (
      <View style={styles.container}>
        <Button
          raised={true}
          title={strings.painButtonTitle}
          buttonStyle={styles.painButton}
          titleStyle={styles.title}
          onPress={this.handlePress}
        />
      </View>
    );
  }
}

And here is the test I write for testing the interaction with the button:

describe("interaction", () => {
  const props = createTestProps({});
  const wrapper = shallow<HomeScreen>(<HomeScreen {...props} />);

  describe("clicking the Pain Button", () => {
    it("should navigate to the 'QuestionsScreen'", () => {
      wrapper.instance().handlePress = jest.fn();
      wrapper.find(Button).prop("onPress")({} as any);

      expect(wrapper.instance().handlePress).toHaveBeenCalledTimes(1);
    });
  });
});

The problem is here that my test won't run, because the linter says that onPress may be undefined:

Cannot invoke an object which is possibly 'undefined'.

How can I fix this?

I tried wrapping my code in an if statement like this:

if (typeof wrapper.find(Button).prop("onPress") !== undefined) {
  wrapper.find(Button).prop("onPress")({} as any);
}

But this also does not work.

Upvotes: 11

Views: 5951

Answers (1)

Brian Adams
Brian Adams

Reputation: 45800

You can either use the non-null assertion operator like this:

wrapper.find(Button).prop("onPress")!({} as any);

...or assign the handler to a variable and call it behind a guard like this:

const handler = wrapper.find(Button).prop("onPress");
if (handler) {
  handler({} as any);
}

Upvotes: 11

Related Questions