This book is written for Vue.js 2 and Vue Test Utils v1.
Find the Vue.js 3 version here.
# Finding Elements
vue-test-utils provides a number of ways to find and assert the presence of html elements or other Vue components using the find and findComponent methods. The main use of find is asserting a component correctly renders an element or child component.
Note: If you used Vue Test Utils prior to v1, you may remember
findworking with components as well as DOM elements. Now you usefindandfindAllfor DOM elements, andfindComponentandfindAllComponentsfor Vue components. There is also agetandgetComponentpair, which are exactly the same asfindandfindComponent, but they will raise an error if they do not find anything. This guide chooses to usefindandfindComponent.
The source code for the test described on this page can be found here.
# Creating the Components
For this example, we will create a <Child> and <Parent> component.
Child:
<template>
<div>Child</div>
</template>
<script>
export default {
name: "Child"
}
</script>
Parent:
<template>
<div>
<span v-show="showSpan">
Parent Component
</span>
<Child v-if="showChild" />
</div>
</template>
<script>
import Child from "./Child.vue"
export default {
name: "Parent",
components: { Child },
data() {
return {
showSpan: false,
showChild: false
}
}
}
</script>
# find with querySelector syntax
Regular elements can easily be selected using the syntax used with document.querySelector. vue-test-utils also provides a isVisible method to check if elements conditionally rendered with v-show are visible. Create a Parent.spec.js, and inside add the following test:
import { mount } from "@vue/test-utils"
import '@testing-library/jest-dom'
import Parent from "@/components/Parent.vue"
describe("Parent", () => {
it("does not render a span", () => {
const wrapper = mount(Parent)
expect(wrapper.find("span").element).not.toBeVisible()
})
})
Since v-show="showSpan" defaults to false, we expect the found <span> element's not to be visible. We are using the awesome @testing-library/jest-dom matchers to validate this - determining visibility is tricky business, so Vue Test Utils leaves it up to another battle tested library. The tests passes when run with yarn test:unit. Next, a test around the case when showSpan is true.
it("does render a span", () => {
const wrapper = mount(Parent, {
data() {
return { showSpan: true }
}
})
expect(wrapper.find("span").element).toBeVisible()
})
It passes!
# Finding Components with name and Component
Finding child components is a little different to finding regular HTML elements. There two main ways to assert the presence of child Vue components:
findComponent(Component)findComponent({ name: "ComponentName" })
These are a bit easier to understand in the context of an example test. Let's start with the findComponent(Component) syntax. This requires us to import the component, and pass it to the findComponent function.
import Child from "@/components/Child.vue"
it("does not render a Child component", () => {
const wrapper = mount(Parent)
expect(wrapper.findComponent(Child).exists()).toBe(false)
})
The implementation for find and findComponent is quite complex, since it works with the querySelector for DOM elements, as well as several other syntaxes for Vue components. You can see the part of the source that finds children Vue components here. It basically checks the component's name against each child rendered, and then checks the constructor, and some other properties.
As mentioned in the previous paragraph, the name property is one of the checks done by find when you pass a component. Instead of passing the component, you can simply pass an object with the correct name property. This means you do not need to import the component. Let's test the case when <Child> should be rendered:
it("renders a Child component", () => {
const wrapper = mount(Parent, {
data() {
return { showChild: true }
}
})
expect(wrapper.findComponent({ name: "Child" }).exists()).toBe(true)
})
It passes! Using the name property can be a little unintuitive, so importing the actual component is an alternative. Another option is to simply add a class or id and query using the querySelector style syntax presented in the first two examples.
# findAll and findAllComponents
There are often cases when you want to assert that a number of elements are rendered. A common case is a list of items rendered with v-for. Here is a <ParentWithManyChildren> that renders several <Child> components.
<template>
<div>
<Child v-for="id in [1, 2 ,3]" :key="id" />
</div>
</template>
<script>
import Child from "./Child.vue"
export default {
name: "ParentWithManyChildren",
components: { Child }
}
</script>
We can write a test using findAllComponents to assert three <Child> components are rendered like this:
it("renders many children", () => {
const wrapper = mount(ParentWithManyChildren)
expect(wrapper.findAllComponents(Child).length).toBe(3)
})
Running yarn test:unit shows the test passes. You can use the querySelector syntax with findAll as well.
# Conclusion
This page covers:
- using
findandfindAllwith thequerySelectorsyntax for DOM elements - use
findComponentandfindAllComponentsfor Vue components - use
existsto check if something is present,toBeVisiblefrom@testing-library/jest-domto see if something is present but not visible
The source code for the test described on this page can be found here.