Vue Jest Aliases Configuration - vue.js

I have an error when I want to run Jest because of moduleNameMapper settings.
I tried several methods, but nothing changes.
To reproduce:
clone the repo: https://github.com/zoztorun/reproduce-webpack-alias-error
npm install
npm run test

Since you're using Vue CLI, you should use #vue/cli-plugin-unit-jest, which can be added to your Vue CLI project with this command:
vue add unit-jest
This will also add a <rootDir>/test directory with a sample test, but that doesn't fit your project's test file pattern, which places *.spec.js adjacent to the source files.
To adapt the result to your project:
Delete <rootDir>/test (as it would be unused, and because it points to a nonexistent HelloWorld.vue)
Edit the jest config in package.json to be:
{
"jest": {
"preset": "#vue/cli-plugin-unit-jest",
"testMatch": [
"**/src/**/*.spec.[jt]s?(x)"
]
}
}
Delete your test NPM script, since #vue/cli-plugin-unit-jest automatically adds its own test:unit script, which must be used instead (i.e., use npm run test:unit).

Related

Not finding relative modules on build when linked over "npm link xyz"

When running npm run serve, my VueJS projekt (Vue 2.6.11) running webpack is not finding my locally changed node module.
If i install it normally, it works (of course) and i see the changes i made in it, in the node modules folder of the project that linked it - so the link itself should be fine.
I linked it by using "npm link" in the project i want to link (i ran the build before) and then using "npm link [name]" in my main project.
The import i'm using in the main.js looks like this:
import [module-name] from '[module-name]'
just as it did when i had it installed regularly.
I also changed the settings of webpack by doing this:
module.exports = {
configureWebpack: {
resolve: {
symlinks: false //npm link
},
...
because the documentation of vue stated (for version 2, the new version has information about chainWebpack in it), that links won't work otherwhise as they're not resolved without it. still, this is the output on npm run serve:
This dependency was not found:
* [module-name] in ./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/views/CommentWriteArea.vue?vue&type=script&lang=js&
To install it, you can run: npm install --save [module-name]
(with the correct name in it of course)
Other solutions like installing the local version or forking the repository are not an option. It has to be linked for my use case

Missing node_modules bin on PATH

I have run the command
yarn add -D jest to install jest to my project.
This does successfully add jest to my node_modules
> find . -name jest
./node_modules/.bin/jest
./node_modules/jest
When I use iterm2 to run jest however I get the following output
> jest
zsh: command not found: jest
FWIW When I use the IntelliJ terminal it does work
> jest
Determining test suites to run...^C
What am I missing in the iterm environment to be able to have node_modules bin in my classpath depending on the current repo?
An OS shell doesn't know about your locally installed node_modules, but IntelliJ terminal does. So if you want to run jest from outside of an IDE you should perform several additional steps.
The most common way to run locally installed packages is to define a separate script in the "scripts" section of your package.json file. Then you will be able to run it using the yarn/npm itself from any terminal. You can find an exact example in the Yarn docs.
{
"name": "my-package",
"scripts": {
"test": "jest"
}
}
yarn run test
Or you could install jest globally so it will be accessible from anywhere, but it's not a best practice.

Unexpected import token - testing React Native with Jest

I'm getting a weird import error when I try to test my react-native app with jest. I have babel-jest, babel-preset-react-native, jest, jest-react-native and react-test-render all installed but get this error message when I run npm test.
● Test suite failed to run
/Users/maftalion/www/stars20/kiosk/node_modules/native-base/index.js:4
import Drawer from './Components/vendor/react-native-drawer';
^^^^^^
**SyntaxError: Unexpected token import**
at transformAndBuildScript (node_modules/jest-runtime/build/transform.js:316:10)
at Object.<anonymous> (src/routes/Identification.js:3:17)
at Object.<anonymous> (src/routes/router.js:4:21)
Test Suites: 1 failed, 1 passed, 2 total
Tests: 1 passed, 1 total
Snapshots: 1 passed, 1 total
Time: 1.011s
Figured it out, basically throw any node modules that use es6 syntax in transformIgnorePatterns.
"transformIgnorePatterns": [
"node_modules/(?!react-native|native-base|react-clone-referenced-element)"
],
Try adding transformIgnorePatterns to your package.json:
{
"name": "MyAwesomeApp",
...
"jest": {
"transformIgnorePatterns": ["/node_modules/"]
}
}
For me Jest works out of the box, however:
$ react-native init MyAwesomeApp
$ cd MyAwesomeApp
$ npm test
...
Tests: 2 passed
I'm using React Native v0.37.0.
I found the answers given earlier didn't solve Unexpected token import errors in the tests itself, if they are written in ES6 (like the boilerplate tests created by the Ignite CLI after ignite new MyProject).
I finally managed to remove ES6-related errors by adding to the test task in package.json:
"test": "NODE_ENV=test jest --no-cache"
I am using RN 0.45.1, Node 7.10.1 (and 8.1.2), Yarn 0.24.6 and Jest 20.0.4
PS: Don't always see this in the console, but in VS Code v1.13.1 setting --no-cache makes the difference.
You configured Babel in your webpack config and this will only apply to webpack. When other tools, like Jest, use Babel, they won't see that configuration because they don't look at the webpack config. You can use a .babelrc file to configure Babel and that will apply to anything that runs Babel (not just webpack).
Using a .babelrc is usually preferred as you want to have a general babel config, and if you need to override a setting, you can still do that in the specific application like in the webpack config.
Create the following .babelrc:
{
"presets": ["es2015", "react"]
}
With that, you can remove the presets option in your webpack config because it will use the .babelrc. Note that the [cacheDirectory option][3] is specific to babel-loader and is not used to configure the underlying Babel.
You also have a typo in your test, toMatchSnapShot() should be toMatchSnapshot().
expect(rendered.toJSON()).toMatchSnapshot();
I needed to add .babelrc with:
{
"presets": ["#babel/env","#babel/react"]
}
I also needed to install this module
npm install add --dev react-test-renderer

How to avoid React loading twice with Webpack when developing

Given the following directory structure:
my-project
|
|-- node_modules
|
|-- react
|-- module-x
|
|--node_modules
|
|--react
You can see both my-project and module-x require React. I have the same problem as described on this question, but the suggestion is to remove react from the package.json dependencies. I do that and it works fine, as long as no node_modules are installed in module-x, because Webpack will use React from my-project. But if I'm in the process of developing module-x and the node_modules are installed, Webpack uses React from both my-project and module-x.
Is there a way I could have Webpack make sure only one instance of React is used, even though it's required on two separate levels?
I know I could keep module-x in a separate directory when developing, but it seems like I'd have to publish it and then install it in my-project to test it, and that's not very efficient. I thought about npm link, but had no luck with it since it still has node_modules installed in module-x.
This here sounds a lot like the same challenge I'm having, but it doesn't seem like npm dedupe or Webpack's dedupe option would work. I'm probably not understanding some important detail.
This issue usually arises when using npm link. A linked module will resolve its dependencies in its own module tree, which is different from the one of the module that required it. As such, the npm link command installs peerDependencies as well as dependencies.
You can use resolve.alias to force require('react') to resolve to your local version of React.
resolve: {
alias: {
react: path.resolve('./node_modules/react'),
},
},
If you don’t want to (or can’t) modify the project configuration, there is a more straightforward solution: just npm link React itself back to your project:
# link the component
cd my-app
npm link ../my-react-component
# link its copy of React back to the app's React
cd ../my-react-component
npm link ../my-app/node_modules/react
Just in case it's useful for others, the solutions suggested above didn't work for me, I had to perform the following steps to solve it:
In the library:
Setup the libraries that are generating issues as peerDependencies in the package.json instead of dependencies or devDependencies, e.g. in my case react:
"peerDependencies": {
"react": "^16.8.6",
...
}
run npm install
build the library (in my case, with a rollup -c npm script
In my main app:
change the version of my library to point to my local project with a relative path in package.json, e.g.
"dependencies": {
"my-library": "file:../../libraries/my-library",
...
}
Add resolve.symlinks = false to my main app's webpack configuration
Add --preserve-symlinks-main and --preserve-symlinks to my package.json start script, e.g:
"scripts": {
"build": "set WEBPACK_CONFIG_FILE=all&& webpack",
"start": "set WEBPACK_CONFIG_FILE=all&& webpack && node --preserve-symlinks-main --preserve-symlinks dist/server.js",
}
run npm install
run npm run start
In the same vein as the accepted answer here's how you can achieve the desired outcome with Craco:
const path = require('path')
module.exports = {
webpack: {
configure: config => {
config = {
...config,
resolve: {
...config.resolve,
alias: {
...config.resolve.alias,
'react': path.resolve('./node_modules/react'),
},
},
}
// console.log(config)
return config
},
},
}
It's important to note you can't just pass resolve as a key, you have to do your own deep merge using the configure callback.

How do I prevent browserify from including multiple versions of sub-dependencies?

In my front-end code, I use require() to pull in libraries which, in turn, depend on different versions of Underscore.js. As a result, when I use browserify to bundle everything together, the output contains multiple copies of Underscore. Is there a way to tell browserify that require('underscore') should always import a particular file?
As a demonstration of the problem, imagine I have the following dependencies:
// package.json
"dependencies": {
// Depends on underscore 1.7.0
"backbone": "^1.1.2",
// Depends on underscore 1.6.0
"backbone.marionette": "^2.3.0"
}
In main.js I use both libraries:
// main.js
var Backbone = require('backbone');
var Marionette = require('backbone.marionette');
console.log("Hello, world!");
When I create a bundle, multiple versions of Underscore are included:
PS> browserify main.js -o out.js
PS> findstr _.VERSION out.js
_.VERSION = '1.7.0';
_.VERSION = '1.6.0';
(I created a GitHub repository with a more complete example. Clone it and run npm install && npm test to see it in action)
I tried adding a browser section to my package.json like the following, but it didn't seem to have any effect:
// package.json
"browser": {
"underscore": "./node_modules/underscore/underscore.js"
}
I understand why npm installs duplicate dependencies (and it makes sense to do it this way for server-side code) but what's the correct way to deal with this when using browserify?
There is a duplicate detection in Browserify that should avoid loading the same version more than once. However, if your node_modules tree contains multiple copies of the same module, this detection might (should?) fail.
The solution that I'm using is to dedupe the package structure with npm:
npm dedupe
This will only leave unavoidable dupes in your dependency tree and it will log a warning about those dupes so that you can double check.