Behaviour of WebElement.getCssValue()

1,375 views
Skip to first unread message

Andreas Tolf Tolfsen

unread,
Jan 2, 2012, 7:55:12 AM1/2/12
to selenium-...@googlegroups.com
Happy new year to everyone!

On multiple occasions there have been discussions on the IRC channel
regarding the behaviour of WebElement.getCssValue() for colour related
CSS parameters.

According to the interface Java documentation [1] getCssValue() colour
related properties are meant to be returned as HEX strings. The
interface documentation says:

> Color values should be returned as hex strings, so, for example if
> the "background-color" property is set as "green" in the HTML
> source, the returned value will be "#008000".

In reality different implementations return different things:

* OperaDriver used to return whatever the browser thought suitable,
which typically meant RGB or RGBA values. After a patch I made
recently it now returns HEX values.

* FirefoxDriver returns RGB values.

* IEDriver returns HEX for everything except parameters set to
values like "green", "red", "silver", &c.

As Jari pointed out to me, in the test suites (for Java and Ruby) we
appear to be making exceptions for every implementation, saying we
accept both "#00FF00", "green" and "rgb(0, 255, 0)" for the colour
green.

The atoms are not making any special cases for different values
returned in dom.getEffectiveStyle():

<URI:http://code.google.com/p/selenium/source/browse/trunk/javascript/atoms/dom.js#498>

In my opinion we need to agree on _either_ deciding to return a
consistent value across all browsers or to just return what the
browser thinks more appropriate.

A thing that complicates this further are new models of defining
colours in CSS, such as the RGBA and CMYK colour models.


1. <URI:http://selenium.googlecode.com/svn/trunk/docs/api/java/org/openqa/selenium/WebElement.html#getCssValue(java.lang.String)>

Jason Leyba

unread,
Jan 2, 2012, 12:09:56 PM1/2/12
to selenium-...@googlegroups.com
I think standardizing on returning a hex string would be the best thing to do.  I've had to write quite a few tests that expect different values based on the browser (not just for colors), and it is a PITA.  Being able to reliably expect a hex string would simplify things greatly.  Of course, a Color class that could convert to/from any format would be nice too :)

-- Jason



--
You received this message because you are subscribed to the Google Groups "Selenium Developers" group.
To post to this group, send email to selenium-...@googlegroups.com.
To unsubscribe from this group, send email to selenium-develo...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/selenium-developers?hl=en.


Simon Stewart

unread,
Jan 3, 2012, 9:21:52 AM1/3/12
to selenium-...@googlegroups.com
The docs have said "hex string" for a long time, and users tend not to try and find new classes. I suggest we always return a hex string, but provide a Colours class to convert that to names and rgb strings.

Simon

Andreas Tolf Tolfsen

unread,
Jan 19, 2012, 9:34:41 AM1/19/12
to selenium-...@googlegroups.com
At Tue, 3 Jan 2012 14:21:52 +0000, Simon Stewart wrote:
>
> The docs have said "hex string" for a long time, and users tend not
> to try and find new classes. I suggest we always return a hex
> string, but provide a Colours class to convert that to names and rgb
> strings.

The result of such a decision is that we are conciously performing a
lossy trunction of some colour values.

One example are colours in the RGBA or CMYK format. Or transparent
colours. How do you translate these in to HEX? There is a reason why
the browsers return what they do.

The colour green, rgb(0,255,0), is not the same as rgba(0,255,0,.5),
which adds an alpha channel to the colour. If you perform a lossy
conversion from rgba(0,255,0,.5) to HEX #00FF00, that's not the same
colour. The correct “HEX colour” would be #7EFF7E:

<URI:data:text/html;charset=utf-8,%3C!DOCTYPE%20html%3E%0D%0A%3Cbody%20style%3D%22background-color%3A%20rgba(0%2C%20255%2C%200%2C%20.5)%22%3E>

Another scenario concerns the static colour names defined in CSS, such
as "green", "yellow", "silver", &c. If we are to convert in to HEX we
need to keep an enum of these colours, complicating the implementation
significantly.

There is also CSS modifiers to consider, such as "transparent". In
such cases we are meant to traverse to the background element and find
the colour of that.

I quite like Jason Leyba's idea of having a Colors class that would
convert _from_ anything _to_ anything. We could alternatively make
the WebDriver atoms return RGB for IE and use that as the fallback
string, since converting to HEX is such a pain.

I've had to add a (bad) RGB to HEX conversion for OperaDriver which
you can see here:

<URI:https://github.com/operasoftware/operadriver/blob/master/src/com/opera/core/systems/model/OperaColor.java>

It only covers a few of the edge cases mentioned above.

So, my solution would be the following:

* Create a Selenium Color class for doing colour model conversions:

new WebColor("#00FF00").getRgb()
new WebColor("rgb(0, 255, 0)").getHex()
new WebColor("rgba(0, 255, 0, .5").getHex()

That way we could take whatever we get from getEffectiveStyle(),
which will figure out the transparent edge case, and return a
colour value of some kind. The user could optionally pass that in
to our new class and convert it to whatever he was doing the
assertion for in her test case.

* Alternatively we specify that browsers are allowed to return
whatever they feel is more sensible. In Opera's case that would
be RGB for normal colours, RGBA for RGBA, &c. That would leave it
up to the user how to interpret the results. Forcing HEX is a bad
idea.

* Optionally: Make atoms return RGB for consistency since most major
browsers seem to be using that.)

Andreas Tolf Tolfsen

unread,
Jan 19, 2012, 9:38:52 AM1/19/12
to selenium-...@googlegroups.com
Oh, and by the way. I notice this commit from Jason:

<URI:http://code.google.com/p/selenium/source/detail?r=15154>

… where FirefoxDriver is now relying on the atoms. Since
getEffectiveStyle(), which uses getComputedStyle() ||
getCascadedStyle() from the Closures library, as far as I can tell
don't convert to HEX; it probably means Firefox is also returning RGB
currently.

Daniel Wagner-Hall

unread,
Jan 19, 2012, 9:34:56 AM1/19/12
to selenium-...@googlegroups.com
I'm not familiar with most of the complexity here; would always
returning RGBA solve these problems?

Reply all
Reply to author
Forward
0 new messages