Фильтрация и сортировка данных — ключевые операции при работе с массивами объектов в Vue-приложениях. Тестирование этих операций с помощью Vue Test Utils обеспечивает корректное поведение компонентов и предотвращает логические ошибки при изменении данных.
В Vue список объектов обычно хранится в реактивном состоянии компонента:
data() {
return {
items: [
{ id: 1, name: 'Apple', category: 'Fruit', price: 50 },
{ id: 2, name: 'Carrot', category: 'Vegetable', price: 20 },
{ id: 3, name: 'Banana', category: 'Fruit', price: 30 }
],
filterCategory: 'Fruit',
sortKey: 'price',
sortOrder: 'asc' // asc или desc
};
}
Реактивные свойства позволяют автоматически обновлять DOM при
изменении данных, что упрощает тестирование. При фильтрации и сортировке
создаются вычисляемые свойства (computed),
чтобы не мутировать оригинальный массив:
computed: {
filteredItems() {
return this.items
.filter(item => this.filterCategory ? item.category === this.filterCategory : true)
.sort((a, b) => {
const modifier = this.sortOrder === 'asc' ? 1 : -1;
return (a[this.sortKey] - b[this.sortKey]) * modifier;
});
}
}
Ключевой момент: фильтрация и сортировка должны быть чистыми
функциями, не изменяющими исходный массив items,
чтобы обеспечить предсказуемое поведение при тестировании.
Vue Test Utils позволяет проверять результат вычисляемых свойств и поведение DOM при изменении фильтров. Например, тест для фильтрации по категории:
import { mount } from '@vue/test-utils';
import ItemList from '@/components/ItemList.vue';
describe('ItemList.vue - фильтрация', () => {
it('отображает только элементы выбранной категории', async () => {
const wrapper = mount(ItemList);
wrapper.setData({ filterCategory: 'Fruit' });
await wrapper.vm.$nextTick();
const renderedItems = wrapper.findAll('.item-name').map(i => i.text());
expect(renderedItems).toEqual(['Apple', 'Banana']);
});
it('отображает все элементы, если фильтр пустой', async () => {
const wrapper = mount(ItemList);
wrapper.setData({ filterCategory: '' });
await wrapper.vm.$nextTick();
const renderedItems = wrapper.findAll('.item-name').map(i => i.text());
expect(renderedItems).toEqual(['Apple', 'Carrot', 'Banana']);
});
});
Важный момент: при тестировании фильтрации рекомендуется
использовать await wrapper.vm.$nextTick(),
чтобы гарантировать обновление DOM после изменения реактивного
свойства.
Сортировка проверяется аналогично, с учетом направления и ключа сортировки:
describe('ItemList.vue - сортировка', () => {
it('сортирует элементы по цене по возрастанию', async () => {
const wrapper = mount(ItemList);
wrapper.setData({ sortKey: 'price', sortOrder: 'asc' });
await wrapper.vm.$nextTick();
const renderedItems = wrapper.findAll('.item-name').map(i => i.text());
expect(renderedItems).toEqual(['Carrot', 'Banana', 'Apple']);
});
it('сортирует элементы по цене по убыванию', async () => {
const wrapper = mount(ItemList);
wrapper.setData({ sortKey: 'price', sortOrder: 'desc' });
await wrapper.vm.$nextTick();
const renderedItems = wrapper.findAll('.item-name').map(i => i.text());
expect(renderedItems).toEqual(['Apple', 'Banana', 'Carrot']);
});
});
Особое внимание уделяется корректной работе вычисляемого свойства при изменении данных и параметров сортировки.
Часто требуется проверять сценарии, когда оба механизма применяются одновременно. В этом случае важно убедиться, что сначала применяется фильтр, затем сортировка, чтобы результаты были предсказуемыми:
describe('ItemList.vue - фильтрация + сортировка', () => {
it('фильтрует и сортирует элементы одновременно', async () => {
const wrapper = mount(ItemList);
wrapper.setData({ filterCategory: 'Fruit', sortKey: 'price', sortOrder: 'desc' });
await wrapper.vm.$nextTick();
const renderedItems = wrapper.findAll('.item-name').map(i => i.text());
expect(renderedItems).toEqual(['Apple', 'Banana']);
});
});
Такой подход гарантирует, что тесты полностью покрывают реальные сценарии использования, включая любые комбинации фильтров и ключей сортировки.
findAll и методы map для извлечения текстового
содержимого, а не просто проверять количество элементов.setValue на
<input> и проверять реактивное вычисленное
свойство.it('поиск по имени и сортировка по цене', async () => {
const wrapper = mount(ItemList);
wrapper.setData({ filterCategory: '', sortKey: 'price', sortOrder: 'asc' });
wrapper.vm.searchQuery = 'a'; // поиск по имени
await wrapper.vm.$nextTick();
const renderedItems = wrapper.findAll('.item-name').map(i => i.text());
expect(renderedItems).toEqual(['Banana', 'Carrot', 'Apple']);
});
Тест охватывает несколько механизмов: фильтрацию по тексту, сортировку и реактивность DOM, что обеспечивает комплексную проверку бизнес-логики.
Фильтрация и сортировка списков в Vue требуют тщательного проектирования вычисляемых свойств и последовательного тестирования с Vue Test Utils. Правильная комбинация фильтров и ключей сортировки вместе с корректным управлением реактивностью обеспечивает предсказуемое поведение компонентов и высокое качество кода.