В библиотеке Vest результаты валидации представлены не просто набором ошибок, а полноценной структурой состояния, содержащей информацию о прохождении тестов, статусах полей, предупреждениях, пропущенных проверках и асинхронных операциях.
Каждый запуск suite возвращает объект результата
(SuiteResult), через который происходит доступ ко всем
сведениям о валидации.
Базовый пример:
import vest, { test, enforce } from 'vest';
const suite = vest.create((data = {}) => {
test('email', 'Некорректный email', () => {
enforce(data.email).isEmail();
});
test('password', 'Минимум 8 символов', () => {
enforce(data.password).longerThanOrEquals(8);
});
});
const result = suite({
email: 'wrong',
password: '123'
});
console.log(result);
Объект result содержит внутреннее состояние проверки и
предоставляет API для анализа результатов.
getErrorsНаиболее распространённый способ получения ошибок — метод
getErrors.
const errors = result.getErrors();
console.log(errors);
Результат:
{
email: ['Некорректный email'],
password: ['Минимум 8 символов']
}
Каждое поле содержит массив сообщений.
const emailErrors = result.getErrors('email');
console.log(emailErrors);
Результат:
['Некорректный email']
Если ошибок нет:
[]
hasErrorsresult.hasErrors();
Результат:
true
Проверка конкретного поля:
result.hasErrors('email');
if (result.hasErrors()) {
console.log('Форма содержит ошибки');
}
Для поля:
if (result.hasErrors('password')) {
showPasswordError();
}
isValidisValid противоположен hasErrors.
result.isValid();
Если все проверки прошли успешно:
true
Проверка отдельного поля:
result.isValid('email');
hasErrors
и isValid| Метод | Возвращает true, если |
|---|---|
hasErrors() |
Есть ошибки |
isValid() |
Ошибок нет |
Пример:
if (result.isValid()) {
submitForm();
}
Vest поддерживает предупреждения (warnings) отдельно от
ошибок.
import vest, { test, warn } from 'vest';
const suite = vest.create((data = {}) => {
test('password', 'Слишком простой пароль', () => {
warn();
if (data.password === '12345678') {
throw new Error();
}
});
});
const result = suite({
password: '12345678'
});
console.log(result.getWarnings());
Результат:
{
password: ['Слишком простой пароль']
}
result.hasWarnings();
Для конкретного поля:
result.hasWarnings('password');
getTestCountПозволяет узнать количество тестов.
result.getTestCount();
Пример результата:
4
result.errorCount;
Пример:
console.log(result.errorCount);
result.warnCount;
testedVest отслеживает поля, участвовавшие в проверке.
result.tested('email');
Результат:
true
Особенно полезно при динамической валидации форм.
if (result.tested('email')) {
renderEmailState();
}
Vest умеет отслеживать состояние асинхронных тестов.
import vest, { test } from 'vest';
const suite = vest.create((data = {}) => {
test('email', 'Email уже используется', async () => {
const exists = await checkEmail(data.email);
if (exists) {
throw new Error();
}
});
});
isPendingПроверка наличия активных асинхронных тестов:
result.isPending();
Для конкретного поля:
result.isPending('email');
if (result.isPending()) {
showLoader();
}
Vest предоставляет агрегированное состояние поля.
getconst state = result.get();
console.log(state);
Пример структуры:
{
valid: false,
pending: false,
tested: true,
errors: [...],
warnings: [...]
}
const emailState = result.get('email');
Пример:
{
valid: false,
pending: false,
tested: true,
errors: ['Некорректный email'],
warnings: []
}
doneПоказывает, завершены ли все асинхронные проверки.
result.done();
Если всё завершено:
true
done от
isPending| Метод | Назначение |
|---|---|
isPending() |
Есть незавершённые тесты |
done() |
Все проверки завершены |
Vest позволяет организовывать тесты по группам.
groupimport vest, { test, group } from 'vest';
const suite = vest.create(data => {
group('auth', () => {
test('email', 'Некорректный email', () => {});
test('password', 'Слабый пароль', () => {});
});
});
result.getErrorsByGroup('auth');
Результат:
{
email: ['Некорректный email'],
password: ['Слабый пароль']
}
Vest может пропускать тесты.
skipimport vest, { test, skip } from 'vest';
const suite = vest.create(data => {
skip(data.isGuest, () => {
test('password', 'Введите пароль', () => {
enforce(data.password).isNotBlank();
});
});
});
Пропущенные тесты:
suite(data, 'email');
Теперь будут выполняться только тесты, связанные с
email.
result.tested('email'); // true
result.tested('password'); // false
В крупных приложениях состояние валидации иногда сохраняется.
toJSONconst json = result.toJSON();
Результат:
{
valid: false,
errors: {
email: ['Некорректный email']
}
}
const errors = result.getErrors('email');
errors.forEach(error => {
renderError(error);
});
const className = result.hasErrors('email')
? 'input-error'
: 'input-success';
const loading = result.isPending('email');
Одно поле может содержать несколько ошибок.
test('password', 'Минимум 8 символов', () => {
enforce(data.password).longerThanOrEquals(8);
});
test('password', 'Требуется спецсимвол', () => {
enforce(data.password).matches(/[!@#$%^&*]/);
});
result.getErrors('password');
Вернёт:
[
'Минимум 8 символов',
'Требуется спецсимвол'
]
Vest интерпретирует выброшенное исключение как провал теста.
test('username', 'Имя занято', async () => {
const exists = await apiCheck();
if (exists) {
throw new Error();
}
});
hasErrors как индикатор успехаconst success = !result.hasErrors('email');
const formIsReady =
result.isValid() &&
result.done();
const validation = suite(formData);
setState({
errors: validation.getErrors(),
valid: validation.isValid(),
pending: validation.isPending()
});
{
validation.hasErrors('email') && (
<div>
{validation.getErrors('email')[0]}
</div>
)
}
Результаты Vest хорошо сериализуются и подходят для хранения в глобальном состоянии.
dispatch({
type: 'SET_VALIDATION',
payload: result.toJSON()
});
Vest использует:
Результаты формируются без полного пересчёта всех тестов при каждом изменении данных.
console.log(result.get());
console.log(result.get('password'));
getErrors вместо hasErrorsНеправильно:
if (result.getErrors('email')) {
}
Поскольку массив всегда truthy.
Правильно:
if (result.hasErrors('email')) {
}
Ошибка:
if (result.isValid()) {
submit();
}
При асинхронных тестах форма может отправиться раньше завершения проверки.
Правильно:
if (result.isValid() && result.done()) {
submit();
}
import vest, { test, enforce } from 'vest';
const suite = vest.create(data => {
test('email', 'Некорректный email', () => {
enforce(data.email).isEmail();
});
test('password', 'Минимум 8 символов', () => {
enforce(data.password).longerThanOrEquals(8);
});
});
const result = suite({
email: 'wrong',
password: '123'
});
console.log(result.isValid());
console.log(result.getErrors());
console.log(result.get('email'));
console.log(result.hasErrors('password'));
Результат:
false
{
email: ['Некорректный email'],
password: ['Минимум 8 символов']
}
{
valid: false,
pending: false,
tested: true,
errors: ['Некорректный email'],
warnings: []
}
true