Vue 测试库不会在状态更改时重新呈现 DOM

Vue Testing Library won't rerender DOM when state changes

我有一个带有直接编辑按钮的组件。 “编辑”按钮调用一个方法,将 isEditing 设置为 true

有几个输入元素带有 v-if="isEditing",因此我正在测试这些输入元素在单击“编辑”按钮后是否可见。

当我的测试运行 fireEvent.click(screen.getByRole('link', {name: 'Edit'})) 时,它正在将 isEditing 更新为真(基于我的 console.log 消息 before/after .click 事件),但是它似乎没有重新呈现测试中的组件(基于 getByRole 失败后在我的终端中呈现的 DOM)。

它在浏览器中按预期工作,但似乎没有更新规范的 DOM。我正在使用 Vue2、Vue 测试库和 Jest。

实施:

<template>
  <a @click.prevent="startEdit" v-if="!isEditing">Edit</a>
  <input :v-if="isEditing" />
</template>
...
methods: {
  startEdit: () => {
    this.isEditing = true
  }
}

规格:

describe('FormComponent', () => {
  beforeEach(() => {
    render(FormComponent)
  })

  it('displays input tags' () => {
    fireEvent.click(screen.getByRole('link', {name: 'Edit'}))
    expect(screen.getByRole('input')).toBeInTheDocument()
  })

})

它不起作用,因为你在应该 v-if 的时候写了 :v-if。我想这只是一个错字,因为你第一次就正确地做到了 (v-if="!isEditing")

问题是在 DOM 有机会更新之前,您的期望是 运行。来自 testing library documentation:

Because Vue applies DOM updates asynchronously during re-renders, the fireEvent tools are re-exported as async functions. To ensure that the DOM is properly updated in response to an event in a test, it's recommended to always await fireEvent.

您应该像这样更新您的测试以等待 fireEvent 承诺:

it('displays input tags' async () => {
    await fireEvent.click(screen.getByRole('link', {name: 'Edit'}))
    expect(screen.getByRole('input')).toBeInTheDocument()
})

正如 Nicole 在她的回答中指出的那样,您在第二个 v-if 中也有错字。