[英]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.