Использование Intl API в JavaScript требует строгого
контроля корректности локализации, поскольку результат форматирования
зависит от множества параметров: языка, региона, календаря, часового
пояса, политик округления и системных настроек окружения. Автоматизация
проверок позволяет гарантировать стабильность поведения форматеров и
предотвращает регрессии при изменении кода, обновлении браузеров или
библиотек.
Поведение объектов Intl.NumberFormat,
Intl.DateTimeFormat, Intl.Collator,
Intl.ListFormat и других не является полностью
детерминированным без фиксации входных параметров. Поэтому тестирование
строится вокруг следующих принципов:
locale и параметров форматированияКлючевое требование — устранение вариативности окружения.
Intl.NumberFormat используется для локализованного
отображения чисел, валют и процентов. Основная задача автоматизации —
контроль стабильности форматирования.
const formatter = new Intl.NumberFormat('de-DE', {
style: 'decimal',
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
formatter.format(1234567.89);
В тестах фиксируется ожидаемое значение:
test('number formatting in de-DE', () => {
const formatter = new Intl.NumberFormat('de-DE', {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
expect(formatter.format(1234567.89)).toBe('1.234.567,89');
});
const formatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
});
Автоматизация проверяет:
Intl.DateTimeFormat зависит от локали, календаря и
временной зоны. Основная проблема автоматизации — нестабильность
системного времени и окружения CI.
const formatter = new Intl.DateTimeFormat('en-GB', {
year: 'numeric',
month: '2-digit',
day: '2-digit'
});
Для детерминированных тестов фиксируется Date:
test('date formatting en-GB', () => {
const formatter = new Intl.DateTimeFormat('en-GB', {
year: 'numeric',
month: '2-digit',
day: '2-digit'
});
const date = new Date('2025-01-15T00:00:00Z');
expect(formatter.format(date)).toBe('15/01/2025');
});
Особую сложность создаёт параметр timeZone. Без его
фиксации результат зависит от окружения.
const formatter = new Intl.DateTimeFormat('en-US', {
timeZone: 'UTC',
hour: '2-digit',
minute: '2-digit'
});
Автоматизированные проверки фиксируют:
Intl.Collator отвечает за корректную сортировку с учётом
локали.
const collator = new Intl.Collator('sv-SE');
['ä', 'z', 'a'].sort(collator.compare);
Автоматизация проверяет:
test('sorting sv-SE locale', () => {
const collator = new Intl.Collator('sv-SE');
const result = ['ä', 'z', 'a'].sort(collator.compare);
expect(result).toEqual(['a', 'z', 'ä']);
});
Intl.ListFormat используется для формирования читаемых
списков.
const formatter = new Intl.ListFormat('en', {
style: 'long',
type: 'conjunction'
});
Автоматизация проверяет:
test('list formatting en', () => {
const formatter = new Intl.ListFormat('en', {
style: 'long',
type: 'conjunction'
});
expect(formatter.format(['apples', 'oranges', 'bananas']))
.toBe('apples, oranges, and bananas');
});
Среда непрерывной интеграции часто имеет непредсказуемые локали. Для устранения вариативности применяются:
localetimeZoneПример конфигурации тестового окружения:
process.env.TZ = 'UTC';
Дополнительно тесты избегают:
Snapshot-подход используется для фиксации строк форматирования.
const formatter = new Intl.NumberFormat('fr-FR', {
style: 'currency',
currency: 'EUR'
});
formatter.format(1999.99);
Snapshot сохраняет результат:
"1 999,99 €"
При изменении ICU-данных или браузерной реализации изменения фиксируются автоматически через дифф.
Обновления Node.js и браузеров могут менять поведение
Intl. Автоматизация направлена на выявление:
Регрессионные тесты сравнивают текущие результаты с эталонными.
Особое внимание уделяется крайним значениям:
new Intl.DateTimeFormat('en-US').format(new Date('2024-03-10T02:30:00'));
Такие сценарии выявляют ошибки временных зон и календарных преобразований.
В некоторых сценариях требуется замена реализации Intl
на предсказуемую версию.
Подходы:
IntlПример изоляции:
global.Intl = require('intl');
Стабильность тестов достигается через:
IntlПри поддержке множества языков применяется массовое тестирование:
const locales = ['en', 'de', 'fr', 'ja'];
locales.forEach(locale => {
const formatter = new Intl.NumberFormat(locale);
formatter.format(12345.67);
});
Форматирование влияет на UI, поэтому проверяется:
Автоматизированные проверки Intl API включаются в pipeline:
Такая схема предотвращает деградацию локализации на уровне сборки.