Como testar envio de arquivos com ActiveStorage

Tutoriais - 15/Out/2020 - por André Kanamura

Desde a versão 5.2 do Rails seu principal recurso para lidar com envio de arquivos é o Active Storage. Atualmente ele facilita muito a configuração da aplicação para upload, o que antes só era possível por meio da instalação de gems.

Neste artigo não vamos mostrar como configurar o Active Storage. Para isso você pode consultar a documentação oficial do Rails ou algum dos links listados nas referências. Aqui vamos mostrar como você pode testar o fluxo de envio de imagens em uma aplicação e anexar arquivos nos seeds do seu projeto.

Vamos considerar uma aplicação em que podemos cadastrar filmes com título, diretor e uma imagem de capa. Chamaremos a classe de Movie e seu atributos title, director e cover. Lembrando que, pela maneira como Active Record funciona, basta incluir cover dentro da classe Movie com has_one_attached :cover:

class Movie < ApplicationRecord
  has_one_attached :cover
end

Se você quiser escrever um teste para o formulário de cadastro de um filme, podemos usar o método attach_file do Capybara para simular o envio da imagem de capa. O teste poderia ficar assim:

feature 'Visitor register movie' do
  scenario 'successfully' do
    visit root_path

    click_on 'Registrar filme'
    fill_in 'Título', with: 'Contos de Terramar'
    fill_in 'Diretor', with: 'Gorō Miyazaki'
    attach_file 'Foto de capa', Rails.root.join('spec', 'support', 'contos_de_terramar.jpg')
    click_on 'Enviar'

    expect(current_path).to eq movie_path(Movie.last)
    expect(page).to have_css('h1', text: 'Contos de Terramar')
    expect(page).to have_css('h2', text: 'Gorō Miyazaki')
    expect(page).to have_css('img[src*="contos_de_terramar.jpg"]')
  end
end

O método attach_file recebe uma string referente ao label do elemento que ele deve encontrar na página e o caminho do arquivo a partir da raiz do projeto que deve ser anexado. No caso deste exemplo, usamos a label 'Foto de capa' para indicar o elemento e o arquivo é o contos_de_terramar.jpg, dentro do diretório spec/support/.

Da mesma maneira que podemos criar expectativas nos testes para avaliar a presença de determinados elementos de textos nas views da aplicação, podemos também procurar por elementos de imagens para sabermos se o arquivo correto é renderizado em tela. Note como na última linha de expectativas do teste acima temos have_css('img[src*="contos_de_terramar.jpg"]'), que procura por um elemento da tag img com o arquivo específico como source. Desde que a view contenha um elemento tipo <img> que carrega o arquivo indicado, seu teste deve passar.

Bônus

Outro lugar em que é útil saber como anexar arquivos com Active Storage é no seeds, na criação de objetos para o banco. Seguindo o exemplo da aplicação de catálogo de filmes, poderíamos criar objetos com imagens de capa da seguinte forma:

movie = Movie.create(title: 'Contos de Terramar',
     director:  'Gorō Miyazaki')
movie.cover.attach(io: File.open(Rails.root.join('spec', 'support', 'contos_de_terramar.jpg')), filename: 'contos_de_terramar.jpg')

Neste exemplo utilizamos spec/support para armazenar a imagem, mas o recomendado é escolher um diretório mais adequado para o caso do seu projeto.

Referências

Foto de perfil do autor
André Kanamura

Dev na Campus Code