Quantcast
Channel: Active questions tagged react-native+typescript - Stack Overflow
Viewing all articles
Browse latest Browse all 6287

react native typescript screen test returning Test suite failed to run. Error react-native-permissions: NativeModule.RNPermissions is null

$
0
0

I am experiencing difficulty writing tests for react-native that involve mocking Internet and Vibration permissions written in typescript

using instructions from the URL below

How to mock PermissionAndroid from react native

I keep getting the below error

FAIL  app/screens/login/login-screen.test.tsx● Test suite failed to run   react-native-permissions: NativeModule.RNPermissions is null. To fix this issue try these steps:    • If you are using CocoaPods on iOS, run `pod install` in the `ios` directory and then clean, rebuild and re-run the app. You may also need to re-open Xcode to get the new pods.• If you are getting this error while unit testing you need to mock the native module. You can use this to get started: https://github.com/react-native-community/react-native-permissions/blob/master/mock.js      If none of these fix the issue, please open an issue on the Github repository: https://github.com/react-native-community/react-native-permissions      at Object.<anonymous> (node_modules/react-native-qrcode-scanner/node_modules/react-native-permissions/lib/commonjs/index.ts:6:9)      at Object.<anonymous> (node_modules/react-native-qrcode-scanner/index.js:19:1)

See the login screen test file content below

import AsyncStorage from "@react-native-community/async-storage"import { render } from "@testing-library/react-native"import React from "react"import { LoginScreen } from ".."it("renders correctly", async () => {  const { getAllByText } = await render(<LoginScreen navigation={undefined} route={undefined} />)  expect(getAllByText("Login").length).toBe(1)  expect(AsyncStorage.getItem).toBeCalledWith("myKey")})

test\setup.ts

// we always make sure 'react-native' gets included firstimport "react-native"// libraries to mockimport "./mock-react-native-image"import "./mock-async-storage"import "./mock-i18n"import "./mock-reactotron"import "./mock-permissions"jest.useFakeTimers()declare global {  let __TEST__}

and test\mock-permissions.ts

// eslint-disable-next-line react-native/split-platform-componentsimport { PermissionsAndroid } from "react-native";const internetPermissionResult: string = PermissionsAndroid.RESULTS.GRANTED;const vibratePermissionResult: string = PermissionsAndroid.RESULTS.GRANTED;const internetPermissionGranted = true;const vibratePermissionGranted = true;const permissionsAndroidModule = jest.requireActual('react-native/Libraries/PermissionsAndroid/PermissionsAndroid.js');jest.doMock('react-native/Libraries/PermissionsAndroid/PermissionsAndroid', () => ({  ...permissionsAndroidModule,  requestMultiple: () => {    return {      [PermissionsAndroid.PERMISSIONS.INTERNET]: internetPermissionResult,      [PermissionsAndroid.PERMISSIONS.VIBRATE]: vibratePermissionResult,    };  },  check: () => {    return internetPermissionGranted && vibratePermissionGranted;  },}));

my package.json

  {"name": "special-project","version": "0.0.1","private": true,"scripts": {"start": "react-native start","ios": "react-native run-ios","android": "react-native run-android","test:e2e": "detox test -c ios.sim.debug","build:e2e": "detox build -c ios.sim.debug","ci:test:e2e": "detox test -c ios.sim.release -l verbose --cleanup","ci:build:e2e": "detox build -c ios.sim.release","compile": "tsc --noEmit -p . --pretty","format": "npm-run-all format:*","format:js": "prettier --write \"app/**/*.js\"","format:json": "prettier --write \"app/**/*.json\"","format:md": "prettier --write \"**/*.md\"","format:ts": "prettier --write \"app/**/*.ts{,x}\"","lint": "eslint index.js app storybook test --fix --ext .js,.ts,.tsx && yarn format","patch": "patch-package","storybook": "start-storybook -p 9001 -c ./storybook","test": "jest","adb": "adb reverse tcp:9090 tcp:9090 && adb reverse tcp:3000 tcp:3000 && adb reverse tcp:9001 tcp:9001 && adb reverse tcp:8081 tcp:8081","postinstall": "node ./bin/postInstall","build-ios": "react-native bundle --entry-file index.js --platform ios --dev false --bundle-output ios/main.jsbundle --assets-dest ios","build-android": "react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res","clean": "react-native-clean-project","clean-all": "npx react-native clean-project-auto"  },"dependencies": {"@react-native-async-storage/async-storage": "^1.15.14","@react-native-community/checkbox": "^0.5.9","@react-native-community/masked-view": "0.1.10","@react-navigation/drawer": "^6.1.8","@react-navigation/material-top-tabs": "^6.0.6","@react-navigation/native": "~6.0.1","@react-navigation/native-stack": "^6.0.2","@react-navigation/stack": "~6.0.1","@reduxjs/toolkit": "^1.6.2","@unimodules/core": "6.0.0","apisauce": "2.0.0","axios": "^0.24.0","expo-linear-gradient": "^9.2.0","expo-localization": "9.1.0","i18n-js": "3.8.0","mobx": "6.1.8","mobx-react-lite": "3.2.0","mobx-state-tree": "5.0.1","node-fetch": "^3.1.0","react": "17.0.1","react-native": "0.64.2","react-native-appearance": "^0.3.4","react-native-camera": "^4.2.1","react-native-gesture-handler": "^1.10.3","react-native-image-crop-picker": "^0.36.4","react-native-keychain": "6.2.0","react-native-material-menu": "^2.0.0","react-native-pager-view": "^5.4.8","react-native-paper": "^4.10.1","react-native-permissions": "^3.1.0","react-native-qrcode-scanner": "^1.5.4","react-native-radio-buttons-group": "^2.2.7","react-native-reanimated": "^2.2.3","react-native-safe-area-context": "3.1.8","react-native-screens": "3.4.0","react-native-tab-view": "^3.1.1","react-native-unimodules": "0.12.0","react-redux": "^7.2.6","reactotron-mst": "3.1.3","reactotron-react-js": "^3.3.7","redux": "^4.1.2","redux-logger": "^3.0.6","redux-persist": "^6.0.0","redux-saga": "^1.1.3","validate.js": "0.13.1"  },"devDependencies": {"@babel/core": "^7.12.9","@babel/plugin-proposal-decorators": "7.12.1","@babel/plugin-proposal-optional-catch-binding": "7.12.1","@babel/runtime": "^7.12.5","@storybook/addon-storyshots": "6.1.10","@storybook/react-native": "5.3.23","@storybook/react-native-server": "5.3.23","@testing-library/react-native": "^8.0.0","@types/i18n-js": "3.0.3","@types/jest": "26.0.19","@types/react": "16.14.0","@types/react-native": "0.63.40","@types/react-test-renderer": "16.9.4","@typescript-eslint/eslint-plugin": "4.10.0","@typescript-eslint/parser": "4.10.0","babel-jest": "26.6.3","babel-loader": "8.2.2","detox": "17.14.5","eslint": "7.15.0","eslint-config-prettier": "7.0.0","eslint-config-standard": "16.0.2","eslint-plugin-import": "2.22.1","eslint-plugin-node": "11.1.0","eslint-plugin-promise": "4.2.1","eslint-plugin-react": "7.21.5","eslint-plugin-react-native": "3.10.0","fbjs-scripts": "3.0.0","jest": "^25.5.4","jest-circus": "25.5.4","jest-expo": "^40.0.1","jetifier": "1.6.6","npm-run-all": "4.1.5","patch-package": "6.2.2","postinstall-prepare": "1.0.1","prettier": "2.2.1","react-devtools-core": "4.10.1","react-dom": "^17.0.2","react-native-clean-project": "^3.6.3","react-native-web": "^0.16.3","react-powerplug": "1.0.0","reactotron-react-native": "^5.0.0","solidarity": "2.3.1","typescript": "4.2.3"  },"jest": {"preset": "jest-expo","setupFiles": ["<rootDir>/test/setup.ts"    ],"testPathIgnorePatterns": ["/node_modules/","/e2e"    ],"transformIgnorePatterns": ["node_modules/(?!(jest-)?react-native|expo-linear-gradient|@react-native|@react-native-async-storage|@react-navigation|@storybook|@react-native-community|expo-localization|@unimodules)"    ]  },"prettier": {"printWidth": 100,"semi": false,"singleQuote": false,"trailingComma": "all"  },"detox": {"test-runner": "jest","configurations": {"ios.sim.debug": {"binaryPath": "ios/build/Build/Products/Debug-iphonesimulator/codix.app","build": "xcodebuild -workspace ios/codix.xcworkspace -scheme codix -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build -destination 'name=iPhone 11'","type": "ios.simulator","device": {"name": "iPhone 11","os": "iOS 13.2"        }      },"ios.sim.release": {"binaryPath": "ios/build/Build/Products/Release-iphonesimulator/codix.app","build": "xcodebuild -workspace ios/codix.xcworkspace -scheme codix -configuration Release -sdk iphonesimulator -derivedDataPath ios/build -destination 'name=iPhone 11'","type": "ios.simulator","device": {"name": "iPhone 11","os": "iOS 13.2"        }      }    }  },"eslintConfig": {"root": true,"parser": "@typescript-eslint/parser","extends": ["plugin:@typescript-eslint/recommended","plugin:react/recommended","plugin:react-native/all","standard","prettier","prettier/@typescript-eslint"    ],"plugins": ["@typescript-eslint","react","react-native"    ],"parserOptions": {"ecmaFeatures": {"jsx": true      },"project": "./tsconfig.json"    },"settings": {"react": {"pragma": "React","version": "detect"      }    },"globals": {"__DEV__": false,"jasmine": false,"beforeAll": false,"afterAll": false,"beforeEach": false,"afterEach": false,"test": false,"expect": false,"describe": false,"jest": false,"it": false    },"rules": {"@typescript-eslint/ban-ts-ignore": 0,"@typescript-eslint/explicit-function-return-type": 0,"@typescript-eslint/explicit-member-accessibility": 0,"@typescript-eslint/explicit-module-boundary-types": 0,"@typescript-eslint/indent": 0,"@typescript-eslint/member-delimiter-style": 0,"@typescript-eslint/no-empty-interface": 0,"@typescript-eslint/no-explicit-any": 0,"@typescript-eslint/no-object-literal-type-assertion": 0,"@typescript-eslint/no-var-requires": 0,"comma-dangle": 0,"multiline-ternary": 0,"no-undef": 0,"no-unused-vars": 0,"no-use-before-define": "off","quotes": 0,"react-native/no-raw-text": 0,"react/no-unescaped-entities": 0,"react/prop-types": "off","space-before-function-paren": 0    }  }}

The actual login screen file

import React, { FC, useState } from "react"import {  View,  SafeAreaView,  TouchableOpacity,  ScrollView,  TextInput,  ImageBackground,  KeyboardAvoidingView,  Alert,} from "react-native"import { StackScreenProps } from "@react-navigation/stack"import { observer } from "mobx-react-lite"import { Button, Text, AutoImage as Image } from "../../components"import { NavigatorParamList } from "../../navigators"import { Images } from "../../config"import { setIsLoggedIn } from "../../reducers/loginReducer"import { useDispatch } from "react-redux"import { setTokenValue } from "../../reducers/tokenReducer"import { LOGIN_URL, showErrorAlert } from "../../utils/constants"import axios from "axios"import { setSalesAgentIdValue } from "../../reducers/salesAgentIdReducer"import {  BLUESIGNUP_TEXT,  BOTTOM_HALF,  CONTINUE,  CONTINUE_TEXT,  FOOTER_CONTENT,  FULL,  HOME_LOGO,  KEYBOARD_AVOID_VIEW,  LABEL,  LOGO_TEXT,  RED_ACTION_LINK,  RED_TEXT,  REGULAR_TEXT,  SUBJECT,  TEXT_INPUT,  TEXT_INPUT_END,} from "./loginscreen-styles"import { setRefreshTokenValue } from "../../reducers/refreshTokenReducer"export const LoginScreen: FC<StackScreenProps<NavigatorParamList, "login">> = observer(  ({ navigation }) => {    const dispatch = useDispatch()    const [email, setEmail] = useState("")    const [password, setPassword] = useState("")    const [errortext] = useState("")    let tokenValue: any    let refreshTokenValue: any    let salesAgenIdValue: any    const api = axios.create({      baseURL: LOGIN_URL,    })    const onLogin = async () => {      if (!email) {        showErrorAlert("Your Email")        return      }      if (!password) {        showErrorAlert("Your Password")        return      }      console.log("<<< inside onlogin >>>>>")      const dataToSend = {        email: email,        password: password,      }      try {        console.log("<<<<<<< BEFORE RESPONSE FOR LOGIN >>>>>>>>>")        const res = await api.post("/", dataToSend)        console.log("Res >> ", res)        console.log("<<<<<<<AFTER RESPONSE FOR LOGIN >>>>>>>>>")        // eslint-disable-next-line no-prototype-builtins        if (res.hasOwnProperty("data")) {          tokenValue = res.data.data.userToken          refreshTokenValue = res.data.data.refreshToken          console.log("<<<<<<<TOKEN>>>>>>>>>")          console.log(JSON.stringify(tokenValue))          console.log("<<<<<<<TOKEN>>>>>>>>>")          console.log("<<<<<<< REFRESH TOKEN>>>>>>>>>")          console.log(JSON.stringify(refreshTokenValue))          console.log("<<<<<<< REFRESH TOKEN>>>>>>>>>")          dispatch(setTokenValue(tokenValue))          dispatch(setRefreshTokenValue(refreshTokenValue))          dispatch(setIsLoggedIn(true))          salesAgenIdValue = res.data.data.userId          console.log("<<<<<<<salesAgenIdValue>>>>>>>>>")          console.log(JSON.stringify(salesAgenIdValue))          console.log("<<<<<<<salesAgenIdValue>>>>>>>>>")          dispatch(setSalesAgentIdValue(salesAgenIdValue))          setTimeout(() => {            navigation.navigate("drawer")          }, 1000)        } else {          console.log("<<<<<<< ERRRRRROR >>>>>>>>>")        }      } catch (err) {        console.log(err)        Alert.alert("An Error occurred " + err)      }    }    return (<ImageBackground source={Images.bg} style={FULL}><Image source={Images.wragbyLogo} style={HOME_LOGO} /><View style={LOGO_TEXT}><Text>Special App</Text></View><View style={BOTTOM_HALF}><SafeAreaView><View><Text style={RED_TEXT}>{errortext}</Text></View><ScrollView showsVerticalScrollIndicator={false}><KeyboardAvoidingView                style={KEYBOARD_AVOID_VIEW}><Text style={SUBJECT}>Login</Text><Text style={LABEL}>Email</Text><TextInput                  style={TEXT_INPUT}                  placeholderTextColor="#707070"                  onChangeText={(email) => setEmail(email)}                  placeholder=""                  autoCapitalize="none"                  value={email}                /><Text style={LABEL}>Password</Text><TextInput                  style={TEXT_INPUT_END}                  placeholderTextColor="#707070"                  onChangeText={(password) => setPassword(password)}                  secureTextEntry={true}                  placeholder=""                  autoCapitalize="none"                  value={password}                /><View style={RED_ACTION_LINK}><TouchableOpacity onPress={() => navigation.navigate("resetpassword")}><Text style={RED_TEXT}>Forgot password?</Text></TouchableOpacity></View><View style={FOOTER_CONTENT}><Button                    testID="next-screen-button"                    style={CONTINUE}                    textStyle={CONTINUE_TEXT}                    tx="welcomeScreen.signIn"                    // onPress={showDashboard}                    onPress={onLogin}                  /><TouchableOpacity onPress={() => navigation.navigate("signup")}><Text style={REGULAR_TEXT}>                      Don't have an Account yet? <Text style={BLUESIGNUP_TEXT}>Sign up</Text></Text></TouchableOpacity></View></KeyboardAvoidingView></ScrollView></SafeAreaView></View></ImageBackground>    )  },)

I have been battling with this issue for almost a weekPlease advise me with the right syntax to use in writing proper tests or at least tell me how to resolve the async storage problem


Viewing all articles
Browse latest Browse all 6287

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>