无法使用 Jest 中的提交按钮触发 Vuetify 表单提交
Posted
技术标签:
【中文标题】无法使用 Jest 中的提交按钮触发 Vuetify 表单提交【英文标题】:Fail to trigger Vuetify form submit using submit button in Jest 【发布时间】:2020-06-26 08:11:36 【问题描述】:我正在尝试使用 Jest 和 Avoriaz 验证基于 Vuetify 组件的 Vue 表单的行为。
我可以在表单上触发submit.prevent
,从而产生预期的行为。
但是在提交按钮上触发click
不起作用。
组件:
<template>
<v-form
ref="form"
data-cy="form"
@submit.prevent="login"
>
<v-text-field
id="email"
v-model="email"
label="Email"
name="email"
prepend-icon="mdi-at"
type="text"
required
autofocus
data-cy="email-text"
/>
<v-btn
color="primary"
type="submit"
data-cy="login-btn"
>
Login
</v-btn>
</v-form>
</template>
<script>
export default
data ()
return
email: 'test@test.com',
,
computed: ,
methods:
login: function ()
console.log('Logging in')
</script>
测试设置:
import vuetify from '@/plugins/vuetify'
import mount from 'avoriaz'
import Form from '@/views/Form'
describe('Form', () =>
const mountFunction = options =>
return mount(Form,
vuetify,
...options
)
Vue 和 Vuetify 设置在 @/plugins/vuetify
中完成:
import Vue from 'vue'
import Vuetify from 'vuetify/lib'
Vue.use(Vuetify)
export default new Vuetify(
)
以下测试成功(因此模拟工作):
it('can trigger form directly', () =>
const login = jest.fn()
const wrapper = mountFunction()
wrapper.setData( 'email': 'test@com' )
wrapper.setMethods( login )
let element = wrapper.first('[data-cy=form]')
element.trigger('submit.prevent')
expect(login).toHaveBeenCalledTimes(1)
)
但实际测试提交按钮,失败:
it('can trigger form through button', () =>
const login = jest.fn()
const wrapper = mountFunction()
wrapper.setData( 'email': 'test@test.com' )
wrapper.setMethods( login )
const button = wrapper.first('[type=submit]')
button.trigger('click')
expect(login).toHaveBeenCalledTimes(1)
)
更新:
也许package.json
中的一些相关依赖:
..
"dependencies":
"axios": "^0.19.1",
"core-js": "^3.4.4",
"vue": "^2.6.11",
"vue-router": "^3.1.3",
"vuetify": "^2.1.0",
"vuex": "^3.1.2"
,
"devDependencies":
..
"avoriaz": "^6.3.0",
"vue-jest": "^3.0.5",
"vuetify-loader": "^1.3.0"
更新:
使用 test-utils 时,非 Vuetify 组件(<form>
和 <btn
),以下测试成功:
const localVue = createLocalVue()
localVue.use(Vuetify)
describe('Form', () =>
const mountFunction = options =>
return shallowMount(Form,
localVue,
vuetify,
...options
)
it('can trigger form through button alternative', async () =>
const login = jest.fn()
const wrapper = mountFunction( attachToDocument: true )
try
wrapper.setData( 'email': 'test@test.com' )
wrapper.setMethods( login )
const button = wrapper.find('[type=submit]')
expect(button).toBeDefined()
button.trigger('click')
await Vue.nextTick()
expect(login).toHaveBeenCalledTimes(1)
finally
wrapper.destroy()
)
)
然后切换到 Vuetify 组件会导致测试失败。
【问题讨论】:
【参考方案1】:显然,当使用 Vuetify 组件(<v-form>
和 <v-btn>
)时,需要一些关键要素才能使其工作:
mount
而不是 shallowMount
包括attachToDocument
,之后也需要清理 (wrapper.destroy()
)
正如@Husam Ibrahim 也提到的,需要async
hronously await Vue.nextTick()
要让 setData 充分发挥作用,您可能需要额外的await Vue.nextTick()
。在我的完整代码中,我有表单验证(在输入上使用:rules
,在表单上使用v-model
,并且按钮的:disabled
绑定到v-model
数据元素。这需要两个nextTick()
s
以下工作('@/plugins/vuetify'
与问题中的相同:
import vuetify from '@/plugins/vuetify'
import Vue from 'vue'
import createLocalVue, mount from '@vue/test-utils'
import Form from '@/views/Form'
import Vuetify from 'vuetify/lib'
const localVue = createLocalVue()
localVue.use(Vuetify)
describe('Form', () =>
const mountFunction = options =>
return mount(Form,
localVue,
vuetify,
...options
)
it('can trigger form through button alternative', async () =>
const login = jest.fn()
const wrapper = mountFunction( attachToDocument: true )
try
wrapper.setData( 'email': 'test@test.com' )
await Vue.nextTick() # might require multiple
wrapper.setMethods( login )
const button = wrapper.find('[type=submit]')
button.trigger('click')
await Vue.nextTick()
expect(login).toHaveBeenCalledTimes(1)
finally
wrapper.destroy()
)
)
【讨论】:
很高兴您找到了解决方案 :) 对我来说它只使用mount
而不是shallowMount
就可以工作【参考方案2】:
这可能是一个异步问题。我会尝试在触发点击事件之后和断言之前等待Vue.nextTick()
..
it('can trigger form through button', async () =>
const login = jest.fn()
const wrapper = mountFunction()
wrapper.setData( 'email': 'test@test.com' )
wrapper.setMethods( login )
const button = wrapper.first('[type=submit]')
button.trigger('click')
await Vue.nextTick()
expect(login).toHaveBeenCalledTimes(1)
)
【讨论】:
我必须在 ` () => ` 之前添加async
以允许使用 await
。但仍然只观察到 0 次登录调用。
会不会有一些不确定的行为。我更改了测试运行它,观察到 1 个呼叫。然后清理,没有让测试通过。恢复了,又失败了。我的 IntelliJ 本地历史显示测试成功,使用您的代码,但现在失败了
抱歉,我忘记了 async 关键字。如果涉及任何非确定性行为,我会感到惊讶。你的代码和测试在我看来是完全确定的。
谢谢,但很遗憾无法让测试成功。以上是关于无法使用 Jest 中的提交按钮触发 Vuetify 表单提交的主要内容,如果未能解决你的问题,请参考以下文章