Inputmask часто используется в формах для стандартизации пользовательского ввода: телефоны, даты, номера документов, банковские реквизиты. При E2E тестировании подобных форм возникает специфический слой сложности, связанный не только с DOM-логикой, но и с динамической трансформацией введённого значения.
Механизм работы Inputmask заключается в перехвате пользовательского
ввода и преобразовании его в заданный формат. Внутренне это выражается в
постоянной модификации value input-элемента, а также в
обработке событий keydown, input,
paste, blur.
Ключевая особенность:
отображаемое значение ≠ введённое значение
Это приводит к расхождению между тем, что отправляется в тестовый сценарий, и тем, что фактически хранится в модели формы.
При E2E проверках это проявляется в следующих аспектах:
blurПеред выполнением проверок необходимо учитывать, что Inputmask может применять преобразования не мгновенно. В тестах это выражается в необходимости ожидания стабилизации DOM-состояния.
В рамках Cypress часто используется стратегия повторной проверки значения:
cy.get('input[name="phone"]')
.type('77001234567')
.should('have.value', '+7 (700) 123-45-67')
Ключевой момент — использование should, которое
автоматически ретраит проверку до стабилизации результата.
В Playwright аналогичный подход реализуется через ожидания:
import { expect } from '@playwright/test';
await page.fill('input[name="phone"]', '77001234567');
await expect(page.locator('input[name="phone"]'))
.toHaveValue('+7 (700) 123-45-67');
Inputmask часто предоставляет доступ к «чистому» значению через свойства элемента или API. В тестах важно различать:
Типичная ошибка E2E сценариев заключается в проверке только
value, игнорируя внутреннюю модель.
Пример проверки через DOM:
const input = document.querySelector('input[name="date"]');
console.log(input.value);
// 31.12.2025 (formatted)
В некоторых конфигурациях Inputmask добавляет доступ к raw значению
через dataset или API плагина, что требует отдельной проверки через
evaluate в браузерном контексте.
Inputmask активно реагирует на последовательность событий:
keydown — первичная обработка символаinput — применение маскиchange — фиксация значенияblur — финальная нормализацияE2E тесты должны учитывать порядок событий, особенно при симуляции
ввода через type() или fill().
Пример проблемного сценария:
cy.get('input[name="card"]')
.type('4111111111111111')
.blur();
В момент выполнения blur значение может быть ещё не
нормализовано, если маска имеет задержку или асинхронную логику.
Paste-события часто обрабатываются иначе, чем посимвольный ввод. Inputmask может применять отдельный pipeline для вставленного текста.
В E2E тестах это проявляется следующим образом:
cy.get('input[name="phone"]').invoke('val', '77001234567').trigger('input');
или в Playwright:
await page.locator('input[name="phone"]').fill('77001234567');
Однако при использовании clipboard API возможны расхождения, так как
часть масок фильтрует символы до попадания в value.
Типичный кейс — международные форматы:
+7 (___) ___-__-__+1 (___) ___-____Проверка должна учитывать:
cy.get('input[name="phone"]')
.type('1234567890')
.should('have.value', '+1 (123) 456-7890');
Маски дат часто включают автоматическую подстановку разделителей:
cy.get('input[name="date"]')
.type('31122025')
.should('have.value', '31/12/2025');
Особенность заключается в том, что некоторые реализации Inputmask валидируют диапазоны (например, месяц ≤ 12), что должно учитываться в негативных тестах.
Маски банковских карт часто группируют цифры:
cy.get('input[name="card"]')
.type('4111111111111111')
.should('have.value', '4111 1111 1111 1111');
Дополнительно проверяется:
E2E тестирование масок включает не только позитивные кейсы, но и проверку устойчивости к некорректному вводу:
!@#$%cy.get('input[name="phone"]')
.type('abc!!!123')
.should('have.value', '+1 (123');
Одной из основных проблем является нестабильность тестов, вызванная:
blurСтабилизация достигается через:
should / expect с
ретраямиПример нестабильного подхода:
cy.get('input').type('123');
cy.get('input').should('have.value', '123');
Пример устойчивого подхода:
cy.get('input')
.type('123')
.should('have.value', '(123) ___-____');
Для форм с Inputmask критично использовать стабильные селекторы:
data-testiddata-cydata-qaПример:
<input data-testid="phone-input" />
cy.get('[data-testid="phone-input"]').type('70001234567');
Использование CSS-селекторов по классам нежелательно из-за высокой вероятности изменения разметки при интеграции маски.
При большом количестве форм с масками формируется слой абстракции:
Cypress.Commands.add('typeMaskedPhone', (selector, value) => {
cy.get(selector)
.clear()
.type(value)
.blur();
});
Использование подобных команд снижает дублирование логики и уменьшает влияние изменений Inputmask-конфигурации на тестовый код.
E2E тесты должны учитывать различия:
Inputmask может вести себя по-разному в зависимости от event loop браузера, что требует кроссбраузерной проверки через Playwright или Selenium Grid.
В CI окружениях часто проявляются дополнительные проблемы:
Рекомендуемые практики:
Inputmask реагирует не только на пользовательский ввод, но и на:
input.value = '123456';
input.dispatchEvent(new Event('input'));
В E2E сценариях это используется для:
Однако важно учитывать, что некоторые конфигурации маски требуют дополнительного вызова обновления состояния через API Inputmask, иначе значение останется нефильтрованным.