update:modelValue является стандартным событием во Vue
3, используемым в компонентах с двусторонней привязкой
через директиву v-model. Тестирование таких событий важно
для проверки корректного взаимодействия компонентов и родительских
элементов. Vue Test Utils предоставляет удобные инструменты для
перехвата и проверки эмитированных событий.
update:modelValueВ Vue 3 синтаксис двусторонней привязки выглядит так:
<MyInput v-model="textValue" />
Внутри компонента MyInput изменение значения происходит
через эмит события:
this.$emit('update:modelValue', newValue)
Для тестирования необходимо проверить, что компонент корректно эмитирует событие при взаимодействии пользователя.
Импортируем необходимые функции:
import { mount } from '@vue/test-utils'
import MyInput from '@/components/MyInput.vue'
test('эмитирует update:modelValue при вводе текста', async () => {
const wrapper = mount(MyInput)
// Симулируем пользовательский ввод
const input = wrapper.find('input')
await input.setValue('Hello Vue')
// Проверяем эмитацию события
expect(wrapper.emitted()).toHaveProperty('update:modelValue')
expect(wrapper.emitted('update:modelValue')[0]).toEqual(['Hello Vue'])
})
Разбор кода:
wrapper.find('input') ищет элемент
<input> внутри компонента.setValue('Hello Vue') не только меняет значение поля,
но и вызывает событие input внутри компонента.wrapper.emitted() возвращает объект всех эмитированных
событий.toHaveProperty('update:modelValue')
подтверждает факт эмита.wrapper.emitted('update:modelValue')[0] возвращает
массив аргументов первого вызова события.modelValueИногда требуется убедиться, что компонент корректно инициализируется с переданным значением:
test('инициализируется с переданным modelValue', () => {
const wrapper = mount(MyInput, {
props: {
modelValue: 'Initial'
}
})
const input = wrapper.find('input')
expect(input.element.value).toBe('Initial')
})
Это гарантирует соответствие внутреннего состояния компонента значению пропса.
Если компонент эмитирует несколько событий при последовательных действиях:
test('эмитирует несколько раз при последовательном вводе', async () => {
const wrapper = mount(MyInput)
const input = wrapper.find('input')
await input.setValue('A')
await input.setValue('AB')
await input.setValue('ABC')
const emitted = wrapper.emitted('update:modelValue')
expect(emitted).toHaveLength(3)
expect(emitted.map(e => e[0])).toEqual(['A', 'AB', 'ABC'])
})
Важные моменты:
[значение].await, чтобы Vue
успел обработать реактивные обновления.v-modelКомпоненты могут использовать v-model для нестандартных
типов данных:
<MyCheckbox v-model="checked" />
Тестирование выглядит аналогично:
test('эмитирует update:modelValue для чекбокса', async () => {
const wrapper = mount(MyCheckbox)
const checkbox = wrapper.find('input[type="checkbox"]')
await checkbox.setChecked(true)
expect(wrapper.emitted('update:modelValue')[0]).toEqual([true])
await checkbox.setChecked(false)
expect(wrapper.emitted('update:modelValue')[1]).toEqual([false])
})
setChecked автоматически вызывает соответствующее
событие change и проверка эмита становится прямой.
Для компонентов с вложенными v-model важно убедиться,
что родитель корректно получает обновления:
const Parent = {
template: `<MyInput v-model="text" />`,
components: { MyInput },
data() {
return { text: '' }
}
}
test('родительский data обновляется при эмите', async () => {
const wrapper = mount(Parent)
const input = wrapper.findComponent(MyInput).find('input')
await input.setValue('Vue Test Utils')
expect(wrapper.vm.text).toBe('Vue Test Utils')
})
Таким образом проверяется не только эмит события, но и реактивное обновление данных родителя.
update:modelValuesetValue или
setChecked вместо ручного вызова
$emit, чтобы тест имитировал реальное поведение
пользователя.await с
методами Vue Test Utils.v-model удобно
использовать именованные события: update:modelValue и
update:otherValue.Эти подходы обеспечивают детальное и корректное тестирование
компонентов Vue 3 с двусторонней привязкой, гарантируя, что
v-model работает в полном соответствии с ожиданиями.