3

How to convert #ffffff to #fff or #fff to #ffffff for Assertion?

I am using getCssValue("background") from Selenium which returns rgb(255, 255, 255) which I can split into:

  • r -> 255
  • g -> 255
  • b -> 255

The following line of code:

String hex = String.format("#%02x%02x%02x", r, g, b);

Converts rgb to hex and gives an output as:

#ffffff

But from the console, the background is extracted as #fff

fff

So what can be the ideal way either to:

  • convert #ffffff to #fff
  • convert #fff to #ffffff

I have been through a couple of relevant discussions as:

But my tests are failing and there is a need for conversion. Any recommendations?

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • 2
    From my knowledge short hex colors are compound like this: `#aabbcc` -> `#abc`. You can split the log hex into 3 segments [aa, bb, cc] and check if both chars are identical and for short hex, split into [a, b, c] and duplicate them. – KunLun Feb 19 '19 at 13:24
  • This question has nothing to do with Selenium... that's why I removed the tag. There's not a single mention of it. – JeffC Feb 19 '19 at 14:44
  • @JeffC Perhaps you missed to notice the entire discussion is based on the output of `getCssValue("background")` which is pretty much specific to _Selenium_ – undetected Selenium Feb 19 '19 at 14:44
  • Why all the conversions? What's wrong with `Assert.assertEquals("rgb(255,255,255)", e.getCssValue("background"));`? You are going to hard code the expected value anyway. – JeffC Feb 19 '19 at 14:45
  • The question is `How to convert #ffffff to #fff or #fff to #ffffff for Assertion?`... how you get the value is not consequential to the question. – JeffC Feb 19 '19 at 14:45
  • @JeffC The question title field is `varchar[150]` only but then we need to keep the title short and sweet. – undetected Selenium Feb 19 '19 at 14:47

2 Answers2

3

You can use replaceAll with a regular expression that looks for the case where all three parts use the same digit:

static String getHex(int r, int g, int b) {
    return String.format("#%02x%02x%02x", r, g, b).replaceAll("^#([a-fA-F])\\1([a-fA-F])\\2([a-fA-F])\\3$", "#$1$2$3");
}

That looks for a string starting with # followed by three pairs of matching hex digits, and replaces them with just the short form. (I suppose I could have just used [a-f] instead of [a-fA-F] in your specific example, since you know you'll be getting lower case only, but...)

Complete example (on Ideone):

public class Example {
    public static void main(String[] args) {
        System.out.println(getHex(255, 255, 255)); // #fff
        System.out.println(getHex(255, 240, 255)); // #fff0ff
    }

    static String getHex(int r, int g, int b) {
        return String.format("#%02x%02x%02x", r, g, b).replaceAll("^#([a-fA-F])\\1([a-fA-F])\\2([a-fA-F])\\3$", "#$1$2$3");
    }
}
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
3

You could write a simple method that "normalizes" your HTML color codes to short or long format if they have all the same hex digits:

public static void main(String[] args) {
    System.out.println(normalizeHtmlColors("#ffffff", true));
    System.out.println(normalizeHtmlColors("#fff", true));
    System.out.println(normalizeHtmlColors("#ffffff", false));
    System.out.println(normalizeHtmlColors("#fff", false));
}

public static String normalizeHtmlColors(String colorCode, boolean toShort) {
    if (toShort && colorCode.matches("^#?([0-9a-fA-F])\\1{5}$"))
        colorCode = colorCode.replaceFirst("#?([0-9a-fA-F])\\1{5}", "#$1$1$1");
    else if (!toShort && colorCode.matches("^#?([0-9a-fA-F])\\1{2}$"))
        colorCode = colorCode.replaceFirst("#?([0-9a-fA-F])\\1{2}", "#$1$1$1$1$1$1");
    return colorCode;
}

This would print:

#fff
#fff
#ffffff
#ffffff

...so you can decide in which direction to transform. If the input doesn't match the two cases, it will just be returned.

bkis
  • 2,530
  • 1
  • 17
  • 31