Capybara, capybara-webkit and custom file upload form

With capybara-webkit you can tell the driver to run any javascript you want within the context of the page, so you can write something custom to hack around the visibility issue:

script = "$('thelabel').toggle(); " # hide the label
script << "$('myfield').toggle();"  # show your field

page.driver.browser.execute_script(script)

This is pseudo-code, but you should be able to do something similar to make the field visible before you call attach_file on it.

That said, every time (I at least) do something a little gross like this in my tests it is a good idea to take a quick moment and ask if it is the test or the interface that needs to be fixed. If you're happy with the interface, you should be able to use a small js snippet like the above to get the element visible for your test.

Update:

Support for this behavior has become more widespread and is now standardized in capybara, so you can just:

page.execute_script(script)

This shorter version should work with capybara 2.x and recent versions of capybara-webkit or poltergeist, which is a lower-dependency alternative I'm using now.

There is also a partner method, evaluate_script:

result = page.evaluate_script('4 + 4');

Hope this helps!


Matt Sanders suggests using JS to toggle the element's visibility. That'll work but here's another solution which is a bit cleaner, IMO.

I recommend including hidden fields only when necessary. To accomplish this, I used this helper for those rare cases when you actually want Capybara to include hidden fields. For example:

# features/support/capybara_helpers.rb
module CapybaraHelpers
  # By default, capybara will ignore all hidden fields. This is a smart default
  # except in rare cases. For example, our AS3 file uploader requires you to
  # click a hidden file field - and that makes perfect sense. In those rare
  # cases, you can use this helper to override the default and force capybara
  # to include hidden fields.
  #
  # Examples
  #
  #   include_hidden_fields do
  #     attach_file("hidden-input", "path/to/fixture/file")
  #   end
  #
  def include_hidden_fields
    Capybara.ignore_hidden_elements = false
    yield
    Capybara.ignore_hidden_elements = true
  end
end
World(CapybaraHelpers)