more testing with jspm mocha and vuejs

Testing with Mocha and JSPM (and SystemJS), continued

So after messing with my testing set up for a while, I found that there was a little more setup required to get my components to test properly with mocha.

tldr; some more setup is required to get the code in the previous blog post to work properly, check it out below:

Multi-part blog post alert

This is a multi-part blog-post!

  1. Part 1 - Unit testing with JSPM, Mocha, and Vue.js
  2. Part 2 - More testing with JSPM, Mocha, and Vue.js
  3. Part 3 - Testing the DOM
  4. Part 4 - Switching from mocha to tape

BONUS Want to see it all working? Check out the gitlab repo with a fully-built example

Back to your regularly scheduled programming

The code

The component’s javascript file (app/components/alert-notification/component.js):

import Vue from "vue";
import t from "./template.html!vtc";
import styles from "./style.css!";
import _ from "lodash";

const comp = {
  render: t.render,
  staticRenderFns: t.staticRenderFns,

  props: {

    alert: {
      type: Object,
      default: null
    },

    alertIdx: Number,

    onlyShowLatest: {
      type: Boolean,
      default: false
    }
  },

  data: function() {
    return {};
  },

  computed: {
    alertClass: function() {
      var statusClass = _.has(this, "alert.status") ? ` alert-${this.alert.status}` : "";
      return `alert-notification-component alert${statusClass}`;
    }
  },

  methods: {
    log: function() { console.log.apply(this, ["[alert-notification]", ...arguments]); },

    // Destroy this alert (emits event to parent)
    destroy: function() { this.$emit('destroy', this.alert, this.alertIdx); }
  }
};

// Register as global component & export
Vue.component('alert-notification', comp);
export default comp;

NOTE I changed how these components are exported, where as I had export default Vue.component(.....) before, I now make sure to export just the object, but still do the registration of the component.

The component’s template (app/components/alert-notification/template.html):

<div v-bind:class="alertClass">
  <div class="pull-right cursor-pointer" v-on:click="destroy">&times;</div>
  {{ alert ? alert.message : "" }}
</div>

Styling isn’t so important here, so I’ll leave it out. Now that you’ve familiarized yourself with this super simple component, here’s the test that makes it work:

The working test file (app/components/alert-notification/component.spec.js), with close-to-trivial but slightly-non-trivial tests:

var should = require('should');

// Set up systemjs & JSPM
var Loader = require('jspm').Loader;
var SystemJS = new Loader();

// Define the systemjs path to the component code
var COMPONENT_JS_PATH = 'app/components/alert-notification/component.js';

describe("alert-notification component", done => {
  var Vue, Component;

  before(done => {
    Promise.all([SystemJS.import("vue"),
                 SystemJS.import(COMPONENT_JS_PATH)])
      .then(modules => {
        // Save Vue and component class to test-globals for later
        Vue = modules[0];
        Component = modules[1].default;
      })
      .then(done)
      .catch(err => {
        console.log("Error occurred during done:", err);
        done(err);
      });
  });

  describe("initial data", () => {

    it("is the correct type", () => {
      Component.data.should.have.type('function');
    });

    it("has the correct fields and default values", () => {
      var data = Component.data();
      data.should.have.type('object', "Data function should return an object");
      should(data.alert).be.undefined(); // No alert was passed in
      should(data.onlyShowLatest).be.undefined();
    });

    it("has the default data values after instantiation (with no params)", () => {
      var inst = new Vue(Component).$mount();
      should(inst.alert).be.null();
      should(inst.onlyShowLatest).be.false();
    });

    it("has the correct status class when created", () => {
      var inst = new Vue(Component).$mount();
      inst.alertClass.should.be.eql('alert-notification-component alert');
    });

  });

});

As you can see, the example is a little different from the previous blog post in a few ways:

  • Expanded importing (added vue using Promise.all)
  • More true-to-life use of describe and it
  • Use of .default due to the way I exported the components after registering them
  • More VueJS type testing

With this setup, here’s the output of make test (which is wired up to run something like mocha app/**/*.spec.js):

./node_modules/.bin/mocha app/**/*.spec.js


  alert-notification component
    initial data
      ✓ is the correct type
      ✓ has the correct fields and default values
      ✓ has the default data values after instantiation (with no params)
      ✓ has the correct status class when created

  4 passing (530ms)

If you liked this, you’ll love the next installation of this adventure in testing: Part 3 - Testing DOM with mocha