Testing
Asynchronous Behavior
When writing tests for apps that are using VeeValidate, there are a couple of things to keep in mind:
- Vue DOM updates are asynchronous.
- VeeValidate validations and state changes are also asynchronous.
Consider this simple assertion:
test('my test', () => {
vm.$validator.validate();
expect(vm.$validator.errors.any()).toBe(true);
});
This assertion might fail because the validate
method runs the validators asynchronously, meaning by the time the code moves on to the assertion, the validations might have not yet executed, causing the assertion to fail.
You can fix this using async/await
, something like this:
test('my test', async () => {
await vm.$validator.validate();
expect(vm.$validator.errors.any()).toBe(true);
});
Flushing the Update Queue
Since both the Vue rendering and the validation are async, it can prove a difficult task to await
all the async changes, for example:
test('my test', () => {
vm.myValue = 'newVal';
expect(vm.$validator.errors.any()).toBe(true);
});
This will not work, since the model updates do not happen immediately and the validations triggered are also async. But you can't wait for either since the validation and the DOM updates all happen under the hood.
Here we would like to be able to wait for all async operations to finish, which can be done using the flush-promises
package:
yarn add flush-promises --dev
# or
npm i flush-promises -D
Our example will then be updated to look like this:
import flushPromises from 'flush-promises';
test('my test', async () => {
vm.myValue = 'newVal';
await flushPromises(); // wait for all async stuff to finish up.
expect(vm.$validator.errors.any()).toBe(true);
});
Testing Example
Here is a full test written using vue-test-utils. We test the basic validation functionality for both the directive and the ValidationProvider component.