Юнит-тестирование форматирования числовых значений в браузерных и Node.js-библиотеках требует особого подхода, поскольку поведение часто зависит от локали, DOM-среды, событий ввода и внутренних правил округления. В контексте AutoNumeric ключевой задачей становится проверка корректности преобразования входных данных в отформатированные строки и обратно, включая сценарии частичного ввода, удаления символов, вставки и программного изменения значений.
Форматирование чисел нельзя тестировать как чистую функцию в классическом виде, поскольку библиотека работает с состоянием DOM-элемента и перехватывает пользовательские события. Это приводит к необходимости разделения тестов на несколько уровней:
Ключевая сложность заключается в том, что одно и то же число может иметь разные корректные представления в зависимости от конфигурации:
digitGroupSeparator);decimalCharacter);decimalPlaces);roundingMethod);currencySymbol).Для тестирования AutoNumeric в Node.js чаще всего используется связка Jest и JSDOM. JSDOM эмулирует браузерный DOM, позволяя создавать input-элементы и симулировать пользовательский ввод.
Типовая конфигурация тестового окружения включает:
input,
keydown, blur);Важно учитывать, что некоторые браузерные API могут отсутствовать в JSDOM, поэтому требуется их частичное мокирование.
Пример базовой инициализации тестового инпута:
document.body.innerHTML = `<input id="price" type="text">`;
const input = document.getElementById("price");
После этого к элементу применяется AutoNumeric-конфигурация:
import AutoNumeric from "autonumeric";
const anElement = new AutoNumeric(input, {
digitGroupSeparator: " ",
decimalCharacter: ",",
decimalPlaces: 2
});
Первый уровень проверки — корректное преобразование входного числа в строковое представление.
Проверяется:
Пример теста:
test("форматирует число с разделением тысяч", () => {
document.body.innerHTML = `<input id="price">`;
const input = document.getElementById("price");
new AutoNumeric(input, {
digitGroupSeparator: " ",
decimalCharacter: ".",
decimalPlaces: 2
});
input.value = "1000000.5";
input.dispatchEvent(new Event("input", { bubbles: true }));
expect(input.value).toBe("1 000 000.50");
});
В этом сценарии проверяется не только форматирование, но и реакция на
событие input, которое активирует внутренний парсер
AutoNumeric.
Округление является одной из наиболее чувствительных частей логики. Разные режимы могут давать разные результаты даже при одинаковом входном значении.
Основные режимы:
Тестирование требует проверки пограничных значений:
test("округление HALF_UP до двух знаков", () => {
document.body.innerHTML = `<input id="price">`;
const input = document.getElementById("price");
new AutoNumeric(input, {
decimalPlaces: 2,
roundingMethod: "HALF_UP",
decimalCharacter: "."
});
input.value = "10.555";
input.dispatchEvent(new Event("input", { bubbles: true }));
expect(input.value).toBe("10.56");
});
Особое внимание уделяется значениям вида x.5,
x.555, x.554, поскольку именно они выявляют
ошибки в алгоритме округления.
AutoNumeric работает в режиме live-форматирования, поэтому пользователь может вводить число поэтапно:
11010001000000На каждом этапе значение должно оставаться валидным и корректно форматироваться.
Пример теста:
test("постепенный ввод числа форматируется корректно", () => {
document.body.innerHTML = `<input id="price">`;
const input = document.getElementById("price");
new AutoNumeric(input, {
digitGroupSeparator: ",",
decimalPlaces: 0
});
input.value = "1";
input.dispatchEvent(new Event("input", { bubbles: true }));
expect(input.value).toBe("1");
input.value = "1000";
input.dispatchEvent(new Event("input", { bubbles: true }));
expect(input.value).toBe("1,000");
input.value = "1000000";
input.dispatchEvent(new Event("input", { bubbles: true }));
expect(input.value).toBe("1,000,000");
});
Здесь проверяется устойчивость форматирования к промежуточным состояниям.
Удаление символов часто приводит к нестабильным состояниям, особенно если задействованы групповые разделители.
Проверяется:
Пример:
test("удаление символов сохраняет корректный формат", () => {
document.body.innerHTML = `<input id="price">`;
const input = document.getElementById("price");
new AutoNumeric(input, {
digitGroupSeparator: " ",
decimalPlaces: 0
});
input.value = "1 000 000";
input.dispatchEvent(new Event("input", { bubbles: true }));
input.value = "100 000";
input.dispatchEvent(new Event("input", { bubbles: true }));
expect(input.value).toBe("100 000");
});
Отрицательные числа требуют проверки положения знака минус и его сохранения при форматировании.
Ключевые сценарии:
test("форматирование отрицательного числа", () => {
document.body.innerHTML = `<input id="price">`;
const input = document.getElementById("price");
new AutoNumeric(input, {
digitGroupSeparator: ",",
decimalPlaces: 2
});
input.value = "-12345.6";
input.dispatchEvent(new Event("input", { bubbles: true }));
expect(input.value).toBe("-12,345.60");
});
При включении валютного символа добавляется дополнительный слой логики:
test("форматирование с валютным символом", () => {
document.body.innerHTML = `<input id="price">`;
const input = document.getElementById("price");
new AutoNumeric(input, {
currencySymbol: "$",
currencySymbolPlacement: "p",
digitGroupSeparator: ",",
decimalPlaces: 2
});
input.value = "2500";
input.dispatchEvent(new Event("input", { bubbles: true }));
expect(input.value).toBe("$2,500.00");
});
Локализация влияет на:
Типичный тест локали:
test("локаль с запятой как десятичным разделителем", () => {
document.body.innerHTML = `<input id="price">`;
const input = document.getElementById("price");
new AutoNumeric(input, {
decimalCharacter: ",",
digitGroupSeparator: ".",
decimalPlaces: 2
});
input.value = "1234.56";
input.dispatchEvent(new Event("input", { bubbles: true }));
expect(input.value).toBe("1.234,56");
});
Для более точного тестирования требуется имитация реальных пользовательских действий:
keydown для проверки ограничений ввода;keypress для устаревших сценариев;blur для финального форматирования;focus для перехода в режим редактирования.Пример теста blur-форматирования:
test("переформатирование при потере фокуса", () => {
document.body.innerHTML = `<input id="price">`;
const input = document.getElementById("price");
new AutoNumeric(input, {
decimalPlaces: 2
});
input.value = "12.3";
input.dispatchEvent(new Event("input", { bubbles: true }));
input.dispatchEvent(new Event("blur"));
expect(input.value).toBe("12.30");
});
AutoNumeric позволяет изменять значение программно, минуя пользовательский ввод. Это требует отдельного тестирования:
set();get();clear();setUnformatted().Пример:
test("set и get работают корректно", () => {
document.body.innerHTML = `<input id="price">`;
const input = document.getElementById("price");
const anElement = new AutoNumeric(input, {
decimalPlaces: 2
});
anElement.set(9999.9);
expect(anElement.get()).toBe(9999.9);
expect(input.value).toBe("9,999.90");
});
Особое внимание уделяется:
Пример:
test("обработка NaN и пустого значения", () => {
document.body.innerHTML = `<input id="price">`;
const input = document.getElementById("price");
new AutoNumeric(input, {
decimalPlaces: 2
});
input.value = "";
input.dispatchEvent(new Event("input", { bubbles: true }));
expect(input.value).toBe("");
});