vue.jsmocha.jsmocha-webpack

mocha-webpack - dom is not updating


I am using Vue with Webpack4. And I was installed mocha-webpack for test. But I got a result of failed from Mocha. I think to count is updating, so I think to pass to test. But failed. Why I got a result like this? Maybe, VirtualDom is not updating on running of test. increment method was called on test, But not updated dom.

Test result.

 MOCHA  Testing...



  Counter.vue
    1) increments count when button is clicked


  0 passing (26ms)
  1 failing

  1) Counter.vue
       increments count when button is clicked:
     Error: expect(received).toMatch(expected)

Expected substring: "1"
Received string:    "0"
      at Context.it (/path/to/project/static/bundles/main-92a73207cfb074150def.js:7:220294)



 MOCHA  Tests completed with 1 failure(s)

setup.js

require('jsdom-global')();

global.expect = require('expect');

window.Date = Date;

Counter.vue

<template>
  <div>
    <span>{{ count }}</span>
    <button @click="increment()">Increment</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      count: 0,
    }
  },

  methods: {
    increment() {
      this.count++;
    }
  },
}
</script>

Counter.spec.js

import { shallowMount } from '@vue/test-utils'
import Counter from './Counter.vue'

describe('Counter.vue', () => {
  it('increments count when button is clicked', () => {
    const wrapper = shallowMount(Counter);
    wrapper.find('button').trigger('click');
    expect(wrapper.find('div span').text()).toMatch('1');
  });
});

package.json

    "jsdom": "^15.1.1",
    "jsdom-global": "^3.0.2",
    "mocha": "^6.2.0",
    "mocha-webpack": "^2.0.0-beta.0",

Solution

  • The problem is when you change count actual DOM is not updated at that moment. So you should wait until Vue manipulate the DOM, since Vue performs DOM manipulations asynchronously.

    For example, when you set vm.someData = 'new value', the component will not re-render immediately. It will update in the next “tick”, when the queue is flushed. Most of the time we don’t need to care about this, but it can be tricky when you want to do something that depends on the post-update DOM state.

    Exampel of code from vue-test-utilds docs:

    it('fetches async when a button is clicked', done => {
      const wrapper = shallowMount(Foo)
      wrapper.find('button').trigger('click')
      wrapper.vm.$nextTick(() => {
        expect(wrapper.vm.value).toBe('value')
        done()
      })
    })
    

    I have not worked with mocha but i assume that your code should look something like this:

    describe('Counter.vue', done => {
      it('increments count when button is clicked', () => {
        const wrapper = shallowMount(Counter);
        wrapper.find('button').trigger('click');
        wrapper.vm.$nextTick(() => {
          expect(wrapper.find('div span').text()).toMatch('1');
          done();
        });
      });
    });
    

    Async Update Queue.

    Testing Asynchronous Behavior.