В Vue.js directive — это механизм для расширения
HTML-атрибутов с пользовательской логикой. Они позволяют управлять
поведением DOM-элементов напрямую. Стандартные директивы включают
v-if, v-show, v-model, но часто
используются пользовательские директивы для реализации
специфического функционала. Тестирование таких директив важно для
обеспечения корректной работы приложения и предотвращения регрессий.
Пользовательская директива представляет собой объект с хуками жизненного цикла:
const myDirective = {
mounted(el, binding) {
el.style.color = binding.value;
},
updated(el, binding) {
el.style.color = binding.value;
}
};
mounted вызывается при монтировании элемента.updated вызывается при обновлении привязанных
данных.beforeMount и
beforeUpdate.Тестирование сосредоточено на проверке того, как директива изменяет DOM при различных состояниях.
Vue Test Utils позволяет легко интегрировать директивы в тестируемый компонент:
import { mount } from '@vue/test-utils';
const TestComponent = {
template: `<div v-my-directive="color"></div>`,
props: ['color']
};
const wrapper = mount(TestComponent, {
global: {
directives: {
myDirective
}
},
props: {
color: 'red'
}
});
global.directives используется для регистрации директив
в тестовой среде.После монтирования компонента важно убедиться, что директива корректно изменила DOM:
expect(wrapper.element.style.color).toBe('red');
Обновление пропсов позволяет протестировать реакцию
updated:
await wrapper.setProps({ color: 'blue' });
expect(wrapper.element.style.color).toBe('blue');
Ключевой момент: важно тестировать не только начальное состояние, но и поведение при изменении данных.
Директивы могут принимать аргументы и модификаторы:
const focusDirective = {
mounted(el, binding) {
if (binding.modifiers.autofocus) {
el.focus();
}
}
};
Тестирование модификаторов включает проверку состояния элемента после монтирования:
const wrapper = mount({ template: `<input v-focus.autofocus />` }, {
global: { directives: { focus: focusDirective } }
});
expect(document.activeElement).toBe(wrapper.element);
Для аргументов используется структура binding.arg, что
позволяет динамически менять поведение:
const colorDirective = {
mounted(el, binding) {
el.style[binding.arg] = binding.value;
}
};
const wrapper = mount({ template: `<div v-color:background="bgColor"></div>` }, {
global: { directives: { color: colorDirective } },
props: { bgColor: 'yellow' }
});
expect(wrapper.element.style.background).toBe('yellow');
Для более сложных директив имеет смысл писать тесты напрямую для самой директивы, без оборачивающего компонента:
import { nextTick } from 'vue';
test('директива изменяет текст', async () => {
const el = document.createElement('div');
myDirective.mounted(el, { value: 'Hello' });
expect(el.textContent).toBe('Hello');
myDirective.updated(el, { value: 'World' });
await nextTick();
expect(el.textContent).toBe('World');
});
nextTick гарантирует, что все реактивные
обновления завершены.Если директива выполняет асинхронные действия, например, работу с API
или таймером, важно использовать async/await и Vue Test
Utils методы flushPromises:
import flushPromises from 'flush-promises';
const asyncDirective = {
async mounted(el, binding) {
const result = await fetchData(binding.value);
el.textContent = result;
}
};
await flushPromises();
expect(wrapper.element.textContent).toBe('данные');
flushPromises гарантирует обработку всех промисов в
тестовой среде.Vue Test Utils совместим с Jest, поэтому можно легко проверять вызовы методов или побочные эффекты:
const spy = jest.fn();
const directive = {
mounted: spy
};
mount({ template: `<div v-directive />` }, {
global: { directives: { directive } }
});
expect(spy).toHaveBeenCalled();
Тестирование директив в Vue с Vue Test Utils — это комбинация проверки изменений DOM, реактивности данных, модификаторов и аргументов, а также асинхронных эффектов. Подходы могут быть как через оборачивающие компоненты, так и напрямую с элементами DOM, что делает процесс максимально гибким и надёжным.