title: How to mock React Navigation's navigation prop for unit tests with TypeScript in React Native?
body: <p>I'm building a React Native app with TypeScript. For my navigation I use React Navigation and for my unit testing I use Jest and Enzyme.</p>
  
  <p>Here is the (stripped down) code for one of my screen (LoadingScreen.tsx):</p>
  
  <pre><code>import styles from "./styles";
  import React, { Component } from "react";
  import { Text, View } from "react-native";
  import { NavigationScreenProps } from "react-navigation";
  
  // Is this correct?
  export class LoadingScreen extends Component&lt;NavigationScreenProps&gt; {
  // Or should I've done:
  // export interface Props {
  //   navigation: NavigationScreenProp&lt;any, any&gt;;
  // }
  
  // export class LoadingScreen extends Component&lt;Props&gt; {
    componentDidMount = () =&gt; {
      this.props.navigation.navigate("LoginScreen");
    };
  
    render() {
      return (
        &lt;View style={styles.container}&gt;
          &lt;Text&gt;This is the LoadingScreen.&lt;/Text&gt;
        &lt;/View&gt;
      );
    }
  }
  
  export default LoadingScreen;
  </code></pre>
  
  <p>When trying to test the screens I came across a problem. The screens expects a prop with a type of NavigiationScreenProps because I'm accessing React Navigations <code>navigation</code> prop. Here is the testing file's code (LoadingScreen.test.tsx):</p>
  
  <pre><code>import { LoadingScreen } from "./LoadingScreen";
  import { shallow, ShallowWrapper } from "enzyme";
  import React from "react";
  import { View } from "react-native";
  import * as navigation from "react-navigation";
  
  const createTestProps = (props: Object) =&gt; ({
    ...props
  });
  
  describe("LoadingScreen", () =&gt; {
    describe("rendering", () =&gt; {
      let wrapper: ShallowWrapper;
      let props: Object;
      beforeEach(() =&gt; {
        props = createTestProps({});
        wrapper = shallow(&lt;LoadingScreen {...props} /&gt;);
      });
  
      it("should render a &lt;View /&gt;", () =&gt; {
        expect(wrapper.find(View)).toHaveLength(1);
      });
    });
  });
  </code></pre>
  
  <p>The problem is, that <code>LoadingScreen</code> expects a <code>navigation</code> prop.</p>
  
  <p>I get the error:</p>
  
  <pre><code>[ts]
  Type '{ constructor: Function; toString(): string; toLocaleString(): string; valueOf(): Object; hasOwnProperty(v: string | number | symbol): boolean; isPrototypeOf(v: Object): boolean; propertyIsEnumerable(v: string | ... 1 more ... | symbol): boolean; }' is not assignable to type 'Readonly&lt;NavigationScreenProps&lt;NavigationParams, any&gt;&gt;'.
    Property 'navigation' is missing in type '{ constructor: Function; toString(): string; toLocaleString(): string; valueOf(): Object; hasOwnProperty(v: string | number | symbol): boolean; isPrototypeOf(v: Object): boolean; propertyIsEnumerable(v: string | ... 1 more ... | symbol): boolean; }'.
  (alias) class LoadingScreen
  </code></pre>
  
  <p>How can I fix this?</p>
  
  <p>I think I somehow have to mock the <code>navigation</code> prop. I tried doing that (as you can see I imported <code>*</code> from React Navigation in my test), but couldn't figure out. There is only <code>NavigationActions</code> that is remotely useful but it only includes <code>navigate()</code>. TypeScript expects everything, even the state, to be mocked. How can I mock the <code>navigation</code> prop? </p>
  
  <p><strong>Edit 1:</strong> Is the approach of using <code>NavigationScreenProps</code> even correct or should I use the <code>interface Props</code> approach? If yes how would you then mock than (it results in the same error).</p>
  
  <p><strong>Edit 2:</strong>
  Using the second approach with the interface and </p>
  
  <pre><code>export class LoadingScreen extends Component&lt;Props, object&gt;
  </code></pre>
  
  <p>I was able to "solve" this problem. I literally had to mock every single property of the navigation object like this:</p>
  
  <pre><code>const createTestProps = (props: Object) =&gt; ({
    navigation: {
      state: { params: {} },
      dispatch: jest.fn(),
      goBack: jest.fn(),
      dismiss: jest.fn(),
      navigate: jest.fn(),
      openDrawer: jest.fn(),
      closeDrawer: jest.fn(),
      toggleDrawer: jest.fn(),
      getParam: jest.fn(),
      setParams: jest.fn(),
      addListener: jest.fn(),
      push: jest.fn(),
      replace: jest.fn(),
      pop: jest.fn(),
      popToTop: jest.fn(),
      isFocused: jest.fn()
    },
    ...props
  });
  </code></pre>
  
  <p>The question remains: Is this correct? Or is there a better solution?</p>
  
  <p><strong>Edit 3:</strong>
  Back when I used JS, it was enough to mock only the property I needed (often just navigate). But since I started using TypeScript, I had to mock every single aspects of navigation. Otherwise TypeScript would complain that the component expects a prop with a different type.</p>