Загрузка файлов может осуществляться различными способами, но все они имеют несколько общих черт. Прежде всего, при загрузке файлов необходимо иметь фронтенд, готовый принять файл, а затем бэкенд, готовый обработать файл. Начнем с фронтенда и с того, как можно выполнить загрузку с помощью Cypress.
Содержание:
Подпишитесь на наш ТЕЛЕГРАМ КАНАЛ ПО АВТОМАТИЗАЦИИ ТЕСТИРОВАНИЯ
Загрузка файла с помощью Cypress
Начиная с версии 9.3.0, в Cypress появилась команда .selectFile()
, которая может обрабатывать все необходимые загрузки файлов. Ее использование очень просто:
cy.get('#upload') .selectFile('cypress/fixtures/logo.png')
Итак, здесь немного углубимся в код. Каждый раз, когда вы выполняете загрузку, на странице присутствует элемент <input type=file>
. Даже если вы его не видите, он там есть. Это элемент HTML5, который предоставляет API вашему приложению, чтобы взаимодействовать с браузером и открывать окно «Выбрать файл». Данный элемент обычно отображается на странице следующим образом:
![Choose a file to upload](choose-file.png w-1/2)
Однако, когда нам нужно загрузить файл с помощью Cypress, мы не нажимаем на эту кнопку, а выбираем элемент <input>
и используем для него функцию .selectFile()
. Таким образом, вместо того чтобы взаимодействовать с диалоговым окном для выбора файла, мы просто указываем путь к файлу, который хотим загрузить. Но что делать, если кнопки «Выбрать файл» не видно, а вместо нее есть кнопка загрузки или область перетаскивания?
Загрузка через область перетаскивания
Многие страницы имеют более приятный пользовательский интерфейс, в котором клиент может просто перетащить файл или нажать на красиво оформленную кнопку. Это может выглядеть примерно так:
В подобных случаях элемент <input>
часто оказывается скрытым. Интересно то, что элемент <input>
можно найти в странных местах в DOM, часто далеко от области перетаскивания. Это происходит потому, что JavaScript обрабатывает вставку файла. Можно представить себе, что файл берется из области перетаскивания и передается в элемент <input>
, где он и обрабатывается.
В проекте Trelloapp область перетаскивания выглядит примерно так:
Видно, что элемент <input>
имеет стиль display: none
и поэтому скрыт от пользователя. Для загрузки файла в эту область перетаскивания можно выбрать одну из трех стратегий:
// input is invisible, so we need to skip Cypress UI checks cy.get('input[type=file]') .selectFile('cypress/fixtures/logo.png', { force: true }) // make our input visible by invoking a jQuery function to it cy.get('input[type=file]') .invoke('show') .selectFile('cypress/fixtures/logo.png') // use Cypress’ abilty to handle dropzones cy.get('[data-cy=upload-image]') .selectFile('cypress/fixtures/logo.png', { action: 'drag-drop' })
Обратите внимание на то, что в третьем примере выбирается вся область перетаскивания, вместо того, чтобы выделять элемент <input>
. Это важно, поскольку существует разница между использованием этих двух стратегий. Если бы мы выбрали не тот элемент, то могли бы получить сообщение типа: cy.selectFile() cy.selectFile() can only be called on an <input type="file"> or a <label for="fileInput"> pointing to or containing one
.
Загрузка через API
Еще один способ – это отправка изображения на сервер. Фронтенд может обрабатывать загрузку изображения различными способами, поэтому в вашем приложении могут быть небольшие отличия в обработке загрузки файлов, но общая идея выглядит примерно так:
cy.fixture('logo.png', 'binary').then( image => { const blob = Cypress.Blob.binaryStringToBlob(image, 'image/png'); const formData = new FormData(); formData.append('image', blob, 'logo.png'); cy.request({ method: 'POST', url: '/api/upload', body: formData, headers: { 'content-type': 'multipart/form-data' }, }) })
Теперь разберемся с этим подробнее. Элемент <input type=file>
обычно является частью <form>
в html. Как правило, элемент <form>
содержит несколько элементов <input>
. Перед передачей в API они обрабатываются интерфейсом FormData
. По сути, каждый элемент данных добавляется к объекту FormData
и затем отправляется на сервер с помощью API.
В Cypress необходимо вручную создать этот объект FormData
и добавить в него изображение. А также, перед добавлением с помощью метода .append()
изображения к объекту FormData
, нужно обработать его. Это достигается двумя способами:
- изображение нужно загрузить как фикстуру, с использованием двоичного,
binary
, кодирования - это двоично закодированное изображение необходимо преобразовать в тип данных Blob
Blob означает «Двоичный большой объект» – другими словами, мы преобразуем наше изображение в текст. Обычно этим занимается фронтенд-часть приложения. Причина, по которой в Cypress тесте нужно делать это вручную, заключается в том, что мы избегаем использования фронтенда.
После обработки файла и заполнения объекта FormData
, можно вызывать API. В качестве body
запроса будет выступать сам объект FormData
. Единственная дополнительная деталь – это добавление заголовка 'content-type': 'multipart/form-data'
, чтобы сервер знал, что мы посылаем запрос такого типа.
Как уже упоминалось, окончательное решение по загрузке файла через API будет зависеть от самого API и тестируемого приложения, но общая идея должна оставаться примерно такой же, как в приведенном выше примере.
Перевод статьи “Cypress basics: Uploading a file”.