# Vue Test Utils

# Wrapper

Vue Test Utils 是一个基于包裹器的 API。

一个 Wrapper 是一个包括了一个挂载组件或 vnode,以及测试该组件或 vnode 的方法 通过mount、shallow等方法进行挂载返回一个包裹器对象,包裹器会暴露很多封装、遍历和查询其内部的Vue组件实例的便捷的方法。

// 通过mount挂载返回包含所有子组件的包裹器
const wrapper =  mount(Button,{
  propsData: {
    type: 'primary'
  }
});
// 使用shallowMount进行挂载不返回包含子组件的包裹器
const wrapper =  shallowMount(Button,{
  propsData: {
    type: 'primary'
  }
});

# Wrapper具有的属性

vm:这是该组件的实例。你可以通过 wrapper.vm 访问一个实例所有的方法和属性。

const vm =  shallowMount(Button,{
  propsData: {
    type: 'primary'
  }
}).vm;
console.log(vm.$el);  // 获取这个实例的节点结构

element:包裹器的根 DOM 节点,他的值与vm.$el相同。

const element =  shallowMount(Button,{
  propsData: {
    type: 'primary'
  }
}).element;
console.log(element);  // 获取这个实例的节点结构

options:options.attachedToDocument,如果组件在渲染之后被添加到了文档上则为真。

const options =  shallowMount(Button,{
    propsData: {
      type: 'primary'
    }
  }).options;
console.log(options);  // Object{attachedToDocument: false}

# Wrapper具有的方法

attributes:返回 Wrapper DOM节点的特性对象。如果提供了 key,则返回这个 key 对应的值。

const wrapper =  shallowMount(Button,{
    propsData: {
      type: 'primary'
    }
  });
console.log(wrapper.attribute());
// Object{data-v-03ab08b4: '', class: 'y-button y-button-primary y-button-left'}

classes:返回 class 名称的数组。

const wrapper =  shallowMount(Button,{
    propsData: {
      type: 'primary'
    }
});
console.log(wrapper.classes());// ['y-button', 'y-button-primary', 'y-button-left']

contains:是否包含匹配的选择器或者组件

import Icon from './icon.vue;
console.log(wrapper.contains('button.y-button-primary'));// 是否包含类名为y-button-primary的button组件
console.log(wrapper.contains(Icon));// 是否包含Icon组件

这里需要注意,我们这里引入的Icon与我们实际在Button组件中使用的Icon名字可能不一样。比如我们实际中使用的Icon名字是y-icon,如下所示:

<button data-v-03ab08b4="" class="y-button y-button-primary y-button-left">
  <y-icon data-v-03ab08b4="" name="settings"></y-icon>
</button>

那么这时候我们需要使用替换功能,将y-icon替换为Icon,通过设置stubs值即可。

const wrapper =  shallowMount(Button,{
  propsData: {
    type: 'primary',
    icon:'settings'
  },
  stubs:{  //替换功能
    'y-icon':Icon
  },
});

html:返回DOM节点的HTML字符串。我们可以用来判断是否与我们写的结构相同。

console.log(wrapper.html());
'<button data-v-03ab08b4="" class="y-button y-button-primary y-button-left"><svg data-v-03ab08b4="" aria-hidden="true" class="icon"><use xlink:href="#i-settings"></use></svg></button>'
expect(wrapper.html()).toBe('<button><p>Foo</p></button>')

props:返回 Wrapper vm 的 props 对象。如果提供了 key,则返回这个 key 对应的值。

const wrapper =  shallowMount(Button,{
  propsData: {
    type: 'primary',
    icon:'settings'
  },
  stubs:{  //替换功能
    'y-icon':Icon
  },
});
console.log(wrapper.props());
// Object{type: 'primary', disabled: false, round: false, icon: 'settings', iconPosition: 'left'}

注意:我们这里获得的是实例vm的所有的props对象,而不仅仅只是我们自己写的{type,icon}这两个对象。我们写的这两个 对象会覆盖原来的实例props的默认值而已。 setData:设置vm的data值。

const wrapper = shallowMount(Button)
wrapper.setData({ foo: 'bar' })
expect(wrapper.vm.foo).toBe('bar')

setProps:设置vm的props值,并强制更新。

const wrapper = moshallowMountunt(Button)
wrapper.setProps({ foo: 'bar' })
expect(wrapper.vm.foo).toBe('bar');

我们同样可以使用传入一个propsData对象来实现初始化设置props值:

const wrapper =  shallowMount(Button,{
  propsData: {
    type: 'primary',
    icon:'settings'
  }
});

trigger:在节点上触发一个事件:

import sinon from 'sinon'
test('trigger demo', async () => {
  const clickHandler = sinon.stub()
  const wrapper = mount(Foo, {
    propsData: { clickHandler }
  })
  wrapper.trigger('click')
  wrapper.trigger('click', {
    button: 0
  })
  wrapper.trigger('click', {
    ctrlKey: true // 用于测试 @click.ctrl 处理函数
  })
  await wrapper.vm.$nextTick() // 等待事件处理完成
  expect(clickHandler.called).toBe(true)
})

事实上,我们很难直接判断一个点击的回调函数是否执行了。这里需要使用sinon来帮助我们判断 函数是否执行了。对于点击事件这种异步事件,需要等待事件处理完成,下一个nextTick更新后才能够判断。

await wrapper.vm.$nextTick() // 等待事件处理完成
expect(clickHandler.called).toBe(true)