Как вызвать событие с Vue Test Utils на элементе BootstrapVue? - PullRequest
2 голосов
/ 05 марта 2020

Эта проблема доставляет мне трудности, и я не могу понять, как заставить Vue Test Utils и BootstrapVue хорошо играть вместе.

Минимальный пример будет выглядеть так:

MyComponent.vue

<template>
  <div>
    <b-button variant="primary" @click="play">PLAY</b-button>
  </div>
</template>

<script>
export default {
  name: 'MyComponent',
  methods: {
    play() {
      console.log("Let's play!");
    }
  }
}
</script>

В main.js мы используем BootstrapVue: Vue.use(BootstrapVue).

Вот как я пытаюсь проверить, было ли инициировано событие click:

import { expect } from 'chai';
import sinon from 'sinon';
import Vue from 'vue';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import BootstrapVue, { BButton } from 'bootstrap-vue';
import MyComponent from '@/components/MyComponent.vue';

const localVue = createLocalVue();
localVue.use(BootstrapVue);

describe('MyComponent.vue', () => {
  it('should call the method play when button is clicked', () => {
    const playSpy = sinon.spy();
    const wrapper = shallowMount(MyComponent, {
      localVue,
      methods: {
        play: playSpy,
      },
    });
    wrapper.find(BButton).trigger('click');
    expect(playSpy.called).to.equal(true);
  });
});

Это дает мне:

  AssertionError: expected false to equal true
  + expected - actual

  -false
  +true

Я проверил Как проверить наличие bootstrap vue компонента в модульных тестах с шуткой? , но это не относится к BButton.

При выполнении теста я также не вижу никаких выходных данных в командной строке, где я ожидал бы, что эта строка будет выполнена:

console.log("Let's play!");

Что здесь не так?

1 Ответ

2 голосов
/ 05 марта 2020

Причина, по которой событие click не может быть вызвано, заключается в том, как shallowMount работает в отличие от mount.

Как мы знаем, Vue Test Utils предоставляют два метода для смонтировать компонент, т.е. отрендерить шаблон и сгенерировать дерево DOM:

  • mount
  • shallowMount

Первый метод mount создает полный DOM дерево и проходит через все дочерние компоненты. В большинстве случаев в этом нет необходимости, поэтому метод shallowMount предпочтителен - он заглушает дочерние компоненты всего на один уровень ниже родительского компонента.

В моем случае это была также root проблемы , BootstrapVue предоставляет компоненты, такие как BButton, которые могут использоваться в ваших собственных Vue шаблонах. Это означает, что в следующем шаблоне:

<template>
  <div>
    <b-button variant="primary" @click="play">PLAY</b-button>
  </div>
</template>

кнопка b является дочерним компонентом, который заглушается при использовании shallowMount в модульных тестах для нашего компонента. Вот почему мы не можем найти кнопку элемента:

const wrapper = shallowMount(MyComponent);
wrapper.find('button'); // won't work

Мы можем найти дочерний компонент следующим образом:

wrapper.find(BButton); // BButton has to be imported from bootstrap-vue

, но если мы попытаемся вывести визуализированный элемент:

console.log(wrapper.find(BButton).element);

мы получим:

HTMLUnknownElement {}

BButton как дочерний компонент не был полностью обработан, и в дереве DOM нет элемента button. Но когда мы используем mount, мы имеем такое поведение:

const wrapper = mount(MyComponent);
console.log(wrapper.find(BButton).element);

, мы получим:

HTMLButtonElement { _prevClass: 'btn btn-primary' }

Мы видим, что mount визуализировал дочерний компонент. Когда мы используем mount, мы можем напрямую получить доступ к элементу button:

wrapper.find('button');

Теперь, когда у нас есть button, мы можем вызвать на нем событие типа click.

Надеюсь, это поможет и другим новичкам. Примеры очень упрощены, не забудьте создать localVue с использованием createLocalVue и передать его методу mount, как показано в вопросе.

При использовании BootstrapVue очень тщательно продумайте, какой способ монтажа вам нужен.

...