Vue2下Vue Testing Library状态变更后未重新渲染DOM问题咨询
问题解决方法
原因分析
- Vue的响应式数据更新是同步的,但DOM更新是异步执行的微任务。你能打印到
isEditing变成true,但是此时DOM还没完成更新,测试代码里同步调用getByRole会在DOM渲染前执行查询,自然查不到对应元素。
- Vue的响应式数据更新是同步的,但DOM更新是异步执行的微任务。你能打印到
- 测试代码中查询input的
role参数错误:原生input元素默认的ARIA role是textbox,不存在input这个role值,参数错误也会导致查询失败。
- 测试代码中查询input的
- 现有代码存在两处语法问题:
- 组件模板中input的条件渲染指令写为
:v-if多了多余的冒号,正确写法是v-if="isEditing" - methods里的
startEdit方法用了箭头函数,会导致this指向不是组件实例;同时测试用例的it方法参数少了逗号分隔。
修复代码
组件代码修正
<template> <a @click.prevent="startEdit" v-if="!isEditing">Edit</a> <input v-if="isEditing" /> </template> ... methods: { startEdit() { this.isEditing = true } }
测试代码修正
两种可选方案:
方案1:使用findBy*异步查询(推荐)
findBy*系列方法是getBy*和waitFor的组合,默认会等待最多1000ms直到元素出现,适配Vue异步更新的场景。
describe('FormComponent', () => { beforeEach(() => { render(FormComponent) }) it('displays input tags', async () => { fireEvent.click(screen.getByRole('link', {name: 'Edit'})) // 改用findBy异步查询,注意测试函数要加async expect(await screen.findByRole('textbox')).toBeInTheDocument() }) })
方案2:手动加waitFor包裹断言
describe('FormComponent', () => { beforeEach(() => { render(FormComponent) }) it('displays input tags', async () => { fireEvent.click(screen.getByRole('link', {name: 'Edit'})) await waitFor(() => { expect(screen.getByRole('textbox')).toBeInTheDocument() }) }) })
内容的提问来源于stack exchange,提问作者Eddie
相关产品推荐
相关产品推荐

