Inline snapshot'ы

Inline snapshot — это техника тестирования компонентов во Vue с использованием Vue Test Utils и Jest, которая позволяет фиксировать ожидаемый вывод прямо в исходном коде теста. В отличие от обычных снапшотов, хранящихся в отдельных файлах, inline snapshot’ы находятся рядом с тестом, что повышает читаемость и облегчает поддержку.

Основы синтаксиса

Использование inline snapshot’ов строится вокруг метода toMatchInlineSnapshot(). Пример:

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

test('рендерит компонент с текстом', () => {
  const wrapper = mount(MyComponent, {
    props: { title: 'Hello' }
  })
  expect(wrapper.html()).toMatchInlineSnapshot(`
    "<div>
      <h1>Hello</h1>
    </div>"
  `)
})

В этом примере ожидаемый HTML компонента фиксируется внутри теста, что позволяет сразу видеть результат рендера без необходимости переходить к отдельному файлу снапшота.

Преимущества inline snapshot’ов

  1. Прозрачность тестов — результат рендера виден рядом с проверкой.
  2. Легкость рефакторинга — при изменении структуры компонента Jest предложит обновить snapshot прямо в тесте.
  3. Меньше файлов — нет необходимости создавать дополнительные .snap файлы для каждого теста.

Обновление inline snapshot’ов

При изменении компонента snapshot может перестать соответствовать реальному выводу. Jest предоставляет возможность автоматического обновления с помощью флага:

jest -u

Если использовать VS Code, интеграция с Jest позволяет автоматически применить изменения по нажатию кнопки, не меняя ручной код теста.

Совмещение с Vue Test Utils

Vue Test Utils предоставляет методы для получения HTML, текстового содержимого или состояния компонента:

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

Все эти методы можно комбинировать с inline snapshot’ами:

test('вызывает событие при клике', async () => {
  const wrapper = mount(MyComponent)
  await wrapper.find('button').trigger('click')
  expect(wrapper.emitted().submit).toMatchInlineSnapshot(`
    Array [
      Array [],
    ]
  `)
})

Многострочные и динамические значения

Для многострочных элементов или вложенных структур лучше использовать шаблонные строки с сохранением отступов, чтобы snapshot был читаем:

expect(wrapper.html()).toMatchInlineSnapshot(`
  "<div class=\\"container\\">
    <h1>Hello</h1>
    <p>Описание компонента</p>
  </div>"
`)

Для динамических данных можно комбинировать inline snapshot с регулярными выражениями или методами Jest, например:

expect(wrapper.text()).toMatchInlineSnapshot(expect.stringMatching(/Hello \d+/))

Ограничения и рекомендации

  • Inline snapshot лучше использовать для небольших компонентов или конкретных частей DOM. Для крупных страниц предпочтительнее отдельные .snap файлы.
  • Поддерживать читаемость — каждый snapshot должен быть максимально компактным и отражать только значимые изменения.
  • Не хранить конфиденциальные данные или большие объёмы HTML прямо в тесте.

Интеграция с TypeScript

При работе с TypeScript необходимо убедиться, что типы Wrapper и mount корректно импортированы:

import { mount, VueWrapper } from '@vue/test-utils'
import MyComponent from '@/components/MyComponent.vue'

let wrapper: VueWrapper<any>
wrapper = mount(MyComponent)

Inline snapshot будет работать аналогично, без дополнительных настроек.

Итоговые рекомендации по использованию

  • Использовать для компактных проверок рендеринга и событий.
  • Поддерживать единый стиль форматирования шаблонных строк.
  • Применять автоматическое обновление Jest при изменении компонентов.
  • Комбинировать с другими методами Vue Test Utils для более точных проверок.

Inline snapshot’ы помогают делать тесты наглядными, снижая расстояние между проверкой и ожидаемым результатом, что особенно ценно при частых изменениях компонентов.