При E2E тестировании интерфейсов, использующих Tom Select, основное внимание сосредоточено на поведении компонента в реальном браузере: вводе текста, открытии выпадающего списка, выборе элементов, очистке значений и взаимодействии с внешними источниками данных. В отличие от unit- и integration-тестов, здесь проверяется полный путь пользователя через DOM, события и асинхронные операции, включая рендеринг и обновление состояния.
Tom Select строится вокруг преобразования стандартного
<select> элемента в управляемый JavaScript-компонент
с кастомным DOM. После инициализации исходный элемент скрывается, а на
его месте появляется структура, включающая контейнер, поле ввода,
dropdown и элементы выбранных значений.
Ключевые DOM-сущности:
.tomselect как корневой узел компонента.ts-control input.ts-dropdown.item.removeE2E тестирование ориентируется именно на эти элементы, поскольку они отражают пользовательское поведение, а не внутреннюю реализацию библиотеки.
В E2E сценариях важно учитывать, что Tom Select может работать в нескольких режимах:
Асинхронность влияет на стабильность тестов, поскольку DOM обновляется не мгновенно. Поэтому ключевым аспектом становится ожидание состояний интерфейса, а не фиксированных таймингов.
В современных тестовых раннерах, таких как Cypress и Playwright, используется ожидание появления элементов:
.ts-dropdown.optionВ E2E сценариях компонент обычно подключается через тестовую HTML-страницу:
<select id="country-select">
<option value="kz">Kazakhstan</option>
<option value="de">Germany</option>
<option value="jp">Japan</option>
</select>
<script>
new TomSelect("#country-select", {
create: false,
searchField: ["text"]
});
</script>
В тестах важно, чтобы страница загружалась в состоянии, идентичном production-среде: стили подключены, скрипты загружены, а DOM уже инициализирован.
Наиболее частый сценарий — открытие dropdown и выбор элемента. В Cypress это выглядит через последовательность действий:
cy.get('.tomselect').click();
cy.get('.ts-dropdown .option').contains('Germany').click();
cy.get('.tomselect .item').should('contain', 'Germany');
В Playwright аналогичный сценарий использует локаторы:
await page.click('.tomselect');
await page.click('.ts-dropdown .option:text("Germany")');
await expect(page.locator('.item')).toContainText('Germany');
Ключевая проверка заключается не в клике как таковом, а в том, что DOM отражает выбранное состояние.
Функция поиска внутри Tom Select часто является наиболее сложной частью для E2E тестов, поскольку включает:
Типовой сценарий:
cy.get('.ts-control input').type('ger');
cy.get('.ts-dropdown .option').should('have.length', 1);
cy.get('.ts-dropdown .option').first().should('contain', 'Germany');
В случае асинхронного источника данных добавляется ожидание сетевого запроса:
cy.intercept('GET', '/api/countries?q=ger').as('search');
cy.get('.ts-control input').type('ger');
cy.wait('@search');
cy.get('.ts-dropdown .option').should('exist');
Tom Select поддерживает режим remote data source, где данные подгружаются через API. В E2E тестировании этот режим требует контроля сетевого слоя.
Часто используется перехват запросов:
cy.interceptpage.routeПример сценария:
page.route('**/api/countries*', route =>
route.fulfill({
status: 200,
body: JSON.stringify([
{ value: 'kz', text: 'Kazakhstan' },
{ value: 'de', text: 'Germany' }
])
})
);
После ввода текста тест проверяет, что данные отрисованы корректно и доступны для выбора.
Tom Select поддерживает режим множественного выбора, где пользователь может добавлять несколько элементов.
DOM в этом случае содержит набор .item внутри
контейнера.
Типовой сценарий:
cy.get('.ts-control input').type('a');
cy.get('.ts-dropdown .option').first().click();
cy.get('.ts-control input').type('b');
cy.get('.ts-dropdown .option').first().click();
cy.get('.item').should('have.length', 2);
Особенность проверки заключается в порядке элементов: он может быть важен, если включена сортировка выбора.
Удаление реализуется через кнопку .remove, встроенную в
каждый .item.
cy.get('.item .remove').first().click();
cy.get('.item').should('have.length', 1);
В сложных сценариях проверяется также синхронизация состояния
<select>:
cy.get('select').find('option:selected').should('have.length', 1);
Tom Select активно использует клавиатурное управление:
E2E тестирование клавиатуры требует имитации событий:
cy.get('.ts-control input').type('{downarrow}');
cy.get('.ts-control input').type('{enter}');
cy.get('.item').should('exist');
В Playwright:
await page.keyboard.press('ArrowDown');
await page.keyboard.press('Enter');
Ключевая проверка заключается в изменении состояния интерфейса без использования мыши.
Tom Select может быть инициализирован на disabled
<select> элементе. В этом случае взаимодействие
должно быть заблокировано.
cy.get('.tomselect').should('have.class', 'disabled');
cy.get('.ts-control input').should('not.be.visible');
Readonly режим проверяется через отсутствие возможности изменения значений:
cy.get('.ts-control input').type('test');
cy.get('.item').should('have.length', 0);
В некоторых сценариях список опций может изменяться после инициализации. Это требует проверки реактивности компонента.
cy.window().then(win => {
const select = win.document.querySelector('#country-select');
const tom = select.tomselect;
tom.addOption({ value: 'fr', text: 'France' });
tom.refreshOptions(false);
});
После этого E2E тест проверяет появление новой опции в dropdown.
Функция очистки состояния используется через метод clear или UI-кнопку.
cy.get('.clear-button').click();
cy.get('.item').should('not.exist');
Дополнительно проверяется сброс значения
<select>:
cy.get('select').should('have.value', '');
Основная сложность E2E тестирования Tom Select заключается в нестабильности, связанной с:
Решение заключается в опоре на состояния DOM:
should('exist')should('be.visible')should('have.length')Использование фиксированных wait(1000) считается
источником флаки-тестов и заменяется на событийные ожидания.
В CI среде E2E тесты Tom Select выполняются в headless-браузерах. Особое внимание уделяется:
Пример стабилизации:
* {
transition: none !important;
animation: none !important;
}
В продвинутых сценариях проверяется комбинация:
Пример сценария создания нового элемента:
cy.get('.ts-control input').type('new item');
cy.get('.create').click();
cy.get('.item').should('contain', 'new item');
Tom Select позволяет переопределять отображение опций через
render.option и render.item. E2E тестирование
здесь фокусируется на структуре DOM, а не на логике:
cy.get('.option.custom').should('exist');
cy.get('.item.custom').should('contain', 'Germany');
Полное E2E тестирование Tom Select сводится к проверке связки:
Каждый этап проверяется через DOM-состояние, поскольку внутренние структуры библиотеки остаются скрытыми и не должны использоваться в тестах напрямую.