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

Unit-тестирование в проектах с использованием Element Plus строится на тестировании отдельных Vue-компонентов в изоляции, без необходимости запуска всего приложения. Основными инструментами являются Vue Test Utils и тестовые раннеры, такие как Jest или Vitest.

Установка необходимых зависимостей

Для тестирования компонентов Element Plus требуется установить несколько библиотек:

npm install --save-dev @vue/test-utils jest vue-jest babel-jest @babel/preset-env
npm install element-plus

Если проект использует Vite, предпочтительно использовать Vitest:

npm install --save-dev vitest @vitejs/plugin-vue vue-test-utils

Важно, чтобы версии Vue и Element Plus были совместимы с установленными тестовыми утилитами.

Импорт компонентов и глобальная регистрация

Компоненты Element Plus часто требуют глобальной регистрации для корректной работы в тестах. Например, для тестирования кнопки:

import { mount } from '@vue/test-utils'
import { ElButton } from 'element-plus'
import { h } from 'vue'

const wrapper = mount({
  render() {
    return h(ElButton, { type: 'primary' }, 'Click me')
  }
}, {
  global: {
    components: { ElButton }
  }
})

Ключевой момент: Element Plus использует динамическую загрузку стилей, поэтому для корректного рендеринга некоторых компонентов (например, ElDatePicker или ElTable) может потребоваться подключение CSS через import 'element-plus/dist/index.css'.

Тестирование пропсов

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

import { mount } from '@vue/test-utils'
import { ElButton } from 'element-plus'

test('ElButton рендерит текст из пропса', () => {
  const wrapper = mount(ElButton, {
    props: { type: 'success' },
    slots: { default: 'Сохранить' }
  })

  expect(wrapper.text()).toBe('Сохранить')
  expect(wrapper.classes()).toContain('el-button--success')
})

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

Тестирование событий

Большинство компонентов Element Plus взаимодействуют через события. Их можно тестировать с помощью метода trigger из Vue Test Utils.

import { mount } from '@vue/test-utils'
import { ElButton } from 'element-plus'

test('клик по кнопке вызывает событие', async () => {
  const wrapper = mount(ElButton)
  await wrapper.trigger('click')
  expect(wrapper.emitted()).toHaveProperty('click')
})

Для сложных компонентов, таких как ElInput или ElSelect, важно проверять изменение состояния через события update:modelValue:

import { mount } from '@vue/test-utils'
import { ElInput } from 'element-plus'

test('ввод текста генерирует событие update:modelValue', async () => {
  const wrapper = mount(ElInput, { props: { modelValue: '' } })
  const input = wrapper.find('input')
  await input.setValue('Тест')
  
  expect(wrapper.emitted('update:modelValue')[0]).toEqual(['Тест'])
})

Тестирование слотов

Element Plus активно использует слоты для кастомизации контента компонентов. Unit-тестирование слотов обеспечивает корректное отображение вложенных элементов.

import { mount } from '@vue/test-utils'
import { ElTooltip } from 'element-plus'

test('ElTooltip рендерит контент в слоте', () => {
  const wrapper = mount(ElTooltip, {
    slots: {
      default: '<button>Кнопка</button>',
      content: '<span>Подсказка</span>'
    }
  })

  expect(wrapper.html()).toContain('<button>Кнопка</button>')
  expect(wrapper.html()).toContain('<span>Подсказка</span>')
})

Моки и заглушки для глобальных зависимостей

Компоненты Element Plus могут зависеть от глобальных функций или плагинов (например, $message, $loading). Для unit-тестов их необходимо мокать:

import { mount } from '@vue/test-utils'
import { ElButton } from 'element-plus'

const $message = { success: jest.fn() }

const wrapper = mount(ElButton, {
  global: { mocks: { $message } }
})

// Вызов $message.success
$message.success('Событие произошло')
expect($message.success).toHaveBeenCalledWith('Событие произошло')

Тестирование асинхронного поведения

Некоторые компоненты, например, ElTable с загрузкой данных, требуют проверки асинхронных действий. Используется flushPromises для ожидания всех промисов:

import { mount } from '@vue/test-utils'
import { ElTable } from 'element-plus'
import flushPromises from 'flush-promises'

test('ElTable рендерит строки после загрузки данных', async () => {
  const data = [{ name: 'Item1' }, { name: 'Item2' }]
  const wrapper = mount(ElTable, { props: { data } })
  await flushPromises()

  expect(wrapper.findAll('tbody tr').length).toBe(2)
})

Интеграция с Jest и Vitest

Для Jest:

"jest": {
  "transform": {
    "^.+\\.vue$": "vue-jest",
    "^.+\\.js$": "babel-jest"
  },
  "moduleFileExtensions": ["js", "json", "vue"]
}

Для Vitest достаточно настроить плагин Vue в vite.config.js:

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

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

Практические рекомендации

  • Проверять все критические пропсы и события компонента.
  • Использовать слоты для проверки кастомного контента.
  • Мокать глобальные зависимости для изоляции тестов.
  • Для асинхронных компонентов использовать flushPromises или nextTick.
  • Организовывать тесты по отдельным методам и состояниям компонента, чтобы облегчить отладку.

Unit-тестирование компонентов Element Plus обеспечивает стабильность пользовательского интерфейса и позволяет быстро выявлять регрессии при обновлениях библиотеки или проекта.