Файловые инпуты (<input type="file">) представляют
собой особый тип элементов формы, взаимодействие с которыми требует
специфических подходов при тестировании компонентов во Vue.js. В Vue
Test Utils работа с ними строится на симуляции событий изменения
значения и правильной имитации объектов File или
FileList.
Чтобы имитировать загрузку файлов, необходимо создать объекты типа
File. Они представляют собой реальные файлы, которые можно
передать компоненту через событие change:
const file = new File(["Hello, world!"], "example.txt", { type: "text/plain" });
Ключевые параметры:
Blob.image/png или application/pdf.Для передачи нескольких файлов используется массив:
const files = [
new File(["File 1 content"], "file1.txt", { type: "text/plain" }),
new File(["File 2 content"], "file2.txt", { type: "text/plain" })
];
Файловый инпут реагирует на событие change. В Vue Test
Utils его можно эмулировать через метод trigger:
const wrapper = mount(MyFileInputComponent);
const input = wrapper.find('input[type="file"]');
await input.trigger('change', {
target: {
files: [file]
}
});
Обратите внимание на структуру объекта
target — она должна содержать поле
files, которое является массивом или объектом
FileList. Vue Test Utils автоматически обновляет
привязанные модели v-model или обработчики
@change.
Если инпут имеет атрибут multiple, тестирование
нескольких файлов выглядит аналогично:
await input.trigger('change', {
target: {
files
}
});
Внутри компонента files можно обрабатывать через
event.target.files или через v-model.
Часто требуется убедиться, что компонент корректно передает файлы в
методы или API. Для этого можно использовать шпионы
(jest.fn()) и проверять аргументы:
const onFileUpl oad = jest.fn();
const wrapper = mount(MyFileInputComponent, {
props: { onFileUpload }
});
await input.trigger('change', { target: { files } });
expect(onFileUpload).toHaveBeenCalled();
expect(onFileUpload.mock.calls[0][0]).toEqual(files);
Важно сравнивать объекты File по ссылке или по ключевым
свойствам (name, type, size), так
как прямое сравнение объектов File иногда не
срабатывает.
Если компонент использует FileReader для чтения
содержимого файла, тесты должны учитывать асинхронность:
const wrapper = mount(MyFileInputComponent);
const file = new File(["Hello"], "hello.txt", { type: "text/plain" });
const input = wrapper.find('input[type="file"]');
await input.trigger('change', { target: { files: [file] } });
// Использование nextTick для ожидания обновления состояния компонента
await wrapper.vm.$nextTick();
expect(wrapper.vm.fileContent).toBe("Hello");
Для сложных сценариев можно замокать FileReader:
jest.spyOn(window, 'FileReader').mockImplementation(() => ({
readAsText: function(file) { this.onload({ target: { result: "Mock content" } }); },
onload: null,
result: null
}));
Файловые инпуты часто имеют ограничения по типу, размеру или количеству файлов. Тестирование таких условий включает:
Пример проверки типа файла:
const invalidFile = new File(["data"], "file.exe", { type: "application/x-msdownload" });
await input.trigger('change', { target: { files: [invalidFile] } });
expect(wrapper.vm.error).toBe("Недопустимый тип файла");
await wrapper.vm.$nextTick() после
изменения файлов для корректного обновления реактивных данных.FileReader или API, если компонент выполняет
чтение или загрузку файлов на сервер.Файловые инпуты в Vue Test Utils требуют точной симуляции событий и структуры данных, но при соблюдении этих правил тесты становятся надежными и легко поддерживаемыми.