Setting up tests for React-Native-Expo-Typescript

ajulibe

Ajulibe

Posted on February 9, 2021

Setting up tests for React-Native-Expo-Typescript

Recently I decided to write tests for my expo react native app written in typescript. Having done this in Reactjs, I didn't expect its native counterpart to be such a pain. I did the usual reading of documentations, checking StackOverflow and there was nothing. I couldn't find any working test or a proper documentation for setting up tests for expo react native apps written in typescript. I must add that I initialised my expo app using a blank template. Using either the tabs or the minimal template automatically sets up test for you (I learnt this much matter).

Luckily after about 2 weeks, I came across an npm package expo-template-typescript-jest [https://www.npmjs.com/package/expo-template-typescript-jest] created by [https://github.com/elgsantos]

It seemed like it was recently put there as an answer to my prayer. I had to take it for a spin. Ah!! yes it worked. Also, seeing that I didn't want to use its template, I had to study the repo and replicate the configurations used in my already existing expo app.

let me walk you through how I added jest and react-test-renderer to my already existing expo app in 4 simple steps.

LIST OF DEPENDENCIES USED
1) React-test-renderer
2) jest
3) jest-expo
4) ts-jest
5) jest-coverage-badges
6) @types/jest
7) @types/react-test-renderer

STEPS:

1) Install all the listed dependencies above best with --save-dev flag to see these in your devDependencies.

2) Add a jest configuration file.

//jest.config.js
module.exports = {
 testEnvironment: "jsdom",
  preset: "jest-expo",
  globals: {
    "ts-jest": {
      tsconfig: {
        jsx: "react",
      },
    },
  },
  transform: {
    "^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js",
    "^.+\\.tsx?$": "ts-jest",
  },
  testMatch: ["**/?(*.)+(spec|test).ts?(x)"],
  collectCoverageFrom: [
    "**/*.{ts,tsx}",
    "!**/coverage/**",
    "!**/node_modules/**",
    "!**/babel.config.js",
    "!**/jest.setup.js",
  ],
  moduleFileExtensions: ["js", "ts", "tsx"],
  transformIgnorePatterns: [
    "node_modules/(?!(jest-)?react-native|react-clone-referenced-element|@react-native-community|expo(nent)?|@expo(nent)?/.*|react-navigation|@react-navigation/.*|@unimodules/.*|sentry-expo|native-base)",
  ],
  coverageReporters: ["json-summary", "text", "lcov"],
})
Enter fullscreen mode Exit fullscreen mode

3) Add "esModuleInterop": true to your tsconfig.json file. Your final configuration file should look like the one below.

//tsconfig.json
  {
  "compilerOptions": {
    "allowSyntheticDefaultImports": true,
    "jsx": "react-native",
    "lib": ["dom", "esnext"],
    "moduleResolution": "node",
    "noEmit": true,
    "skipLibCheck": true,
    "resolveJsonModule": true,
    "strict": true,
    "esModuleInterop": true
  }
}
Enter fullscreen mode Exit fullscreen mode

4) Add scripts for running your tests in different modes in your package.json.

//package.json
"test": "jest",
"test:watch": "npm run test --watch",
"test:ci": "npm run test --coverage",
"test:badges": "npm run test:ci  && jest-coverage-badges --input coverage/coverage-summary.json --output __badges__"
Enter fullscreen mode Exit fullscreen mode

Now we can go ahead to check if this works
I will have two files here: App.tsx and App.test.tsx

1) App.tsx

//App.tsx
import { StatusBar } from "expo-status-bar"
import React from "react"
import { StyleSheet, Text, View, Image } from "react-native"

export default function App() {
  return (
    <View style={styles.container}>
      <Image
        source={require("./assets/adaptive-icon.png")}
        style={styles.logo}
      />
      <Text>Open up App.tsx to start working on your app!</Text>
      <StatusBar style="auto" />
    </View>
  )
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: "#fff",
    alignItems: "center",
    justifyContent: "center",
  },
  logo: {
    width: 120,
    height: 120,
    margin: 10,
  },
})
Enter fullscreen mode Exit fullscreen mode

2) App.spec.tsx

//App.spec.tsx
import React from "react"
import renderer from "react-test-renderer"

import App from "./App"

describe("<App />", () => {
  it("has 2 child", () => {
    const tree: any = renderer.create(<App />).toJSON()
    expect(tree?.children?.length).toBe(2)
  })
})
Enter fullscreen mode Exit fullscreen mode

You can go ahead and test with npm run test.

To have a better overview of the code and template used here, you can check out the repo below.

GitHub logo elgsantos / expo-template-typescript-jest

🔥 A React Native Template using Expo, Typescript and Jest

React Native Template Expo Typescript with Jest

Runs with expo npm IOS Android Web Typescript Tested with jest coverage Stars Issues MIT License

A React Native Template using Expo, Typescript and Jest
Explore the docs »
Report Bug · Request Feature

Table of Contents

  1. About The Project
  2. Getting Started
  3. Usage
  4. Contributing
  5. License
  6. Author
  7. Acknowledgements

About The Project

This template was developed to facilitate the creation of a new project using Expo, React Native and Jest.

React Native Template Expo Typescript with Jest

Built With

Getting Started

To get this template up and running follow these simple steps.

Prerequisites

  • Install Node.js
  • Expo
    npm i -g expo-cli
    Enter fullscreen mode Exit fullscreen mode
  • Yarn
    npm install -g yarn
    Enter fullscreen mode Exit fullscreen mode

Installation

Create a project with this template:

expo init --template expo-template-typescript-jest
Enter fullscreen mode Exit fullscreen mode

(It will prompt you to enter a project name)

Usage

  • Navigate to the created directory
  • Start the project:
    yarn start
    Enter fullscreen mode Exit fullscreen mode
  • Then develop your app, creating files .tsx for React Native components and .ts for plain typescript files.

Testing

There are some…

💖 💪 🙅 🚩
ajulibe
Ajulibe

Posted on February 9, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related