ddraper

Unit Testing with Karma

Blog Post created by ddraper Employee on Dec 22, 2016
This is a personal blog post that is primarily intended for tracking my own learning rather than provided to the Alfresco Community for educational purposes. However if you find it useful, informative or have any comments on it then please comment below.

 

At the end of my last post I'd got to the point where I had something working. I could quite conceivably have continued developing but it makes sense to get some automated testing in place to ensure that I don't break anything that I've previously implemented. I've also got into the practice of Test Driven Development (TDD) and find it very rewarding.

 

For Aikau we've always used Intern for automated testing but I wanted to investigate other options that were available. On doing some research I found another Vue.js project template that met my needs. Once again thought I didn't want to start over and I also wanted to understand what the project provided so I started to copy across the unit test elements and try them out. Each time I hit a failure (usually the result of a missing NPM package) I would debug and resolve the problem. My once small package.json file is suddenly bloating out of control and I wanted to make sure that I was only pulling in the packages that I really needed.

 

The project template was using Karma for unit testing (I've not looked at end-to-end testing yet) but the template provided was actually much more complex that I wanted to use so I made the effort to just use the pieces I want for the time being.

 

The first thing to do was so update the main List.vue component so that it no longer made XHR requests itself, but instead used a service that was provided for accessing the data. The idea behind this was to avoid needing to setup Sinon.js for mock XHR handling. However, I wasn't able to get the tests working using the approach described in the documentation.

 

This is no bad thing as moving the data handling out to a service makes the List component much more re-usable. Especially as the new V1 REST APIs have a consistent response schema (meaning that it will be easy to add different services for different APIs). 

 

In the end I resorted to setting up a Sinon.js server and used the json-loader for webpack to load some mock a mock response from a file. Since I've only just got started with this testing approach I'm not sure of how to do everything yet - however one immediately problem was in handling asynchronous loading of elements. Intern provides some excellent capabilities through Leadfoot for waiting for elements to appear and disappear.

 

I'm sure there's a better solution but for the time being I've just used a simple timeout, however this approach won't scale as it forces the test to wait for a maximum amount of time before checking the DOM for the object.

 

My single test looks like this thought:

import Vue from 'vue';
import List from '../../../src/components/lists/List.vue';

// Import a fake response...
var nodes = require('json-loader!./Nodes.json');

// Create our mock server...
var server= sinon.fakeServer.create();
server.autoRespond = true;
server.xhr.useFilters = true;
server.respondWith('GET',
                  /(.*)/,
                  [200,
                   {'Content-Type':'application/json;charset=UTF-8'},
                   JSON.stringify(nodes)]);

// Describe the tests...
describe('List.vue', () => {
  it('should render correct contents', (done) => {
    const vm = new Vue({
      el: document.createElement('div'),
      render: (h) => h(List),
    });
    setTimeout(function() {
        expect(vm.$el.querySelector('li.components-lists-ListView__item').textContent).to.equal('Data Dictionary');
        done();
    }, 1500);
   
  });
});

 

...and I've proven that it works:

Outcomes