My project is Vue 2.x. I am using @babel/plugin-proposal-optional-chaining
and I have a line of code in my component.vue file that uses "?"
this.$refs.refreshBtn?.$el.addEventListener("animationend", _ => { ... });
which works well when run the app. However, my unit tests are failing because it cannot recognize the token "?"
unknown: Unexpected token (149:26)
Jest encountered an unexpected token
......
......
......
Details:
147 |
148 |
> 149 | this.$refs.refreshBtn?.$el.addEventListener("animationend", _ => {
| ^
150 | this.refreshClicked = false;
151 | });
152 |
my babel.config.js
module.exports = {
presets: [
[
'@vue/app',
{
useBuiltIns: "entry",
}
],
],
plugins: [
'@babel/plugin-proposal-optional-chaining'
],
sourceType: 'unambiguous'
};
my partial package.json
:
"scripts": {
"test:unit": "vue-cli-service test:unit --no-cache"
},
"dependencies": {
"@casl/ability": "^2.5.1",
"@casl/vue": "^0.2.0"
"axios": "^0.18.1",
"babel-polyfill": "^6.26.0",
"base64-js": "^1.3.0",
"commonjs": "0.0.1",
"echarts": "^4.2.0-rc.2",
"element-ui": "^2.4.4",
"eureka-js-client": "^4.4.1",
"express": "^4.16.3",
"express-actuator": "^1.1.0",
"google-protobuf": "3.6.1",
"grpc": "^1.22.2",
"gsap": "^1.20.4",
"jasmine-core": "^3.2.1",
"jest-junit": "^4.0.0",
"js-cookie": "^2.2.0",
"lodash": "^4.17.15",
"material-design-icons": "^3.0.1",
"moment": "^2.22.2",
"moment-timezone": "^0.5.21",
"normalize.css": "^8.0.0",
"npm": "^6.4.1",
"nprogress": "^0.2.0",
"platform": "^1.3.5",
"requirejs": "^2.3.5",
"sjcl": "^1.0.8",
"uuid": "^3.3.2",
"vue": "^2.5.21",
"vue-acl": "^3.0.4",
"vue-animate-number": "^0.4.2",
"vue-content-loader": "^0.2.1",
"vue-echarts": "^3.1.3",
"vue-echarts-v3": "^1.0.19",
"vue-material": "^1.0.0-beta-10.1",
"vue-router": "^3.0.1",
"vue-toasted": "^1.1.24",
"vue2-dropzone": "^3.5.2",
"vuex": "^3.0.1",
"vuex-persistedstate": "^2.5.2"
},
"devDependencies": {
"@babel/plugin-proposal-optional-chaining": "^7.2.0",
"@vue/cli-plugin-babel": "^3.9.2",
"@vue/cli-plugin-e2e-nightwatch": "^3.9.2",
"@vue/cli-plugin-eslint": "^3.9.2",
"@vue/cli-plugin-unit-jest": "^3.9.0",
"@vue/cli-service": "^3.9.3",
"@vue/test-utils": "^1.0.0-beta.25",
"autoprefixer": "^7.1.2",
"babel-core": "7.0.0-bridge.0",
"babel-eslint": "^10.0.1",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-jest": "^23.6.0",
"babel-loader": "^7.1.1",
"babel-plugin-add-module-exports": "^0.2.1",
"babel-plugin-dynamic-import-node": "^1.2.0",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-plugin-transform-vue-jsx": "^3.5.0",
"babel-preset-env": "^1.3.2",
"babel-preset-es2015": "^6.24.1",
"babel-preset-stage-2": "^6.22.0",
"babel-register": "^6.22.0",
"chalk": "^2.0.1",
"chromedriver": "^76.0.0",
"copy-webpack-plugin": "^4.0.1",
"cross-spawn": "^5.0.1",
"csp-html-webpack-plugin": "^2.4.0",
"css-loader": "^0.28.0",
"detect-browser": "^2.5.1",
"eslint": "^5.8.0",
"eslint-config-google": "^0.9.1",
"eslint-config-standard": "^10.2.1",
"eslint-friendly-formatter": "^3.0.0",
"eslint-loader": "^1.7.1",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-node": "^5.2.0",
"eslint-plugin-promise": "^3.4.0",
"eslint-plugin-standard": "^3.0.1",
"eslint-plugin-vue": "^5.0.0",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^1.1.4",
"friendly-errors-webpack-plugin": "^1.6.1",
"html-webpack-plugin": "^2.30.1",
"jest": "^23.5.0",
"jest-localstorage-mock": "^2.2.0",
"jest-serializer-vue": "^0.3.0",
"jest-transform-stub": "^1.0.0",
"jsdom": "^12.0.0",
"jsdom-global": "^3.0.2",
"karma": "^3.0.0",
"karma-chrome-launcher": "^2.2.0",
"karma-firefox-launcher": "^1.1.0",
"karma-ie-launcher": "^1.0.0",
"karma-jasmine": "^1.1.2",
"karma-webpack": "^3.0.0",
"nightwatch": "^0.9.21",
"node-notifier": "^5.1.2",
"node-sass": "^4.12.0",
"optimize-css-assets-webpack-plugin": "^3.2.0",
"ora": "^1.2.0",
"portfinder": "^1.0.13",
"postcss-import": "^11.0.0",
"postcss-loader": "^2.0.8",
"postcss-url": "^7.2.1",
"rimraf": "^2.6.0",
"sass-loader": "^7.0.1",
"selenium-server": "^3.12.0",
"semver": "^5.3.0",
"shelljs": "^0.7.6",
"uglifyjs-webpack-plugin": "^1.1.1",
"url-loader": "^0.5.8",
"vue-jest": "^1.0.2",
"vue-loader": "^15.5.1",
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "^2.5.21",
"webpack": "^4.28.1",
"webpack-bundle-analyzer": "^2.9.0",
"webpack-dev-server": "^2.11.1",
"webpack-merge": "^4.1.0"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"rules": {},
"parserOptions": {
"parser": "babel-eslint"
}
},
"postcss": {
"plugins": {
"autoprefixer": {}
}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
my jest.config.js
module.exports = {
moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
transform: {
'^.+\\.vue$': 'vue-jest',
'.+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$':
'jest-transform-stub',
'^.+\\.(js|jsx)?$': 'babel-jest'
},
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1'
},
snapshotSerializers: ['jest-serializer-vue'],
testMatch: [
'<rootDir>/(tests/unit/**/*.test.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx))'
],
transformIgnorePatterns: ['<rootDir>/node_modules/']
};
I am pretty new to Babel and Webpack..not sure what is the correct way to make Jest to be able to recognize the plugins that I use for my project. I am thinking it is because the .vue file is processed by vue-jest which does not take babel config... if that is the case I don't know how to fix it...
If someone knows please help....appreciate it...
For questions or help please see:
Any updates on this?
+1
I recommend upgrading to jest 24, it uses babel itself to load config. If that doesn't work, please provide a minimal reproduction we can pull down and test
I actually think I found a solution from this comment: https://github.com/kulshekhar/ts-jest/issues/1283#issuecomment-552147794. Adding this to my jest.config.js
seems to work for me, though it does open up a number of other issues for me.:
globals: {
'ts-jest': {
babelConfig: true,
}
},
@zeroarst issue is likely due to using Jest 23 or vue-jest
transformer not respecting their Babel config.
@dandriushchenko what's your issue exactly? Please provide a detailed repro, otherwise it's really hard to help ("proper babel config with a minimal set of plugins" is not something we can measure unfortunately).
Oh, and your attacking comments won't help anybody, so please calm down.
I have the same problem. Unit Tests fail because of
Add @babel/plugin-proposal-optional-chaining (https://git.io/vb4Sk) to the 'plugins' section of your Babel config to enable transformation.
Jest 24.9.0 (25.0.0 fails too)
.babelrc
{
"presets": [
[
"@babel/preset-env",
{
"useBuiltIns": "usage",
"shippedProposals": true,
"corejs": 3
}
]
],
"plugins": [
["transform-react-jsx", {"pragma": "h"}],
"@babel/plugin-syntax-dynamic-import",
"@babel/plugin-proposal-optional-chaining"
]
}
jest.config.js
module.exports = {
preset: 'ts-jest',
testEnvironment: 'jsdom',
roots: [
"<rootDir>/src"
],
collectCoverageFrom: [
"<rootDir>/src/**/*.tsx",
"<rootDir>/src/**/*.ts",
"!<rootDir>/src/test/**",
"!<rootDir>/src/types/**",
],
coverageReporters: [
"text-summary",
"html",
],
coverageDirectory: "./coverage/",
collectCoverage: true,
moduleDirectories: [
"src",
"node_modules",
],
moduleFileExtensions: [
"ts",
"tsx",
"js",
],
moduleNameMapper: {
"\\.(jpg|png|otf|svg|ttf|woff|woff2)$": "<rootDir>/src/test/stubs/file.js",
"\\.(css)$": "identity-obj-proxy",
},
snapshotSerializers: [
"preact-render-spy/snapshot",
],
snapshotResolver: "<rootDir>/src/test/snapshot-resolver.js",
};
I will try to setup a minimal repo. The workaround does not work for me:
globals: {
'ts-jest': {
babelConfig: true,
}
},
Then my imports don't work anymore and I got muuuch more errors.
Minimal Repo
https://github.com/hbroer/test-optional-chaining-jest
Maybe I do something else wrong. The error is different but the same spot:
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.
You'll find more details and examples of these config options in the docs:
https://jestjs.io/docs/en/configuration.html
Details:
/home/hauke/projects/test-optionalchaining/src/optional.ts:4
return value?.prop?.is;
^
SyntaxError: Unexpected token .
Does not work:
globals: {
'ts-jest': {
babelConfig: true,
}
},
But this does:
globals: {
'ts-jest': {
babelConfig: '.babelrc',
}
},
Duno why everyting is finding .babelrc
but ts-jest
. So this problem is related to ts-jest
Or if you use a babel.config.js
instead:
globals: {
'ts-jest': {
babelConfig: 'babel.config.js',
}
},
Babel 7.8.0 removes the requirement for separately using the optional chaining etc plugins. It looks like jest hasn't caught up yet. Just ran into this. You resolve it by adding preset-env to the babel presets.
@mschipperheyn can you provide your babelrc/jest config files and dependencies versions please?
In jest.config.js, I solved this problem with following.
Another thing that works for ts-jest
users, without using Babel but by changing the target of the TypeScript compiler to anything lower than ES2020 or ESNext (see https://github.com/kulshekhar/ts-jest/issues/1283#issuecomment-592711385):
globals: {
'ts-jest': {
tsConfig: {
target: 'ES2019'
}
}
}
This isn't actually an issue in Jest (it's a configuration error), so I'll close this.
Most helpful comment
Any updates on this?