Проверка modelValue prop

При тестировании компонентов Vue, которые используют двустороннюю привязку через v-model, основным объектом взаимодействия является проп modelValue. Он служит источником данных для компонента и позволяет отслеживать изменения состояния. Тестирование этого пропа критически важно для проверки корректности работы как внутренней логики компонента, так и его взаимодействия с родительскими компонентами.

Основные принципы

  1. Инициализация компонента с modelValue Для проверки поведения компонента с конкретным состоянием, modelValue передаётся через опцию props при монтировании:

    import { mount } from '@vue/test-utils'
    import MyInput from '@/components/MyInput.vue'
    
    const wrapper = mount(MyInput, {
      props: { modelValue: 'тестовое значение' }
    })

    Это позволяет убедиться, что компонент корректно отображает переданное значение при инициализации.

  2. Отслеживание изменений через update:modelValue В Vue 3 изменение v-model инициируется событием update:modelValue. Проверка того, что компонент эмиттирует правильное событие при изменении состояния, выполняется следующим образом:

    wrapper.vm.$emit('update:modelValue', 'новое значение')
    expect(wrapper.emitted()['update:modelValue'][0]).toEqual(['новое значение'])

    Этот подход гарантирует, что компонент корректно уведомляет родителя о внутренних изменениях.

  3. Тестирование реактивного связывания Если компонент использует локальное состояние на основе modelValue, важно проверять реактивность. Например:

    await wrapper.setProps({ modelValue: 'обновлённое значение' })
    expect(wrapper.find('input').element.value).toBe('обновлённое значение')

    Здесь setProps имитирует изменение пропа родителем, а expect проверяет, что внутренний DOM компонента обновился.

Практические сценарии тестирования

Сценарий 1: Отображение переданного значения Проверка того, что при инициализации modelValue корректно отражается в элементе ввода:

const wrapper = mount(MyInput, { props: { modelValue: '123' } })
expect(wrapper.find('input').element.value).toBe('123')

Сценарий 2: Эмит события при изменении значения Имитируется ввод пользователя и проверяется, что компонент эмиттирует событие update:modelValue:

const input = wrapper.find('input')
await input.setValue('456')
expect(wrapper.emitted('update:modelValue')[0]).toEqual(['456'])

Сценарий 3: Реакция на обновление пропа Проп обновляется извне, и проверяется синхронизация внутреннего состояния:

await wrapper.setProps({ modelValue: '789' })
expect(wrapper.find('input').element.value).toBe('789')

Особенности тестирования сложных компонентов

  • Компоненты с кастомной логикой обработки данных Если компонент изменяет modelValue перед отображением (например, форматирует строку), важно проверять оба этапа: внутреннее состояние и эмит события:

    await wrapper.setProps({ modelValue: 'abc' })
    expect(wrapper.find('input').element.value).toBe('ABC') // форматирование
    await wrapper.find('input').setValue('def')
    expect(wrapper.emitted('update:modelValue')[0]).toEqual(['DEF'])
  • Комбинация нескольких v-model Для компонентов с несколькими пропами modelValue (например, modelValue и modelValueOther) требуется тестировать каждый отдельно, чтобы убедиться в независимости реактивности и корректности эмитов.

Рекомендации по структуре тестов

  1. Использовать setProps для симуляции изменений родителя.
  2. Проверять не только эмит, но и состояние DOM.
  3. Проверять реакцию на неправильные или пустые значения modelValue.
  4. Разделять тесты на три категории: инициализация, реактивное обновление, эмит событий.

Понимание и тестирование modelValue является основой надёжной проверки компонентов с двусторонней привязкой, позволяя убедиться, что пользовательский ввод и внешние изменения пропов обрабатываются корректно и предсказуемо.