You’re browsing the documentation for Vue Test Utils for Vue v2.x and earlier.
To read docs for Vue Test Utils for Vue 3, click here.
Wrapper
Vue Test Utils 是一个基于包裹器的 API。
Wrapper
是一个对象,该对象包含了一个挂载的组件或 vnode,以及测试该组件或 vnode 的方法。
属性
vm
Component
(只读):这是该 Vue 实例。你可以通过 wrapper.vm
访问一个实例所有的方法和属性。这只存在于 Vue 组件包裹器或绑定了 Vue 组件包裹器的 HTMLElement 中。
element
HTMLElement
(只读):包裹器的根 DOM 节点
options
options.attachedToDocument
Boolean
(只读):如果组件在渲染之后被添加到了文档上则为 true
selector
Selector
: 被 find()
或 findAll()
创建这个 wrapper 时使用的选择器。
方法
attributes
返回 Wrapper
DOM 节点的特性对象。如果提供了 key
,则返回这个 key
对应的值。
参数:
{string} key
可选的
返回值:
{[attribute: string]: any} | string
示例:
import { mount } from '@vue/test-utils'
import Foo from './Foo.vue'
const wrapper = mount(Foo)
expect(wrapper.attributes().id).toBe('foo')
expect(wrapper.attributes('id')).toBe('foo')
classes
返回 Wrapper
DOM 节点的 class。
返回 class 名称的数组。或在提供 class 名的时候返回一个布尔值。
参数:
{string} className
可选的
返回值:
Array<{string}> | boolean
示例:
import { mount } from '@vue/test-utils'
import Foo from './Foo.vue'
const wrapper = mount(Foo)
expect(wrapper.classes()).toContain('bar')
expect(wrapper.classes('bar')).toBe(true)
contains
判断 Wrapper
是否包含了一个匹配选择器的元素或组件。
参数:
{string|Component} selector
返回值:
{boolean}
示例:
import { mount } from '@vue/test-utils'
import Foo from './Foo.vue'
import Bar from './Bar.vue'
const wrapper = mount(Foo)
expect(wrapper.contains('p')).toBe(true)
expect(wrapper.contains(Bar)).toBe(true)
- 延伸阅读:选择器
destroy
销毁一个 Vue 组件实例。
- 示例:
import { mount } from '@vue/test-utils'
import sinon from 'sinon'
const spy = sinon.stub()
mount({
render: null,
destroyed() {
spy()
}
}).destroy()
expect(spy.calledOnce).toBe(true)
如果挂载时 attachTo
或 attachToDocument
选项导致组件被挂载到文档,则组件的 DOM 元素也将会从文档中被移除。
对于函数式组件来说,destroy
只会从文档中移除渲染出来的 DOM 元素。
emitted
返回一个包含由 Wrapper
vm
触发的自定义事件的对象。
返回值:
{ [name: string]: Array<Array<any>> }
示例:
import { mount } from '@vue/test-utils'
test('emit demo', async () => {
const wrapper = mount(Component)
wrapper.vm.$emit('foo')
wrapper.vm.$emit('foo', 123)
await wrapper.vm.$nextTick() // 等待事件处理完成
/*
wrapper.emitted() 返回如下对象:
{
foo: [[], [123]]
}
*/
// 断言事件已经被触发
expect(wrapper.emitted().foo).toBeTruthy()
// 断言事件的数量
expect(wrapper.emitted().foo.length).toBe(2)
// 断言事件的有效数据
expect(wrapper.emitted().foo[1]).toEqual([123])
})
你也可以把上面的代码写成这样:
// 断言事件已经被触发
expect(wrapper.emitted('foo')).toBeTruthy()
// 断言事件的数量
expect(wrapper.emitted('foo').length).toBe(2)
// 断言事件的有效数据
expect(wrapper.emitted('foo')[1]).toEqual([123])
该 .emitted()
方法每次被调用时都返回相同的对象,而不是返回一个新的,所以当新事件被触发时该对象会被更新:
const emitted = wrapper.emitted()
expect(emitted.foo.length).toBe(1)
// 想办法让 `wrapper` 触发 "foo" 事件
expect(emitted.foo.length).toBe(2)
emittedByOrder
废弃警告
emittedByOrder
已经被废弃并会在未来的发布中被移除。
请换用 wrapper.emitted
。
返回一个包含由 Wrapper
vm
触发的自定义事件的数组。
返回值:
Array<{ name: string, args: Array<any> }>
示例:
import { mount } from '@vue/test-utils'
const wrapper = mount(Component)
wrapper.vm.$emit('foo')
wrapper.vm.$emit('bar', 123)
/*
`wrapper.emittedByOrder() 返回如下数组:
[
{ name: 'foo', args: [] },
{ name: 'bar', args: [123] }
]
*/
// 断言事件的触发顺序
expect(wrapper.emittedByOrder().map(e => e.name)).toEqual(['foo', 'bar'])
exists
断言 Wrapper
或 WrapperArray
是否存在。
如果被一个空 Wrapper
或 WrapperArray
调用则返回 false
。
返回值:
{boolean}
示例:
import { mount } from '@vue/test-utils'
import Foo from './Foo.vue'
const wrapper = mount(Foo)
expect(wrapper.exists()).toBe(true)
expect(wrapper.find('does-not-exist').exists()).toBe(false)
expect(wrapper.findAll('div').exists()).toBe(true)
expect(wrapper.findAll('does-not-exist').exists()).toBe(false)
find
废弃警告
使用 find
搜索组件的方式已经被废弃并会被移除。请换用 findComponent
。
返回匹配选择器的第一个 DOM 节点或 Vue 组件的 Wrapper
。
可以使用任何有效的 DOM 选择器 (使用 querySelector
语法)。
参数:
{string} selector
返回值:
{Wrapper}
示例:
import { mount } from '@vue/test-utils'
import Foo from './Foo.vue'
import Bar from './Bar.vue'
const wrapper = mount(Foo)
const div = wrapper.find('div')
expect(div.exists()).toBe(true)
const byId = wrapper.find('#bar')
expect(byId.element.id).toBe('bar')
注意:
- 你可以链式调用
find
:
- 你可以链式调用
const button = wrapper.find({ ref: 'testButton' })
expect(button.find('.icon').exists()).toBe(true)
- 延伸阅读:get
findAll
废弃警告
使用 findAll
搜索组件的方式已经被废弃并会被移除。请换用 findAllComponents
。
返回一个 WrapperArray
。
可以使用任何有效的选择器。
参数:
{string|Component} selector
返回值:
{WrapperArray}
示例:
import { mount } from '@vue/test-utils'
import Foo from './Foo.vue'
import Bar from './Bar.vue'
const wrapper = mount(Foo)
const div = wrapper.findAll('div').at(0)
expect(div.is('div')).toBe(true)
const bar = wrapper.findAll(Bar).at(0) // 已废弃的用法
expect(bar.is(Bar)).toBe(true)
findComponent
返回第一个匹配的 Vue 组件的 Wrapper
。
参数:
{Component|ref|name} selector
返回值:
{Wrapper}
示例:
import { mount } from '@vue/test-utils'
import Foo from './Foo.vue'
import Bar from './Bar.vue'
const wrapper = mount(Foo)
const bar = wrapper.findComponent(Bar) // => 通过组件实例找到 Bar
expect(bar.exists()).toBe(true)
const barByName = wrapper.findComponent({ name: 'bar' }) // => 通过 `name` 找到 Bar
expect(barByName.exists()).toBe(true)
const barRef = wrapper.findComponent({ ref: 'bar' }) // => 通过 `ref` 找到 Bar
expect(barRef.exists()).toBe(true)
findAllComponents
为所有匹配的 Vue 组件返回一个 WrapperArray
。
参数:
{Component|ref|name} selector
返回值:
{WrapperArray}
示例:
import { mount } from '@vue/test-utils'
import Foo from './Foo.vue'
import Bar from './Bar.vue'
const wrapper = mount(Foo)
const bar = wrapper.findAllComponents(Bar).at(0)
expect(bar.exists()).toBeTruthy()
const bars = wrapper.findAllComponents(Bar)
expect(bars).toHaveLength(1)
html
返回 Wrapper
DOM 节点的 HTML 字符串。
返回值:
{string}
示例:
import { mount } from '@vue/test-utils'
import Foo from './Foo.vue'
const wrapper = mount(Foo)
expect(wrapper.html()).toBe('<div><p>Foo</p></div>')
get
废弃警告
使用 get
搜索组件的方式已经被废弃并会被移除。请换用 getComponent
。
和 find 工作起来一样,但是如果未匹配到给定的选择器时会抛出错误。当搜索一个可能不存在的元素时你应该使用 find
。当获取一个应该存在的元素时你应该使用这个方法,并且如果没有找到的话它会提供一则友好的错误信息。
import { mount } from '@vue/test-utils'
const wrapper = mount(Foo)
// 和 `wrapper.find` 相似。
// 如果 `get` 没有找到任何元素将会抛出一个而错误。`find` 则不会做任何事。
expect(wrapper.get('.does-exist'))
expect(() => wrapper.get('.does-not-exist'))
.to.throw()
.with.property(
'message',
'Unable to find .does-not-exist within: <div>the actual DOM here...</div>'
)
is
废弃警告
使用 is
断言 DOM 结点或 vm
匹配选择器的方式已经被废弃并会被移除。
可以考虑一个诸如 jest-dom 提供的自定义匹配。或为 DOM 元素类型断言换用原生的 Element.tagName
。
为了保留这些测试,一个有效替换:
is('DOM_SELECTOR')
的方式是一个wrapper.element.tagName
的断言。is('ATTR_NAME')
的方式是一个wrapper.attributes('ATTR_NAME')
的 truthy 断言。is('CLASS_NAME')
的方式是一个wrapper.classes('CLASS_NAME')
的 truthy 断言。
当使用 findComponent
时,通过 findComponent(Comp).element
访问 DOM 元素。
断言 Wrapper
DOM 节点或 vm
匹配选择器。
参数:
{string|Component} selector
返回值:
{boolean}
示例:
import { mount } from '@vue/test-utils'
import Foo from './Foo.vue'
const wrapper = mount(Foo)
expect(wrapper.is('div')).toBe(true)
isEmpty
废弃警告
isEmpty
已经被废弃并会在未来的发布中被移除。
可以考虑一个诸如 jest-dom 中提供的自定义匹配。
当使用 findComponent
时,可以通过 findComponent(Comp).element
访问其 DOM 元素。
断言 Wrapper
并不包含子节点。
返回值:
{boolean}
示例:
import { mount } from '@vue/test-utils'
import Foo from './Foo.vue'
const wrapper = mount(Foo)
expect(wrapper.isEmpty()).toBe(true)
isVisible
断言 Wrapper
是否可见。
如果有一个祖先元素拥有 display: none
或 visibility: hidden
样式则返回 false
。
这可以用于断言一个组件是否被 v-show
所隐藏。
返回值:
{boolean}
示例:
import { mount } from '@vue/test-utils'
import Foo from './Foo.vue'
const wrapper = mount(Foo)
expect(wrapper.isVisible()).toBe(true)
expect(wrapper.find('.is-not-visible').isVisible()).toBe(false)
isVueInstance
废弃警告
isVueInstance
已经被废弃并会在未来的发布中被移除。
依赖 isVueInstance
断言的测试并没有特别大的意义,我们建议将与之相关的断言替换为更有目的性的断言。
为了保留这些测试,一个替换 isVueInstance()
的可行方式是对 wrapper.find(...).vm
的 truthy 断言。
断言 Wrapper
是 Vue 实例。
返回值:
{boolean}
示例:
import { mount } from '@vue/test-utils'
import Foo from './Foo.vue'
const wrapper = mount(Foo)
expect(wrapper.isVueInstance()).toBe(true)
name
废弃警告
name
已经被废弃并会在未来的发布中被移除。
如果 Wrapper
包含一个 Vue 实例则返回组件名,否则返回 Wrapper
DOM 节点的标签名。
返回值:
{string}
示例:
import { mount } from '@vue/test-utils'
import Foo from './Foo.vue'
const wrapper = mount(Foo)
expect(wrapper.name()).toBe('Foo')
const p = wrapper.find('p')
expect(p.name()).toBe('p')
props
返回 Wrapper
vm
的 props 对象。如果提供了 key
,则返回这个 key
对应的值。
注意:该包裹器必须包含一个 Vue 实例。
参数:
{string} key
可选的
返回值:
{[prop: string]: any} | any
示例:
import { mount } from '@vue/test-utils'
import Foo from './Foo.vue'
const wrapper = mount(Foo, {
propsData: {
bar: 'baz'
}
})
expect(wrapper.props().bar).toBe('baz')
expect(wrapper.props('bar')).toBe('baz')
setChecked
设置 checkbox 或 radio 类 <input>
元素的 checked 值并更新 v-model
绑定的数据。
参数:
{Boolean} checked (默认值:true)
示例:
import { mount } from '@vue/test-utils'
import Foo from './Foo.vue'
test('setChecked demo', async () => {
const wrapper = mount(Foo)
const radioInput = wrapper.find('input[type="radio"]')
await radioInput.setChecked()
expect(radioInput.element.checked).toBeTruthy()
})
- 注意:
当你尝试通过 radioInput.element.checked = true; radioInput.trigger('input')
经由 v-model
向 state 设置值的时候,v-model
不会被触发。v-model
是被 change
事件触发的。
checkboxInput.setChecked(checked)
是接下来这段代码的别名。
checkboxInput.element.checked = checked
checkboxInput.trigger('click')
checkboxInput.trigger('change')
setData
设置 Wrapper
vm
的属性。
setData
通过递归调用 Vue.set
生效。
注意:该包裹器必须包含一个 Vue 示例。
参数:
{Object} data
示例:
import { mount } from '@vue/test-utils'
import Foo from './Foo.vue'
test('setData demo', async () => {
const wrapper = mount(Foo)
await wrapper.setData({ foo: 'bar' })
expect(wrapper.vm.foo).toBe('bar')
})
setMethods
废弃警告
setMethods
已经被废弃并会在未来的发布中被移除。
这里没有明确的路径替换 setMethods
,因为这取决于你之前的用法。这很容易导致依赖实现细节的琐碎的测试,而这是不推荐的。
我们建议重新考虑那些测试。
如果是为了存根一个复杂方法,可将其从组件中提取出来并单独测试。如果是为了断言一个方法被调用,可使用你的测试运行器窥探它。
设置 Wrapper
vm
的方法并强制更新。
注意:该包裹器必须包含一个 Vue 示例。
参数:
{Object} methods
示例:
import { mount } from '@vue/test-utils'
import sinon from 'sinon'
import Foo from './Foo.vue'
const wrapper = mount(Foo)
const clickMethodStub = sinon.stub()
wrapper.setMethods({ clickMethod: clickMethodStub })
wrapper.find('button').trigger('click')
expect(clickMethodStub.called).toBe(true)
setProps
参数:
{Object} props
用法:
设置 Wrapper
vm
的 prop 并强制更新。
注意:该包裹器必须包含一个 Vue 示例。
import { mount } from '@vue/test-utils'
import Foo from './Foo.vue'
test('setProps demo', async () => {
const wrapper = mount(Foo)
await wrapper.setProps({ foo: 'bar' })
expect(wrapper.vm.foo).toBe('bar')
})
你也可以传递一个 propsData
对象,这会用该对象来初始化 Vue 示例。
// Foo.vue
export default {
props: {
foo: {
type: String,
required: true
}
}
}
import { mount } from '@vue/test-utils'
import Foo from './Foo.vue'
const wrapper = mount(Foo, {
propsData: {
foo: 'bar'
}
})
expect(wrapper.vm.foo).toBe('bar')
setSelected
选择一个 option 元素并更新 v-model
绑定的数据。
- 示例:
import { mount } from '@vue/test-utils'
import Foo from './Foo.vue'
test('setSelected demo', async () => {
const wrapper = mount(Foo)
const options = wrapper.find('select').findAll('option')
await options.at(1).setSelected()
expect(wrapper.find('option:checked').element.value).toBe('bar')
})
- 注意:
当你尝试通过 option.element.selected = true; parentSelect.trigger('input')
经由 v-model
向 state 设置值的时候,v-model
不会被触发。v-model
是被 change
事件触发的。
option.setSelected()
是接下来这段代码的别名。
option.element.selected = true
parentSelect.trigger('change')
setValue
设置一个文本控件或 select 元素的值并更新 v-model
绑定的数据。
参数:
{String} value
示例:
import { mount } from '@vue/test-utils'
import Foo from './Foo.vue'
test('setValue demo', async () => {
const wrapper = mount(Foo)
const textInput = wrapper.find('input[type="text"]')
await textInput.setValue('some value')
expect(wrapper.find('input[type="text"]').element.value).toBe('some value')
const select = wrapper.find('select')
await select.setValue('option value')
expect(wrapper.find('select').element.value).toBe('option value')
// requires <select multiple>
const multiselect = wrapper.find('select')
await multiselect.setValue(['value1', 'value3'])
const selectedOptions = Array.from(multiselect.element.selectedOptions).map(
o => o.value
)
expect(selectedOptions).toEqual(['value1', 'value3'])
})
注意:
textInput.setValue(value)
是接下来这段代码的别名。
textInput.element.value = value textInput.trigger('input')
select.setValue(value)
是接下来这段代码的别名。
select.element.value = value select.trigger('change')
text
返回 Wrapper
的文本内容。
返回值:
{string}
示例:
import { mount } from '@vue/test-utils'
import Foo from './Foo.vue'
const wrapper = mount(Foo)
expect(wrapper.text()).toBe('bar')
trigger
在该 Wrapper
DOM 节点上异步触发一个事件。
trigger
带有一个可选的 options
对象。options
对象内的属性会被添加到事件上。trigger
会返回一个 Promise,当这个 Promise 被解决时,会确保组件已经被更新。
参数:
{string} eventType
必填{Object} options
可选
示例:
import { mount } from '@vue/test-utils'
import sinon from 'sinon'
import Foo from './Foo'
test('trigger demo', async () => {
const clickHandler = sinon.stub()
const wrapper = mount(Foo, {
propsData: { clickHandler }
})
await wrapper.trigger('click')
await wrapper.trigger('click', {
button: 0
})
await wrapper.trigger('click', {
ctrlKey: true // 用于测试 @click.ctrl 处理函数
})
expect(clickHandler.called).toBe(true)
})
- 设置事件目标:
在这背后,trigger
创建了一个 Event
对象并分发到其包裹器的元素上。
我们没有机会编辑 Event
对象的 target
值,所以你无法在选项对象中设置 target
。
如果想在 target
中添加一个特性,你需要在调用 trigger
之前设置包裹器元素的那个值。你可以通过 element
属性做到这件事。
const input = wrapper.find('input')
input.element.value = 100
input.trigger('click')
← API WrapperArray →