找到元素

通过 find 方法,vue-test-utils 提供了找到并断言 HTML 元素或其他 Vue 组件是否存在的许多方式。find 的主要用处就是断言一个组件是否正确地渲染了元素或子组件。

在本页中所描述的测试源码可以在 这里找到元素和组件 - 图1 找到。

创建组件

对于本例,我们将创建一个 <Child> 组件和一个 <Parent> 组件。

Child:

  1. <template>
  2. <div>Child</div>
  3. </template>
  4. <script>
  5. export default {
  6. name: "Child"
  7. }
  8. </script>

Parent:

  1. <template>
  2. <div>
  3. <span v-show="showSpan">
  4. Parent Component
  5. </span>
  6. <Child v-if="showChild" />
  7. </div>
  8. </template>
  9. <script>
  10. import Child from "./Child.vue"
  11. export default {
  12. name: "Parent",
  13. components: { Child },
  14. data() {
  15. return {
  16. showSpan: false,
  17. showChild: false
  18. }
  19. }
  20. }
  21. </script>

有着 querySelector 语法的 find

正如通过使用 document.querySelector 语法,可以轻易地选取普通的 HTML 元素;vue-test-utils 也提供了一个 isVisible 方法以检查元素是否被 v-show 条件性地渲染了。创建一个 Parent.spec.js,并输入下面的测试代码:

  1. import { mount, shallowMount } from "@vue/test-utils"
  2. import Parent from "@/components/Parent.vue"
  3. describe("Parent", () => {
  4. it("does not render a span", () => {
  5. const wrapper = shallowMount(Parent)
  6. expect(wrapper.find("span").isVisible()).toBe(false)
  7. })
  8. })

因为 v-show="showSpan" 默认为 false,我们期望找到的 <span> 元素的 isVisible 方法会返回 false。当运行 yarn test:unit 后测试通过了。下一步,添加一个当 showSpantrue 时的测试:

  1. it("does render a span", () => {
  2. const wrapper = shallowMount(Parent, {
  3. data() {
  4. return { showSpan: true }
  5. }
  6. })
  7. expect(wrapper.find("span").isVisible()).toBe(true)
  8. })

它也通过了!

isVisible 之于 v-show 非常相似的是,vue-test-utils 提供了一个 exists 方法以用来测试当使用 v-if 时元素被条件性渲染的情况。

通过 nameComponent 找到组件

找到子组件和找到普通 HTML 元素稍有不同。主要有两种方法来断言 Vue 子组件的存在:

  1. find(Component)
  2. find({ name: "ComponentName" })

这两种方法在一个例子中可能更好理解一些。让我们从 find(Component) 语法开始。这需要 import 组件,并将其引用传入 find 函数中。

  1. import Child from "@/components/Child.vue"
  2. it("does not render a Child component", () => {
  3. const wrapper = shallowMount(Parent)
  4. expect(wrapper.find(Child).exists()).toBe(false)
  5. })

find 的实现颇为复杂,因为它要以 querySelector 的语法工作,同时也有很多其他的语法。你可以看看源码中关于找到 Vue 子组件的 这个部分找到元素和组件 - 图2。基本上它检查了每个渲染过的子组件的 name 属性,其后检查 constructor,还有一些其他属性。

正如上一段中提到的,当你传给 find 方法一个组件时,name 属性是其检查手段之一(译注:源码在 这里找到元素和组件 - 图3)。其实除了传递一个组件,你也可以简单地传入一个有着正确 name 属性的对象。这意味着你无需 import 相应的组件。让我们用这种方法来试试 <Child> 应当被渲染的情况:

  1. it("renders a Child component", () => {
  2. const wrapper = shallowMount(Parent, {
  3. data() {
  4. return { showChild: true }
  5. }
  6. })
  7. expect(wrapper.find({ name: "Child" }).exists()).toBe(true)
  8. })

通过!使用 name 会有那么一点不直观, 所以引入真实的组件也是个辙。另一个选项是像头两个例子中出现的那样简单地添加一个 classid 并用 querySelector 的语法样式查询。

findAll

想要断言一定数量的元素都被渲染了也是个频发的场景。一个通常的案例是通过 v-for 渲染出的一个项目列表。比如下面这个 <ParentWithManyChildren> 就渲染出了若干 <Child> 组件。

  1. <template>
  2. <div>
  3. <Child v-for="id in [1, 2 ,3]" :key="id" />
  4. </div>
  5. </template>
  6. <script>
  7. import Child from "./Child.vue"
  8. export default {
  9. name: "ParentWithManyChildren",
  10. components: { Child }
  11. }
  12. </script>

我们可以像这样用 findAll 编写测试以断言有三个 <Child> 组件被渲染了:

  1. it("renders many children", () => {
  2. const wrapper = shallowMount(ParentWithManyChildren)
  3. expect(wrapper.findAll(Child).length).toBe(3)
  4. })

运行 yarn test:unit 显示测试通过。对于 findAll 同样适用 querySelector 语法。

总结

本页覆盖了:

  • 使用有着 querySelector 语法的 findfindAll
  • isVisibleexists
  • 将组件或名称选择器传入 findfindAll

在本页中所描述的测试源码可以在 这里找到元素和组件 - 图4 找到。