簡體   English   中英

如何使用 Mocha 在 Vue.js 中測試 DOM 更新?

[英]How to test DOM update in Vue.js with Mocha?

我正在努力理解使用 Karma、Mocha 和 Chai 在 Vue.js 中進行單元測試的一些基本概念。

這是我的組件:

VueExample.vue

<template>
    <div>
        <p>{{ name }}</p>
        <input v-model="name">
    </div>
</template>

<script>
    export default {
        name: 'VueExample',
        data () {
            return {
                name: 'Bruce Lee'
            };
        }
    }
</script>

這就是我試圖測試它的方式:

VueExample.spec.js

import Vue from 'vue';
import VueExample from "../../../components/VueExample";

describe('VueExample.vue', () => {
    let vm;

    beforeEach(() => {
        const Constructor = Vue.extend(VueExample);
        vm = new Constructor().$mount();
    });

    it('should change the name', done => {
        const input = vm.$el.querySelector('input');
        input.value = 'Chuck Norris';
        expect(vm.$el.querySelector('p').textContent).to.equal('Bruce Lee');
        Vue.nextTick(() =>{
            expect(vm.$el.querySelector('p').textContent).to.equal('Chuck Norris');
            console.log(vm.$el.querySelector('p').textContent);
            done();
        });
    });
});

我使用 Karma 來運行測試,使用 Chai 作為斷言庫。 一切都在karma.conf.js正確配置。 當我運行這個測試時,它失敗了。 標簽<p>內的文本不會改變。 console.log命令輸出Bruce Lee

測試是在 Firefox 上運行的。

v-model 依賴於 input event ,這不是簡單地通過在 JavaScript 中編輯輸入的值來發生的。 在 Vue 之外也是如此,如下所示:

 function logInput(e) { console.log('input', e.target.value) } function update() { const input = document.querySelector('#input1') input.value = "foo" }
 <input oninput="logInput(event)" id="input1"> <button onclick="update()">Update textbox</button> <div>Clicking button changes text but does not emit <code>input</code> event. See console.</div>

在您的測試中手動調度輸入事件應該可以工作。 在您的示例中,在設置input.value后執行input.dispatchEvent(new Event('input'))

const input = vm.$el.querySelector('input');
input.value = 'Chuck Norris';
input.dispatchEvent(new Event('input')); // input event required to update v-model

更改 input 的值不會觸發 Vue 更新模型(因為 input 的屬性不是響應式的)。

您可以在瀏覽器中嘗試。 在控制台中運行document.getElementsByTagName('input')[0].value = 'Chuck Norris'並沒有任何反應, p元素的文本仍然是“李小龍”。

觸發Vue的方式是通過input事件。 所以你應該調度一個input事件。 這可能是這樣的:

let event = document.createEvent('HTMLEvents')
event.initEvent('input', true, true)
vm.$el.querySelector('input').dispatchEvent(event)

在@Anatoly 的評論之一中,建議使用Vue Test Utils 我在玩,想出了一個我想分享的解決方案:

yarn add -D @vue/test-utils

或者:

npm install --save-dev @vue/test-utils

然后測試文件如下所示:

import Vue from 'vue';
import { shallowMount } from '@vue/test-utils';
import VueExample from "../../../components/VueExample";

describe('VueExample.vue', () => {
  let wrapper;

  beforeEach(() => {
    wrapper = shallowMount(VueExample);
  });

  it('should change the name', done => {
    const textInput = wrapper.find('input');
    textInput.setValue('Chuck Norris');
    textInput.trigger('input');
    expect(wrapper.find('p').text()).to.equal('Bruce Lee');
    Vue.nextTick(() => {
      expect(wrapper.find('p').text()).to.equal('Chuck Norris');
      done();
    });
  });
});

在這個例子中只有一個測試,但我仍然使用beforeEach使它更容易通過進一步的測試進行擴展。 這里我們掛載了 Vue 組件VueExample 在測試中我們找到了<input>標簽,將其值設置為Chuck Norris並觸發input事件。 我們可以看到<p>標簽的文本節點沒有變化,仍然是Bruce Lee 這是由於 Vue 中 DOM 更新的異步性質。

使用nextTick()我們可以檢查nextTick()是否生效並且<p>標簽的文本節點等於之前的設置值,即Chuck Norris

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM