oblador/react-native-vector-icons

[Bug]: When snapshot testing, jest throws `Invariant Violation: TurboModuleRegistry.getEnforcing(...): 'VectorIcons' could not be found`

Opened this issue · 7 comments

Which package are you using?

@react-native-vector-icons/*

What platform(s) does this occur on?

Android, iOS

What happened?

After scaffolding a new react native app, the default tests pass.

But, upon installing react-native-vector-icons and using them in a component, the test suite crashes with:

Invariant Violation: TurboModuleRegistry.getEnforcing(...): 'VectorIcons' could not be found. Verify that a module by this name is registered in the native binary.

Unsuccessful Workarounds

Mocking out RNVI: https://github.com/thehale/reproduction-react-native-vector-icons-with-jest-invariant-violation/tree/NOT_A_FIX_mocks
Using moduleNameMapper: https://github.com/thehale/reproduction-react-native-vector-icons-with-jest-invariant-violation/tree/NOT_A_FIX_moduleNameMapper

Relevant log output

$ yarn test

yarn run v1.22.15
$ jest
 FAIL  __tests__/App.test.tsx
  ● Test suite failed to run

    Invariant Violation: TurboModuleRegistry.getEnforcing(...): 'VectorIcons' could not be found. Verify that a module by this name is registered in the native binary.

      23 | } from 'react-native';
      24 |
    > 25 | import EntypoIcon from '@react-native-vector-icons/entypo';
         | ^
      26 | import type {PropsWithChildren} from 'react';
      27 | import React from 'react';
      28 |

      at invariant (node_modules/invariant/invariant.js:40:15)
      at Object.getEnforcing (node_modules/react-native/Libraries/TurboModule/TurboModuleRegistry.js:47:12)
      at Object.getEnforcing (node_modules/@react-native-vector-icons/common/src/NativeVectorIcons.ts:10:36)
      at Object.require (node_modules/@react-native-vector-icons/common/src/create-icon-set.tsx:5:1)
      at Object.require (node_modules/@react-native-vector-icons/common/src/index.ts:3:1)
      at Object.require (node_modules/@react-native-vector-icons/entypo/src/index.ts:9:1)
      at Object.require (App.tsx:25:1)
      at Object.require (__tests__/App.test.tsx:7:1)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        0.812 s
Ran all test suites.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Minimal reproducible example

https://github.com/thehale/reproduction-react-native-vector-icons-with-jest-invariant-violation

A newly scaffolded app passes tests

  1. Clone the repo
  2. Checkout the blank app scaffolded in the first commit: git checkout HEAD~
  3. Install dependencies: yarn
  4. Run the tests: yarn test
  5. See the tests pass

Adding react-native-vector-icons causes the test suite to crash

  1. Switch to the commit with RNVI: git checkout main
  2. Install updated dependencies: yarn
  3. Run the tests again: yarn test
  4. See the test suite crash.

Your computer environment

info Fetching system and libraries information...
(node:9112) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
System:
  OS: macOS 15.1.1
  CPU: (6) x64 Intel(R) Core(TM) i5-8500B CPU @ 3.00GHz
  Memory: 161.91 MB / 32.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 22.12.0
    path: ~/.nvm/versions/node/v22.12.0/bin/node
  Yarn:
    version: 1.22.15
    path: /usr/local/bin/yarn
  npm:
    version: 10.9.0
    path: ~/.nvm/versions/node/v22.12.0/bin/npm
  Watchman:
    version: 2024.12.02.00
    path: /usr/local/bin/watchman
Managers:
  CocoaPods:
    version: 1.16.2
    path: /usr/local/bin/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 24.1
      - iOS 18.1
      - macOS 15.1
      - tvOS 18.1
      - visionOS 2.1
      - watchOS 11.1
  Android SDK: Not Found
IDEs:
  Android Studio: 2024.2 AI-242.23339.11.2421.12700392
  Xcode:
    version: 16.1/16B40
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: javac 17
    path: /usr/bin/javac
  Ruby:
    version: 2.6.10
    path: /Users/jhale/.rbenv/shims/ruby
npmPackages:
  "@react-native-community/cli":
    installed: 15.0.1
    wanted: 15.0.1
  react:
    installed: 18.3.1
    wanted: 18.3.1
  react-native:
    installed: 0.76.5
    wanted: 0.76.5
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: true
iOS:
  hermesEnabled: true
  newArchEnabled: true

I can get a different error message if I mock out the Turbo Modules as described in this StackOverflow post: https://stackoverflow.com/a/77498117/14765128

$ yarn test

yarn run v1.22.15
$ jest
 FAIL  __tests__/App.test.tsx
  ● Test suite failed to run

    Jest encountered an unexpected token

    Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.

    Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.

    By default "node_modules" folder is ignored by transformers.

    Here's what you can do:
     • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
     • If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/configuration
    For information about custom transformations, see:
    https://jestjs.io/docs/code-transformation

    Details:

    /Users/jhale/git/RNVIandJest/node_modules/@react-native-vector-icons/entypo/fonts/Entypo.ttf:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,jest){
                                                                                      

    SyntaxError: Invalid or unexpected token

      23 | } from 'react-native';
      24 |
    > 25 | import EntypoIcon from '@react-native-vector-icons/entypo';
         | ^
      26 | import type {PropsWithChildren} from 'react';
      27 | import React from 'react';
      28 |

      at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1505:14)
      at Object.require (node_modules/@react-native-vector-icons/entypo/src/index.ts:15:15)
      at Object.require (App.tsx:25:1)
      at Object.require (__tests__/App.test.tsx:7:1)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        0.599 s
Ran all test suites.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Reproduction: https://github.com/thehale/reproduction-react-native-vector-icons-with-jest-invariant-violation/tree/NOT_A_FIX-mock-turbo-instead-errors-unexpected-token

I'm getting this error, but not as a test failure, as an error when running the app. Any immediate fix? Downgrade?

johnf commented

I suspect you either need to add @react-native-vector-icons/common and/or on ios pod install

I suspect you either need to add @react-native-vector-icons/common

@react-native-vector-icons/common is in the package.json of the reproduction example: https://github.com/thehale/reproduction-react-native-vector-icons-with-jest-invariant-violation/blob/main/package.json#L13

and/or on ios pod install

RNVI works fine on the device itself. The error highlighted in this issue only arises when running Jest tests, which are JS only, no native component.

Typically, when I face this sort of error, I simply mock out the native calls, but even that approach is not working here (see Unsuccessful Workarounds)

Unfortunately, already had common and ran pod install.. Even did a full cache clear, no dice.

 pod deintegrate
rm Podfile.lock
rm -rf build
 pod cache clean --all
 pod install

Ended up going back to the old way of doing it for now.

johnf commented

@thehale Apologies I didn't have time to look at this properly during the week.
I've explored at the repro, and I understand the issue now.

I think the real answer will be the change we are considering in #1682

I suspect there is some way to mock this away as a workaround, but I don't have enough jest experience to help.

@johnf No worries! I'll keep trying to find a workaround too.