Search code examples
xpathseleniumselenium-rc

How to get second attribute level with Selenium's xpath


I'm trying to check in Selenium if an element has a green border or not.

i can use //div[@id="target"]/@style to get the parsed style string applied... and use string search to search for the border... i have to work around some brosers showing the shorthand (border: solid 3px green) and other showing the expanded (border-style: solid; border-color: green....) ...but how could i do that more cleanly?

ideally something like: //div[@id="target"]/@style.borderColor

I also would like to avoid using the contains selector because the syntax is awful. But if it's the only way, so be it. of course.


Solution

  • XPath doesn't know anything about CSS styles, it doesn't understand the attributes and takes them just as simple strings. It would be weird if a XML query language understood CSS styles, right?

    Besides, the getAttribute() uses a construct similar to XPath, but not XPath! It also selects the attribute via @ sign, right. But consider this locator: "id=target@style". It would work, but it's definitely no XPath.

    It would also return the explicitly set style attribute, not it's internal computed value, so it's useless unless there actually is a style attribute on the element. If there is style attribute defined, go for it.

    Selenium itself can't give you the right answer (WebDriver has getCssValue(), but there's no counterpart for it in Selenium RC, afaik).

    Therefore, the only way to get the computed style (the final value computed from all sources) of an element in Selenium RC is via JavaScript.

    The script that has been working for me for ages (after a slight edit) is this (from quirksmode.org):

    function getStyle(id, stylePropJs, stylePropCss) {
        var x = document.getElementById(id);
        if (x.currentStyle)
            var y = x.currentStyle[stylePropJs];
        else if (window.getComputedStyle)
            var y = document.defaultView.getComputedStyle(x,null).getPropertyValue(stylePropCss);
        return y;
    }
    

    Note that IE needs a JavaScript name of the property, but every other browser uses CSS names. Also, you can't use the shorthand property and you definitely must use the expanded one. Therefore, in your case:

    String script = "var x = document.getElementById('target');" +
                    "if (x.currentStyle) var y = x.currentStyle['borderTopColor'];" +
                    "else if (window.getComputedStyle) var y = document.defaultView.getComputedStyle(x,null).getPropertyValue('border-top-color');" +
                    "y;";
    String color = selenium.getEval(script);
    

    This returns the color of the top border (yep, you'll need to call it four times in order to get the whole border) of the target element. But guess what! Every browser returns the color in a different format. Fortunately, at least in Java, there's a Color class that can easily reformat it:

    String color = Color.fromString(color).asHex();
    

    Now that you have a hex encoded color stored, you can trivially make check whether it's green or not.