loading...

How to test Vue components with Laravel Mix and Mocha

tuandm profile image Tuan Duong ・4 min read

Introduction

While adding tests to Laravue, I found that setting unit tests for Vue with Laravel Mix is not simple like Vue's official document. After working around with some google-ing, I've passed the setup steps and just want to share what I've done so far.

Setup Laravel and npm dependencies

Firstly, we create new Laravel project with the command which every Laravel developer shoud know:

composer create-project --prefer-dist laravel/laravel test
cd test
npm install

Very easy!

Then we have to setup tests environment as well as required libraries/dependencies. I picked Mocha + Webpack because many articles mentioned this.

npm install --save-dev webpack vue-template-compiler @vue/test-utils mocha mocha-webpack jsdom jsdom-global expect

Ok, seems everything is set, let us double check with npm list --depth=0

Wow, something is wrong!

➜  test npm list --depth=0
...
├── UNMET PEER DEPENDENCY mocha@6.0.2
...
└── UNMET PEER DEPENDENCY webpack@4.29.6

npm ERR! peer dep missing: mocha@>=2.4.5 <=5, required by mocha-webpack@1.1.0
npm ERR! peer dep missing: webpack@^2.0.0 || ^3.0.0, required by mocha-webpack@1.1.0
npm ERR! peer dep missing: webpack@^2.0.0 || ^3.0.0, required by mocha-webpack@1.1.0

It says that dependencies' versions are not matched. Seems mocha-webpack is not up-to-date with webpack and mocha, it requires old versions (mocha 2.4.5-5 and webpack 2 or 3 while latest versions are mocha@6 and webpack@2.49.6). Now let's go to the mocha-webpack repo to see what happens. Indeed, there is no update since last year. Ok, what to do next? We may want to check the issue list to see any similar cases and solutions. Luckily, the first issue is the one we are finding:

Hi there, mocha-webpack users!

mocha-webpack has no activity since May, 2018. We at SysGears are maintaining a fork here:
https://github.com/sysgears/mochapack

A new version of mochapack@1.1.0 has been released today with Mocha 6 support.

Check it out!

Now we go to Mochapack as the author recommended, we can see the installation guide for Mochapack:

npm install --save-dev mochapack

Seems it works. Ok, let's remove the outdated mocha-webpack:

npm remove mocha-webpack

Wow, npm list --depth=0 returns very clean result. Don't forget to give the mochapack a star for this awesome work.

Setup test enviroment

Now we are ready to create test cases for our Vue components following this guide. To start it, we have to prepare a environment for tests by creating new folder inside /tests/.

mkdir tests/js

Then create file setup.js inside folder tests/js and put this line on top:

require('jsdom-global')();

Next step will be the npm command to run tests, we have to open package.json and add this line inside scripts section

        "test": "mochapack --webpack-config=node_modules/laravel-mix/setup/webpack.config.js --require tests/js/setup.js tests/js/\\*\\*/\\*.spec.js"

You can pick any name for tests/js folder and setup.js file, don't forget to indicate them in the test command

Now is the show time:

➜ npm test

 WEBPACK  Compiled successfully in 140ms

 MOCHA  Testing...



  0 passing (0ms)

 MOCHA  Tests completed successfully

Wow, it works with 0 test passing - because we haven't added yet. We are going to do it now.

Writing a test

To save time, we can use resources/js/components/ExampleComponent.vue of Laravel to write test. If you take a look to this component, you will see it just shows the Example Component header. Now we create a test file tests/js/components/ExampleComponent.spec.js and put these lines to that file

// tests/js/components/ExampleComponent.spec.js
import { mount } from '@vue/test-utils';
import expect from 'expect';
import ExampleComponent from '../../../resources/js/components/ExampleComponent.vue';

describe('ExampleComponent.vue', () => {
  it('says that it is an example component', () => {
    const wrapper = mount(ExampleComponent);
    expect(wrapper.html()).toContain('Example Component');
  });
});

This test case is to check after ExampleComponent mounted, Example Component should be in the output html.

Save the file and run the test command again:

➜ npm test
 WEBPACK  Failed to compile with 1 error(s)

Error in ./resources/js/components/ExampleComponent.vue?vue&type=template&id=299e239e&

  Module build failed (from ./node_modules/vue-loader/lib/loaders/templateLoader.js):
  TypeError: Super expression must either be null or a function
      at /.../test/node_modules/prettier/index.js:40358:5
      at /.../test/node_modules/prettier/index.js:40378:4

npm ERR! Test failed.  See above for more details.

Ok, we've got the error. You will be crazy to find out the answer for this error from internet. Don't worry, just do this fix: Open tests/js/setup.js again and put this line next to the first one:

window.Date = Date;

Save setup.js file and run test command again

➜ npm test

 WEBPACK  Compiled successfully in 1436ms

 MOCHA  Testing...



  ExampleComponent.vue
Component mounted.
    ✓ says that it is an example component


  1 passing (22ms)

 MOCHA  Tests completed successfully

Yeah, it works, test case passed. Now we can put more Vue components and tests them.

Please enjoy testing! You can find my sample here: https://github.com/tuandm/laravel-vue-tests-with-mocha

Noted: I'm using MacOS Mojave 10.14.2, all related tools (npm, composer...) are considered as last versions.

Posted on by:

tuandm profile

Tuan Duong

@tuandm

I'm a PHP coder who wants to make PHP great again!

Discussion

markdown guide
 

Great article! The part on using mochapack rather than mocha-webpack helped a lot!

However for my own laravel project I did not install webpack, but rather updated laravel-mix to the latest version "4.0.15" as it's already using webpack of course.

Thanks!

 
 

助かりました ありがとう!

 

Good article! Updating mocha-webpack to latest beta version (2.0.0-beta.0) works too (instead of using mochapack) if anyone already has it installed and wants to skip a step.

 

How and Why did window.Date = Date cleared the error? can you please explain?

 

This doesn't work if your vue component imports sass files like @import "@/variabless.scss"