Search code examples
ruby-on-railsrubycapybara

Remove file after Capybara test in Rails 7


In my Rails 7 app I've got Capybara test which checks if downloading a PDF file works. The issue is that after a successful check, Capybara saves this file in the main path of the project. How do I delete this file right after the test?

  it 'download invoice' do
    payment = build :isor_payment, :with_pdf
    stub_payment(payment)

    login_as user
    visit payment_path(payment.platform_payment_id)

    click_on 'Download'
    expect(page).to have_content I18n.t('payments.main_data_component.invoice_pdf')
  end

After that test it will save me a pdf named payment-43523452.pdf.


Solution

  • I'm assuming you're using Rspec as your test runner. You can configure an after(:each) callback to remove the file:

    RSpec.configure do |config|
    # all the rspec configuration options...
    
      config.after(:each) do
        FileUtils.rm('payment-43523452.pdf')
      end
    end
    

    But this is a little brittle, you have to change the configuration whenever your download file name changes. I prefer to create a download directory under tmp/, like tmp/test_downloads/, then use the above callback method to remove all files from the tmp/test_downloads/ directory.

    Configure the download file directory in the Capybara driver configuration, usually in spec_helper.rb. My driver configuration looks like this:

    Capybara.register_driver :headless_chrome do |app|
      chrome_options = Selenium::WebDriver::Chrome::Options.new
      chrome_options.add_argument('--headless')
      chrome_options.add_argument('--window-size=1400,800')
    
      chrome_options.add_preference(:download,
                                directory_upgrade: true,
                                prompt_for_download: false,
                                default_directory: 'tmp/test_downloads/'
                                )
    
      chrome_options.add_preference(:plugins, always_open_pdf_externally: true)
    
      driver = Capybara::Selenium::Driver.new(app, :browser => :chrome, :capabilities => [chrome_options])
    
      driver
    end
    
    

    Then your RSpec after(:each) callback will be:

    FileUtils.rm_rf(Dir.glob("tmp/test_downloads/*"))