1

The webpage in question is an SPA, I could describe it as a single large div with several div "boards" inside it, which we scroll into view by applying a webkit transform on the parent div.

Unfortunately, once scrolled too far, the elements returned by WebDriver are "disabled" - the WebElement property "Displayed" is false, the Text property is blank, and I can't execute any clicks/actions on the element. It is however visible on the page at the time and perfectly functional.

While investigating the problem, I created a small test webpage to see under what conditions this occurs.

Link to JSFiddle sample page to show functionality

NB Note that we are not using IFrames in this website, JSFiddle is just to demonstrate functionality.

<html><head>
<script type="text/javascript" src="jquery-1.8.3.js"></script>
<style type="text/css">
    .board-nav {
        font-size: 12px;
        color: #1b1a1a;
        margin-right: 10px;
        vertical-align: middle;
    }

    .scroller{
        -webkit-transition: -webkit-transform 0ms; transition: -webkit-transform 0ms; 
        -webkit-transform-origin: 0px 0px; 
        -webkit-transform: translate(0px, 0px) scale(1) translateZ(0px);
        transition-property: transform; 
        transform-origin: 0px 0px 0px; 
        transform: translate(0px, 0px) scale(1) translateZ(0px);
        height: 4000px;
    }
</style>
<script type="text/javascript">
 var boardPositions = [0, -878, -1748, -2598, -3468];
var $scroller = null;
function changeBoard(event) {
    var newValue = 'translate(0px, ' + boardPositions[event.target.id] + 'px) scale(1) translateZ(0px)';
    
    $('.scroller').css('-webkit-transform',newValue);
    $('.scroller').css('transform', newValue);
}

$(document).ready( function(){
    var $boards = $('.board-nav'); 
    $boards.on('click', changeBoard);
});

</script>
</head><body>
<div>
    <div class="board-nav" id="0">Info</div>
    <div class="board-nav" id="1">Board1</div>
    <div class="board-nav" id="2">Board2</div>
    <div class="board-nav" id="3">Board3</div>
    <div class="board-nav" id="4">Board4</div>
</div>
<div id="content" style="width:1612px; height:864px; position:absolute; left:58px;         overflow:hidden">
    <div class="scroller">
        <ul class="vertical">
            <li class="v" id="li0">
                <div class="target"><span>Info</span></div>
            </li>
        <li class="v" id="li1">
            <div class="target"><span>Board1</span></div>
        </li>
        <li class="v" id="li2">
            <div class="target"><span>Board2</span></div>
        </li>
        <li class="v" id="li3">
            <div class="target"><span>Board3</span></div>
        </li>
        <li class="v" id="li4">
            <div class="target"><span>Board4</span></div>
        </li>
    </ul>
    </div>
</div>
</body></html>

It seems that as soon as the parent div Y location becomes less than around -2000, all child elements become "disabled" in this manner. Prior to this (around -1900 for example), the elements are returned with all information valid. I can switch from Board 3, back to Board 2, and then all elements are returned correctly again. Back to Board 3 - all boards "disabled". So this seems to be a browser WebDriver limitation.

WebDriver C# test code :

 var driver = new FirefoxDriver();
 driver.Manage().Window.Maximize();
 driver.Navigate().GoToUrl("testpage.html");

 var elements = driver.FindElements(By.ClassName("v"));
 return elements[3].FindElement(By.TagName("span")).Text;

Firefox handles this the best - it at least shows Info/Board1/Board2 before giving up. Chrome doesn't handle any of the Boards, returning the same Displayed = false, blank Text for all boards.

So my question is - is there any way to get around this? I can test the text on the other boards are correct, while Board1/Info is showing, but won't be able to interact with the last 2 Boards.

ANSWER:

Just resolved my problem by adding a height attribute to the parent div "scroller" element - my guess is WebDriver couldn't determine the height of the parent div and so assumed beyond a certain location it was no longer visible.

I've updated the code above and JSFiddle with the solution

Community
  • 1
  • 1
lvanzyl
  • 143
  • 1
  • 8

1 Answers1

4

I guess this happens Firefox and IE, but not Chrome? If so, then we are experiencing the similar issue. I suspect Chrome doesn't care about the WebDriver W3C standards and determines the visibility in a slightly different way.

If this answer is not related to your question, I hope it will still be beneficial for those find this through search engine.

The issue I'm facing is that Selenium returns elements as invisible, but real end users can see and perform actions without any issues. The best solution here would be change site's source code to make Selenium's FirefoxDriver and InternetExplorerDriver happy. As this is related to elements' positions and overlapping, which seems pretty hard to reproduce and fix.

However, apart from that, here are few workarounds and hacks through Selenium might be helpful.

  • Use element.GetAttribute("textContent") instead of element.Text for those invisible elements
 return elements[3].FindElement(By.TagName("span")).GetAttribute("textContent");
  • Use Actions click or JavaScript click, instead of normal click. For example, if you need this method many time, you might want to create extension methods for either IWebElement or IWebDriver.
// example of JavaScriptClick extension method for IWebDriver
// use as driver.JavaScriptClick(element);
// or you can make it IWebElement's extension and pass in IWebDriver
// or just create a normal method and pass in both driver and element
public static void JavaScriptClick(this IWebDriver driver, IWebElement element) {
    IJavaScriptExecutor executor = driver as IJavaScriptExecutor;
    executor.ExecuteScript("arguments[0].click();", element);
}

public static void ActionsClick(this IWebDriver driver, IWebElement element) {
    new Actions(driver).Click(element).Perform();
}

Related reading:

Community
  • 1
  • 1
Yi Zeng
  • 32,020
  • 13
  • 97
  • 125
  • Thanks for the answer - the GetAttribute did indeed work to fetch the Text in my case. I was using Actions to attempt to click, and that was not working unfortunately (was throwing an exception about the Element not being available). However - I managed to resolve the original problem which I've added to my question. – lvanzyl Sep 04 '13 at 22:04