Como testar upload - Anexando arquivos com o Capybara - Rails/RSpec

Você está criando suas features specs e precisa anexar um arquivo num certo formulário. Vamos aprender a fazer isso. A sintaxe é bem simples e direta.

Suponha que a sua view então tenha um input tal como este de exemplo

<input id="post_banner name="banner" type="file"/>.

Você pode anexar um arquivo na sua Feature Spec com o Capybara utilizando a sintaxe:

# alguma_feature_spec.rb

attach_file 'banner', 'caminho/pro/arquivo.txt'

O primeiro parâmetro desse método é o atributo name da tag input e o segundo é o caminho para o arquivo. Logicamente, para usar o método attach_file você precisa estar usando o Capybara.

Múltiplos arquivos

Se você quiser anexar múltiplos arquivos, quando seu input aceitar, basta você passar um vetor com os caminhos dos arquivos. Por exemplo,

<input id="post_banner name="banner" type="file" multiple="multiple"/>

ficaria

# alguma_feature_spec.rb

attach_file 'banner', ['arquivo1.txt', 'arquivo2.pdf', ...]

Input não visível

Se por algum motivo você não tiver o atributo name no input, use os métodos find e set do Capybara para anexar. Veja.

# alguma_feature_spec.rb

find('input#some_css_selector').set('caminho/pro/arquivo.txt')

Se o input não estiver visível, o Capybara vai reclamar. Para resolver, use a opção visible: false.

# alguma_feature_spec.rb

find('input#some_css_selector', visible: false).set('caminho/pro/arquivo.txt')

Onde colocar os arquivos para teste de upload?

Eu gosto de criar um diretório dummy_files dentro da minha pasta spec. Lá, eu deixo alguns arquivos sem importância de algumas extensões diferentes só para testar o upload.

Para que eu possa anexar arquivos mais facilmente, eu implemento alguns métodos de suporte. Assim, eu posso anexar arquivos desta forma:

# alguma_feature_spec.rb

# anexando qualquer coisa
attach_file 'input_name', dummy_file

# anexando um pdf
attach_file 'input_name', dummy_pdf

# anexando uma imagem
attach_file 'input_name', dummy_image

# anexando várias imagens
attach_file 'input_name', dummy_images

# anexando um arquivo específico
attach_file 'input_name', dummy_file_path('dummy.txt')

# anexando todos arquivos
attach_file 'input_name', all_dummy_files

Se você quiser fazer o mesmo, crie um módulo de suporte e dê um require nele (se você já não tiver feito isso) no seu arquivo rails_helper.rb ou spec_helper.rb.

# spec/support/dummy_files_support.rb

module DummyFilesSupport

  def dummy_files_dir
    Rails.root.join('spec', 'dummy_files')
  end

  def dummy_files_path filename
    dummy_files_dir.join(filename)
  end

  def all_dummy_files
    dummy_files_dir.glob('*')
  end

  def dummy_file
    all_dummy_files.first
  end

  def dummy_image
    dummy_images.first
  end

  def dummy_images
    dummy_files_dir.glob('*.{jpg,png,gif,jpge}')
  end

  def dummy_pdf
    dummy_files_dir.glob('*.pdf').first
  end

end

RSpec.configure do |config|
  config.include DummyFilesSupport
end

E é isso. Espero ter ajudado! :)