Интеграционное тестирование

Интеграционное тестирование направлено на проверку корректного взаимодействия компонентов в приложении, построенном с использованием Element Plus. В отличие от модульного тестирования, которое изолирует отдельные компоненты, интеграционные тесты проверяют, как компоненты взаимодействуют друг с другом и с внешними сервисами.

В контексте Element Plus, интеграционное тестирование часто включает:

  • Взаимодействие между элементами UI (кнопки, формы, таблицы).
  • Проверку реактивных свойств компонентов Vue.
  • Корректность событий и их обработчиков.
  • Работу с API через axios или fetch в связке с компонентами Element Plus.

Подготовка окружения

Для интеграционного тестирования рекомендуется использовать Vue Test Utils и Jest или Vitest. Основная цель — создание реального DOM-окружения, где компоненты могут взаимодействовать друг с другом.

Пример установки:

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

Для Vitest:

npm install vitest @vue/test-utils jsdom element-plus --save-dev

Подключение Element Plus в тестах:

import { mount } from '@vue/test-utils'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import MyComponent from '@/components/MyComponent.vue'

const wrapper = mount(MyComponent, {
  global: {
    plugins: [ElementPlus]
  }
})

Использование глобального подключения позволяет корректно тестировать компоненты Element Plus, такие как ElButton, ElForm, ElTable, без ошибок отсутствия стилей или зависимостей.


Тестирование взаимодействия компонентов

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

import { mount } from '@vue/test-utils'
import { nextTick } from 'vue'
import ElementPlus from 'element-plus'
import LoginForm from '@/components/LoginForm.vue'

describe('LoginForm Integration', () => {
  it('правильно обновляет данные формы и вызывает submit', async () => {
    const wrapper = mount(LoginForm, {
      global: { plugins: [ElementPlus] }
    })

    const usernameInput = wrapper.find('input[name="username"]')
    const passwordInput = wrapper.find('input[name="password"]')
    const submitButton = wrapper.findComponent({ name: 'ElButton' })

    await usernameInput.setValue('testuser')
    await passwordInput.setValue('123456')
    
    await submitButton.trigger('click')
    await nextTick()

    expect(wrapper.emitted('submit')).toBeTruthy()
    expect(wrapper.emitted('submit')[0][0]).toEqual({
      username: 'testuser',
      password: '123456'
    })
  })
})

Ключевые моменты:

  • Использование mount вместо shallowMount для полной интеграции дочерних компонентов.
  • Проверка взаимодействия событий через emitted.
  • Проверка реактивности полей формы и их синхронизации с моделью данных.

Тестирование таблиц и списков

ElTable и ElTableColumn требуют проверки правильного рендеринга данных и событий сортировки/фильтрации.

import { mount } from '@vue/test-utils'
import DataTable from '@/components/DataTable.vue'
import ElementPlus from 'element-plus'

const data = [
  { id: 1, name: 'Alice', age: 25 },
  { id: 2, name: 'Bob', age: 30 }
]

describe('DataTable Integration', () => {
  it('корректно отображает данные и сортирует их', async () => {
    const wrapper = mount(DataTable, {
      global: { plugins: [ElementPlus] },
      props: { rows: data }
    })

    const rows = wrapper.findAll('tbody tr')
    expect(rows).toHaveLength(2)
    expect(rows[0].text()).toContain('Alice')

    // Симуляция сортировки по возрасту
    const ageHeader = wrapper.find('.el-table th:nth-child(3)')
    await ageHeader.trigger('click')
    await wrapper.vm.$nextTick()

    const sortedRows = wrapper.findAll('tbody tr')
    expect(sortedRows[0].text()).toContain('Bob')
  })
})

Особенности:

  • Использование findAll для проверки количества и содержимого строк.
  • Симуляция кликов по заголовкам таблицы для тестирования сортировки.
  • Проверка реактивного обновления DOM после изменений.

Работа с модальными окнами

Компоненты ElDialog и ElDrawer требуют проверки отображения и закрытия модальных элементов:

import { mount } from '@vue/test-utils'
import ModalComponent from '@/components/ModalComponent.vue'
import ElementPlus from 'element-plus'

describe('ModalComponent Integration', () => {
  it('открывает и закрывает диалог', async () => {
    const wrapper = mount(ModalComponent, {
      global: { plugins: [ElementPlus] }
    })

    expect(wrapper.findComponent({ name: 'ElDialog' }).exists()).toBe(false)

    await wrapper.vm.openDialog()
    await wrapper.vm.$nextTick()
    expect(wrapper.findComponent({ name: 'ElDialog' }).exists()).toBe(true)

    await wrapper.vm.closeDialog()
    await wrapper.vm.$nextTick()
    expect(wrapper.findComponent({ name: 'ElDialog' }).exists()).toBe(false)
  })
})

Особенности:

  • Проверка видимости диалога через методы компонента.
  • Использование $nextTick для ожидания реактивного обновления DOM.
  • Тестирование вызова событий закрытия и их обработки.

Интеграция с внешними сервисами

Компоненты часто взаимодействуют с API. Для интеграционного тестирования важно мокать HTTP-запросы:

import { mount } from '@vue/test-utils'
import axios from 'axios'
import UserList from '@/components/UserList.vue'
import ElementPlus from 'element-plus'

jest.mock('axios')

describe('UserList Integration', () => {
  it('загружает и отображает пользователей', async () => {
    axios.get.mockResolvedValue({ data: [{ id: 1, name: 'Alice' }] })

    const wrapper = mount(UserList, {
      global: { plugins: [ElementPlus] }
    })

    await wrapper.vm.fetchUsers()
    await wrapper.vm.$nextTick()

    expect(wrapper.find('tbody tr').text()).toContain('Alice')
    expect(axios.get).toHaveBeenCalledWith('/api/users')
  })
})

Ключевые моменты:

  • Мокирование HTTP-запросов через jest.mock или vi.mock (для Vitest).
  • Проверка реакции компонентов на успешный и ошибочный ответ API.
  • Синхронизация данных с таблицами, списками и формами Element Plus.

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

  1. Тестировать сценарии, а не отдельные методы.
  2. Избегать излишнего мокирования компонентов Element Plus, использовать их реальную реализацию.
  3. Делить тесты на блоки по компонентам, сохраняя отдельные файлы для больших форм, таблиц и модальных окон.
  4. Использовать nextTick и ожидание промисов для корректного тестирования реактивных обновлений.
  5. Проверять пользовательский поток, включая ввод данных, нажатия кнопок и отображение элементов интерфейса.

Эффективное интеграционное тестирование Element Plus требует внимания к реактивности Vue, правильной конфигурации окружения и тщательной проверки взаимодействий между компонентами, формами, таблицами и модальными окнами, включая внешние API.