miguel.camba
miguel.camba

Reputation: 1827

Is it possible to interact with hidden elements with capybara?

I have a file field that has opacity: 0 and is overlaping a fake button. Its a common css technic to fake a sort of "Upload button" that displays consistently across different browsers.

Capybara doesn't allows me to call attach_file on that input. The error is Selenium::WebDriver::Error::ElementNotVisibleError: Element is not currently visible and so may not be interacted with.

Anybody knows any way to force capybara to interact with invisible elements?

The answer is still unanswered, but I've found a work around. Nothing intelligent, just make visible the element with a simple script

  page.execute_script %Q{
    $('#photos').css({opacity: 1, transform: 'none'});
  }

I post it for the record.

Upvotes: 46

Views: 35663

Answers (7)

Thomas Walpole
Thomas Walpole

Reputation: 49890

In general interacting with non-visible elements should not be possible when using Capybara (you can find them using the visible: false/hidden option in most finders but not actually do anything to them). However, the file input is a special case because of how common it is to hide the element and, due to security restrictions, no other way to actually add a file by interacting with the pages visible elements. Because of this attach_file has a make_visible option which can be used to have Capybara make the element visible, attach the file, and then reset the CSS to the original setting.

attach_file('photos', file_path, make_visible: true)

Upvotes: 9

Vijay Chouhan
Vijay Chouhan

Reputation: 4883

You can interact with hidden elements using the visible: false property in Capybara.

If you want to click on hidden element use:

find("#photos", visible: false).click

Don't use click_button('#photo') directly

Upvotes: 76

Kevin Qi
Kevin Qi

Reputation: 3260

If the hidden element is nested in a visible parent element (e.g. a hidden input inside a visible label), you can click on the parent instead. If you still want to find the input by ID, you can traverse to the parent like so:

find('#hidden_input').find(:xpath, '..').click

Upvotes: 0

karlingen
karlingen

Reputation: 14625

I've done it this way with elements that has the CSS style display:none; set:

page.execute_script("$('.all-hidden-elements').show();");
all('.all-hidden-elements').first.click

Upvotes: 0

user664833
user664833

Reputation: 19505

The author of Capybara recommends setting Capybara.ignore_hidden_elements immediately prior to needing to see the invisible element, and resetting it afterwards:

Capybara.ignore_hidden_elements = false
click_button 'my invisible button'
Capybara.ignore_hidden_elements = true

Upvotes: 19

Jay
Jay

Reputation: 358

I ended up resolving it a different route.

execute_script() was giving me a hard time (it would freeze test execution on FireFox), so this is what I did:

I already had an appropriate javascript file. I appended the following

<% if ENV["RAILS_ENV"] == "test" %>
  $('#photos').show()
<% end %>

I also had to append .erb to my javascript file for proper Rails asset handling.

And in my test file, I was already setting ENV["RAILS_ENV"] = "test"

This way I could just dumb down the UI for test, and yet maintain the look and feel for production.

Upvotes: 1

Alexander Kobets
Alexander Kobets

Reputation: 11

Miquel, thanks for workaraund.

I have similar issue for interacting with hidden file input on C# binding for Selenium Webdriver 2.35 and Firefox 24. To make file selection working did similar trick:

((IJavaScriptExecutor)webdriver).ExecuteScript("$('#fileUploadInput').css({opacity: 1, transform: 'none'});");

IWebElement e = webdriver.FindElement(By.CssSelector("input#fileUploadInput")));

e.SendKeys("c:\\temp\\inputfile.txt");

Upvotes: 1

Related Questions