Основы Cypress: Загрузка файла

Загрузка файлов может осуществляться различными способами, но все они имеют несколько общих черт. Прежде всего, при загрузке файлов необходимо иметь фронтенд, готовый принять файл, а затем бэкенд, готовый обработать файл. Начнем с фронтенда и с того, как можно выполнить загрузку с помощью 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, нужно обработать его. Это достигается двумя способами:

  1. изображение нужно загрузить как фикстуру, с использованием двоичного, binary, кодирования
  2. это двоично закодированное изображение необходимо преобразовать в тип данных Blob

Blob означает «Двоичный большой объект» – другими словами, мы преобразуем наше изображение в текст. Обычно этим занимается фронтенд-часть приложения. Причина, по которой в Cypress тесте нужно делать это вручную, заключается в том, что мы избегаем использования фронтенда.

После обработки файла и заполнения объекта FormData, можно вызывать API. В качестве body запроса будет выступать сам объект FormData. Единственная дополнительная деталь – это добавление заголовка 'content-type': 'multipart/form-data', чтобы сервер знал, что мы посылаем запрос такого типа.

Как уже упоминалось, окончательное решение по загрузке файла через API будет зависеть от самого API и тестируемого приложения, но общая идея должна оставаться примерно такой же, как в приведенном выше примере.

Перевод статьи “Cypress basics: Uploading a file”.

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *