Jest encountered an unexpected token when testing a Vue single file component - javascript

I have a vue application with single file components and i want to add unit tests to test the components. I'm trying to use jest like described here but i keep getting the error "Jest encountered an unexpected token" with the following details:
/some_path/MyRecipe.vue:1
<template>
^
SyntaxError: Unexpected token <
1 | import { shallowMount } from "#vue/test-utils"
> 2 | import MyRecipe from "../src/components/MyRecipe.vue"
| ^
3 |
4 | describe('MyRecipe', () => {
5 | test('is a Vue instance', () => {
at Runtime._execModule (node_modules/jest-runtime/build/index.js:1166:56)
at Object.<anonymous> (__tests__/MyRecipe.test.js:2:1)
After some research (e.g. from here) I gather that this is probably due to jest expecting a .js file, but the .vue single file components have html, javascript and css in them, usually dealt with by webpack and vue-loader. I've tried to follow jest configurations from various tutorials to make jest use vue-jest to transform .vue files, but the error persists. This is my package.json file (unnecessary parts removed):
{
"name": "all-recipes ",
"version": "0.1.0",
"private": true,
"scripts": {
// ...
"test": "jest"
},
"dependencies": {
// ...
"core-js": "^3.4.3",
"vue": "^2.6.10"
// ...
},
"devDependencies": {
"#vue/cli-plugin-babel": "^4.1.0",
"#vue/cli-plugin-eslint": "^4.1.0",
"#vue/cli-service": "^4.1.0",
"#vue/test-utils": "^1.0.3",
"babel-core": "^7.0.0-bridge.0",
"babel-eslint": "^10.0.3",
"babel-jest": "^26.0.1",
// ...
"jest": "^26.0.1",
"jest-serializer-vue": "^2.0.2",
"vue-jest": "^3.0.5",
"vue-template-compiler": "^2.6.10",
"vue-test-utils": "^1.0.0-beta.11"
},
// ...
"jest": {
"moduleFileExtensions": [
"js",
"json",
"vue"
],
"transform": {
".*\\.,(vue)$": "vue-jest",
"^.+\\.js$": "babel-jest"
},
"snapshotSerializers": [
"jest-serializer-vue"
]
}
}
Any idea what might be wrong, or some tips on how to debug this?
EDIT: I have looked into this question and I don't believe the answer there would solve my problem since what I am trying to import is a .vue file and not an .html file.
EDIT 2: I have a feeling that jest is somehow just not picking up the transforms, because removing them from package.json doesn't change anything.
EDIT 3: No, jest is correctly using vue-jest for transforming. If I uninstall vue-jest and try running the test again, jest complains that vue-jest is missing.

The solution to my problem turns out to be a bit anti-climatic.
The problem was that my regexp string to recognize .vue files was wrong and didn't pick up my MyRecipe.vue file. Therefore, vue-jest wasn't used to transform it for jest to interpret, hence the trouble understanding that the file in question started with a very non-js line; <template>. The regexp that works is ^[^.]+.vue$, so the transform section of my package.json file becomes
{
// ...
"jest": {
// ...
"transform": {
"^[^.]+.vue$": "vue-jest",
"^.+\\.js$": "babel-jest"
},
// ...
}
}

Met same issuesome time ago. What i found.
The problem was in the short note of template v-slot
template(v-slot:body)
It works to compile, but Jest throws an error
Jest encountered an unexpected token
This usually means that you are trying to import a file which Jest cannot 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.
There was two ways i fount to solve this:
Edit my jest.config.js, like this
globals: {
'vue-jest': {
pug: {
doctype: 'html',
},
},
},
Write a full note like this
template(v-slot:body="")

What worked for me was changing the transform of the vue-jest to what is shown in the documentation.
https://github.com/vuejs/vue-jest
so try using "^.+\\.vue$": "vue-jest" instead of "^[^.]+.vue$": "vue-jest"
full config might look like this
{
"jest": {
"moduleFileExtensions": ["js", "json", "vue"],
"transform": {
"^.+\\.js$": "babel-jest",
"^.+\\.vue$": "vue-jest"
}
}
}

I faced same issues tried many solution but none of them work ..below is following workaround in my case
Check package json has following dev dependency entries and jest configurations
"devDependencies": {
"babel-jest": "^23.6.0",
"#vue/cli-plugin-babel": "~4.5.0",
"#vue/cli-plugin-eslint": "~4.5.0",
"#vue/cli-plugin-unit-jest": "~4.5.0",
"#vue/cli-service": "~4.5.0",
"#vue/eslint-config-airbnb": "^5.0.2",
"#vue/test-utils": "^1.0.3",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-import": "^2.20.2",
"eslint-plugin-vue": "^6.2.2",
},
"jest": {
"moduleFileExtensions": [
"js",
"jsx",
"json",
"vue"
],
"transform": {
"^.+\\.vue$": "vue-jest"
},
"moduleNameMapper": {
"^#/(.*)$": "<rootDir>/src/$1"
},
"snapshotSerializers": [
"jest-serializer-vue"
],
"testMatch": [
"**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.
(js|jsx|ts|tsx)"
],
"testURL": "http://localhost/"
}
Check babel.config.js
module.exports = {
presets: [
'#vue/cli-plugin-babel/preset',
],
};
check jest.config.js
module.exports = {
preset: '#vue/cli-plugin-unit-jest',
};

You need to install vue-jest (https://github.com/vuejs/vue-jest) with
npm install -D #vue/vue3-jest
Here are the available versions and their corresponding vue and jest versions
Vue version
Jest Version
Package
Vue 2
Jest <= 26
vue-jest#4
Vue 3
Jest <= 26
vue-jest#5
Vue 2
Jest 27
#vue/vue2-jest
Vue 3
Jest 27
#vue/vue3-jest
Then, you'll just have to update your jest configuration (in jest.config.ts for example) and add a transform section
"transform": {
"^.+\\.vue$": "#vue/vue3-jest"
}
Warning: be sure to update the npm install and the jest.config.ts with the vue-jest package that match your need!

Related

Error TS2305: Module #types/angular has no exported member 'cookies'

I am having an issue with cookies not being defined in angular scope.
npm run start builds and starts the app just fine,
but when trying to run npm test that executes jest command, I am getting this error:
`Test suite failed to run app/components/Component1/Component1.ts:1:10
error TS2305: Module '"../../../../../node_modules/#types/angular"' has no exported member 'cookies'.`
in Component1.ts there is this import: import { cookies } from 'angular';
Build and run - ok.
Testing - not ok.
If you know where the issue can be hidden, please help :) Thank you.
my package.json:
{
"dependencies": {
...,
"angular": "^1.8.0",
"angular-cookies": "1.8.0",
"babel-polyfill": "^6.2.0",
...
},
"devDependencies": {
"#types/angular": "^1.8.0",
"#types/angular-cookies": "^1.8.0",
"#types/jest": "^26.0.19",
"angular-mock": "^1.0.0",
"angular-mocks": "^1.8.2",
"angularjs-jest": "^0.1.4",
"babel-core": "^6.24.1",
"babel-loader": "^7.0.0",
"jest": "^26.6.3",
"ts-jest": "^26.4.4",
...
}
}
solution for my issue was adding angular-cookies to tsconfig.test.json file.
I still do not understand why angular-cookies since source code and production build is taking types and definitions from angular package (and through IDE I can link to angular module rather than angular-cookies).
But that's life is all about - mysteries.
{
"extends": "./tsconfig.json",
"compilerOptions": {
"types": [
"node",
"jest",
"angular-cookies" --> THIS VERY LINE SOLVED MY ISSUE
]
},
"include": [
"index.d.ts",
"**/*.test.ts"
]
}

Cannot resolve module while trying to organize modules in React Native

I'm new to React Native and am trying to organize my React Native classes into modules to get rid of the "import from '../../../" mess. Here's my very simple folder structure:
Following the tutorial at here, I've structured my package.json as this for each folder:
{
"name": "#foldername"
}
Now, I'm trying to import Page (which is just a component superclass at this time, exported as default in the file):
import Page from '#app/components/core';
But it cannot be resolved. I've also tried:
import Page from '#app/#components/#core';
import { Page } from '#app/#components/#core';
import { Page } from '#app/components/core';
import { Page } from 'app/components/core';
None of them seem to be working. I've also tried them all without the # sign (removing it from both the package files and import statement), but no avail.
How can I organize my components to work that way (and it would be great if I knew what that # sign in front does, as I've also seen some tutorials without it)?
Here is my package.json in my root folder if it helps (haven't touched it, it's the way created by react-native init):
{
"name": "redacted",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",
"test": "jest"
},
"dependencies": {
"react": "16.8.3",
"react-native": "0.59.3"
},
"devDependencies": {
"#babel/core": "^7.4.0",
"#babel/runtime": "^7.4.2",
"babel-jest": "^24.5.0",
"jest": "^24.5.0",
"metro-react-native-babel-preset": "^0.53.1",
"react-test-renderer": "16.8.3"
},
"jest": {
"preset": "react-native"
}
}
add babel-plugin-module-resolver to devDependencies.
If you have .babelrc just delete it and add babel.config.js. And add aliases there. It should look like this
function babelConfig(api) {
if (api) {
api.cache(false);
}
const presets = ['module:metro-react-native-babel-preset'];
const plugins = [
[
'module-resolver',
{
alias: {
appColors: './src/Colors',
appConstants: './src/Constants',
components: './src/Components',
screens: './src/Screens',
utils: './src/utils'
},
cwd: 'babelrc'
}
]
];
return {
presets,
plugins
};
}
module.exports = babelConfig;
Then you can use import like this
import { YourComonent } from 'components';
make sure you have exported as default.
Also, don't try to set the alias names with capital letters
This works with the latest react-native (0.59.3).
Here is my devDependencies
devDependencies": {
"#babel/core": "7.4.0",
"#babel/runtime": "7.4.2",
"#react-native-community/eslint-config": "0.0.3",
"babel-eslint": "8.2.2",
"babel-jest": "24.5.0",
"babel-plugin-module-resolver": "^3.2.0",
"enzyme": "^3.9.0",
"enzyme-adapter-react-16": "^1.10.0",
"enzyme-to-json": "^3.3.5",
"eslint": "5.15.3",
"eslint-config-airbnb": "16.1.0",
"eslint-plugin-import": "2.12.0",
"eslint-plugin-jsx-a11y": "6.0.3",
"eslint-plugin-react": "7.9.1",
"eslint-plugin-react-native": "3.2.1",
"jest": "24.5.0",
"metro-react-native-babel-preset": "0.53.1",
"react-test-renderer": "16.8.3"
},
If you're using VSCode, Intellisense of the IDE does not recognise just the package.json; include a tsconfig/jsconfig JSON file (TypeScript [ftw]/ JavaScript)
In compilerOptions add :
"paths" : {
"#alias1*" : ["./alias1/*"],
.....
}
For all your aliases. Then the editor should pick up your files.
https://code.visualstudio.com/docs/languages/jsconfig
If you choose not to use VSCode, use Babel:
If your project doesn’t use Webpack - for example if you’re working with React Native, you can use your .babelrc file and a babel plugin to get aliasing set up.
Firstly, you’ll want to install babel-plugin-module-resolver with yarn or npm.
Once you’ve done that, open up your project’s .babelrc file, and under the plugins key, add this:
[
'module-resolver',
{
root: ['./src'],
alias: {
myAlias: './src',
},
},
];
Or use the package.json in root
It was my bad.
Instead of using it like:
import MyComponent from 'package/path/MyComponent'
I was using:
import MyComponent from 'package/path' (without my class file at the end).
I've imported it correctly (also removed the app package and the # prefixes and directly referenced components as a package in its package.json file) (including the component name):
import Page from 'components/core/Page';
It worked perfectly.
In tsconfig.json, add the following :
"compilerOptions": {
"baseUrl": "app"
...
}

Babel 7 - ReferenceError: regeneratorRuntime is not defined

I have an application that is a node backend and a react frontend.
I get the following error when i try to build/run my node application.
Node: v10.13.0
Error:
dist/index.js:314
regeneratorRuntime.mark(function _callee(productId) {
^
ReferenceError: regeneratorRuntime is not defined
.babelrc
{
"presets": [ [
"#babel/preset-env", {
"targets": {
"node": "current"
},
}
], "#babel/preset-react"],
"plugins": [
"#babel/plugin-proposal-class-properties"
]
}
webpack.config.js
{
mode: "development",
entry: "./src/index.js",
target: "node",
externals: [nodeExternals()], // in order to ignore all modules in node_modules folder
stats: {
colors: true
},
devtool: "source-map",
output: {
path: path.resolve(__dirname, "dist"),
filename: "index.js",
sourceMapFilename: "index.js.map"
},
module: {
rules: [
{
enforce: "pre",
test: /\.js$/,
exclude: /node_modules/,
loader: "eslint-loader",
},
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: "babel-loader",
options: {
presets: ["#babel/preset-env"]
}
}
}
],
},
node: {
__dirname: false,
__filename: false,
},
"plugins": [
new CleanWebpackPlugin(),
new WebpackShellPlugin({
onBuildStart: [],
onBuildEnd: ["nodemon dist/index.js"]
}),
]
},
package.json
"dependencies": {
"connect": "^3.6.6",
"cors": "^2.8.5",
"dotenv": "^6.1.0",
"express": "^4.16.4",
"hellojs": "^1.17.1",
"i18n-iso-countries": "^3.7.8",
"morgan": "^1.9.1",
"react": "^16.6.3",
"react-dom": "^16.6.3",
"request": "^2.88.0",
"request-promise-native": "^1.0.5",
"serve-static": "^1.13.2",
"vhost": "^3.0.2"
},
"devDependencies": {
"#babel/cli": "^7.1.5",
"#babel/core": "^7.1.6",
"#babel/plugin-proposal-class-properties": "^7.1.0",
"#babel/preset-env": "^7.1.6",
"#babel/preset-react": "^7.0.0",
"babel-eslint": "^10.0.1",
"babel-loader": "^8.0.4",
"clean-webpack-plugin": "^1.0.0",
"copy-webpack-plugin": "^4.6.0",
"css-loader": "^1.0.1",
"eslint": "^5.9.0",
"eslint-config-google": "^0.10.0",
"eslint-loader": "^2.1.1",
"eslint-plugin-react": "^7.11.1",
"extract-loader": "^3.0.0",
"file-loader": "^2.0.0",
"node-sass": "^4.10.0",
"sass-loader": "^7.1.0",
"style-loader": "^0.23.1",
"webpack": "^4.26.0",
"webpack-cli": "^3.1.2",
"webpack-node-externals": "^1.7.2",
"webpack-shell-plugin": "^0.5.0"
}
Updated Answer:
If you are using Babel 7.4.0 or newer, then #babel/polyfill has been deprecated. Instead, you will want to use the following at the top of your main js file (likely index.js or similar):
import "core-js/stable";
import "regenerator-runtime/runtime";
Install these packages either with npm:
npm install --save core-js
npm install --save regenerator-runtime
or with yarn:
yarn add core-js
yarn add regenerator-runtime
Original Answer:
I just encountered this problem and came across the following solution:
In package.json I had #babel/polyfill as a dependency. However, in my index.js (My main js file) I had neglected to place the following line at the the top:
import '#babel/polyfill'
Once I imported it, everything worked fine.
I did not need to install babel-runtime as other answers are suggesting.
Babel 7.4.0 and later
There are two main configurations - one for apps and one for libraries.
Option 1: App
When to use: ✔ for applications ✔ global scope polyfills ✔ smallest bundle size ✔ selective inclusion via targets ✔ No need to process node_modules for polyfills
"presets": [
[
"#babel/preset-env",
{
"useBuiltIns": "usage", // alternative mode: "entry"
"corejs": 3, // default would be 2
"targets": "> 0.25%, not dead"
// set your own target environment here (see Browserslist)
}
]
]
Install dependencies:
npm i --save-dev #babel/preset-env
npm i regenerator-runtime core-js // run-time dependencies
// regenerator-runtime: transform (async) generators and `async`/`await`
// core-js: other ECMAScript features like Promise, Set, etc.
#babel/preset-env selectively includes polyfills for targets, specified by a Browserslist query. There are two modes - try usage first (more convenient), else entry (more flexible and robust):
useBuiltIns 'usage': no need to import anything manually. All polyfills are added automatically based on their code usage in a file.
useBuiltIns 'entry': Add these import entries once (!) in your app - akin to #babel/polyfill:
import "regenerator-runtime/runtime";
import "core-js/stable"; // or more selective import, like "core-js/es/array"
Extension
For advanced cases, you might use #babel/transform-runtime (dev) and #babel/runtime (run-time) only for Babel helpers to reduce bundle size a bit more - called helper aliasing.
Option 2: Library
When to use: ✔ for libraries ✔ no global scope pollution ✔ includes all polyfills, not selective ✔ bigger bundle size neglectable
"plugins": [
[
"#babel/plugin-transform-runtime",
{
"regenerator": true,
"corejs": 3
}
]
]
Install compile-time and run-time dependencies:
npm i --save-dev #babel/plugin-transform-runtime // only for build phase
npm i #babel/runtime // runtime babel helpers + just regenerator runtime
// OR (choose one!)
npm i #babel/runtime-corejs3
// also contains other JS polyfills (not only regenerator runtime)
// depends on core-js-pure ("ponyfills"/polyfills that don't pollute global scope)
See #babel/plugin-transform-runtime, #babel/runtime, #babel/runtime-corejs.
Extension
You can additionally use #babel/preset-env for syntax transpilation only, with useBuiltIns: false. As the library option does not use global polyfills, you might want to transpile node_modules as well - see the absoluteRuntime option.
Closing notes
Breaking Change: #babel/polyfill is deprecated starting with Babel 7.4.0.
Legacy: If you can't switch to core-js#3, set corejs option to 2 (see migrations). Install #babel/runtime-corejs2 in case of option 2 (#babel/plugin-transform-runtime).
Excellent summary in #9853 by Jovica Markoski
Currently, the library approach doesn't take selective targets into account - meaning you take locally scoped polyfills at the price of bigger bundle size (including all polyfills).
babel-polyfills is a new, experimental approach to inject different polyfills (not just core-js) with different strategies.
This also allows to selectively include locally scoped polyfills.
There is already a very good answer here (originally posted on the Babel6 question) which I will just translate to Yarn. Basically, you need babel runtime (NOT as a dev dependency) and the plugin transform-runtime
yarn add #babel/runtime
yarn add -D #babel/plugin-transform-runtime
And, in .babelrc, add:
{
"presets": ["#babel/preset-env"],
"plugins": ["#babel/transform-runtime"]
}
I had this error in my react project with webpack 4 and this was preventing the whole project to get rendered.
This is how I solved it:
Install plugin-transform-runtime:
npm install #babel/plugin-transform-runtime -D
Add plugin-transform-runtime to the plugin's list in the .babelrc file:
{
"presets": [
"#babel/preset-env",
"#babel/preset-react"
],
"plugins": [
["#babel/transform-runtime"] // <= Add it here
]
}
For me worked:
module.exports = {
presets: [
[
'#babel/preset-env',
{
targets: {
esmodules: true,
},
},
],
],
}
I just solved this error when I imported babel-polyfill directly into the file that shows the error, for example, the error says "ReferenceError: regeneratorRuntime is not defined at /dist/models/usersSchema.js", so I use this in my usersSchema.js file:
require("babel-polyfill");
(you can use import "babel-polyfill";as well)
You will need to have the regeneratorRuntime.
Install this two packages - babel-plugin-transform-regenerator and babel-polyfill
Add the following Babel configuration via .babelrc
{
"plugins": ["transform-regenerator"]
}
React.js Users
If this issue faced you while using react (specifically while trying to use Async/Wait), then Valentino Gagliardi provided a detailed approach on his blog regarding how to address this issue

JEST test not understanding import statement

Im using JEST to test my app. But Im getting an error from the test file --
import xyz from './XYZ.js';
^^^^^^
SyntaxError: Unexpected token import
Then I created a .babelrc file and it has the following code --
{
"presets": [
"es2015"
]
}
After this, whichever file I have imported in the test file does not throw this error. But if one of the imported files (like XYZ.js) have import statement in itself, then it gives the same error on that file.
My package.json devDependencies (significant packages) --
"devDependencies": {
"babel-jest": "^19.0.0",
"babel-preset-es2015": "^6.22.0",
"eslint": "2.0.0",
"eslint-plugin-react": "latest",
"express": "^4.12.2",
"jest": "^19.0.1",
"react": "^15.3.2",
"react-dom": "^15.3.2",
"react-router": "^2.8.1"
},
Can anyone point out what I have missed?
Try using
import { xyz } from './XYZ.js';
Also make sure you exported the module
export function xyz() {}
And check out Babel stage-0

Karma+Mocha+Browserify+ES6 testing stack setup problems

I am trying to create a testable front-end project along these guidelines:
React component architecture with __test__ folders in each component folder;
tests use ES6 modules;
browserify bundles everything into one file while babelify transpiles ES6;
karma uses the bundle for testing.
This is my karma.conf.js:
module.exports = function (karma) {
const testFiles = __dirname + '/proj/static/src/**/__tests__/*.js';
karma.set({
frameworks: ['browserify', 'mocha'],
browsers: ['Chrome'],
files: [
testFiles
],
logLevel: 'LOG_DEBUG',
preprocessors: {
testFiles: ['browserify'],
},
reporters: ['dots'],
singleRun: true,
browserify: {
debug: true,
transform: [ 'babelify' ]
},
});
};
This is my .babelrc
{
presets: ['es2015', 'react']
}
However, after launching karma, I get this error:
...
Uncaught SyntaxError: Unexpected token import
at proj/static/src/js/some-component/__tests__/some.test.js:1
Clearly the code doesn't get transpiled. I've read multiple tutorials, and all use different technologies. Any ideas how to fix the problem?
P.S. I am still very fresh with TDD in the front-end.
Edit
These are the installed npm dependencies:
"babel-preset-es2015": "^6.18.0",
"babel-preset-react": "^6.16.0",
"babelify": "^7.3.0",
"browserify": "^13.1.1",
"expect": "^1.20.2",
"karma": "^1.3.0",
"karma-browserify": "^5.1.0",
"karma-chrome-launcher": "^2.0.0",
"karma-cli": "^1.0.1",
"karma-mocha": "^1.3.0",
"mocha": "^3.1.2",
"reactify": "^1.1.1",
"watchify": "^3.7.0"
The problem is that testFiles is the value of the key in the preprocessors configuration. You need the value of the key to be a glob that matches the files that are to be preprocessed. No files are being matched, so no files are being preprocessed.
I would try this:
preprocessors: {
'**/*.js': ['browserify']
}
Your question doesn't go into detail about your project's directory structure, so I've suggested a glob that matches all .js files. You could refine it to match only your source files that need to be transpiled.
Be aware that the glob will need to match all of your source files - not just the tests.

Categories

Resources