Upgrade guides
Upgrading from V3 to V4
Vest 4.0 is a major release that contains several breaking changes. Most should be pretty simple to migrate, but there are a few things that require a bit more attention.
Removed: Default import support
For better tree shaking, we removed the default import support. This means that if you need a part of the library, you will need to import it explicitly, resulting in a smaller eventual bundle size.
V3
import vest from 'vest';
V4
import * as vest from 'vest';
// OR:
import { create, test, enforce } from 'vest';
Renamed: classNames to classnames
Vest 3 included the vest/classNames
import. It is now renamed to vest/classnames
.
V3
import classNames from 'vest/classNames';
V4
import classnames from 'vest/classnames';
Changed: Do not use if/else statements to conditionally run tests
Vest version 4 relies on order of execution and remembers the result of each test based on its location in the suite, similar to the way hooks in react work. This means that tests wrapped in an if/else statement make Vest go out of sync with the suite order, and unexecuted test results will be recorded. Instead of using if/else statements, you should use the skipWhen
function that achieves the same result.
V3
if (!suite.get().hasErrors('password')) {
test('confirm', 'passwords do not match', () => {
/*...*/
});
}
V4
import { skipWhen, test } from 'vest';
// ...
skipWhen(
res => res.hasErrors('password'),
() => {
test('confirm', 'passwords do not match', () => {
/*...*/
});
},
);
// ...
Replaced: test.each with each
When writing dynamic validations, previous versions of Vest used test.each
to run tests for each value in an array. test.each was very limited, and could only handle one test of the same field. It also was unable to retain state after reordering. test.each is now replaced with the more useful each
function.
Now iterated tests require a key
argument as their last argument, this guarantees state retention after reordering.
V3
test.each(fields)(field.name, 'field is required', field => {
enforce(field.value).isNotEmpty();
});
V4
each(fields, field => {
test(
field.name,
'field is required',
() => {
enforce(field.value).isNotEmpty();
},
field.id,
);
});
Replaced: enforce.template
enforce.template was a helpful function that allowed the composition of multiple validators. It is now replaced by the compose
function, exported from vest/enforce-compose
Upgrading from V2 to V3
Vest version 3 comes with many new features, yet with a reduced bundle size. To achieve this, some redundant interfaces were removed. All v2 capabilities still exist, but the way to use some of them changed.
Replaced interfaces
Removed: vest.get()
From now on, use suite.get() to get the latest validation result.
v2
const suite = vest.create('user_form', () => {
/*...*/
});
vest.get('user_form'); // Returns the most recent validation result
v3
const suite = create(() => {
/*...*/
});
suite.get(); // Returns the most recent validation result
Removed: vest.reset() // To reset suite state
From now on, use suite.reset() to reset the validation result.
v2
const suite = vest.create('user_form', () => {
/*...*/
});
vest.reset('user_form'); // Resets the validity state
v3
const suite = create(() => {
/*...*/
});
suite.reset(); // Resets the validity state
Removed: vest.draft() // To retrieve intermediate result
From now on, use suite.get() to get the validation result.
v2
const suite = vest.create('user_form', () => {
if (vest.draft().hasErrors('username')) {
/* ... */
}
});
v3
const suite = create('user_form', () => {
skipWhen(
res => res.hasErrors('username'),
() => {
/* ... */
},
);
});
Removed: validate() // For non persistent validations
The stateless validate export is not needed anymore due to a change in the state structure.
v2
import { validate } from 'vest';
const result = data =>
validate('user_form', () => {
/*...*/
})();
v3
import { create } from 'vest';
const suite = data =>
create(() => {
/* ... */
})();
const result = suite({ username: 'example' });