URL: https://www.progressiverobot.com/vuejs-unit-testing-karma-mocha/

At some point, any serious development project should implement testing for their components. Generally, the first step is <^>unit testing<^>. Unit testing allows you to ensure that the behavior of your individual components is reliable and consistent. By using <^>Karma<^> and <^>Mocha<^>, combined with <^>Webpack<^>, we can unit-test Vue components with relative ease.

Installation

karma illustration for: Installation

There's no soft way to put it, the JavaScript web app testing scene is a complicated beast. As a result, the configuration required for a successful unit-testing setup is fairly extensive. Accordingly, you'll probably be best off using vue-cli with the webpack template (<^>$ vue init webpack my-project<^>) and testing enabled.

Even then, there are some configuration changes to make to <^>test/unit/karma.conf.js<^>. You'll need to specify the plugins you're using, and possibly change the launcher. In this case, I'm using <^>karma-chrome-launcher<^> instead of <^>karma-phantomjs-launcher<^>.

				
					
[label karma.conf.js]

var webpackConfig = require('../../build/webpack.test.conf');



module.exports = function (config) {

  config.set({

    // To run in additional browsers:

    // 1. install corresponding karma launcher

    //    http://karma-runner.github.io/0.13/config/browsers.html

    // 2. add it to the `browsers` array below.

    browsers: ['Chrome'],

    frameworks: ['mocha', 'sinon-chai'],

    reporters: ['spec', 'coverage'],

    files: ['./index.js'],

    preprocessors: {

      './index.js': ['webpack', 'sourcemap']

    },

    // ** ADD THIS IN ** (vue-cli's webpack template doesn't add it by default)

    plugins: [

      // Launchers

      'karma-chrome-launcher',



      // Test Libraries

      'karma-mocha',

      'karma-sinon-chai',



      // Preprocessors

      'karma-webpack',

      'karma-sourcemap-loader',



      // Reporters

      'karma-spec-reporter',

      'karma-coverage'

    ],

    webpack: webpackConfig,

    webpackMiddleware: {

      noInfo: true

    },

    coverageReporter: {

      dir: './coverage',

      reporters: [

        { type: 'lcov', subdir: '.' },

        { type: 'text-summary' }

      ]

    }

  })

}



				
			

Your First Component Unit Test

Let's create a small component to test.

				
					
[label TestMe.vue]

&lt;template&gt;

  &lt;p&gt;{{propValue}}&lt;/p&gt;

&lt;/template&gt;



&lt;script&gt;

export default {

  props: ['propValue']

}

&lt;/script&gt;

				
			

Now we'll add a spec for it in <^>test/unit/specs<^>. This just checks that the component's text is set to the property value.

				
					
[label specs/TestMe.spec.js]

import Vue from 'vue';

// The path is relative to the project root.

import TestMe from 'src/components/TestMe';



describe('TestMe.vue', () =&gt; {

  it(`should render propValue as its text content`, () =&gt; {

    // Extend the component to get the constructor, which we can then initialize directly.

    const Constructor = Vue.extend(TestMe);



    const comp = new Constructor({

      propsData: {

        // Props are passed in "propsData".

        propValue: 'Test Text'

      }

    }).$mount();



    expect(comp.$el.textContent)

      .to.equal('Test Text');

  });

});

				
			

Waiting For Async Updates

Vue updates the DOM asynchronously, in ticks. Therefore, when we modify anything that affects the DOM, we need to wait for the DOM to update using <^>Vue.nextTick()<^> before making any assertions.

				
					
[label TestMe2.vue]

&lt;template&gt;

  &lt;p&gt;{{dataProp}}&lt;/p&gt;

&lt;/template&gt;



&lt;script&gt;

export default {

  data() {

    return {

      dataProp: 'Data Text'

    }

  }

}

&lt;/script&gt;

				
			
				
					
[label specs/TestMe2.spec.js]

import Vue from 'vue';

// The path is relative to the project root.

import TestMe2 from 'src/components/TestMe2';



describe('TestMe2.vue', () =&gt; {

  ...

  it(`should update when dataText is changed.`, done =&gt; {

    const Constructor = Vue.extend(TestMe2);



    const comp = new Constructor().$mount();



    comp.dataProp = 'New Text';



    Vue.nextTick(() =&gt; {

      expect(comp.$el.textContent)

        .to.equal('New Text');

      // Since we're doing this asynchronously, we need to call done() to tell Mocha that we've finished the test.

      done();

    });

  });

});

				
			

Reference

Hopefully that helps get you started!

However, the way components are instanced and extended in Vue can be a bit confusing, so you may want to take a look at the official Vue tests to get a better idea on how to test various component capabilities.