Search code examples
testingcapybaradropzone.js

How do you test uploading a file with Capybara and Dropzone.js?


I've switched to using the Dropzone.js plugin for drag-and-drop file uploads. How can I write a Capybara test to ensure this functionality keeps on working?

Previously I had a template with an input file element:

<input type="file" name="attachments">

And the test was simple:

When(/^I upload "([^"]*)"$/) do |filename|
  attach_file("attachments", File.expand_path(filename))
  # add assertion here
end

However this no longer works because Dropzone doesn't have a visible file input.


Solution

  • To solve this, simulate a drop event to trigger dropping an attachment onto Dropzone. First add this function to your step definition:

        # Upload a file to Dropzone.js
        def drop_in_dropzone(file_path)
          # Generate a fake input selector
          page.execute_script <<-JS
            fakeFileInput = window.$('<input/>').attr(
              {id: 'fakeFileInput', type:'file'}
            ).appendTo('body');
          JS
          # Attach the file to the fake input selector
          attach_file("fakeFileInput", file_path)
          # Add the file to a fileList array
          page.execute_script("var fileList = [fakeFileInput.get(0).files[0]]")
          # Trigger the fake drop event
          page.execute_script <<-JS
            var e = jQuery.Event('drop', { dataTransfer : { files : [fakeFileInput.get(0).files[0]] } });
            $('.dropzone')[0].dropzone.listeners[0].events.drop(e);
          JS
        end
    

    Then test with:

        When(/^I upload "([^"]*)"$/) do |filename|
          drop_in_dropzone File.expand_path(filename)
          # add assertion here
        end
    

    NOTE: You need to have jQuery loaded, and the Dropzone element requires the dropzone class.