Trying to use Jest with ESM configuration to test React Native components and getting errors that Jest can't parse the imports from 'react-native'
. The errors look like this: SyntaxError: The requested module 'react-native' does not provide an export named 'StyleSheet'
. Any idea what I'm doing wrong?
RN version: 0.70.4
Example component:
import React, { ReactElement } from 'react';
import { StyleSheet, Text, View } from 'react-native';
const { container } = StyleSheet.create({
container: {
padding: 50,
},
});
const ThisComponent = (): ReactElement => (
<View style={container}>
<Text>Hello World!</Text>
</View>
);
export default ThisComponent;
Example test:
import React, { ReactElement } from 'react';
import { render } from '@testing-library/react-native';
import ThisComponent from '../ThisComponent';
describe('<OTPInputs>', () => {
test('Renders without exploding', async () => {
const { getByText } = render(
<ThisComponent />,
);
expect(getByText('Hello World!')).not.toBeDisabled();
});
});
Jest config (in package.json
):
"jest": {
"haste": {
"defaultPlatform": "ios",
"platforms": [
"android",
"ios",
"native"
]
},
"resetMocks": true,
"testEnvironment": "node",
"testMatch": [
"**/src/**/*.(spec|test).[tj]s?(x)"
],
"preset": "ts-jest/presets/default-esm",
"transform": {
"^.+\\.js$": "babel-jest"
},
"transformIgnorePatterns": [
"node_modules/(?!((jest-)?react-native|@react-native(-community)?)/)"
],
"extensionsToTreatAsEsm": [
".ts",
".tsx"
],
"globals": {
"ts-jest": {
"useESM": true
}
},
"setupFiles": [
"<rootDir>/node_modules/react-native/jest/setup.js"
],
"setupFilesAfterEnv": [
"@testing-library/jest-native/extend-expect"
],
"moduleNameMapper": {
"^~/(.*)$": "<rootDir>/src/$1",
"^~components/(.*)$": "<rootDir>/src/components/$1",
"^~util/(.*)$": "<rootDir>/src/util/$1",
"^~types/(.*)$": "<rootDir>/src/types/$1"
}
}
EDIT: Looks like the main RN export is a cjs file with some weird syntax in it. Here is a mock that makes it work (with const ThisComponent = (await import('../ThisComponent').default
):
jest.unstable_mockModule('react-native', () => ({
__esModule: true,
StyleSheet: jest.requireActual(
'react-native/Libraries/StyleSheet/StyleSheet',
),
Text: jest.requireActual('react-native/Libraries/Text/Text'),
TextInput: jest.requireActual(
'react-native/Libraries/Components/TextInput/TextInput',
),
TouchableOpacity: jest.requireActual(
'react-native/Libraries/Components/Touchable/TouchableOpacity',
),
View: jest.requireActual('react-native/Libraries/Components/View/View'),
}));