Vue Test Utils is the official test library for Vue.js components. It provides a set of utility functions that make it easier to test Vue components in isolation.
Unit testing is crucial for maintaining a reliable and robust Vue.js application. It helps developers:
Vue Test Utils provides a simple and intuitive API for mounting components, triggering events, and making assertions about the component's output. The library works seamlessly with popular testing frameworks like Jest and Vitest.
In the following example, we’ve got a MessageComponent
that takes a title prop and displays it as an h1
. It also binds some local message data to an input and emits and clears that data when a button is clicked.
<!--MessageComponent.vue-->
<script setup>
import { ref } from 'vue'
const props = defineProps({
title: {
type: String,
default: 'Message Form'
}
})
const emit = defineEmits(['message-sent'])
const message = ref('')
const submit = () => {
emit('message-sent', message.value)
message.value = ''
}
</script>
<template>
<div>
<h1>{{ title }}</h1>
<input v-model="message" data-test="message-input" />
<button @click="submit" data-test="send-button">Send</button>
</div>
</template>
In order to test that component we can write the following test with Vitest and Vue Test Utils.
// MessageComponent.spec.ts
import { mount } from '@vue/test-utils'
import { describe, it, expect } from 'vitest'
import MessageComponent from '../MessageComponent.vue'
describe('MessageComponent', () => {
// Test that the component correctly renders the title prop
// This verifies props are properly passed and displayed
it('renders props.title when passed', () => {
const title = 'New Message'
const wrapper = mount(MessageComponent, { props: { title } })
expect(wrapper.find('h1').text()).toBe(title)
})
// Test the full message sending workflow:
// 1. Enter text in input
// 2. Click send button
// 3. Verify event is emitted with correct data
// 4. Verify input is cleared afterwards
it('emits message-sent event when button clicked', async () => {
// Mount the component
const wrapper = mount(MessageComponent)
// Find the input element using data-test attribute
// More reliable than using element selectors
const input = wrapper.find('[data-test="message-input"]')
// Simulate user typing a message
await input.setValue('Hello World')
// Simulate clicking the send button
await wrapper.find('[data-test="send-button"]').trigger('click')
// Verify the correct event was emitted with the message
expect(wrapper.emitted('message-sent')[0]).toEqual(['Hello World'])
// Verify the input was cleared after sending
expect(input.element.value).toBe('')
})
})
Notice how we’re testing the interface of the component (what passing a certain prop does and the effect of events). It’s a good habit to focus on testing your component interface as opposed to it’s internal logic. This makes for less brittle tests.
This leads us to some other best practices to consider when writing tests for Vue.js components:
By implementing a solid testing strategy with Vue Test Utils, you can ensure your Vue.js applications remain maintainable and reliable as they grow in complexity.
To dive deeper into Vue.js testing and Vue Test Utils, check out these valuable resources:
Good luck using tests to build your rock solid Vue apps!
Our goal is to be the number one source of Vue.js knowledge for all skill levels. We offer the knowledge of our industry leaders through awesome video courses for a ridiculously low price.
More than 200.000 users have already joined us. You are welcome too!
© All rights reserved. Made with ❤️ by BitterBrains, Inc.