При тестировании компонентов Vue часто возникает необходимость убедиться, что изменения в состоянии компонента или его реактивных данных полностью отразились на DOM. Vue использует асинхронный механизм обновления, что означает, что изменения в реактивных данных не мгновенно отображаются в шаблоне. Для правильного тестирования необходимо дождаться завершения этих асинхронных обновлений.
$nextTickМетод $nextTick является встроенным в экземпляр Vue и
возвращает промис, который разрешается после того, как все реактивные
обновления DOM будут завершены. Это позволяет безопасно проверять
состояние компонента и его разметку после изменений данных.
Пример базового использования:
import { mount } from '@vue/test-utils';
import Counter from '@/components/Counter.vue';
test('увеличение счётчика', async () => {
const wrapper = mount(Counter);
wrapper.vm.count++;
await wrapper.vm.$nextTick();
expect(wrapper.text()).toContain('1');
});
В этом примере увеличение значения count не сразу
отражается в DOM. Без await wrapper.vm.$nextTick() проверка
expect(wrapper.text()).toContain('1') может завершиться
неудачей, так как обновление DOM ещё не произошло.
$nextTickdata или computed, которые влияют на
шаблон.@click или @input.Пример с событием:
test('обработка клика кнопки', async () => {
const wrapper = mount(Counter);
await wrapper.find('button').trigger('click');
await wrapper.vm.$nextTick();
expect(wrapper.text()).toContain('1');
});
trigger автоматически вызывает обработчик события,
который изменяет count. Чтобы убедиться, что DOM обновился,
необходимо дождаться nextTick.
Если метод компонента возвращает промис или использует
setTimeout внутри,
await wrapper.vm.$nextTick() гарантирует, что все
микротаски Vue будут выполнены. Для асинхронных действий, которые
зависят от промисов, часто используют комбинацию с
await flushPromises() (внешняя утилита для ожидания всех
промисов) перед $nextTick.
Пример:
import flushPromises from 'flush-promises';
test('асинхронное обновление данных', async () => {
const wrapper = mount(AsyncComponent);
wrapper.vm.loadData(); // метод возвращает промис
await flushPromises();
await wrapper.vm.$nextTick();
expect(wrapper.text()).toContain('Данные загружены');
});
$nextTick следует вызывать после изменения
реактивного состояния, а не до него.$nextTick один раз после всех изменений, что
ускоряет тесты и уменьшает количество промисов.$nextTick гарантирует обновление всех зависимых частей
DOM.Пример с несколькими изменениями:
test('несколько изменений данных', async () => {
const wrapper = mount(Counter);
wrapper.vm.count++;
wrapper.vm.message = 'Привет';
await wrapper.vm.$nextTick();
expect(wrapper.text()).toContain('1');
expect(wrapper.text()).toContain('Привет');
});
await wrapper.vm.$nextTick()В некоторых случаях можно использовать метод
wrapper.setData() или wrapper.setProps(),
который автоматически ждёт обновления DOM и возвращает промис:
await wrapper.setData({ count: 1 });
expect(wrapper.text()).toContain('1');
Однако $nextTick остаётся универсальным инструментом,
особенно когда изменения выполняются напрямую через vm или
в пользовательских методах компонента.
$nextTick для контроля точного
момента обновления DOM после любых асинхронных или синхронных
изменений.$nextTick с утилитами ожидания промисов.await wrapper.vm.$nextTick() является ключевым
инструментом для создания надёжных и стабильных тестов, которые
проверяют реальные изменения DOM после всех обновлений Vue.