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)