Юнит-тестирование поведения UI-компонентов на основе Slim Sel ect
требует изоляции логики работы селекта от реального DOM-браузера и
управления состоянием через программные интерфейсы библиотеки. Основная
сложность заключается в том, что Slim Select активно взаимодействует с
DOM, заменяет стандартный <select>, создает
собственную разметку и обрабатывает события выбора, поиска и обновления
данных.
При тестировании подобных компонентов ключевая задача — проверка не визуального результата, а состояния модели: выбранных значений, корректности инициализации, реакции на изменения данных и событий API.
Для тестирования Slim Select обычно используется jsdom,
так как библиотека предполагает наличие DOM-структуры.
Базовая подготовка тестовой среды включает создание HTML-элемента:
document.body.innerHTML = `
<select id="test-select">
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
</select>
`;
Инициализация экземпляра:
import SlimSelect fr om 'slim-select';
const slim = new SlimSelect({
select: '#test-select'
});
В юнит-тестах важно контролировать жизненный цикл экземпляра, чтобы исключить утечки состояния между тестами.
Первый слой тестирования — корректное создание экземпляра и
преобразование исходного <select>.
Типичные проверки:
<select>Пример:
test('инициализация SlimSelect создает инстанс и оборачивает select', () => {
const slim = new SlimSelect({ select: '#test-select' });
expect(slim).toBeDefined();
expect(document.querySelector('.ss-main')).not.toBeNull();
});
Дополнительно проверяется, что оригинальный
<select> становится скрытым:
const select = document.querySelector('#test-select');
expect(select.style.display).toBe('none');
Одним из центральных аспектов является синхронизация состояния между UI и внутренней моделью.
Slim Select предоставляет API для установки значений:
slim.setSelected('2');
Юнит-тест должен проверять:
isMultiple)test('выбор значения обновляет состояние', () => {
const slim = new SlimSelect({ select: '#test-select' });
slim.setSelected('2');
const select = document.querySelector('#test-select');
expect(select.value).toBe('2');
});
При множественном выборе:
slim.setSelected(['1', '3']);
expect(slim.getSelected()).toEqual(['1', '3']);
Методы getSelected и setSelected являются
основой взаимодействия с компонентом.
Проверяется:
test('getSelected возвращает текущее значение', () => {
const slim = new SlimSelect({ select: '#test-select' });
slim.setSelected('1');
expect(slim.getSelected()).toBe('1');
});
Обработка несуществующих значений:
slim.setSelected('999');
expect(slim.getSelected()).toBe(null);
Slim Select позволяет динамически обновлять список опций.
slim.setData([
{ text: 'Alpha', value: 'a' },
{ text: 'Beta', value: 'b' }
]);
Юнит-тесты для этого сценария проверяют:
test('setData обновляет список опций', () => {
const slim = new SlimSelect({ select: '#test-select' });
slim.setData([
{ text: 'A', value: 'a' },
{ text: 'B', value: 'b' }
]);
expect(document.querySelectorAll('.ss-option').length).toBe(2);
});
Если включен режим поиска, Slim Select фильтрует элементы на лету.
Проверяется:
slim.open();
slim.search('Al');
Проверка результата:
test('поиск фильтрует элементы', () => {
const slim = new SlimSelect({
select: '#test-select',
searchText: 'Search...'
});
slim.open();
slim.search('Tw');
const visibleOptions = document.querySelectorAll('.ss-option:not(.ss-hide)');
expect(visibleOptions.length).toBe(1);
});
Slim Select генерирует события при изменении состояния. Основные
сценарии тестирования связаны с onChange.
const slim = new SlimSelect({
select: '#test-select',
events: {
afterChange: (newVal) => {
callback(newVal);
}
}
});
Тестирование событий требует использования мок-функций:
test('afterChange вызывается при изменении выбора', () => {
const callback = jest.fn();
const slim = new SlimSelect({
select: '#test-select',
events: {
afterChange: callback
}
});
slim.setSelected('2');
expect(callback).toHaveBeenCalled();
});
Состояние раскрытия списка также подлежит проверке.
Методы:
open()close()Проверка DOM-состояния:
test('open добавляет активное состояние', () => {
const slim = new SlimSelect({ select: '#test-select' });
slim.open();
expect(document.querySelector('.ss-content').classList.contains('ss-open')).toBe(true);
});
Закрытие:
slim.close();
expect(document.querySelector('.ss-content').classList.contains('ss-open')).toBe(false);
Корректное удаление экземпляра критично для предотвращения утечек памяти.
Метод destroy должен:
<select>test('destroy восстанавливает исходный select', () => {
const slim = new SlimSelect({ select: '#test-select' });
slim.destroy();
expect(document.querySelector('.ss-main')).toBeNull();
expect(document.querySelector('#test-select').style.display).not.toBe('none');
});
Slim Select может использоваться в SPA, где элементы появляются и исчезают динамически.
Тестируются сценарии:
document.querySelector('#test-select').remove();
expect(() => slim.setSelected('1')).not.toThrow();
При тестировании поиска и debounce-логики часто используется управление таймерами:
jest.useFakeTimers();
slim.search('a');
jest.runAllTimers();
Это позволяет контролировать асинхронные обновления UI без реального ожидания.
Полноценное тестирование Slim Select-оберток обычно разделяется на уровни:
Особое внимание уделяется стабильности повторных операций, так как библиотека часто используется в формах, где компоненты пересоздаются или обновляются без перезагрузки страницы.
В интеграции со сборщиками модулей и фреймворками важно учитывать:
Тесты в таких условиях часто комбинируют юнит-подход и легкую интеграционную проверку поведения DOM-структуры.
Юнит-тестирование позволяет обнаружить типичные проблемы: