I have created custom upload form using the following html stack:
<form>
<label></label>
<input type="file">
</form>
The file field is hidden via css with display: none
property. So the file attach dialogue is being called by user when she clicks on label (which is custom styled).
In my feature test I can't attach a file since the input field is hidden. I've tried few possible solutions, but neither of them work:
find(:xpath, '//input', visible: false).set(some_file_path)
or
within('form') do
attach_file(:input, some_file_path, visible: false)
end
And many others. All of the time I end up with Failed to click element at unknown position error. Once I remove the label overlapping the input field, make it visible and run my spec everything passes. So the issue here is the fact that:
display: none
property (and by thus is can't be found)Is there any way to make Capybara with Capybara-webkit driver handle this delicate situation in some sane way?
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.
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With