Jest + Vue

Who is this for?

What should you know?

Structure of this talk

  • Set up Jest in a Vue project
  • Syntax and test example
  • Running jest on a terminal
  • Is it worth it?

What is Jest?

  • Jest is a javascript testing framework
  • Works with many js libraries, like Babel, TypeScript, Node, React, Angular, Vue
  • Contains entire toolkit - running on browser (like karma), framework (describe, it, like mocha), expectation library (expect, like chai), mocking (.stub(), like sinon), coverage (uses istanbul), snapshot support.
    • Note this guide does not go into testing snapshots.
  • Created originally for React by Facebook developers.

How to set it up?

  • Using VueCLI you can select 'Jest' as a unit testing option so it is set up for you (recommended)
  • npm install -g vue-cli
  • vue create my-jest-vue-app

How to set it up?

How to set it up?

vue cli setup reference

How to set it up?

module.exports = {
    moduleFileExtensions: ['js', 'jsx', 'json', 'vue'],
    collectCoverageFrom: [
        'src/**/*.{vue,js}',
        '!src/main.js',
        '!src/shared/*',
    ],
    transform: {
        '^.+\\.vue$': 'vue-jest',
        '.+\\.(css|styl|less|sass|scss|svg|png|jpg|ttf|woff|woff2)$':
      'jest-transform-stub',
        '^.+\\.jsx?$': 'babel-jest',
    },
    moduleNameMapper: {
        '^@/test(.*)$': '<rootDir>/test/$1',
        '^@/(.*)$': '<rootDir>/src/$1',
    },
    snapshotSerializers: ['jest-serializer-vue'],
    testMatch: [
        '**/test/unit/**/*.spec.(js|jsx|ts|tsx)|**/__test__/*.(js|jsx|ts|tsx)',
    ],
    testURL: 'http://localhost/',
};
  • You will get a jest.config.js file that will look something like this:

How to set it up?

  • You can run unit testing commands through npm/yarn:

Using Jest

Before we start

  • Jest is basically a replacement for Mocha, chai, karma, and sinon, but it isn't a replacement for vue-test-utils (or avoriaz, if you're living in 2017), we still need that to test vue components.
  • I won't be going over the snapshot feature here

Basic setup of a jest file

  • Basic setup is similar to a Mocha/chai/sinon file, but:
    • there's no sinon sandbox setup needed
    • the syntax for expects and stubs is different.

Basic setup of a jest file

Vue file to test

Basic setup of a jest file

Using mocha/chai/sinon

😬

Basic setup of a jest file

Using mocha/chai/sinon (cont'd)

Basic setup of a jest file

Using Jest

😮

Stubs syntax

// sinon:

vm.$store.dispatch = sandbox.stub();

// Jest:

vm.$store.dispatch = jest.fn();

Expect syntax

// chai:

expect(vm.property).to.be.true;

expect(vm.property).to.equal(1);

expect(vm.property).to.deep.equal({ prop: "1" });

// Jest:

expect(vm.$store.dispatch).toEqual(true);

expect(vm.$store.dispatch).toEqual(1);

expect(vm.$store.dispatch).toEqual({ prop: "1" });

Expect syntax

// chai:

expect(vm.$store.dispatch).to.have.been.calledOnce;

// Jest:

expect(vm.$store.dispatch).toHaveBeenCalledTimes(1);

Running Jest

Running Jest

  • Tests run in parallel
  • You get great output just from the terminal
    • I won't be going over browser testing

Running Jest

A dispatch success/fail example

method in vue

Jest test

Terminal error example

Is it worth it?

TL;DR:

For new projects? yes.

For existing ones? no.

The good parts of Jest: a summary

  • All-in-one 
  • Expectation autocomplete in IDE
  • Limited expect choices
    • easier to remember, more consistency
  • No need for setup/tear down in spec files
  • Runs fast
  • Pinpoint failures in terminal is easy
  • uncovered lines show in IDE

The bad parts of Jest: a summary

  • All-in-one 
    • Can't pick and choose best tools for the job
  • Parallel test running is fast but MAGIC
    • if it breaks how do we fix it?
  • .only not working
    • The docs say it does, but stackoverflow and my own testing says different
  • Have to stub every design system component or you get errors
  • Snapshots?? (TODO)
  • coverage:
    • doesn't output to html file, just terminal (that I know of)
    • mounted/destroy/watch/mapState/mapGetters shown as not covered on coverage report

My impressions: in this essay i will

Jest runs really fast, and I like how straightforward it is. There isn't much "magic" involved; you have to explicitly state everything you're passing into it, and doesn't do much for you. I'm not a fan of how .only and .skip don't work properly, however - the documentation says it should work, but there are a few stackoverflow questions opened about it and in my own testing I haven't seen it work correctly. I think the snapshots feature would be cool if we can find a good way to use it, but until then, it just kind of gets in the way of doing reliable searches.

 

The thing that is "magic" about Jest is that it looks like it's handling a lot behind the scenes when it comes to running the tests quickly, like breaking them up into suites and running in parallel. This is great, and makes them run lightning fast, but it also means that if something breaks with that async magic it's going to be really hard to debug.

 

I really like how we don't have to use sinon, and the spy/stub logic in jest seems less bloated and full of things we don't need/use. That being said, I still like using the piecemeal solution of separate, small, easy-to-use and ubiquitous libraries as opposed to the one solution that jest brings. Having different small parts makes them easier to replace individually, and the drawbacks listed previously can be a real pain.

 

It's clear that jest has a lot of traction in the community, and should be considered for new projects;

however, I don't think it has enough plusses to warrant changing our existing projects that use Vue to the Jest framework.

Resources

Jest + Vue

By Laurel Bruggeman

Jest + Vue

  • 572