Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my jest test failing in React native with typescript?

I have set up a really, really simple component in react native using typescript. My goal is just to get Jest set up and a simple test to pass. Here is the code for App.tsx:

import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>
      <Text>Hello World!</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

and the test:

import React from 'react';
import App from '../App';

import { create } from "react-test-renderer";

test('renders correctly', () => {
  const tree = create(<App />);
  expect(tree.toJSON()).toMatchSnapshot();
});

'Hello World' renders as expected but when I run the test I get:

  console.error
    Warning: React.createElement: type is invalid -- expected a string (for built-in componen
ts) or a class/function (for composite components) but got: object.

And indeed when I check the exported function 'App's type it is a React.Element not a component. But why is that? It is returning an element but I thought thats what a component was supposed to do. The export itself is a stateless function so I am a bit confused...

UPDATE: Dennis Tsoi added

"moduleFileExtensions": [
  "ts",
  "tsx",
  "js"
],

to the 'jest' object in package.json and that fixed the typerror. It seems expo client does not create everything needed to run tpyescript in react native

like image 752
HelloWorld Avatar asked Apr 28 '20 05:04

HelloWorld


People also ask

Does Jest work with TypeScript?

Jest supports TypeScript, via Babel. First, make sure you followed the instructions on using Babel above. Next, install the @babel/preset-typescript : npm.

Does Jest work with react native?

The Jest preset built into react-native comes with a few default mocks that are applied on a react-native repository. However, some react-native components or third party components rely on native code to be rendered. In such cases, Jest's manual mocking system can help to mock out the underlying implementation.

Does Jest need TS node?

When you run jest with a jest. config. ts file it will use ts-node to compile that file, then it will pass it to ts-jest which will compile your tests, then it will pass those . js tests to jest to run it.


1 Answers

Edit:

From looking at the remote repository, https://github.com/adamglang/rnTranslatedBible

The error was related a missing jest configuration in the package.json.


Note:

  • Github pull request

Solution:

package.json

  "jest": {
    "preset": "react-native",
    "moduleFileExtensions": [
      "ts",
      "tsx",
      "js"
    ]
  },

According to the jest docs, the default configuration is:

Default: ["js", "json", "jsx", "ts", "tsx", "node"]

By altering the order, whereby "ts" and "tsx" are moved infront of js, the issue is resolved.


Suggest react-native-testing-library as react-test-renderer can have some issues with react native;

Note: requires react-native-testing-library as a devDependancy.

Commentary:

  • someRN developer use react-native-testing-library as a simple way to test their components; as well as allowing methods to quickly assert values based on a deeply nested component tree.

Why React-native-testing-library resolves:

You want to write maintainable tests for your React Native components without testing implementation details, but then you're told to use Enzyme, which you learn has no React Native adapter, meaning only shallow rendering is supported. And you want to render deep! But deep rendering may otherwise require jsdom (React Native isn't the web!), while doing deep rendering with react-test-renderer is so painful.

Example

App.tsx

import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

export default function App() {
  return (
    <View style={styles.container}>
      <Text>Hello World!</Text>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    alignItems: 'center',
    justifyContent: 'center',
  },
});

test.ts

import React from "react";
import { render } from "react-native-testing-library";
import App from "../App";

describe("App", () => {

  it("App", async () => {
    const component = render(<App />);
    expect(component.toJSON()).toMatchSnapshot();
  });
});

Edit [Attach snapshot]

exports[`App App 1`] = `
<View
  style={
    Object {
      "alignItems": "center",
      "backgroundColor": "#fff",
      "flex": 1,
      "justifyContent": "center",
    }
  }
>
  <Text>
    Hello World!
  </Text>
</View>
`;
like image 123
Denis Tsoi Avatar answered Nov 15 '22 04:11

Denis Tsoi