Question

I've created another question which I think is the cause for this error: Why does the Selenium Firefox Driver consider my modal not displayed when the parent has overflow:hidden?

Selenium version 2.33.0
Firefox driver

The code that causes the error:

        System.Threading.Thread.Sleep(5000);
        var dimentions = driver.Manage().Window.Size;
        var field = driver.FindElement(By.Id("addEmployees-password")); //displayed is true
        field.Click(); //works fine
        var element = driver.FindElement(By.Id(buttonName)); //displayed is false
        element.Click(); //errors out

The button that its trying to click:

<div id="addEmployees" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="addEmployeesLabel" aria-hidden="true">

    <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
        <h3>Add Employee</h3>
    </div>

    <div class="modal-body">
        <p class="alert alert-info">
            <input name="addEmployees-username" id="addEmployees-username" />
            <input name="addEmployees-password" id="addEmployees-password" type="password" />
            <input name="addEmployees-employee" id="addEmployees-employee" />
        </p>
    </div>

    <div class="modal-footer">
        <button name="addEmployees-add" id="addEmployees-add" type="button" class="btn" data-ng-click="submit()">Add</button>
    </div>

</div>
  • If I change the call to FindElements then I get ONE element, so there isn't anything else on the page.
  • If I FindElement on a field that occurs right before the button, say addEmployees-employee, then addEmployees-employee is displayed
  • In the browser itself, it shows up fine, all i need to do is actually click the button and the desired behavior executes, but the webdriver refuses to consider the element displayed

How is it that one field can be considered displayed and the other is not?

enter image description here

The modal with the add button in the bottom right, all the other elements are displayed = true

The window size is 1200x645 per driver.Manage().Window.Size;
The element location is: 800x355y per driver.FindElement(By.Id(buttonName)).Location
The element dimentions are: 51x30 per driver.FindElement(By.Id(buttonName)).Size
The password element location is: 552x233y per driver.FindElement(By.Id("addEmployees-password")).Size

Was it helpful?

Solution 2

Selenium WebDriver does not just check for opacity != 0, visibility = true, height > 0 and display != none on the current element in question, but it also searches up the DOM's ancestor chain to ensure that there are no parent elements that also match these checkers. (UPDATE After looking at the JSON wire code that all the bindings refer back to, SWD also requires overflow != hidden, as well as a few other cases.)

I would do two things before restructuring the code as @Brian suggests.

  1. Ensure that the "div.modal_footer" element does not have any reason for SWD to consider it to not be visible.

  2. Inject some Javascript to highlight the element in question in your browser so you know absolutely you have selected the right element. You can use this gist as a starting point. If the button is highlighted in a yellow border, then you know you have the right element selected. If not, it means that the element selected is located elsewhere in the DOM. If this is the case, you probably don't have unique IDs as you would expect, which makes manipulation of the DOM very confusing.

If I had to guess, I would say that number two is what you are running into. This has happened to me as well, where a Dev reused an element ID, causing contention in which element you're supposed to find.

OTHER TIPS

Brian's response was right: use an explicit wait versus Thread.Sleep(). Sleep() is generally brittle, you're losing five seconds needlessly, and moreover it's just a really rotten practice for automated testing. (It took me a long, LONG time to learn that, so you're not alone there.)

Avoid implicit waits. They generally work for new items being added to the DOM, not for transitions for things like a modal to become active.

Explicit waits have a great set of ExpectedConditions (detailed in the Javadox) which can get you past these problems. Use the ExpectedCondition which matches the state you need for your next action.

Also, see Ian Rose's great blogpost on the topic, too.

After discussing this with you in chat, I think the best solution (for now, at least) is to move the button out of the footer for your modal and into the body of it.

This is what you want (for now):

<div class="modal-body">
   <p class="alert alert-info">
      <input name="addEmployees-username" id="addEmployees-username" />
      <input name="addEmployees-password" id="addEmployees-password" type="password" />
      <input name="addEmployees-employee" id="addEmployees-employee" />
      <button name="addEmployees-add" id="addEmployees-add" type="button" class="btn" data-ng-click="submit()">Add</button>
   </p>
</div>

And not this:

<div class="modal-body">
   <p class="alert alert-info">
      <input name="addEmployees-username" id="addEmployees-username" />
      <input name="addEmployees-password" id="addEmployees-password" type="password" />
      <input name="addEmployees-employee" id="addEmployees-employee" />
   </p>
</div>

<div class="modal-footer">
   <button name="addEmployees-add" id="addEmployees-add" type="button" class="btn" data-ng-click="submit()">Add</button>
</div>

I had the same issue of element not visible so cannot be interacted with. it just got solved. i updated my selenium stand alone server. previous version was 2.33.0 and now it is 2.35.0

In my case the element was already present in the page but it was disabled, so this didn't work (python):

wait.until(lambda driver: driver.find_element_by_id("myBtn"))
driver.find_element_by_id("myBtn").click()

it failed with error:

“Element is not currently visible and so may not be interacted with"

To solve my problem, I had to wait a couple of seconds ( time.sleep(5) ) until the element became visible.

You can also enable the element using JavaScript, a python example:

driver.execute_script("document.getElementById('myBtn').disabled='' ")
driver.execute_script("document.getElementById('myBtn').click() ")
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top