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!