How do I resolve the error "don't know how to turn this value into a node" for a Vue 3 app using babel-plugin-istanbul extending .vue - babeljs

My ultimate goal is to get e2e and unit code coverage for my Vue 3 app using Cypress in my CI/CD pipelines.
However, when using the following configuration in my babel.config.js I get a flood of repeated error messages that read don't know how to turn this value into a node at transformFile.next (<anonymous>) for each Vue file in my app that uses <script setup>.
babel.config.js
module.exports = {
presets: [
'#vue/cli-plugin-babel/preset',
],
plugins: [
['babel-plugin-istanbul', {
extension: ['.js', '.vue']
}]
],
};
package.json
"dependencies": {
"core-js": "^3.6.5",
"vue": "^3.0.0"
},
"devDependencies": {
"#vue/cli-plugin-babel": "~4.5.15",
"#vue/cli-plugin-eslint": "~4.5.15",
"#vue/cli-service": "~4.5.15",
"#vue/compiler-sfc": "^3.0.0",
"babel-eslint": "^10.1.0",
"babel-plugin-istanbul": "^6.1.1",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^7.0.0"
},
App.vue
<script setup>
import HelloWorld from './components/HelloWorld.vue'
</script>
My concern is that the plugin doesn't know how to handle Vue 3's script setup syntax.
Sadly, the only how-to guides I can find online are for Vue 2 or React apps.
https://docs.cypress.io/guides/tooling/code-coverage#Using-NYC
https://vuejsdevelopers.com/2020/07/20/code-coverage-vue-cypress/
So my question is: what can I do to get my app to transpile while using babel-plugin-istanbul and script setup?
Steps to Reproduce:
Create a new Vue 3 app with vue-cli-service
Install babel-plugin-istanbul in your dev dependencies
Configure your babel.config.js as shown above
Convert your App.vue to use <script setup>
Run npm run serve
Expected behavior:
The app transpiles with no errors
Actual behavior:
Transpilation failure with don't know how to turn this value into a node errors for App.vue.

The resolve is to use istanbul in the babel config (as given in Cypress docs).
The cause isn't apparent, without <script setup> the full name babel-plugin-istanbul works ok.
plugins: [
['istanbul', {
extension: ['.js', '.vue']
}]
],

I am solving same problem and I can point out two things:
The problem is in babel.config.js file especially with .vue extension, when you remove it works, but for me it instrument all files.
I have a feeling another problem is with CLI versions plugins. I don't have problem to run the cypress code coverage plugin with older packages.

If add extension:['.vue'] in bable.config.js configuration, getting below error.
src/pages/somefile.vue?vue&type=script&setup=true&lang=js
Module build failed (from ./node_modules/#vue/cli-plugin-babel/node_modules/babel-loader/lib/index.js):
Error: src/pages/somefile.vue: don't know how to turn this value into a node

I ran into this as well. It turned out to be a bug in the istanbul-lib-instrument package, which was fixed in this PR: https://github.com/istanbuljs/istanbuljs/pull/662
If you upgrade your installed copy of istanbul-lib-instrument to 5.2.1 (i.e., npm update istanbul-lib-instrument) the issue should go away.

Related

Not able to use babel "preset-env" plugin with NextJS

I have a requirement where I am trying to use the Babel plugin "preset-env". This plugin compiles my NextJS project from ES6 to ES5. I have created the .babelrlc file as suggested by NextJS documentation and added my plugin like this:
{
"presets": ["next/babel"],
"plugins": ["#babel/preset-env"]
}
When I try to run my project locally I get this error:
error - ./node_modules/next/dist/client/router.js
Error: Cannot find module '#babel/plugin-preset-env' from '/Users/agastya/Local/testcap/Sample-proj'
- If you want to resolve "#babel/preset-env", use "module:#babel/preset-env"
- Did you accidentally pass a preset as a plugin?
NextJS documentation says "Next.js includes the next/babel preset to your app, which includes everything needed to compile React applications and server-side code. ".
It would be great if someone can explain where/what is the right approach to fix this.
You have to do the following:
// .babelrc file, also could be babel.config.js
{
"presets": [
[
"next/babel",
{
"preset-env": {},
"transform-runtime": {},
"styled-jsx": {},
"class-properties": {}
}
]
],
"plugins": []
}
Taken from: https://nextjs.org/docs/advanced-features/customizing-babel-config

gatsby build fails when adding mapbox-gl-geocoder to gatsby.js

I have a gatsby.js application with mapbox-gl and it all worked successfully until I tried to include the mapbox-gl-geocoder package to add search functionality.
I have installed it using npm as the following:
npm install mapbox/mapbox-gl-geocoder --save
then, added it to the React component:
import '#mapbox/mapbox-gl-geocoder/lib/mapbox-gl-geocoder.css';
import MapboxGeocoder from '#mapbox/mapbox-gl-geocoder';
and inside a useEffect hook:
map.addControl(
new MapboxGeocoder({
accessToken: mapboxgl.accessToken,
zoom: 20,
placeholder: 'Enter City',
mapboxgl: mapboxgl
}), 'top-left'
);
locally, when I run gatsby develop it works as it should, but when I deploy it with Netlify, I get the following error:
:24:21 PM: error Generating SSR bundle failed
1:24:21 PM: Can't resolve 'electron' in '/opt/build/repo/node_modules/#mapbox/mapbox-sdk/node_modules/got'
1:24:21 PM: If you're trying to use a package make sure that 'electron' is installed. If you're trying to use a local file make sure that the path is correct.
it seems that mapbox-gl-geocoder has a dependency to #mapbox/mapbox-sdk and the mapbox-sdk has a dependency to got that somehow needs electron ?
The only thing i can read about electron in the got npm page is the following:
Electron support has been removed
The Electron net module is not consistent with the Node.js http module. See #899 for more info.
In any way, I tried to install electron with npm to see if the errors are gone, and the build started to fail with new error indicating that the window object is not available.
10:35:45 AM: error "window" is not available during server side rendering.
Googling that error led me to some answers about not loading the packages in gatsby-node.js but that didn't help either.
When dealing with third-party modules that use window in Gatsby you need to add a null loader to its own webpack configuration to avoid the transpilation during the SSR (Server-Side Rendering). This is because gatsby develop occurs in the browser while gatsby build occurs in the Node server where obviously there isn't a window or other global objects.
exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
if (stage === "build-html") {
actions.setWebpackConfig({
module: {
rules: [
{
test: /#mapbox/,
use: loaders.null(),
},
],
},
})
}
}
Keep in mind that the test value is a regular expression that will match a folder under node_modules so, ensure that the /#mapbox/ is the right name.
Using a patch-package may work but keep in mind that you are adding another package, another bundled files which may have a performance effect. The proposed snippet is a built-in solution that happens when you build your application.

Unit testing ionic services with jest

I'm building an ionic app and would like to add unit tests for a couple of services. I'm trying to get jest working with typescript but it doesn't seem to play well.
I'm getting this error:
/myuser/project/node_modules/#ionic/storage/dist/index.js:1
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import { NgModule } from '#angular/core';
^^^^^^
SyntaxError: Unexpected token import
Now I have read that you have to add the babel-plugin-transform-es2015-modules-commonjs and use that in the test env of babel. However I am using babel 7 and this plugin is not available for babel 7. Is there a different solution?
I will also provide my package.json and .babelrc below.
gist
You just need to add #ionic/storage to your transformIgnorePatterns in jest config. For example, here's mine, take note of the #ionic/storage part:
"transformIgnorePatterns": [
"node_modules/(?!#ngrx|moment|#ionic/storage|#ionic-native)"
]
Additionally, make sure in your tsconfig compiler options you have module: 'commonjs'
Also, if you need localstorage mocks, you can just use the following npm module:
npm install --save-dev jest-localstorage-mock
and then (in your setupJest.ts file)
import 'jest-localstorage-mock
Lastly, I recommend taking a look at:
https://github.com/thymikee/jest-preset-angular
for more help with jest + ionic configurations.

vscode automatic type acquisition for jest

I have vscode 1.9 and I want to have intellisense for jest tests. The problem is that describe, it, expect etc are globally available in jest and you don't need to import them in your test files. So vscode will not show intellisense for them.
Is there any configuration for globals for automatic type acquisition?
You have a few options in this case:
Add jest to your package.json:
"dependencies": {
"jest": "^18.1.0"
}
This only works if you are working JavaScript and do not have a tsconfig.json.
Install #types/jest
$ npm install -D #types/jest
This should work for both JavaScript and TypeScript projects. However #types but may be disabled by a jsconfig.json/tsconfig.json: http://www.typescriptlang.org/docs/handbook/tsconfig-json.html
Create a jsconfig.json file in the root of your workspace to specifically include jest:
{
"typeAcquisition": {
"include": [
"jest"
]
}
}
This will only work for JavaScript projects when automatic typings acquisition is enabled.
All of these should allow VSCode to pick up jest's typings without an import or require
I tried installing the #types/jest, and it did work, but the problem is that it resulted in the jest suggestions appearing in my .js files as well. I couldn't figure out how to get global suggestions for test, expect, etc. in only .test.js files but not .js files.
So I decided to just manually import each jest global I was going to use in each .test.js file, which allowed the suggestions to appear with types but avoided having the suggestions appear in the .js files:
import { test, expect } from '#jest/globals'
npm install -D #types/jest
edit jest.config.js
typeAcquisition: {
include: ['jest'],
},

babel-jest doesn't handle ES6 within modules

I am trying to set up Jest on a React based project which uses ES6 modules. However I seem to be having issues with ES6 modules, I am using babel-jest and believe I have this set up properly (Jest detects it automatically).
Jest doesn't seem to have a problem using ES6 imports however as soon as it hits on an import statement within one of the imported modules it chokes. It's as if it is only transpiling the initial test script and not any of the imported modules. I have tried various configurations and tried searching Google with no luck. Running tests without any imports works fine.
Here is the error:
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import Predications from './predications';
^^^^^^
SyntaxError: Unexpected token import
Here are the relevant bits of config:
jest.conf.json
{
"testRegex": "\/test\/spec\/.*\\.js$",
}
.babelrc
{
"presets": ["es2015", "stage-0", "react"]
}
Test script
import React from 'react';
import { mount, shallow } from 'enzyme';
import Slider from 'react-slick';
import Carousel from '../../client/components/carousel/carousel.js'; // test chokes on when I include this module
describe('carousel component', () => {
it('is a test test case', () => {
expect(1 + 2).toEqual(3);
});
});
Update:
As suggested, I have tried running the test without jest.conf.js, however the testRegex is needed in order for Jest to find my tests, I tried moving tests to the default test directory and they still fail.
I would like to clarify that tests themselves are running fine, the issue seems to be where one of my imported modules uses ES6, in my example above, if I don't import my carousel component the test runs fine, as soon as I import that the test chokes on the import statement within that file. It seems as though the imported modules are not getting transpiled.
Update #2
After some investigation it appears the issue is that babel is not transpiling ES6 within node_modules. I have created an example repo to demonstrate this here: https://github.com/jamiedust/babel-jest-example
I understand that third party modules should be handling their own transpiling, however we have a number of modules which are hosted on our own npm registry and are re-used between projects, in these cases Webpack handles transpiling, for the Jest tests we need these node_modules to be transpiled by Babel, or a way of leveraging our webpack set up to do this for us.
Solution
Add the following config in package.json (or Jest config file).
"jest": {
"transformIgnorePatterns": [
"/node_modules/(?!test-component).+\\.js$"
]
}
By default any code in node_modules is ignored by babel-jest, see the Jest config option transformIgnorePatterns. I've also created a PR on your example repo, so you can see it working.
While this works, I've found it to be extremely slow in real applications that have a lot of dependencies containing ES modules. The Jest codebase has a slightly different approach to this as you can find in babel-jest transforming dependencies. This can also take much longer on Windows, see Taking 10 seconds on an empty repo.
If doing "unit" testing, mocking is probably the better way to go.
You could try adding the transform-es2015-modules-commonjs plugin to your babel config file for testing only. Here is an example config file which tells babel to transpile modules only when in a testing environment. You can put it underneath your presets:
{
"presets": [
"react",
["es2015", {"modules": false, "loose": true}]
],
"env": {
"test": {
"plugins": ["transform-es2015-modules-commonjs"]
}
}
}
You can read about the plugin here:
https://www.npmjs.com/package/babel-plugin-transform-es2015-modules-commonjs
Then, when running your Jest tests on the command line specify NODE_ENV=test (you may need to add the --no-cache flag to the command the first time after making the change to the babel config because Jest caches babel output, but after that you can leave it off:
NODE_ENV=test jest --no-cache
I learned about this issue in a React seminar by Brian Holt at Frontend Masters. https://frontendmasters.com/courses/
faced the same issue, followed the steps to resolve,
install babel-jest
in jest config add this configuration
transform: {
'^.+\\.js?$': require.resolve('babel-jest')
}
make sure you have babel.config.js present (your config might be different than provided below)
module.exports = {
"env": {
"test": {
presets: [
[
'#babel/preset-env',
{
targets: {
node: 'current',
},
},
],
]
}
}
};
I faced the same problem (node_module not transpiled by babel-jest), without being able to solve it.
Instead, I finally succeed by mocking the node_module, like described here https://facebook.github.io/jest/docs/manual-mocks.html
NB: setting mocks in __mocks__ subfolders did not work for me. So I passed the mock as the second parameter of the jest.mock() function. Something like :
jest.mock('your_node_module', () => {})
Another possible cause. Babel now ignores your .babelrc inside node_modules and uses the one provided by the dependency. If you have control of the dependency you would have to add a .babelrc to it and babel would use those settings for it.
this can cause problems though if your dependency and your project use different babel versions or modules.