This article was written for laravel-mix@0.11.3 and jest@19.0.2

Mix is a new tool that helps you build front-end assets for your Laravel application without touching Webpack API directly.

Although it is somewhat opinionated, in truth it doesn’t take much effort to customize Mix or integrate it with other tools. Here we’ll take a look at how to configure the popular testing framework Jest.

Why Jest?

Until you hit into Vue single file components, Jest takes the least amount of effort to configure. It also has a nice momentum in the industry with Facebook backing and it being an official testing framework in Create React App. Jest has popular features like OS notifications, caching etc. provided out of the box and recent versions are proved to be very fast.

The first step is to install necessary dependencies:

npm install --save-dev jest babel-jest

Let’s then add Jest to our npm scripts. Although the framework already sets NODE_ENV variable to test, we pass it here explicitly so that its value doesn’t get accidentally overridden by your environment:

"test": "cross-env NODE_ENV=test jest",

"tdd": "npm run test -- --watch --notify",

At this point you can already run Jest and with babel-jest transformer installed it will even attempt to transpile your JavaScript files, but our setup isn’t quite there yet.

Firstly, we want to make sure Jest doesn’t process unnecessary files by adding the following lines to your package.json:

"jest": {

"roots": ["<rootDir>/resources/assets/js/"]

}

This will instruct Jest to only look for files in specific directory.

Secondly, babel-jest doesn’t really know how to proceed because of Laravel Mix not exposing its babel settings. Let’s dive into source at pull the necessary settings into our project’s .babelrc:

Now, this is a file that babel-jest will pick up automatically when doing transformations. However, this won’t work because while Webpack 2.0+ can process ES6 modules, Node.js cannot and there may be other options we may want to apply specifically for our tests. What we want to use is .babelrc env option that will merge configurations for specific environment:

With the above setup, babel-jest is told to transform import statements to CommonJS require.

If by any chance, you have already overridden your .babelrc and use dynamic import syntax proposal make sure to replace it with babel-plugin-dynamic-import-node for test environment.

Now you’re ready to use Jest in your Laravel application. You can follow along with their documentation for more details. To execute tests, run:

npm test

The rest of this article will address some of the more popular tricks and gotchas when using Jest. Feel free to skip these sections until you encounter related issues.

How to make Jest aware of resolve.modules

Say you hit a wall with imports like this:

import MyComponents from './../../../MyComponent.vue'

and want something more elegant. You configure underlying Webpack instance in Laravel Mix to look for shared modules in the directory of choice in addition to usual node_modules:

.webpackConfig({

resolve: {

modules: [path.resolve(__dirname, 'resources/assets/js/modules'), 'node_modules']

}

})

Then, assuming your component is located directly under modules directory, you can now import it in a more succinct manner:

import MyComponents from 'MyComponent.vue'

To make Jest aware of these shenanigans, simply add moduleDirectories option to your package.json config:

"jest": {

"roots": ["<rootDir>/resources/assets/js/"],

"moduleDirectories": ["resources/assets/js/modules", "node_modules"]

}

How to mock static assets?

Although unlikely, you may run into testing files that import static assets. We can safely mock these assets like this:

{

"jest": {

"roots": ["<rootDir>/resources/assets/js/"],

"moduleNameMapper": {

"\\.(jpg|jpeg|png|gif|eot|otf|svg|ttf|woff|woff2)$": "<rootDir>/resources/assets/js/jest/mocks/fileMock.js",

"\\.(css|less|scss)$": "<rootDir>/resources/assets/js/jest/mocks/styleMock.js"

}

}

}

And the mock files themselves:

resources/assets/js/jest/mocks/styleMock.js

module.exports = {}

resources/assets/js/jest/mocks/fileMock.js

module.exports = 'test-file-stub'

How to test Vue single file components (experimental)

We’ll take inspiration from this amazing article written by Cristian Carlesso.

First, create custom vue-jest.js transformer in resources/assets/js/jest/transformers directory:

Then edit you package.json jest config:

"jest": {

"roots": ["<rootDir>/resources/assets/js/"],

"moduleNameMapper": {

"^vue$": "vue/dist/vue.common.js"

},

"transform": {

"^.+\\.vue$": "<rootDir>/resources/assets/js/jest/transformers/vue-jest.js",

"^.+\\.js$": "babel-jest"

},

"coveragePathIgnorePatterns": ["<rootDir>/resources/assets/js/components"]

}

Here we instruct Jest to transform vue files and resolve Vue to full instead of runtime-only build (because that’s what Laravel Mix is doing under the hood).

Note, that we also ignore Vue components when doing code coverage. That’s pretty much a sweep under the rug solution for known issue with Jest not doing it properly. However, if you know how to fix this, feel free to comment.

That’s it. Enjoy your unit testing workflow with Laravel Mix and Jest.