Unit тестирование компонентов

Unit тестирование компонентов в Naive UI строится на изоляции каждого компонента и проверке его поведения в различных состояниях. Основная цель — убедиться, что отдельный компонент работает корректно независимо от внешней среды. Для этого чаще всего используется комбинация Vue Test Utils и Vitest или Jest.

Настройка окружения для тестирования

  1. Установка зависимостей Для работы с компонентами Naive UI понадобятся следующие пакеты:
npm install @vue/test-utils vitest vue@next naive-ui
  1. Конфигурация тестового раннера В vitest.config.js необходимо указать поддержку Vue:
import { defineConfig } from 'vitest/config'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  test: {
    globals: true,
    environment: 'jsdom'
  }
})

jsdom позволяет эмулировать DOM, что критично для работы компонентов, зависящих от визуальной части.

Структура теста компонента

Стандартный unit тест для Naive UI компонента состоит из нескольких блоков:

  • Импорт компонента и утилит
  • Рендеринг компонента в изолированной среде
  • Проверка начального состояния
  • Симуляция пользовательских действий
  • Проверка изменений состояния и DOM

Пример теста для кнопки NButton:

import { mount } from '@vue/test-utils'
import { describe, it, expect } from 'vitest'
import { NButton } from 'naive-ui'

describe('NButton', () => {
  it('должна рендериться с правильным текстом', () => {
    const wrapper = mount(NButton, {
      props: { 
        type: 'primary' 
      },
      slots: { default: 'Нажми меня' }
    })
    expect(wrapper.text()).toBe('Нажми меня')
    expect(wrapper.classes()).toContain('n-button--primary')
  })

  it('должна реагировать на клик', async () => {
    const onCl ick = vi.fn()
    const wrapper = mount(NButton, {
      props: { onClick },
      slots: { default: 'Кликни' }
    })
    await wrapper.trigger('click')
    expect(onClick).toHaveBeenCalled()
  })
})

Тестирование реактивных свойств и слотов

Naive UI активно использует реактивные свойства и слоты для кастомизации. При тестировании необходимо учитывать:

  • Слоты: проверка правильного рендеринга контента.
  • Reactive props: проверка реактивного обновления при изменении данных.

Пример проверки слота и реактивного свойства:

import { ref } from 'vue'
import { mount } from '@vue/test-utils'
import { NInput } from 'naive-ui'

describe('NInput', () => {
  it('должен отображать реактивное значение', async () => {
    const value = ref('начальное')
    const wrapper = mount(NInput, {
      props: { modelValue: value.value, 'onUpdate:modelValue': val => value.value = val }
    })

    const input = wrapper.find('input')
    await input.setValue('новое значение')
    expect(value.value).toBe('новое значение')
  })
})

Mock компонентов Naive UI

Иногда компоненты используют сложные внутренние зависимости или темы. В таких случаях рекомендуется использовать моки:

import { h } from 'vue'

vi.mock('naive-ui', () => ({
  NMessage: {
    render() { return h('div', 'Сообщение') }
  }
}))

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

Тестирование событий и пользовательских взаимодействий

Naive UI предоставляет множество интерактивных компонентов — кнопки, селекты, модальные окна. Для unit тестов важны:

  • Проверка эмиссии событий (emits)
  • Симуляция пользовательских действий (click, input, keydown)
  • Асинхронные эффекты, например, открытие NModal
it('NModal открывается и закрывается', async () => {
  const visible = ref(false)
  const wrapper = mount(NModal, { props: { show: visible.value } })
  
  visible.value = true
  await wrapper.vm.$nextTick()
  expect(wrapper.find('.n-modal').exists()).toBe(true)
  
  visible.value = false
  await wrapper.vm.$nextTick()
  expect(wrapper.find('.n-modal').exists()).toBe(false)
})

Организация тестов

  • Разделение по компонентам: каждый компонент в отдельной папке __tests__.
  • Сценарии поведения: отдельные тесты для рендеринга, событий, слотов и реактивных пропсов.
  • Покрытие граничных случаев: проверка пустых значений, неправильных типов данных, отключенных состояний компонентов.

Важные рекомендации

  • Использовать комбинацию mount и shallowMount. Для интеграционных тестов лучше mount, для unit — shallowMount (игнорирует дочерние компоненты).
  • Всегда проверять классы и атрибуты DOM, а не только текст, чтобы убедиться, что стили и состояния применяются корректно.
  • Для асинхронных компонентов использовать await nextTick() для корректного обновления DOM.
  • Эмиссии событий проверять через wrapper.emitted().

Unit тестирование компонентов Naive UI позволяет создавать надёжные и предсказуемые интерфейсы, минимизируя ошибки на этапе интеграции и обеспечивая поддержку реактивных и интерактивных возможностей библиотеки.