Как проверить обновление DOM в Vue. js с помощью Mocha? - PullRequest
6 голосов
/ 24 января 2020

Я изо всех сил пытаюсь понять некоторые основные c концепции модульного тестирования в 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.conf.js. Когда я запускаю этот тест, он не проходит. Текст внутри тега <p> не меняется. Команда console.log выводит Брюса Ли .

Тесты выполняются с Firefox.

Ответы [ 3 ]

3 голосов
/ 01 февраля 2020

v-model зависит от события ввода , которое не происходит просто путем редактирования значения ввода в 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.dispatchEvent(new Event('input')) после установки input.value:

const input = vm.$el.querySelector('input');
input.value = 'Chuck Norris';
input.dispatchEvent(new Event('input')); // input event required to update v-model
1 голос
/ 11 февраля 2020

В одном из комментариев @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>, устанавливаем его значение Чак Норрис и запускаем событие input. Мы видим, что текстовый узел тега <p> не изменился и по-прежнему говорит Брюс Ли . Это связано с асинхронным характером обновлений DOM в Vue.

. Используя nextTick(), мы можем проверить, что изменение вступило в силу, а текстовый узел тега <p> равен предыдущему установленному значению. Чак Норрис .

1 голос
/ 29 января 2020

При изменении значения ввода не запускайте Vue для обновления модели (поскольку свойства ввода не реагируют). '

Вы можете попробовать его в своем браузере. Запустите в консоли 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)
...