Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeError: Cannot read property 'viewManagersNames' of undefined - Integrating Jest and Enzyme with React Native TypeScript Package

I'm trying to integrate Jest unit testing with Enzyme on my React-Native Typescript package, but after reading docs and tutorials, I can't seem to make it work.

The problem only happens when using LinearGradient from expo-linear-gradient.
After having configured the file settings (see below), running npm test throws the error :

TypeError: Cannot read property 'viewManagersNames' of undefined at 
requireNativeViewManager (node_modules/@unimodules/react-native- 
adapter/src/NativeViewManagerAdapter.tsx:26:10) at Object.<anonymous> 
(node_modules/expo-linear-gradient/src/NativeLinearGradient.ios.tsx:20:59) 
at Object.<anonymous> (node_modules/expo-linear- 
gradient/src/LinearGradient.tsx:5:34).

I have tried to link the @unimodules/react-native-adapter as it seems that it's what's causing the issue, but I then get the error :

SyntaxError: Unexpected token {

  at ScriptTransformer._transformAndBuildScript (node_modules/@jest/transform/build/ScriptTransformer.js:537:17)
  at ScriptTransformer.transform (node_modules/@jest/transform/build/ScriptTransformer.js:579:25)
  at Object.<anonymous> (node_modules/@unimodules/core/src/AdapterProxy.ts:1:50)

package.json :

{
   ...
  "scripts": {
    "build": "tsc",
    "format": "prettier --write \"src/**/*.ts\" \"src/**/*.js\"",
    "lint": "tslint -p tsconfig.json",
    "test": "jest --config jest.config.json --detectOpenHandles",
    "prepare": "npm run build",
    "prepublishOnly": "npm test && npm run lint",
    "preversion": "npm run lint",
    "version": "npm run format && git add -A src",
    "postversion": "git push && git push --tags"
  },
  "devDependencies": {
    "@babel/plugin-proposal-class-properties": "^7.5.5",
    "@babel/plugin-proposal-nullish-coalescing-operator": "^7.4.4",
    "@babel/preset-env": "^7.6.3",
    "@babel/preset-flow": "^7.0.0",
    "@babel/preset-react": "^7.6.3",
    "@types/enzyme": "^3.10.3",
    "@types/enzyme-adapter-react-16": "^1.0.5",
    "@types/jest": "^24.0.18",
    "@types/react": "^16.9.5",
    "@types/react-native": "^0.60.19",
    "@types/react-test-renderer": "^16.9.0",
    "@unimodules/core": "^4.0.0",
    "@unimodules/react-native-adapter": "^4.0.0",
    "babel-jest": "^24.9.0",
    "babel-plugin-transform-export-extensions": "^6.22.0",
    "enzyme": "^3.10.0",
    "enzyme-adapter-react-16": "^1.15.0",
    "enzyme-to-json": "^3.4.2",
    "install": "^0.13.0",
    "jest": "^24.9.0",
    "jest-expo": "^35.0.0",
    "metro-react-native-babel-preset": "^0.55.0",
    "npm": "^6.12.0",
    "prettier": "^1.18.2",
    "react": "16.10.2",
    "react-dom": "16.10.2",
    "react-native": "0.61.2",
    "react-native-renderer": "^15.5.3",
    "react-test-renderer": "^16.10.2",
    "ts-jest": "^24.1.0",
    "tslint": "^5.20.0",
    "tslint-config-prettier": "^1.18.0",
    "typescript": "^3.6.3"
  },
  "dependencies": {
    "@babel/plugin-proposal-optional-chaining": "^7.6.0",
    "expo-linear-gradient": "^7.0.1",
    "lodash": "^4.17.14"
  },
  "peerDependencies": {
    "react": "*",
    "react-dom": "*",
    "react-native": "*"
  }
}

jest.config.json:

{
  "preset": "react-native",
  "transform": {
    "^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js",
    "\\.(ts|tsx)$": "ts-jest"
  },
  "setupFiles": ["./src/setupTests.js"],
  "globals": {
    "ts-jest": {
      "tsConfig": "tsconfig.jest.json"
    }
  },
  "transformIgnorePatterns": [
    "node_modules/(?!(react-native|react-native-skeleton-content|expo-linear-gradient|@unimodules/core)/)"
  ],
  "moduleFileExtensions": ["ts", "tsx", "js"],
  "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$"
}

babel.config.js:

module.exports = {
  presets: ['@babel/preset-env', '@babel/preset-react', '@babel/preset-flow'],
  plugins: [
    '@babel/plugin-proposal-class-properties',
    '@babel/plugin-proposal-nullish-coalescing-operator',
    '@babel/plugin-proposal-optional-chaining',
  ],
};

setupTests.js:

import Enzyme from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';

Enzyme.configure({ adapter: new Adapter() });

tsconfig.jest.json:

{
  "extends": "./tsconfig",
  "compilerOptions": {
    "jsx": "react",
    "module": "commonjs"
  }
}

tsconfig.json:

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "jsx": "react-native",
    "noEmit": true,
    "strict": true,
    "moduleResolution": "node",
    "baseUrl": "./",
    "allowSyntheticDefaultImports": true,
    "esModuleInterop": true,
    "exclude": ["node_modules"]
  }
}

SkeletonContent.test.tsx:

import React from 'react';
import { SkeletonContent } from '../SkeletonContent';
import { shallow } from 'enzyme';

describe('SKC', () => {
  const wrapper = shallow<SkeletonContent>(<SkeletonContent />);

  describe('rendering', () => {
    it('is defined', () => {
      expect(wrapper).toBeDefined();
    });
  });
});
like image 402
Alexandre Zajac Avatar asked Nov 07 '22 13:11

Alexandre Zajac


1 Answers

I found a fix for this that worked for me.

All I had to do was change my jest preset from react-native (which is what expo says to set it to) to jest-expo, and add the recommended transformationIgnorePatterns. In my package.json:

  "jest": {
    "preset": "jest-expo",
    "transformIgnorePatterns": [
      "node_modules/(?!(jest-)?react-native|react-clone-referenced-element|@react-native-community|expo(nent)?|@expo(nent)?/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|@sentry/.*)"
    ]
  },
like image 86
Ehren Murdick Avatar answered Nov 15 '22 12:11

Ehren Murdick