Валидация в Vest строится вокруг декларативного описания тестов, которые выполняются последовательно внутри единого набора правил (suite). Каждый тест может завершиться либо успехом, либо фиксацией ошибки. При этом результат не прерывает выполнение остальных проверок по умолчанию: система стремится собрать максимально полную картину нарушений.
Каждое поле формирует собственный набор ошибок. Если для одного значения определено несколько проверок, каждая из них потенциально может добавить запись в результат. Однако итоговая структура ошибок после выполнения suite проходит нормализацию: для каждого поля формируется агрегированный список, который затем может быть дополнительно сокращён или приоритизирован в зависимости от конфигурации.
Ключевая особенность модели — разделение этапов:
Именно на этапе постобработки вступают в силу правила приоритизации.
В Vest порядок объявления тестов напрямую влияет на порядок их исполнения. Это критично, поскольку первая обнаруженная ошибка часто становится основной в пользовательском интерфейсе.
import { create, test, enforce } from 'vest';
const suite = create((data = {}) => {
test('email', 'Почта обязательна', () => {
enforce(data.email).isNotBlank();
});
test('email', 'Неверный формат почты', () => {
enforce(data.email).matches(/.+@.+\..+/);
});
});
В данном случае приоритет ошибок определяется порядком:
Если поле пустое, обе проверки формально могут быть выполнены, но первая ошибка, соответствующая первому тесту, становится приоритетной при отображении.
Таким образом, естественный приоритет задаётся порядком объявления тестов, что позволяет управлять логикой отображения без дополнительных механизмов.
По умолчанию Vest группирует ошибки по полям и применяет стратегию «первая ошибка поля».
Это означает:
const result = suite(data);
console.log(result.getErrors('email'));
В большинстве UI-сценариев используется именно этот подход, поскольку он снижает когнитивную нагрузку: пользователь видит одну проблему за раз.
Однако внутри объекта результата сохраняется полная информация, включая все обнаруженные нарушения, что позволяет переключаться между стратегиями отображения.
Механизм fail-fast (или «ранняя остановка») изменяет модель приоритизации кардинально. Вместо накопления всех ошибок выполнение прерывается при первой критической ошибке.
Хотя Vest не навязывает единую реализацию fail-fast, подобное поведение достигается через управление выполнением тестов и условные конструкции.
test('password', 'Пароль слишком короткий', () => {
enforce(data.password).longerThan(8);
if (suite.get().hasErrors('password')) return;
});
Здесь приоритет задаётся вручную: после первой ошибки дальнейшие проверки не имеют смысла.
В более строгих конфигурациях применяется логика:
Группы (group) позволяют структурировать тесты и задавать приоритет целым блокам правил. Это особенно важно, когда необходимо разделить базовую и вторичную валидацию.
import { create, test, group, enforce } from 'vest';
const suite = create((data) => {
group('required', () => {
test('email', 'Обязательное поле', () => {
enforce(data.email).isNotBlank();
});
});
group('format', () => {
test('email', 'Неверный email', () => {
enforce(data.email).matches(/.+@.+\..+/);
});
});
});
Приоритет групп определяется порядком их объявления:
Это создаёт двухуровневую модель:
Если поле не заполнено, ошибки формата логически теряют смысл, и их отображение может быть подавлено на уровне UI.
Vest предоставляет возможность тонко управлять тем, какие ошибки считаются первичными внутри одного поля.
Основная стратегия:
Однако возможна более сложная логика через условные проверки.
test('username', 'Некорректное имя', () => {
const value = data.username;
enforce(value).isNotBlank();
if (!value) return;
enforce(value).longerThan(3);
enforce(value).shorterThan(20);
});
Здесь реализуется зависимая приоритизация:
Это позволяет исключить «шум» из результатов и гарантировать, что пользователь видит только релевантные ошибки.
Vest поддерживает условное выполнение тестов, что напрямую влияет на приоритет ошибок. Условные конструкции позволяют пропускать целые цепочки проверок, если базовое условие не выполнено.
test('age', 'Возраст должен быть числом', () => {
enforce(data.age).isNumber();
});
test('age', 'Возраст должен быть не меньше 18', () => {
if (!Number.isFinite(data.age)) return;
enforce(data.age).greaterThanOrEquals(18);
});
В данном сценарии:
Таким образом формируется иерархия:
Объект результата suite позволяет переопределять логику отображения ошибок без изменения тестов.
const result = suite(data);
const emailErrors = result.getErrors('email');
const firstEmailError = emailErrors?.[0];
На уровне потребления результата возможны стратегии:
Vest предоставляет необработанный набор ошибок, что делает приоритизацию частью слоя представления, а не только слоя валидации.
Когда поле участвует в большом количестве проверок, возникает необходимость контролировать порядок значимости ошибок.
test('password', 'Пароль обязателен', () => {
enforce(data.password).isNotBlank();
});
test('password', 'Слабый пароль', () => {
enforce(data.password).matches(/(?=.*[A-Z])(?=.*\d)/);
});
test('password', 'Слишком короткий пароль', () => {
enforce(data.password).longerThan(8);
});
В этом случае порядок становится критически важным:
Если не соблюдать последовательность, пользователь может получать менее полезные сообщения, например о сложности вместо сообщения о пустом значении.
Каждый запуск suite полностью пересчитывает результат, что означает отсутствие накопления состояния между вызовами. Это важно для приоритизации:
suite(data1);
suite(data2);
Это обеспечивает детерминированность: одинаковый порядок тестов всегда даёт одинаковую структуру приоритетов.
На практике применяются несколько устойчивых моделей:
1. Слоистая модель
Каждый слой имеет свой приоритет.
2. Линейная модель
3. Зависимая модель
4. UI-ориентированная модель
Приоритизация ошибок в Vest напрямую связана с качеством UX. Избыточное количество сообщений снижает эффективность интерфейса, поэтому система естественным образом поощряет:
С точки зрения архитектуры, приоритет ошибок становится не побочным эффектом, а частью проектирования схемы валидации, где порядок тестов и их зависимость формируют итоговое поведение системы.