Поиск компонентов: findComponent и findAllComponents

В Vue Test Utils поиск компонентов является одной из основных задач при тестировании. Для этого используются методы findComponent и findAllComponents, которые предоставляют доступ к компонентам, их свойствам, событиям и состоянию. Эти методы позволяют не только проверять наличие компонентов в дереве, но и взаимодействовать с ними напрямую, что особенно важно для комплексных приложений.


findComponent

Метод findComponent используется для поиска первого подходящего компонента в обернутом дереве. Он возвращает объект типа Wrapper, который инкапсулирует найденный компонент и предоставляет методы для взаимодействия с ним.

Синтаксис:

const wrapper = mount(ParentComponent)
const child = wrapper.findComponent(ChildComponent)

Параметры поиска:

  1. Компонент (класс/объект):

    const child = wrapper.findComponent(MyButton)

    Позволяет искать по самим компонентам, а не по селекторам DOM.

  2. CSS-селектор:

    const child = wrapper.findComponent('.my-button')

    Позволяет искать компонент по его корневому элементу с определённым классом, идентификатором или атрибутом.

  3. Определение через объект с ref:

    const child = wrapper.findComponent({ ref: 'submitButton' })

    Поиск компонента по ref в шаблоне Vue.

Важные методы Wrapper после поиска:

  • exists() — проверка существования компонента.
  • text() — получение текста компонента.
  • props() — доступ к свойствам компонента.
  • emitted() — проверка событий, вызванных компонентом.
  • vm — экземпляр компонента, через который можно вызывать методы и изменять состояние.

Пример использования:

import { mount } from '@vue/test-utils'
import ParentComponent from '@/components/ParentComponent.vue'
import ChildComponent from '@/components/ChildComponent.vue'

const wrapper = mount(ParentComponent)
const child = wrapper.findComponent(ChildComponent)

expect(child.exists()).toBe(true)
expect(child.props().title).toBe('Привет')
child.vm.someMethod()

findAllComponents

Метод findAllComponents используется для поиска всех компонентов, удовлетворяющих условию, возвращая коллекцию WrapperArray. Это полезно при тестировании списков, таблиц, повторяющихся элементов или компонентов, которые могут рендериться динамически.

Синтаксис:

const children = wrapper.findAllComponents(ChildComponent)

Методы WrapperArray:

  • length — количество найденных компонентов.
  • at(index) — получение компонента по индексу.
  • wrappers — массив всех Wrapper, с которыми можно работать в цикле.
  • forEach(fn) — итерация по всем найденным компонентам.
  • filter(fn) — фильтрация компонентов по условию.
  • map(fn) — трансформация списка компонентов.

Пример использования:

import { mount } from '@vue/test-utils'
import ListComponent from '@/components/ListComponent.vue'
import ListItem from '@/components/ListItem.vue'

const wrapper = mount(ListComponent, {
  props: {
    items: ['A', 'B', 'C']
  }
})

const items = wrapper.findAllComponents(ListItem)
expect(items.length).toBe(3)

items.forEach((item, index) => {
  expect(item.props().value).toBe(['A', 'B', 'C'][index])
})

Отличия между findComponent и findAllComponents

Параметр findComponent findAllComponents
Возвращаемое значение Wrapper WrapperArray
Найдено одно/множество Первое совпадение Все совпадения
Проверка существования exists() length > 0 или wrappers.length
Используется чаще для Конкретного дочернего компонента Списков или повторяющихся компонентов

Особенности и рекомендации:

  • Если компонент может рендериться несколько раз, findComponent вернёт только первый экземпляр, поэтому для полного тестирования лучше использовать findAllComponents.
  • Методы поиска по ref удобны для уникальных компонентов, особенно когда структура DOM сложная.
  • Методы поиска по CSS-селекторам позволяют тестировать компоненты как обычные DOM-элементы, что полезно при тестировании внешнего вида и классов.

Взаимодействие с найденными компонентами

После поиска компонента можно:

  1. Вызвать методы компонента:
const child = wrapper.findComponent(ChildComponent)
child.vm.increment()
expect(child.vm.count).toBe(1)
  1. Проверить события:
child.vm.$emit('update', 42)
expect(child.emitted().update[0]).toEqual([42])
  1. Изменить пропсы через setProps:
child.setProps({ title: 'Новый заголовок' })
expect(child.props().title).toBe('Новый заголовок')
  1. Тестировать вложенные компоненты:
const nested = child.findComponent(NestedComponent)
expect(nested.exists()).toBe(true)

Поиск по пользовательским условиям

findComponent и findAllComponents могут использовать объект с функцией проверки:

const wrapper = mount(ParentComponent)
const child = wrapper.findComponent(comp => comp.props().title === 'Тест')
const allChildren = wrapper.findAllComponents(comp => comp.props().active)

Это позволяет гибко искать компоненты по любым условиям, включая пропсы, слоты и внутреннее состояние.


Совместное использование

Часто методы комбинируются: сначала findComponent для доступа к родительскому компоненту, затем findAllComponents для проверки всех дочерних:

const parent = wrapper.findComponent(ParentComponent)
const children = parent.findAllComponents(ChildComponent)
expect(children.length).toBe(5)

Такой подход позволяет тестировать дерево компонентов на разных уровнях вложенности, сохраняя контроль над каждым узлом.


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