Skip to content

条件渲染

¥Conditional Rendering

Vue Test Utils 具有一系列用于渲染和对组件状态进行断言的功能,目的是验证其行为是否正确。本文将探讨如何渲染组件,以及验证它们是否正确渲染内容。

¥Vue Test Utils has a range of features for rendering and making assertions about the state of a component, with the goal of verifying it is behaving correctly. This article will explore how to render components, as well as verify they are rendering content correctly.

本文也可作为 短视频 提供。

¥This article is also available as a short video.

寻找元素

¥Finding Elements

Vue 最基本的功能之一是能够使用 v-if 动态插入和删除元素。让我们看看如何测试使用 v-if 的组件。

¥One of the most basic features of Vue is the ability to dynamically insert and remove elements with v-if. Let's look at how to test a component that uses v-if.

js
const Nav = {
  template: `
    <nav>
      <a id="profile" href="/profile">My Profile</a>
      <a v-if="admin" id="admin" href="/admin">Admin</a>
    </nav>
  `,
  data() {
    return {
      admin: false
    }
  }
}

<Nav> 组件中,显示了指向用户个人资料的链接。此外,如果 admin 值为 true,我们会显示一个指向管理部分的链接。我们应该验证三种情况的行为是否正确:

¥In the <Nav> component, a link to the user's profile is shown. In addition, if the admin value is true, we reveal a link to the admin section. There are three scenarios which we should verify are behaving correctly:

  1. 应显示 /profile 链接。

    ¥The /profile link should be shown.

  2. 当用户是管理员时,应显示 /admin 链接。

    ¥When the user is an admin, the /admin link should be shown.

  3. 当用户不是管理员时,不应显示 /admin 链接。

    ¥When the user is not an admin, the /admin link should not be shown.

使用 get()

¥Using get()

wrapper 有一个 get() 方法来搜索现有元素。它使用 querySelector 语法。

¥wrapper has a get() method that searches for an existing element. It uses querySelector syntax.

我们可以使用 get() 断言配置文件链接内容:

¥We can assert the profile link content by using get():

js
test('renders a profile link', () => {
  const wrapper = mount(Nav)

  // Here we are implicitly asserting that the
  // element #profile exists.
  const profileLink = wrapper.get('#profile')

  expect(profileLink.text()).toEqual('My Profile')
})

如果 get() 没有返回与选择器匹配的元素,它将引发错误,并且你的测试将失败。如果找到元素,则 get() 返回 DOMWrapperDOMWrapper 是 DOM 元素的一个薄封装,它实现了 封装 API - 这就是为什么我们能够执行 profileLink.text() 并访问文本。你可以使用 element 属性访问原始元素。

¥If get() does not return an element matching the selector, it will raise an error, and your test will fail. get() returns a DOMWrapper if an element is found. A DOMWrapper is a thin wrapper around the DOM element that implements the Wrapper API - that's why we are able to do profileLink.text() and access the text. You can access the raw element using the element property.

还有另一种类型的封装器 - 一个 VueWrapper - 从以相同方式工作的 getComponent 返回。

¥There is another type of wrapper - a VueWrapper - that is returned from getComponent that works in the same manner.

使用 find()exists()

¥Using find() and exists()

get() 的工作原理是假设元素确实存在,如果不存在则抛出错误。不建议使用它来断言存在。

¥get() works on the assumption that elements do exist and throws an error when they do not. It is not recommended to use it for asserting existence.

为此,我们使用 find()exists()。下一个测试断言如果 adminfalse(默认情况下),则管理链接不存在:

¥To do so, we use find() and exists(). The next test asserts that if admin is false (which it is by default), the admin link is not present:

js
test('does not render an admin link', () => {
  const wrapper = mount(Nav)

  // Using `wrapper.get` would throw and make the test fail.
  expect(wrapper.find('#admin').exists()).toBe(false)
})

请注意,我们正在对 .find() 返回的值调用 exists()find()mount() 一样,也返回 wrappermount() 有一些额外的方法,因为它封装了一个 Vue 组件,而 find() 只返回一个常规 DOM 节点,但许多方法在两者之间共享。其他一些方法包括 classes()(获取 DOM 节点所具有的类)和 trigger()(用于模拟用户交互)。你可以找到支持 此处 的方法列表。

¥Notice we are calling exists() on the value returned from .find(). find(), like mount(), also returns a wrapper. mount() has a few extra methods, because it's wrapping a Vue component, and find() only returns a regular DOM node, but many of the methods are shared between both. Some other methods include classes(), which gets the classes a DOM node has, and trigger() for simulating user interaction. You can find a list of methods supported here.

使用 data

¥Using data

最后的测试是断言当 admintrue 时渲染管理链接。默认情况下是 false,但我们可以使用 mount() 的第二个参数(即 mounting options)覆盖它。

¥The final test is to assert that the admin link is rendered when admin is true. It's false by default, but we can override that using the second argument to mount(), the mounting options.

对于 data,我们使用恰当命名的 data 选项:

¥For data, we use the aptly named data option:

js
test('renders an admin link', () => {
  const wrapper = mount(Nav, {
    data() {
      return {
        admin: true
      }
    }
  })

  // Again, by using `get()` we are implicitly asserting that
  // the element exists.
  expect(wrapper.get('#admin').text()).toEqual('Admin')
})

如果你在 data 还有其他属性,不用担心 - Vue Test Utils 会将两者合并在一起。挂载选项中的 data 将优先于任何默认值。

¥If you have other properties in data, don't worry - Vue Test Utils will merge the two together. The data in the mounting options will take priority over any default values.

要了解存在哪些其他挂载选项,请参阅 Passing Datamounting options

¥To learn what other mounting options exist, see Passing Data or see mounting options.

检查元素可见性

¥Checking Elements visibility

有时你只想隐藏/显示一个元素,同时将其保留在 DOM 中。Vue 为此类场景提供了 v-show。(可以查看 v-ifv-show 此处 的区别)。

¥Sometimes you only want to hide/show an element while keeping it in the DOM. Vue offers v-show for scenarios as such. (You can check the differences between v-if and v-show here).

具有 v-show 的组件如下所示:

¥This is how a component with v-show looks like:

js
const Nav = {
  template: `
    <nav>
      <a id="user" href="/profile">My Profile</a>
      <ul v-show="shouldShowDropdown" id="user-dropdown">
        <!-- dropdown content -->
      </ul>
    </nav>
  `,
  data() {
    return {
      shouldShowDropdown: false
    }
  }
}

在这种情况下,元素不可见,但始终渲染。get()find() 将始终返回 Wrapperfind(),而 .exists() 始终返回 true – 因为该元素仍在 DOM 中。

¥In this scenario, the element is not visible but always rendered. get() or find() will always return a Wrapperfind() with .exists() always return true – because the element is still in the DOM.

使用 isVisible()

¥Using isVisible()

isVisible() 提供了检查隐藏元素的能力。特别是 isVisible() 将检查是否:

¥isVisible() gives the capacity to check for hidden elements. In particular isVisible() will check if:

  • 元素或其祖级具有 display: nonevisibility: hiddenopacity :0 样式

    ¥an element or its ancestors have display: none, visibility: hidden, opacity :0 style

  • 元素或其祖级位于折叠的 <details> 标签内

    ¥an element or its ancestors are located inside collapsed <details> tag

  • 元素或其祖级具有 hidden 属性

    ¥an element or its ancestors have the hidden attribute

对于任何这些情况,isVisible() 返回 false

¥For any of these cases, isVisible() returns false.

使用 v-show 的测试场景如下所示:

¥Testing scenarios using v-show will look like:

js
test('does not show the user dropdown', () => {
  const wrapper = mount(Nav)

  expect(wrapper.get('#user-dropdown').isVisible()).toBe(false)
})

结论

¥Conclusion

  • 使用 find()exists() 来验证元素是否在 DOM 中。

    ¥Use find() along with exists() to verify whether an element is in the DOM.

  • 如果你希望元素位于 DOM 中,请使用 get()

    ¥Use get() if you expect the element to be in the DOM.

  • data 挂载选项可用于设置组件的默认值。

    ¥The data mounting option can be used to set default values on a component.

  • 使用 get()isVisible() 来验证 DOM 中元素的可见性

    ¥Use get() with isVisible() to verify the visibility of an element that is in the DOM

Vue Test Utils 中文网 - 粤ICP备13048890号