При тестировании компонентов, использующих AutoNumeric, ключевой
сложностью становится необходимость имитации реального поведения
пользователя в браузере. Библиотека работает на стыке DOM-событий,
форматирования строкового представления числа и внутреннего состояния
поля ввода, поэтому простого вызова value = ...
недостаточно для воспроизведения реальных сценариев.
Мокирование пользовательских действий в данном контексте означает генерацию последовательности событий, которые браузер обычно формирует при взаимодействии с полем ввода: клавиатурный ввод, вставка из буфера обмена, потеря/получение фокуса, программные изменения значения, а также события композиции текста.
Основная цель такого подхода — проверить не только итоговое значение, но и корректность реакций AutoNumeric на цепочку событий, включая форматирование, позицию курсора и триггеры обновления состояния.
AutoNumeric опирается на стандартные DOM-события:
keydown / keyupkeypress (в устаревших сценариях)inputbeforeinputpastefocus / blurcompositionstart / compositionupdate /
compositionendПри тестировании важно учитывать, что внутренние алгоритмы библиотеки
часто завязаны на input и beforeinput, а
остальные события используются для контекстной синхронизации
состояния.
Мокирование должно учитывать не только факт вызова события, но и его свойства:
event.target.valueevent.data (для InputEvent)event.inputType (например, insertText,
deleteContentBackward)event.clipboardData (при вставке)key, code,
keyCode в старых тестах)В тестовой среде чаще всего используется программное создание событий
через dispatchEvent.
Пример базового подхода:
const input = document.createElement('input');
document.body.appendChild(input);
const event = new InputEvent('input', {
bubbles: true,
cancelable: true,
data: '1234',
inputType: 'insertText'
});
input.value = '1234';
input.dispatchEvent(event);
Однако для AutoNumeric такой упрощённый вариант часто недостаточен,
поскольку библиотека может перехватывать ввод до изменения
value или ожидать согласованности между
inputType и фактическим содержимым поля.
Клавиатурный ввод остаётся одним из наиболее сложных сценариев мокирования, так как включает несколько последовательных событий.
Типичная последовательность:
keydownbeforeinputvalueinputkeyupПример имитации:
function simulateKey(input, key) {
input.dispatchEvent(new KeyboardEvent('keydown', {
key,
bubbles: true
}));
input.value += key;
input.dispatchEvent(new InputEvent('input', {
data: key,
inputType: 'insertText',
bubbles: true
}));
input.dispatchEvent(new KeyboardEvent('keyup', {
key,
bubbles: true
}));
}
Для AutoNumeric важно, что изменение value вручную часто
должно происходить до или синхронно с input, иначе
внутренняя логика форматирования может не сработать корректно.
Удаление символов требует иной семантики событий:
input.dispatchEvent(new KeyboardEvent('keydown', {
key: 'Backspace',
bubbles: true
}));
input.value = input.value.slice(0, -1);
input.dispatchEvent(new InputEvent('input', {
inputType: 'deleteContentBackward',
data: null,
bubbles: true
}));
AutoNumeric использует тип удаления для корректного пересчёта форматированного значения, особенно при работе с разделителями тысяч и десятичными знаками.
Вставка данных является отдельным сценарием, так как включает
ClipboardEvent.
const pasteEvent = new ClipboardEvent('paste', {
bubbles: true,
clipboardData: new DataTransfer()
});
pasteEvent.clipboardData.setData('text/plain', '12,345.67');
input.dispatchEvent(pasteEvent);
После события paste AutoNumeric обычно инициирует
переразбор строки, поэтому тестовая среда должна либо:
valueСценарии focus и blur критичны для проверки
форматирования при выходе из поля.
AutoNumeric часто переключает отображение между “сырым” и “форматированным” состоянием именно на этих событиях.
input.dispatchEvent(new FocusEvent('focus', {
bubbles: true
}));
input.value = '1234.5';
input.dispatchEvent(new FocusEvent('blur', {
bubbles: true
}));
При blur часто активируется финальное форматирование,
включая округление, добавление разделителей и приведение к заданной
локали.
Для языков с составным вводом (например, азиатские раскладки) используются события композиции:
input.dispatchEvent(new CompositionEvent('compositionstart', {
bubbles: true
}));
input.value = '123';
input.dispatchEvent(new CompositionEvent('compositionend', {
data: '123',
bubbles: true
}));
input.dispatchEvent(new InputEvent('input', {
data: '123',
inputType: 'insertCompositionText',
bubbles: true
}));
AutoNumeric может временно отключать форматирование во время композиции, чтобы не мешать вводу символов, поэтому корректная последовательность событий критична.
В средах вроде Jest используется jsdom, который не полностью воспроизводит поведение браузера. Это требует дополнительного контроля над состоянием DOM.
Часто применяется явное переопределение value и ручной
вызов событий:
input.value = '1000';
input.dispatchEvent(new Event('input', { bubbles: true }));
Для более точного контроля может использоваться обёртка:
function setValueAndTrigger(input, value) {
input.value = value;
input.dispatchEvent(new Event('input', { bubbles: true }));
input.dispatchEvent(new Event('change', { bubbles: true }));
}
AutoNumeric реагирует на change реже, но в некоторых
конфигурациях это событие используется для синхронизации внешнего
состояния.
Ключевая часть мокирования — валидация результата после цепочки событий.
Типовой сценарий:
simulateKey(input, '1');
simulateKey(input, '0');
simulateKey(input, '0');
simulateKey(input, '0');
expect(input.value).toBe('1,000');
Однако в AutoNumeric значение может зависеть от конфигурации:
Поэтому тестовые сценарии часто фиксируют конфигурацию заранее, чтобы исключить вариативность.
AutoNumeric предоставляет API для установки значений без пользовательского ввода. В тестах важно различать:
input.value = ...)setValue вызовыПример:
autoNumericInstance.set('2500.75');
После этого DOM-события могут не генерироваться автоматически,
поэтому тесты, проверяющие реакцию UI, должны явно инициировать
input или blur.
Реалистичное мокирование часто включает смешанные цепочки:
Пример последовательности:
input.dispatchEvent(new FocusEvent('focus', { bubbles: true }));
simulateKey(input, '1');
simulateKey(input, '0');
input.dispatchEvent(new ClipboardEvent('paste', {
bubbles: true,
clipboardData: new DataTransfer()
}));
input.value = '10abc0';
input.dispatchEvent(new InputEvent('input', {
inputType: 'insertFromPaste',
data: '10abc0',
bubbles: true
}));
input.dispatchEvent(new FocusEvent('blur', { bubbles: true }));
AutoNumeric в таких сценариях обязан:
Отдельным аспектом тестирования становится
selectionStart и selectionEnd.
input.value = '12345';
input.setSelectionRange(2, 2);
После симуляции ввода важно проверять, изменилось ли положение курсора корректно, так как AutoNumeric может перерасчитывать позицию после форматирования.
Наиболее частые проблемы:
value и
InputEvent.databubbles: truecomposition-состоянийKeyboardEvent и InputEvent без
синхронизацииОсобенно критичным является рассинхрон между ручным изменением
value и генерацией input события, что приводит
к расхождению внутреннего состояния AutoNumeric.
Для уменьшения флаки-тестов применяется стандартизация:
Такая структура позволяет воспроизводить поведение библиотеки максимально близко к реальному браузерному взаимодействию без зависимости от особенностей jsdom или тестового раннера