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

React Native - SyntaxError: Unexpected token import #604

Closed
nicolashemonic opened this issue Jul 3, 2018 · 13 comments
Closed

React Native - SyntaxError: Unexpected token import #604

nicolashemonic opened this issue Jul 3, 2018 · 13 comments

Comments

@nicolashemonic
Copy link

Issue

SyntaxError: Unexpected token import

Jest throw an error when he try to parse React Navigation package who has ES2015 imports.

Expected behavior

Following dedicated React Native documentation and ES2015 documentation I expect that .js files under node_modules to be processed by babel-jest.

Jest config

module.exports = {
	preset: "react-native",
	transform: {
		"^.+\\.jsx?$": "<rootDir>/node_modules/babel-jest",
		"^.+\\.tsx?$": "ts-jest"
	},
	testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
	moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
	globals: {
		"ts-jest": {
			useBabelrc: true
		}
	}
};

Babel config

{
	"presets": ["react-native"],
	"sourceMaps": "inline"
}

Error

    /Users/nicolas/Projects/react-native-typescript/node_modules/react-navigation/src/navigators/createStackNavigator.js:1
    ({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import React from 'react';
                                                                                             ^^^^^^

Example

You can find an example with a simple test.

Thanks !

@duro
Copy link

duro commented Jul 6, 2018

I am having the same issue. Started happening when I tried to upgrade to RN 0.56

@mattyclarkson
Copy link

What version of Babel are you using? Babel 7 now handles .babelrc files different (i.e. doesn't handle them). See jestjs/jest#6229. This means that the instructions for setting up ts-jest with React Native and Babel 7 do not work. The workaround to change .babelrc to babel.config.js doesn't work for me.

@w3z315
Copy link

w3z315 commented Aug 15, 2018

Also see my comment in jestjs/jest#6229

@mattyclarkson
Copy link

mattyclarkson commented Aug 17, 2018

@huafu, @kulshekhar this is blocking me use ts-jest ^23 with any of our React Native projects. I'm happy to investigate this if you can point me in the right direction?

You can reproduce it on ef-carbon/react-native-async-button.

Upgrading ts-jest to ^23 results in the following error when yarn test is ran:

 FAIL  test/ContextAsyncButton.test.tsx
  ● Test suite failed to run

    TypeError: Cannot read property 'bindings' of null

      at Scope.moveBindingTo (node_modules/@babel/core/node_modules/@babel/t
raverse/lib/scope/index.js:869:13)
      at BlockScoping.updateScopeInfo (node_modules/babel-plugin-transform-e
s2015-block-scoping/lib/index.js:364:17)
      at BlockScoping.run (node_modules/babel-plugin-transform-es2015-block-scoping/lib/index.js:330:12)
      at PluginPass.BlockStatementSwitchStatementProgram (node_modules/babel-plugin-transform-es2015-block-scoping/lib/index.js:70:24)
      at newFn (node_modules/@babel/core/node_modules/@babel/traverse/lib/visitors.js:193:21)
      at NodePath._call (node_modules/@babel/core/node_modules/@babel/traverse/lib/path/context.js:53:20)
      at NodePath.call (node_modules/@babel/core/node_modules/@babel/traverse/lib/path/context.js:40:17)
      at NodePath.visit (node_modules/@babel/core/node_modules/@babel/traverse/lib/path/context.js:88:12)
      at TraversalContext.visitQueue (node_modules/@babel/core/node_modules/@babel/traverse/lib/context.js:118:16)
      at TraversalContext.visitSingle (node_modules/@babel/core/node_modules/@babel/traverse/lib/context.js:90:19)

I assume this is because something in ts-jest is loading Babel 7, but something else expects Babel 6. If I upgrade babel-core to 7.0.0-bridge.0. Still get the same error, so upgrade babel-preset-react-native. I then start getting the SyntaxError as stated:

 FAIL  test/ContextAsyncButton.test.tsx
  ● Test suite failed to run

    Jest encountered an unexpected token

    This usually means that you are trying to import a file which Jest canno
t parse, e.g. it's not plain JavaScript.

    By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

    Here's what you can do:
     • 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/en/configuration.html

    Details:

    SyntaxError: /Users/mattyclarkson/git/github/ef-carbon/react-native-async-button/node_modules/react-native/Libraries/StyleSheet/StyleSheet.js: Unexpected token (18:12)

      16 | const flatten = require('flattenStyle');
      17 |
    > 18 | import type {
         |             ^
      19 |   ____Styles_Internal,
      20 |   ____DangerouslyImpreciseStyle_Internal,
      21 |   ____DangerouslyImpreciseStyleProp_Internal,

      at Parser.raise (node_modules/@babel/core/node_modules/babylon/lib/index.js:776:15)
      at Parser.unexpected (node_modules/@babel/core/node_modules/babylon/lib/index.js:2079:16)
      at Parser.expectContextual (node_modules/@babel/core/node_modules/babylon/lib/index.js:2047:41)
      at Parser.parseImport (node_modules/@babel/core/node_modules/babylon/lib/index.js:5205:12)
      at Parser.parseStatementContent (node_modules/@babel/core/node_modules/babylon/lib/index.js:4043:27)
      at Parser.parseStatement (node_modules/@babel/core/node_modules/babylon/lib/index.js:3962:17)
      at Parser.parseBlockOrModuleBlockBody (node_modules/@babel/core/node_modules/babylon/lib/index.js:4513:23)
      at Parser.parseBlockBody (node_modules/@babel/core/node_modules/babylon/lib/index.js:4500:10)
      at Parser.parseTopLevel (node_modules/@babel/core/node_modules/babylon/lib/index.js:3938:10)
      at Parser.parse (node_modules/@babel/core/node_modules/babylon/lib/index.js:5304:17)

So I then add the following to the jest configuration:

    "transformIgnorePatterns": [
      "/node_modules/(?!react-native).+\\.js$"
    ],

Still get the same error. I've tried all kinds of different transform patterns and other fruitless investigation.

Not sure if this is a problem with ts-jest anymore or it's a result of babel-preset-react-native. Or if I should be using babel-preset-env instead.

@huafu
Copy link
Collaborator

huafu commented Aug 17, 2018

Thank @mattyclarkson for the investigation. Here is some quick info I can give you know:

First of all, when you try something else, be sure to run jest --clearCache to ensure jest will run with the new settings/packages. I've reported the bug in jest, jest --no-cache does use some of the cache so it's safer to jest --clearCache.

For babel, if you install babel 7, ts-jest will use it. Else it'll use the 6.

For the repository link you gave, it's pointing to a no more existing hash. If the issue is in the master of this repo as well, lemme know and I'll try to investigate when I'll have a bit more time.

@mattyclarkson
Copy link

Ooo, thanks for the tip. That helps.

I've updated the link in the above comment, it was suppose to just point at master, sorry about that 🤦‍♂️ . It's also here for convienence.

@huafu
Copy link
Collaborator

huafu commented Aug 17, 2018

I wrote step by step what I did, maybe it could help you investigate later some other bugs:

  • I removed babel-core, @babel/core and babel-jest to be sure jest will use the defaults sipped with it.
  • I upgraded ts-jest (it was 22).
  • I ran yarn why @babel/core to see if it was still installed, and if so why. Turns out babel 7 WILL be chosen and installed because of react-native (@babel/core => metro => react-native).
  • I finally ran the tests to see what was going on
  • Issue is in a babel AST transformer's visitor, so it's a babel plugin visiting each node of the JS AST to do some modifications: babel-plugin-transform-es2015-block-scoping. It's trying to move a let to parent scope which apparently doesn't exist.
  • I put a breakpoint to see why exactly, as this plugin ships with babel and should work out of the box (I use ndb for debugging, it's the easiest and coolest tool to debug a NodeJS app, especially when it's one having child-processes)
  • ...
  • At the end this plugin is part of the transformation from es2015+ to es5, so I changed the target in test/tsconfig.json to es5, so that this part of the process would be done by TypeScript and not babel. It's weird, but it sounds like a babel 7 bug, or maybe a bug due to the combination of some babel plugins.
  • 🎉 Test were running but I got millions of deprecation from babel related to its plugins
  • ...
  • I then did something I should have done earlier 🤪, searched babel-plugin-transform-es2015-block-scoping in babel issues and boom [Bug] plugin-transform-block-scoping: Cannot read property 'bindings' of null babel/babel#7627 (comment)
  • what's the preset in .babelrc which is bringing some v6 plugins? oh react-native
  • searched in babel-preset-react-native issues and found this: Can't run jest tests with 0.56.0 facebook/react-native#19859
  • so I installed [email protected] and @babel/core (yes, back in for this last one, I shouldn't have removed it...)
  • it's complaining about babel-jest now, ok I shouldn't have removed that one too
  • oh I am at the same point of you Jest encountered an unexpected token!
  • added the right regexp to jest config:
    transformIgnorePatterns: [
      "<rootDir>/node_modules/react-native/.+"
    ]
  • OMFG there is some flow in there node_modules/react-native/Libraries/StyleSheet/StyleSheet.js
  • yarn add --dev @babel/preset-flow
  • update the presets array of .babelrc to prepend with @babel/preset-flow
  • sounds like the preset did not change anything, flow typings is still in there...

My time on this is over sorry, I'll let you follow here, maybe tomorrow or another day if you still stuck I'll continue to drop an eye, I hope these last few steps will help you

@huafu
Copy link
Collaborator

huafu commented Aug 17, 2018

Oh @mattyclarkson look at this facebook/react-native#19859 (comment)

Also something to note: removing all node_modules and re-running yarn is sometimes good thing to do after messing up with multiple yarn add ... and yarn remove ...

@huafu
Copy link
Collaborator

huafu commented Aug 17, 2018

Ahhhhh I must be too tired, going back to my project I realized I made a mistake in the ignore pattern...

  • added the right regexp to jest config:

no, it was wrong! So I fixed it:

  transformIgnorePatterns: [
    "/node_modules/(?!react-native)/.+"
  ]

...because yeah, we want ti to NOT ignore processing the react-native's files

Now it complains about some React thing, so there you go that's not for me :-D

console.error node_modules/fbjs/lib/warning.js:33
      Warning: AsyncButton(...): No `render` method found on the returned component instance: you may have forgotten to define `render`.
    console.error node_modules/react-test-renderer/cjs/react-test-renderer.development.js:6309
      The above error occurred in the <AsyncButton> component:
          in AsyncButton
...

@mattyclarkson if you find out it's related to ts-jest, please re-open this issue.

For others landing here, you might be interested in:
babel/babel#7627 (comment) and facebook/react-native#19859 (comment)

@NachoJusticia
Copy link

See https://stackoverflow.com/questions/52188246/jest-encountered-an-unexpected-token-with-react-native

@nicolashemonic
Copy link
Author

nicolashemonic commented Apr 9, 2019

Finally works fine!

Jest config in package.json:

{
	"devDependencies": {
		"babel-jest": "^23.6.0",
		"jest": "^23.6.0",
		"ts-jest": "^23.1.4",
		"typescript": "^3.2.1"
		...
	},
	"jest": {
		preset: "react-native",
		transform: {
			"^.+\\.jsx?$": "<rootDir>/node_modules/react-native/jest/preprocessor.js",
			"^.+\\.tsx?$": "ts-jest"
		},
		testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
		moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
		globals: {
			"ts-jest": {
				"tsConfigFile": "tsconfig.jest.json"
			}
		}
	}
	...
}

TS config in tsconfig.json:

{
	"compilerOptions": {
		// https://blogs.msdn.microsoft.com/typescript/2018/08/27/typescript-and-babel-7/
		"target": "esnext",
		"moduleResolution": "node",
		"allowJs": true,
		"noEmit": true,
		"isolatedModules": true,
		"esModuleInterop": true,
		"noImplicitAny": true,
		"allowSyntheticDefaultImports": true,
		"jsx": "react-native",
		"lib": [
			"esnext"
		],
		"types": [ // fix declaration collision between react-native and ts-jest
			"react",
			"react-native",
			"react-redux",
			"redux"
			...
		]
	},
	"include": [
		"src"
	]
}

TS config in tsconfig.jest.json:

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

Babel config in .babelrc:

{
	"presets": [
		"module:metro-react-native-babel-preset"
	],
	"env": {
		"test": {
			"presets": [
				"react-native",
				[
					"@babel/preset-env"
				]
			]
		}
	}
}

Thanks 🙏

@ghost
Copy link

ghost commented Jul 17, 2019

@tr3v3r
Copy link

tr3v3r commented Jan 29, 2021

This answer saved my life!:

https://stackoverflow.com/questions/52188246/jest-encountered-an-unexpected-token-with-react-native/52189249#52189249?newreg=7aeb05c2f28e4d3b8b88c796000ec441

 "transform": {
      "^.+\\.ts?$": "ts-jest",
      "^.+\\.tsx?$": "ts-jest",
      "^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js" <--- over here
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants