more testing with jspm mocha and vuejs

Categories

This post still working for you?

It's been a while since this was posted. Hopefully the information in here is still useful to you (if it isn't please let me know!). If you want to get the new stuff as soon as it's out though, sign up to the mailing list below.

Join the Mailing list

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

Like what you're reading? Get it in your inbox