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

Интеграционное тестирование компонентов на базе Slim Sel ect строится вокруг проверки взаимодействия библиотеки с DOM, пользовательскими событиями и внешними источниками данных в условиях, максимально приближенных к реальному браузерному окружению. Основная цель такого тестирования заключается не в изоляции отдельных функций, а в проверке целостного поведения компонента: корректной инициализации, синхронизации состояния, обработки пользовательских действий и интеграции с фреймворками или серверными API.

Для интеграционного тестирования DOM-компонентов используется окружение, имитирующее браузер. Наиболее распространённые варианты:

  • Jest + jsdom — для быстрых тестов логики и DOM-манипуляций
  • Vitest + jsdom — альтернатива с более современной инфраструктурой
  • Cypress / Playwright — для полноценных E2E-сценариев с реальным браузером

Slim Select активно взаимодействует с DOM напрямую, поэтому jsdom подходит только для базовой проверки логики, тогда как полноценные сценарии выбора, открытия списка и обработки кликов требуют headless-браузера.

При использовании Jest важно учитывать ограничения jsdom: отсутствие реального layout-движка, упрощённая обработка событий и частичная эмуляция focus/blur поведения.

Базовая интеграция библиотеки в тестах

Инициализация Slim Select в тестовой среде выполняется на реальном DOM-элементе <select>:

import SlimSelect fr om 'slim-select'

document.body.innerHTML = `
  <select id="test-select">
    <option value="1">One</option>
    <option value="2">Two</option>
  </select>
`

const instance = new SlimSelect({
  select: '#test-select'
})

Интеграционный тест в этом контексте проверяет:

  • создание кастомной структуры DOM
  • замену стандартного select-элемента
  • корректную инициализацию выбранного значения
  • синхронизацию состояния между оригинальным select и UI-обёрткой

Проверка DOM-структуры

После инициализации Slim Select формирует собственную разметку. Тесты фиксируют наличие ключевых элементов:

  • контейнера компонента
  • кнопки открытия списка
  • блока списка опций
  • активных классов состояния

Пример проверок:

test('создаётся контейнер Slim Select', () => {
  const container = document.querySelector('.ss-main')
  expect(container).not.toBeNull()
})

Особое внимание уделяется соответствию состояния оригинального <select> и визуального представления. Любое рассинхронизированное состояние считается критической ошибкой интеграции.

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

Интерактивная часть Slim Select основана на обработке событий мыши и клавиатуры. В интеграционных тестах моделируются следующие действия:

  • открытие списка (click)
  • выбор элемента (click на option)
  • закрытие списка
  • навигация клавишами ArrowUp, ArrowDown, Enter, Escape

Пример имитации клика:

const trigger = document.querySelector('.ss-single-selected')
trigger.click()

После клика проверяется:

  • изменение класса активности списка
  • появление DOM-элементов опций
  • корректное отображение выбранного значения

Проверка синхронизации состояния

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

  • внутренним состоянием Slim Select
  • DOM-элементом <select>
  • визуальным интерфейсом

При выборе значения проверяется:

const select = document.querySelector('select')
expect(select.value).toBe('2')

Дополнительно проверяется UI-слой:

  • обновление текста выбранного элемента
  • изменение активного класса у option
  • корректное закрытие списка после выбора (в зависимости от конфигурации)

Множественный выбор (multiple)

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

  • добавление нескольких значений
  • отображение выбранных элементов в виде тегов
  • возможность удаления выбранного значения
const select = new SlimSelect({
  select: '#test-select',
  settings: {
    isMultiple: true
  }
})

Проверка состояния включает:

  • массив выбранных значений
  • наличие соответствующих UI-тегов
  • корректное удаление элемента через кнопку remove

Особое внимание уделяется отсутствию дублирования значений и корректному обновлению DOM после каждого изменения.

Асинхронная загрузка данных

Slim Select поддерживает сценарии подгрузки данных через AJAX. В интеграционных тестах это требует мокирования сетевых запросов.

Типовой подход:

  • подмена fetch или XMLHttpRequest
  • возврат фиктивного JSON-ответа
  • ожидание асинхронного обновления списка
global.fetch = jest.fn(() =>
  Promise.resolve({
    json: () => Promise.resolve([
      { value: '1', text: 'One' },
      { value: '2', text: 'Two' }
    ])
  })
)

После инициализации проверяется:

  • появление загруженных опций
  • корректная отрисовка списка
  • обновление состояния после выбора

Асинхронные тесты требуют контроля таймингов через await и waitFor, иначе возможны ложные отрицательные результаты.

Обработка динамических изменений DOM

Интеграция Slim Select часто включает сценарии, где исходный <select> изменяется после инициализации:

  • добавление новых <option>
  • удаление существующих
  • изменение атрибутов

Тесты проверяют, отражаются ли изменения в UI без переинициализации компонента или с её необходимостью.

Пример:

select.appendChild(new Option('Three', '3'))
select.dispatchEvent(new Event('change'))

Далее проверяется:

  • появление новой опции в интерфейсе
  • корректность внутренних структур данных
  • отсутствие дублирования DOM-узлов

Клавиатурная навигация

Клавиатурная поддержка является важной частью интеграционного тестирования. Проверяются сценарии:

  • перемещение по списку стрелками
  • выбор через Enter
  • закрытие через Escape
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowDown' }))
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }))

Валидация включает:

  • изменение активного элемента
  • корректное обновление значения
  • закрытие/открытие списка в зависимости от состояния

Изоляция тестов и очистка состояния

Каждый тест должен выполняться в чистом DOM. При использовании Slim Select важно корректно уничтожать экземпляры:

instance.destroy()
document.body.innerHTML = ''

Отсутствие очистки приводит к:

  • утечкам DOM-узлов
  • конфликтам классов
  • некорректным результатам следующих тестов

Проверка доступности и focus-состояний

Интеграционные тесты часто включают проверку accessibility-состояний:

  • переход фокуса на компонент
  • корректное поведение tabindex
  • реакция на blur/focus
trigger.focus()
expect(document.activeElement).toBe(trigger)

Особое внимание уделяется синхронизации состояния раскрытого списка с фокусом, поскольку некорректная реализация приводит к “залипанию” интерфейса.

Тестирование в реальном браузере

Для полной уверенности в корректности интеграции применяется Cypress или Playwright. В таких тестах проверяются:

  • реальные клики
  • отрисовка в браузере
  • поведение при скролле
  • работа в разных viewport

Сценарий может включать:

  • загрузку страницы
  • инициализацию Slim Select
  • выбор значения
  • проверку результата в форме отправки

Реальное браузерное окружение позволяет выявить проблемы, которые невозможно воспроизвести в jsdom: z-index конфликты, проблемы позиционирования dropdown, ошибки CSS-integration.

Типовые проблемы интеграции

В процессе тестирования часто выявляются следующие классы ошибок:

  • рассинхронизация состояния между DOM и внутренним состоянием
  • некорректная работа destroy/re-init
  • утечки событийных слушателей
  • некорректная обработка async-данных
  • конфликт CSS-стилей с внешними библиотеками

Каждая из этих проблем проявляется только в интеграционном слое, что делает такие тесты критически важными для стабильности поведения компонента в продакшене.