Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Jest transpiling from "jest/preprocessor.js" broken #22175

Closed
3 tasks done
lewnelson opened this issue Nov 6, 2018 · 35 comments · Fixed by Sukeltaja-App/sukeltaja-frontend#17
Closed
3 tasks done

Jest transpiling from "jest/preprocessor.js" broken #22175

lewnelson opened this issue Nov 6, 2018 · 35 comments · Fixed by Sukeltaja-App/sukeltaja-frontend#17
Labels
Bug Issue: Author Provided Repro This issue can be reproduced in Snack or an attached project. Priority: Mid Resolution: Locked This issue was locked by the bot. 🔩Test Infrastructure Test infrastructure and continuous integration.

Comments

@lewnelson
Copy link

lewnelson commented Nov 6, 2018

Environment

Run react-native info in your terminal and paste its contents here.

React Native Environment Info:
    System:
      OS: macOS High Sierra 10.13.6
      CPU: x64 Intel(R) Core(TM) i7-4770HQ CPU @ 2.20GHz
      Memory: 178.39 MB / 16.00 GB
      Shell: 3.2.57 - /bin/bash
    Binaries:
      Node: 10.9.0 - ~/.nvm/versions/node/v10.9.0/bin/node
      npm: 6.2.0 - ~/.nvm/versions/node/v10.9.0/bin/npm
      Watchman: 4.7.0 - /usr/local/bin/watchman
    SDKs:
      iOS SDK:
        Platforms: iOS 12.0, macOS 10.14, tvOS 12.0, watchOS 5.0
      Android SDK:
        Build Tools: 23.0.1, 25.0.0, 25.0.1, 25.0.2, 25.0.3, 26.0.1, 26.0.2, 27.0.3, 28.0.1, 28.0.3
        API Levels: 19, 23, 25, 26, 27, 28
    IDEs:
      Android Studio: 3.1 AI-173.4907809
      Xcode: 10.0/10A255 - /usr/bin/xcodebuild
    npmPackages:
      react: ^16.6.0-alpha.8af6728 => 16.6.0-alpha.8af6728
      react-native: ^0.57.4 => 0.57.4
    npmGlobalPackages:
      create-react-native-app: 1.0.0
      react-native-cli: 2.0.1

Description

We have recently upgraded from v0.55.4 to v0.57.4 using react-native-git-upgrade. As part of this upgrade the majority of our jest tests have broken due to transpiling errors.

Full jest config

  "jest": {
    "preset": "react-native",
    "setupTestFrameworkScriptFile": "<rootDir>/jestSetup.js",
    "moduleNameMapper": {
      "^image![a-zA-Z0-9$_-]+$": "GlobalImageStub",
      "^[@./a-zA-Z0-9$_-]+\\.(png|gif|jpg|ttf)$": "RelativeImageStub"
    },
    "transform": {
      "^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js"
    },
    "testMatch": [
      "<rootDir>/src/**/*.test.js?(x)"
    ],
    "snapshotSerializers": [
      "enzyme-to-json/serializer"
    ],
    "collectCoverageFrom": [
      "**/src/**/*.js"
    ],
    "coveragePathIgnorePatterns": [
      "src/helpers/networkDebugger",
      "/node_modules/"
    ],
    "coverageThreshold": {
      "global": {
        "branches": 90,
        "functions": 90,
        "lines": 90,
        "statements": 90
      }
    }
  },

Jest setup file

import { configure } from 'enzyme'
import Adapter from 'enzyme-adapter-react-16'
import fetch from 'jest-fetch-mock'

global.fetch = fetch

const mockedDate = new Date('2018-01-01T12:13:14')
const _Date = Date
global.Date = jest.fn(() => mockedDate)
global.Date.UTC = _Date.UTC
global.Date.parse = _Date.parse
global.Date.now = _Date.now
global.WebSocket = jest.fn(() => ({ addEventListener: jest.fn(), send: jest.fn() }))
global.FileReader = jest.fn(() => ({ addEventListener: jest.fn(), readAsText: jest.fn() }))
global.requestAnimationFrame = jest.fn()

configure({ adapter: new Adapter() })

Some of the errors we are seeing are related to imports/exports and class arrow methods. e.g.

export class MyComponent extends Component {
  static propType = { optionalProp: PropTypes.bool },
  doSomething = () => { ... }
  render () { ... }
}

Fails with the error TypeError: Cannot read property 'default' of undefined. Once changed to

export class MyComponent extends Component {
  static propType = { optionalProp: PropTypes.bool },
  doSomething () { ... }
  render () { ... }
}

It is fine.

Reproducible Demo

Let us know how to reproduce the issue. Include a code sample, share a project, or share an app that reproduces the issue using https://snack.expo.io/. Please follow the guidelines for providing a MCVE: https://stackoverflow.com/help/mcve

I've setup a public repo which contains some example broken tests and how those tests can be fixed temporarily. However the underlying issue is the transpiling. https://github.com/lewnelson/react-native-jest-example

@lewnelson
Copy link
Author

I've just added another example to the repo that I came across, by adding an empty constructor arrow functions transpile correctly on class methods https://github.com/lewnelson/react-native-jest-example/blob/master/src/working/containers/Something.js.

I'm not sure if the issue lies within the jest preprocessor or within the babel plugins themselves. Possibly the ordering of the plugins in the preprocessor?

@letsgojuno
Copy link

We have also ran into this issue on 0.57.3. From an initial investigation I can make it work by disabling inlineRequires in the jest preprocessor https://github.com/facebook/react-native/blob/master/jest/preprocessor.js#L58

This is as far as I got. To get around the issue for now we are binding the methods in the constructor.

@tylergaw
Copy link

@letsgojuno Oh wow, removing inlineRequires fixes it for me too. Been trying to find a fix for this for a few days. Thank you 🙏

I've been keeping a running list of issues/fixes when upgrading from RN 0.54 to 0.57. Added this one to the list https://github.com/tylergaw/RNUpgradePath#issue-4

@lewnelson I tried the empty constructor approach first, but didn't have any luck with it. Got the same Cannot read property 'default' of undefined.

@kelset kelset added the 🔩Test Infrastructure Test infrastructure and continuous integration. label Nov 22, 2018
@pjay79
Copy link

pjay79 commented Nov 24, 2018

This has worked for me too @tylergaw @letsgojuno. Thanks

@ekeuus
Copy link

ekeuus commented Nov 26, 2018

We have also ran into this issue on 0.57.3. From an initial investigation I can make it work by disabling inlineRequires in the jest preprocessor https://github.com/facebook/react-native/blob/master/jest/preprocessor.js#L58

This is as far as I got. To get around the issue for now we are binding the methods in the constructor.

Everyone having this issue - go check out the link to find the solution. I didn't go and was not able to resolve it right away. Thanks!

@karanjthakkar
Copy link
Contributor

@kelset This is an issue in the latest 0.58.3 release as well.

Steps to reproduce:

  1. init a new project
  2. add a class property to App.js
  3. add a transform in the jest config in package.json which uses jest/preprocessor.js.
  4. Run npm test

Would you be happy to accept a fix that changes the inlineRequires flag to false in jest/preprocessor.js? Atleast until the plugin is fixed or the underlying issue which surfaced this in recent versions is discovered.

@kelset
Copy link
Contributor

kelset commented Feb 6, 2019

Would you be happy to accept a fix that changes the inlineRequires flag to false in jest/preprocessor.js?

Yeah I feel that by having a PR we can have a conversation with the FB team about it - because I think that the preprocessor is used around the internal codebase (but not sure atm).

@karanjthakkar
Copy link
Contributor

@kelset Just created a PR to start the conversation: #23326 🙂Thanks!

@Nick-Lucas
Copy link

Nick-Lucas commented Feb 15, 2019

+1 here, we're seeing this in some object-spread syntax which we refactored outside of a reducer.

Disabling inlineRequires also resolves the issue.

    TypeError: Cannot read property 'default' of undefined

      58 |     } = this.calculateNextSection(nextIndex)
      59 |
    > 60 |     return {
         |                       ^
      61 |       ...formSections,

RN 0.57.8

jest and babel-jest 23.6.0 and 24.1.0 both have this.

@kelset
Copy link
Contributor

kelset commented Mar 4, 2019

Quoting @cpojer's answer in @karanjthakkar's PR because it's important:

Unfortunately I don't think that's the right fix. We do use this internally all over Facebook and do not run into a similar issue, and inline requires is probably just exposing a problem that exists elsewhere. While it may be a short-term hotfix that people can apply, we don't want to disable this by default. I'm assuming the problem here is probably babel or some version of Jest :(

One thing that I have noticed is that for Components, adding

constructor(props) {
    super(props)
}

solved the issue (found here).

Not sure if we should keep this open since the proposed workaround above (disabling the inline) is not the right solution, and I feel that probably it's about code outside the main repo.

@olegongit
Copy link

@kelset, having your state defined in a constructor is not a workaround, it is just not using the static class properties feature of ES7.

Since using this feature is ok in react-native, one would like jest tests to embrace it. And this is what this bug is about.

Current workaround that we have employed is to use patch-package and just fix it inlineRequires, so that the tests work. But I don't think it qualifies as a proper solution to the issue...

@retyui
Copy link
Contributor

retyui commented Mar 14, 2019

@kelset kelset added the Issue: Author Provided Repro This issue can be reproduced in Snack or an attached project. label Mar 15, 2019
@steobrien
Copy link

In our upgrade from React Native 0.58.6 → 0.59.0 – a narrow set of changes based on https://github.com/react-native-community/rn-diff-purge – this has become an issue.

Example test failure:

● NotificationBanner › shows the notification

    TypeError: Cannot read property 'default' of undefined

      25 | |}>
      26 | 
    > 27 | class NotificationBanner extends React.Component<Props> {
         |                                                                                                                                                    ^
      28 |   static defaultProps = {
      29 |     notification: undefined,
      30 |     bottom: undefined,

      at new NotificationBanner (src/components/NotificationBanner/index.js:27:447)
      at constructClassInstance (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:3435:22)
      at updateClassComponent (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:6606:9)
      at beginWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:7563:20)
      at performUnitOfWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:11234:16)
      at workLoop (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:11266:28)
      at renderRoot (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:11349:11)
      at performWorkOnRoot (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:12237:11)
      at performWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:12149:11)
      at performSyncWork (node_modules/react-test-renderer/cjs/react-test-renderer.development.js:12123:7)

The constructor hack recommended in #22175 (comment) works.

@cpojer
Copy link
Contributor

cpojer commented Mar 20, 2019

I'm happy to fix this if somebody could make a minimal repo of a Jest+RN setup and share it here.

@retyui

This comment has been minimized.

@olegongit
Copy link

olegongit commented Mar 20, 2019

Good news guys, I have tried to create a simple example as @cpojer asked, but it works in 0.59.
I have tried with a class property state and a class property function.

Moreover I have tested and it worked in 0.58. It failed in 0.57.8 though and probably earlier, so it was actually an issue.

(edit: At least it is the case with default RN jest setup, i.e. without adding a custom transfrom.)

@cpojer
Copy link
Contributor

cpojer commented Mar 20, 2019

Yeah seems like this is only happening for configs that have this setting. It shouldn't be needed when the preset option is used.

@cpojer cpojer closed this as completed Mar 20, 2019
@dani-mp
Copy link

dani-mp commented Mar 20, 2019

So is it possible to make it work for 0.58.X? What changes should we make in the config? I'm afraid I didn't understand the fix.

@olegongit
Copy link

olegongit commented Mar 20, 2019

@danielmartinprieto try the following: in your package.json find the "jest" section and remove the "transform": { "^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js" } line.

It might be needed for some specific babel setup/presets though... so might need some more investigation.

@dani-mp
Copy link

dani-mp commented Mar 20, 2019

Thanks, @olegongit. We'll try that!

@dani-mp
Copy link

dani-mp commented Mar 21, 2019

Just confirming that for 0.58.x, removing the transform doesn’t work.

@adam-sajko
Copy link

adam-sajko commented Mar 27, 2019

transform: {
  '^.+\\.js$': '<rootDir>/jest/preprocessor.js',
},
/**
 * Your own [temporary?] transform for React Native
 */
const generate = require('@babel/generator').default
const transformer = require('metro-react-native-babel-transformer')
const createCacheKeyFunction = require('fbjs-scripts/jest/createCacheKeyFunction')
const metroBabelRegister = require('metro-babel-register')

metroBabelRegister([])

module.exports = {
  process(src, file) {
    const { ast } = transformer.transform({
      filename: file,
      options: {
        ast: true,
        dev: true,
        enableBabelRuntime: false,
        experimentalImportSupport: false,
        hot: false,
        inlineRequires: false,
        minify: false,
        platform: '',
        projectRoot: '',
        retainLines: true,
        sourceType: 'unambiguous',
      },
      src,
      plugins: metroBabelRegister.config.plugins,
    })

    return generate(
      ast,
      {
        code: true,
        comments: false,
        compact: false,
        filename: file,
        retainLines: true,
        sourceFileName: file,
        sourceMaps: true,
      },
      src,
    ).code
  },

  getCacheKey: createCacheKeyFunction([
    __filename,
    require.resolve('metro-react-native-babel-transformer'),
    require.resolve('@babel/core/package.json'),
  ]),
}

@Fausto95
Copy link

I can confirm, when upgrading to RN 0.59+ must remove the transform property from jest config file in order to avoid the error

@dani-mp
Copy link

dani-mp commented Apr 27, 2019

@Fausto95 thanks for the comment and for the reference to the PR where you did the upgrade! We couldn't make it work until I saw your changes, and I realised something: we were using since the beginning .babelrc instead of babel.config.js and TIL they're not interchangeable.

From https://babeljs.io/docs/en/configuration:

Configure Babel
Babel can be configured! Many other tools have similar configs: ESLint (.eslintrc), Prettier (.prettierrc).

All Babel API options are allowed. However, if the option requires JavaScript, you may want to use a JavaScript configuration file.

What's your use case?
You want to programmatically create the configuration?
You want to compile node_modules?
babel.config.js is for you!

You have a static configuration that only applies to your simple single package?
.babelrc is for you!

Have a nice weekend, y'all!

@evian-pring
Copy link

Great finding this thread, I just want to recap the solutions I've read so far.

I encountered this issue while trying to add a Jest test that uses react-test-renderer. I got the TypeError: Cannot read property 'default' of undefined error in react-native-vector-icons, at at new Icon (node_modules/react-native-vector-icons/lib/create-icon-set.js:42:389). This line defines a class with no constructor.

The first solution is adding a simple constructor to the above class, the error goes away.

Alternatively, to "solve" the issue I can remove the above constructor, but modify inlineRequires: true to inlineRequires: false in <rootDir>/node_modules/react-native/jest/preprocessor.js.

The third option is to go to my jest.config.js and remove the line '\\.js$': '<rootDir>/node_modules/react-native/jest/preprocessor.js', from the transform key.

@ronilitman
Copy link

@pro-nasa your solution is working for me, even though I did not fully understand what's going on over there. Are we waiting for a permanent solution from some specific 3rd party, or react-native itself?

Thank you!

chelseatroy added a commit to zooniverse/mobile that referenced this issue Jun 4, 2019
@a-x-
Copy link

a-x- commented Aug 16, 2019

I have a web project. After jest updating I has the same issue. I tried to find any inlineRequires, but I had not succeeded

@olethanh
Copy link

@a-x- inline requires should be in: node_modules/react-native/jest/preprocessor.js

I juste do a ugly sed -i -e 's/inlineRequires: true,/inlineRequires: false,/g' node_modules/react-native/jest/preprocessor.js in all my CI script at the moment

@arthwood
Copy link

arthwood commented Oct 9, 2019

I had the same error and none of the fixes worked for me:

  • adding constructor to node_modules/react-native-vector-icons/lib/create-icon-set.js
  • changing inlineRequires to false
  • I had no transform key specified in jest.config.js

It turned out I had a circular dependency in my components:
Component A was importing Component B via components/index (which in turn was exporting Component A)
Using relative import path fixed the error.

nuKs added a commit to pnplab/Flux that referenced this issue Oct 24, 2019
Attempt to fix jest test issue while keeping react native working by installing
c7b02730c762ab8bebe45fd57cd8ea69290e99ec rn commit

see issues:
facebook/react-native#22437
facebook/react-native#22175
nuKs added a commit to pnplab/Flux that referenced this issue Oct 24, 2019
Attempt to fix jest test issue while keeping react native working by installing
c7b02730c762ab8bebe45fd57cd8ea69290e99ec rn commit

see issues:
facebook/react-native#22437
facebook/react-native#22175

@warning
- jest integration tests have not been tested and might be broken due to
jest haste config removal (unlikely though).
- react-native app as not been tested (only tests) and might be broken
as well (at launch time).
- incompatibility issues may have appeared du to deprecation and
breaking changes (unlikely).
nuKs added a commit to pnplab/Flux that referenced this issue Oct 24, 2019
Attempt to fix jest test issue while keeping react native working by installing
c7b02730c762ab8bebe45fd57cd8ea69290e99ec rn commit

The attempt didn't work out as r-n refused the commit due to the
following comment:
facebook/react-native#23326 (comment)

See my comment here for correct fix patching react-native-vector-icons:
GeekyAnts/NativeBase#2657 (comment)

Original issues letting me to ugrade react-native:
facebook/react-native#22437
facebook/react-native#22175

@warning
- jest integration tests have not been tested and might be broken due to
jest haste config removal (unlikely though).
- react-native app as not been tested (only tests) and might be broken
as well (at launch time).
- incompatibility issues may have appeared du to deprecation and
breaking changes (unlikely).
nuKs added a commit to pnplab/Flux that referenced this issue Oct 24, 2019
Attempt to fix jest test issue while keeping react native working by installing
c7b02730c762ab8bebe45fd57cd8ea69290e99ec rn commit

The attempt didn't work out as r-n refused the commit due to the
following comment:
facebook/react-native#23326 (comment)

See my comment here for correct fix patching react-native-vector-icons:
GeekyAnts/NativeBase#2657 (comment)

Original issues letting me to ugrade react-native:
facebook/react-native#22437
facebook/react-native#22175

@warning
- jest integration tests have not been tested and might be broken due to
jest haste config removal (unlikely though).
- react-native app as not been tested (only tests) and might be broken
as well (at launch time).
- incompatibility issues may have appeared du to deprecation and
breaking changes (unlikely).
@facebook facebook locked as resolved and limited conversation to collaborators Mar 20, 2020
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Mar 20, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Bug Issue: Author Provided Repro This issue can be reproduced in Snack or an attached project. Priority: Mid Resolution: Locked This issue was locked by the bot. 🔩Test Infrastructure Test infrastructure and continuous integration.
Projects
None yet