title: Typescript + Jest (ts-jest) CommonJS / ESM configuration fail
body: <p>My <a href="https://github.com/kulshekhar/ts-jest" rel="nofollow noreferrer">ts-jest</a> test of <a href="https://reactnavigation.org/docs/tab-based-navigation#minimal-example-of-tab-based-navigation" rel="nofollow noreferrer">React Navigation</a> fails with the error:</p>
  <pre><code>yarn run v1.22.10
  $ jest
  FAIL __tests__/App.spec.tsx
    ● Test suite failed to run
  
      Jest encountered an unexpected token
  
      This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.
  
      By default, if Jest sees a Babel config, it will use that to transform your files, ignoring &quot;node_modules&quot;.
  
      Here's what you can do:
       • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/en/ecmascript-modules for how to enable it.
       • To have some of your &quot;node_modules&quot; files transformed, you can specify a custom &quot;transformIgnorePatterns&quot; in your config.
       • If you need a custom transformation specify a &quot;transform&quot; option in your config.
       • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the &quot;moduleNameMapper&quot; config option.
  
      You'll find more details and examples of these config options in the docs:
      https://jestjs.io/docs/en/configuration.html
  
      Details:
  
      /home/rct/cod/rn-testing-issue-github-example/node_modules/react-native-iphone-x-helper/index.js:1
      ({&quot;Object.&lt;anonymous&gt;&quot;:function(module,exports,require,__dirname,__filename,global,jest){import { Dimensions, Platform, StatusBar } from 'react-native';
                                                                                               ^^^^^^
  
      SyntaxError: Cannot use import statement outside a module
  
        at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1350:14)
        at Object.&lt;anonymous&gt; (node_modules/@react-navigation/bottom-tabs/lib/commonjs/views/SafeAreaProviderCompat.tsx:7:1)
  
  Test Suites: 1 failed, 1 total
  Tests:       0 total
  Snapshots:   0 total
  Time:        0.901 s
  Ran all test suites.
  error Command failed with exit code 1.
  info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
  </code></pre>
  <p>The app works as expected in the emulator but I can't get tests running. Obviously, some sort of CommonJS/ESM configuration incompatibility above my pay grade, but I've been unable to resolve it after following half a dozen different tutorials :(</p>
  <p>All ideas welcome!</p>
  <p>Same issue posted <a href="https://github.com/react-navigation/react-navigation/issues/9517" rel="nofollow noreferrer">in React Navigation issue tracker</a>.</p>
  <p>To reproduce:</p>
  <pre><code>git clone https://github.com/githorse/rn-testing-issue-example.git
  cd rn-testing-issue-example
  yarn test
  </code></pre>
  <p><strong>App.tsx</strong>
  (copied from <a href="https://reactnavigation.org/docs/tab-based-navigation#minimal-example-of-tab-based-navigation" rel="nofollow noreferrer">React Navigation docs</a>):</p>
  <pre><code>// App.tsx
  import * as React from 'react';
  import { Text, View } from 'react-native';
  import { NavigationContainer } from '@react-navigation/native';
  import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
  
  function HomeScreen() {
    return (
      &lt;View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}&gt;
        &lt;Text&gt;Home!&lt;/Text&gt;
      &lt;/View&gt;
    );
  }
  
  function SettingsScreen() {
    return (
      &lt;View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}&gt;
        &lt;Text&gt;Settings!&lt;/Text&gt;
      &lt;/View&gt;
    );
  }
  
  const Tab = createBottomTabNavigator();
  
  export default function App() {
    return (
      &lt;NavigationContainer&gt;
        &lt;Tab.Navigator&gt;
          &lt;Tab.Screen name=&quot;Home&quot; component={HomeScreen} /&gt;
          &lt;Tab.Screen name=&quot;Settings&quot; component={SettingsScreen} /&gt;
        &lt;/Tab.Navigator&gt;
      &lt;/NavigationContainer&gt;
    );
  }
  </code></pre>
  <p><strong>App.spec.tsx</strong>:</p>
  <pre><code>// __tests__/App.spec.tsx
  import 'react-native';
  import React from 'react';
  import App from '../App';
  
  // Note: test renderer must be required after react-native.
  import renderer from 'react-test-renderer';
  
  jest.useFakeTimers();
  
  it('renders correctly', () =&gt; {
    renderer.create(&lt;App /&gt;);
  });
  </code></pre>
  <p><strong>babel.config.js</strong> from <a href="https://kulshekhar.github.io/ts-jest/docs/guides/react-native/" rel="nofollow noreferrer">ts-jest React Native docs</a>:</p>
  <pre><code>// babel.config.js
  module.exports = {
    presets: ['module:metro-react-native-babel-preset'],
  }
  </code></pre>
  <p><strong>jest.config.js</strong> from <a href="https://kulshekhar.github.io/ts-jest/docs/guides/react-native/" rel="nofollow noreferrer">ts-jest React Native docs</a>, adding the <code>setupFiles</code> key referring to <code>jest.setup.js</code>:</p>
  <pre><code>// jest.config.js
  const { defaults: tsjPreset } = require('ts-jest/presets')
  
  module.exports = {
    ...tsjPreset,
    preset: 'react-native',
    transform: {
      ...tsjPreset.transform,
      '\\.js$': '&lt;rootDir&gt;/node_modules/react-native/jest/preprocessor.js',
    },
    globals: {
      'ts-jest': {
        babelConfig: true,
      },
    },
    // This is the only part which you can keep
    // from the above linked tutorial's config:
    cacheDirectory: '.jest/cache',
    setupFiles: [
      '&lt;rootDir&gt;/setup.jest.js' 
   ]
  }
  </code></pre>
  <p><strong>setup.jest.js</strong> from <a href="https://reactnavigation.org/docs/testing/#mocking-native-modules" rel="nofollow noreferrer">React Native Mocking Native Modules example</a>, commenting out a line that produces another (presumably unrelated) error:</p>
  <pre><code>// setup.jest.js
  import 'react-native-gesture-handler/jestSetup';
  // import { cleanup } from '@testing-library/react-native';
  
  jest.mock('react-native-reanimated', () =&gt; {
    const Reanimated = require('react-native-reanimated/mock');
  
    // The mock for `call` immediately calls the callback which is incorrect
    // So we override it with a no-op
    Reanimated.default.call = () =&gt; {};
  
    return Reanimated;
  });
  
  // Silence the warning: Animated: `useNativeDriver` is not supported because the native animated module is missing
  // jest.mock('react-native/Libraries/Animated/src/NativeAnimatedHelper');
  
  // As of react-native@0.64.X file has moved
  jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper');
  </code></pre>