aboutsummaryrefslogtreecommitdiffstats
path: root/server
diff options
context:
space:
mode:
authorKatriHaapalinna <katri@vaadin.com>2018-04-19 15:03:16 +0300
committerIlia Motornyi <elmot@vaadin.com>2018-04-19 15:03:16 +0300
commitbdbb0b4328a36a66bb492973ca72497bfd34f6ad (patch)
tree62272a7e1fbe88f868b2fe13345f2d10fadc2c7e /server
parent07c6456da8f15d279340188dc86d7424cee36cd0 (diff)
downloadvaadin-framework-bdbb0b4328a36a66bb492973ca72497bfd34f6ad.tar.gz
vaadin-framework-bdbb0b4328a36a66bb492973ca72497bfd34f6ad.zip
Colorpicker validation handling (#10821)
* ColorTextField, helper methods, and regex for validating and handling text input * Refactored structure to avoid creating new component for validation * Style to adapt to error indicator * Tests for validating input in ColorPickerPreview component's TextField * Merge branch 'master' into colorpicker_validation * Fix path to server class * Fix test: Submit the new value * Fix test: ignore Phantom JS * Fix hsl+hsla validation patterns to accept '%', test value tweaking * Merge branch 'master' of github.com:vaadin/framework into colorpicker_validation * Fix: remove warning when color is updated from elsewhere * Revisions: input validation only once, Logging level WARN * Revisions: unit tests for color pattern matching * Revisions: moved parsing to utility class, tests for parsing all accepted input formats * Fixed import in tests, comments * Revisions: Logger as constant, ignore utility class in serialization test * Corner case tests * Revisions: protected method for parsing error text, fix to test * Revisions: NPE fix
Diffstat (limited to 'server')
-rw-r--r--server/src/main/java/com/vaadin/ui/components/colorpicker/ColorPickerPreview.java100
-rw-r--r--server/src/main/java/com/vaadin/ui/components/colorpicker/ColorUtil.java229
-rw-r--r--server/src/test/java/com/vaadin/tests/server/ClassesSerializableTest.java1
-rw-r--r--server/src/test/java/com/vaadin/tests/server/component/colorpicker/HSLAPatternParsingTest.java88
-rw-r--r--server/src/test/java/com/vaadin/tests/server/component/colorpicker/HSLPatternParsingTest.java89
-rw-r--r--server/src/test/java/com/vaadin/tests/server/component/colorpicker/HexPatternParsingTest.java76
-rw-r--r--server/src/test/java/com/vaadin/tests/server/component/colorpicker/RGBAPatternParsingTest.java92
-rw-r--r--server/src/test/java/com/vaadin/tests/server/component/colorpicker/RGBPatternParsingTest.java87
8 files changed, 704 insertions, 58 deletions
diff --git a/server/src/main/java/com/vaadin/ui/components/colorpicker/ColorPickerPreview.java b/server/src/main/java/com/vaadin/ui/components/colorpicker/ColorPickerPreview.java
index f68ae0ce9f..57da8949bd 100644
--- a/server/src/main/java/com/vaadin/ui/components/colorpicker/ColorPickerPreview.java
+++ b/server/src/main/java/com/vaadin/ui/components/colorpicker/ColorPickerPreview.java
@@ -16,9 +16,15 @@
package com.vaadin.ui.components.colorpicker;
import java.util.Objects;
+import java.util.logging.Level;
+import java.util.logging.Logger;
import com.vaadin.data.HasValue;
+import com.vaadin.server.AbstractErrorMessage.ContentMode;
+import com.vaadin.server.ErrorMessage;
+import com.vaadin.server.UserError;
import com.vaadin.shared.Registration;
+import com.vaadin.shared.ui.ErrorLevel;
import com.vaadin.shared.ui.colorpicker.Color;
import com.vaadin.ui.Component;
import com.vaadin.ui.CssLayout;
@@ -31,6 +37,8 @@ import com.vaadin.ui.TextField;
* @since 7.0.0
*/
public class ColorPickerPreview extends CssLayout implements HasValue<Color> {
+ private static final Logger LOGGER = Logger
+ .getLogger(ColorPickerPreview.class.getName());
private static final String STYLE_DARK_COLOR = "v-textfield-dark";
private static final String STYLE_LIGHT_COLOR = "v-textfield-light";
@@ -86,6 +94,7 @@ public class ColorPickerPreview extends CssLayout implements HasValue<Color> {
String colorCSS = color.getCSS();
field.setValue(colorCSS);
+ field.setComponentError(null);
oldValue = colorCSS;
@@ -120,68 +129,29 @@ public class ColorPickerPreview extends CssLayout implements HasValue<Color> {
}
private void valueChange(ValueChangeEvent<String> event) {
+ ErrorMessage errorMessage = null;
String value = event.getValue();
+ value = Objects.toString(value, "").trim();
Color oldColor = color;
try {
- if (value != null) {
- /*
- * Description of supported formats see
- * http://www.w3schools.com/cssref/css_colors_legal.asp
- */
- if (value.length() == 7 && value.startsWith("#")) {
- // CSS color format (e.g. #000000)
- int red = Integer.parseInt(value.substring(1, 3), 16);
- int green = Integer.parseInt(value.substring(3, 5), 16);
- int blue = Integer.parseInt(value.substring(5, 7), 16);
- color = new Color(red, green, blue);
-
- } else if (value.startsWith("rgb")) {
- // RGB color format rgb/rgba(255,255,255,0.1)
- String[] colors = value.substring(value.indexOf('(') + 1,
- value.length() - 1).split(",");
-
- int red = Integer.parseInt(colors[0]);
- int green = Integer.parseInt(colors[1]);
- int blue = Integer.parseInt(colors[2]);
- if (colors.length > 3) {
- int alpha = (int) (Double.parseDouble(colors[3])
- * 255d);
- color = new Color(red, green, blue, alpha);
- } else {
- color = new Color(red, green, blue);
- }
-
- } else if (value.startsWith("hsl")) {
- // HSL color format hsl/hsla(100,50%,50%,1.0)
- String[] colors = value.substring(value.indexOf('(') + 1,
- value.length() - 1).split(",");
-
- int hue = Integer.parseInt(colors[0]);
- int saturation = Integer
- .parseInt(colors[1].replace("%", ""));
- int lightness = Integer
- .parseInt(colors[2].replace("%", ""));
- int rgb = Color.HSLtoRGB(hue, saturation, lightness);
-
- if (colors.length > 3) {
- int alpha = (int) (Double.parseDouble(colors[3])
- * 255d);
- color = new Color(rgb);
- color.setAlpha(alpha);
- } else {
- color = new Color(rgb);
- }
- }
-
- oldValue = value;
- fireEvent(new ValueChangeEvent<>(this, oldColor,
- event.isUserOriginated()));
- }
- } catch (NumberFormatException nfe) {
- // Revert value
- field.setValue(oldValue);
+ /*
+ * Description of supported formats see
+ * http://www.w3schools.com/cssref/css_colors_legal.asp
+ */
+ color = ColorUtil.stringToColor(value);
+
+ oldValue = value;
+ fireEvent(new ValueChangeEvent<>(this, oldColor,
+ event.isUserOriginated()));
+ } catch (NumberFormatException e) {
+ // Pattern matching ensures the validity of
+ // the input, this should never happen
+ LOGGER.log(Level.INFO, e.getMessage());
+ errorMessage = new UserError(getUserErrorText(value),
+ ContentMode.TEXT, ErrorLevel.WARNING);
}
+ field.setComponentError(errorMessage);
}
@Override
@@ -224,4 +194,18 @@ public class ColorPickerPreview extends CssLayout implements HasValue<Color> {
}
}
}
-}
+
+ /**
+ * Get the client error message text for color input parsing error.
+ *
+ * @param value
+ * input which caused the error
+ * @return error message text
+ */
+ protected String getUserErrorText(String value) {
+ return value.isEmpty() ? "Input cannot be empty"
+ : "Input '".concat(value)
+ .concat("' is not in any recognized format");
+ }
+
+} \ No newline at end of file
diff --git a/server/src/main/java/com/vaadin/ui/components/colorpicker/ColorUtil.java b/server/src/main/java/com/vaadin/ui/components/colorpicker/ColorUtil.java
new file mode 100644
index 0000000000..ae942ea0ce
--- /dev/null
+++ b/server/src/main/java/com/vaadin/ui/components/colorpicker/ColorUtil.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright 2000-2018 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.ui.components.colorpicker;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.vaadin.shared.ui.colorpicker.Color;
+
+/**
+ * Utility class for matching and parsing {@link Color} objects from
+ * {@code String} input.
+ *
+ * Description of supported formats see
+ * http://www.w3schools.com/cssref/css_colors_legal.asp
+ *
+ * @since
+ */
+public class ColorUtil {
+ private ColorUtil() {
+ }
+
+ /**
+ * Parses {@link Color} from any of the following {@link String} inputs:
+ * <br>
+ * - RGB hex (e.g. "#FFAA00"), {@link #HEX_PATTERN}<br>
+ * - RGB "function" (e.g. "rgb(128,0,255)"), {@link #RGB_PATTERN}<br>
+ * - RGBA "function" (e.g. "rgba(50,50,50,0.2)"), {@link #RGBA_PATTERN}<br>
+ * - HSL "function" (e.g. "hsl(50,50,50)"), {@link #HSL_PATTERN}<br>
+ * - HSLA "function" (e.g. "hsl(50,50,50,0.2)"), {@link #HSLA_PATTERN}
+ * <p>
+ * Parsing is case-insensitive.
+ *
+ * @param input
+ * String input
+ * @return {@link Color} parsed from input
+ * @throws NumberFormatException
+ * Input does not match any recognized pattern
+ */
+ public static Color stringToColor(String input) {
+ Matcher m = HEX_PATTERN.matcher(input);
+ if (m.matches()) {
+ return getHexPatternColor(m);
+ }
+ m = RGB_PATTERN.matcher(input);
+ if (m.matches()) {
+ return getRGBPatternColor(m);
+ }
+ m = RGBA_PATTERN.matcher(input);
+ if (m.matches()) {
+ return getRGBAPatternColor(m);
+ }
+ m = HSL_PATTERN.matcher(input);
+ if (m.matches()) {
+ return getHSLPatternColor(m);
+ }
+ m = HSLA_PATTERN.matcher(input);
+ if (m.matches()) {
+ return getHSLAPatternColor(m);
+ }
+
+ throw new NumberFormatException("Parsing color from input failed.");
+ }
+
+ /**
+ * Parses {@link Color} from matched hexadecimal {@link Matcher}.
+ *
+ * @param matcher
+ * {@link Matcher} matching hexadecimal pattern with named regex
+ * groups {@code red}, {@code green}, and {@code blue}
+ * @return {@link Color} parsed from {@link Matcher}
+ */
+ public static Color getHexPatternColor(Matcher matcher) {
+ int red = Integer.parseInt(matcher.group("red"), 16);
+ int green = Integer.parseInt(matcher.group("green"), 16);
+ int blue = Integer.parseInt(matcher.group("blue"), 16);
+ return new Color(red, green, blue);
+ }
+
+ /**
+ * Parses {@link Color} from matched RGB {@link Matcher}.
+ *
+ * @param matcher
+ * {@link Matcher} matching RGB pattern with named regex groups
+ * {@code red}, {@code green}, and {@code blue}
+ * @return {@link Color} parsed from {@link Matcher}
+ */
+ public static Color getRGBPatternColor(Matcher matcher) {
+ int red = Integer.parseInt(matcher.group("red"));
+ int green = Integer.parseInt(matcher.group("green"));
+ int blue = Integer.parseInt(matcher.group("blue"));
+ return new Color(red, green, blue);
+ }
+
+ /**
+ * Parses {@link Color} from matched RGBA {@link Matcher}.
+ *
+ * @param matcher
+ * {@link Matcher} matching RGBA pattern with named regex groups
+ * {@code red}, {@code green}, {@code blue}, and {@code alpha}
+ * @return {@link Color} parsed from {@link Matcher}
+ */
+ public static Color getRGBAPatternColor(Matcher matcher) {
+ Color c = getRGBPatternColor(matcher);
+ c.setAlpha((int) (Double.parseDouble(matcher.group("alpha")) * 255d));
+ return c;
+ }
+
+ /**
+ * Parses {@link Color} from matched HSL {@link Matcher}.
+ *
+ * @param matcher
+ * {@link Matcher} matching HSL pattern with named regex groups
+ * {@code hue}, {@code saturation}, and {@code light}
+ * @return {@link Color} parsed from {@link Matcher}
+ */
+ public static Color getHSLPatternColor(Matcher matcher) {
+ int hue = Integer.parseInt(matcher.group("hue"));
+ int saturation = Integer.parseInt(matcher.group("saturation"));
+ int light = Integer.parseInt(matcher.group("light"));
+ int rgb = Color.HSLtoRGB(hue, saturation, light);
+ return new Color(rgb);
+ }
+
+ /**
+ * Parses {@link Color} from matched HSLA {@link Matcher}.
+ *
+ * @param matcher
+ * {@link Matcher} matching HSLA pattern with named regex groups
+ * {@code hue}, {@code saturation}, {@code light}, and
+ * {@code alpha}
+ * @return {@link Color} parsed from {@link Matcher}
+ */
+ public static Color getHSLAPatternColor(Matcher matcher) {
+ Color c = getHSLPatternColor(matcher);
+ c.setAlpha((int) (Double.parseDouble(matcher.group("alpha")) * 255d));
+ return c;
+ }
+
+ /**
+ * Case-insensitive {@link Pattern} with regular expression matching the
+ * default hexadecimal color presentation pattern:<br>
+ * '#' followed by six <code>[\da-fA-F]</code> characters.
+ * <p>
+ * Pattern contains named groups <code>red</code>, <code>green</code>, and
+ * <code>blue</code>, which represent the individual values.
+ */
+ public static final Pattern HEX_PATTERN = Pattern.compile(
+ "(?i)^#\\s*(?<red>[\\da-f]{2})(?<green>[\\da-f]{2})(?<blue>[\\da-f]{2}"
+ + ")\\s*$");
+ /**
+ * Case-insensitive {@link Pattern} with regular expression matching common
+ * RGB color presentation patterns:<br>
+ * 'rgb' followed by three [0-255] number values. Values can be separated
+ * with either comma or whitespace.
+ * <p>
+ * Pattern contains named groups <code>red</code>, <code>green</code>, and
+ * <code>blue</code>, which represent the individual values.
+ */
+ public static final Pattern RGB_PATTERN = Pattern.compile(
+ "(?i)^rgb\\(\\s*(?<red>[01]?\\d{1,2}|2[0-4]\\d|25[0-5])(?:\\s*[,+|\\"
+ + "s+]\\s*)(?<green>[01]?\\d\\d?|2[0-4]\\d|25[0-5])(?:\\s*[,"
+ + "+|\\s+]\\s*)(?<blue>[01]?\\d\\d?|2[0-4]\\d|25[0-5])\\s*\\"
+ + ")$");
+ /**
+ * Case-insensitive {@link Pattern} with regular expression matching common
+ * RGBA presentation patterns:<br>
+ * 'rgba' followed by three [0-255] values and one [0.0-1.0] value. Values
+ * can be separated with either comma or whitespace. The only accepted
+ * decimal marker is point ('.').
+ * <p>
+ * Pattern contains named groups <code>red</code>, <code>green</code>,
+ * <code>blue</code>, and <code>alpha</code>, which represent the individual
+ * values.
+ */
+ public static final Pattern RGBA_PATTERN = Pattern.compile(
+ "(?i)^rgba\\(\\s*(?<red>[01]?\\d{1,2}|2[0-4]\\d|25[0-5])(?:\\s*[,+|"
+ + "\\s+]\\s*)(?<green>[01]?\\d\\d?|2[0-4]\\d|25[0-5])(?:\\s"
+ + "*[,+|\\s+]\\s*)(?<blue>[01]?\\d\\d?|2[0-4]\\d|25[0-5])(?"
+ + ":\\s*[,+|\\s+]\\s*)(?<alpha>0(?:\\.\\d{1,2})?|0?(?:\\.\\"
+ + "d{1,2})|1(?:\\.0{1,2})?)\\s*\\)$");
+
+ /**
+ * Case-insensitive {@link Pattern} with regular expression matching common
+ * HSL presentation patterns:<br>
+ * 'hsl' followed by one [0-360] value and two [0-100] percentage value.
+ * Values can be separated with either comma or whitespace. The percent sign
+ * ('%') is optional.
+ * <p>
+ * Pattern contains named groups <code>hue</code>,<code>saturation</code>,
+ * and <code>light</code>, which represent the individual values.
+ */
+ public static final Pattern HSL_PATTERN = Pattern.compile(
+ "(?i)hsl\\(\\s*(?<hue>[12]?\\d{1,2}|3[0-5]\\d|360)(?:\\s*[,+|\\s+]"
+ + "\\s*)(?<saturation>\\d{1,2}|100)(?:\\s*%?\\s*[,+|\\s+]\\"
+ + "s*)(?<light>\\d{1,2}|100)(?:\\s*%?\\s*)\\)$");
+
+ /**
+ * Case-insensitive {@link Pattern} with regular expression matching common
+ * HSLA presentation patterns:<br>
+ * 'hsla' followed by one [0-360] value, two [0-100] percentage values, and
+ * one [0.0-1.0] value. Values can be separated with either comma or
+ * whitespace. The percent sign ('%') is optional. The only accepted decimal
+ * marker is point ('.').
+ * <p>
+ * Pattern contains named groups <code>hue</code>,<code>saturation</code>,
+ * <code>light</code>, and <code>alpha</code>, which represent the
+ * individual values.
+ */
+ public static final Pattern HSLA_PATTERN = Pattern.compile(
+ "(?i)hsla\\(\\s*(?<hue>[12]?\\d{1,2}|3[0-5]\\d|360)(?:\\s*[,+|\\s+"
+ + "]\\s*)(?<saturation>\\d{1,2}|100)(?:\\s*%?\\s*[,+|\\s+]\\s*"
+ + ")(?<light>\\d{1,2}|100)(?:\\s*%?[,+|\\s+]\\s*)(?<alpha>"
+ + "0(?:\\.\\d{1,2})?|0?(?:\\.\\d{1,2})|1(?:\\.0{1,2})?)"
+ + "\\s*\\)$");
+}
diff --git a/server/src/test/java/com/vaadin/tests/server/ClassesSerializableTest.java b/server/src/test/java/com/vaadin/tests/server/ClassesSerializableTest.java
index 0b6d67f7a7..0827fc262c 100644
--- a/server/src/test/java/com/vaadin/tests/server/ClassesSerializableTest.java
+++ b/server/src/test/java/com/vaadin/tests/server/ClassesSerializableTest.java
@@ -94,6 +94,7 @@ public class ClassesSerializableTest {
"com\\.vaadin\\.server\\.JsonCodec\\$1", //
"com\\.vaadin\\.server\\.communication\\.PushConnection", //
"com\\.vaadin\\.server\\.communication\\.AtmospherePushConnection.*", //
+ "com\\.vaadin\\.ui\\.components\\.colorpicker\\.ColorUtil", //
"com\\.vaadin\\.util\\.ConnectorHelper", //
"com\\.vaadin\\.server\\.VaadinSession\\$FutureAccess", //
"com\\.vaadin\\.external\\..*", //
diff --git a/server/src/test/java/com/vaadin/tests/server/component/colorpicker/HSLAPatternParsingTest.java b/server/src/test/java/com/vaadin/tests/server/component/colorpicker/HSLAPatternParsingTest.java
new file mode 100644
index 0000000000..548e61df26
--- /dev/null
+++ b/server/src/test/java/com/vaadin/tests/server/component/colorpicker/HSLAPatternParsingTest.java
@@ -0,0 +1,88 @@
+package com.vaadin.tests.server.component.colorpicker;
+
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.regex.Matcher;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+import com.vaadin.shared.ui.colorpicker.Color;
+import com.vaadin.ui.components.colorpicker.ColorUtil;
+
+@RunWith(value = Parameterized.class)
+public class HSLAPatternParsingTest {
+
+ @Parameter(value = 0)
+ public String input;
+
+ @Parameter(value = 1)
+ public int expectedHue;
+ @Parameter(value = 2)
+ public int expectedSaturation;
+ @Parameter(value = 3)
+ public int expectedLight;
+ @Parameter(value = 4)
+ public int expectedAlpha;
+
+ @Parameter(value = 5)
+ public boolean expectedMatches;
+
+ @Parameters(name = "{index}: testHSLAData({0}) = ({1},{2},{3},{4},{5})")
+ public static Collection<Object[]> hsladata() {
+ Object[][] validValues = { { "hsla(0,0,0,0)", 0, 0, 0, 0, true },
+ { "HSLA(0, 0, 0, 0)", 0, 0, 0, 0, true },
+ { "hsla(0,0%,0%, 0.1)", 0, 0, 0, 25, true },
+ { "hsla(0 0 0 0.00 )", 0, 0, 0, 0, true },
+ { "hsla(0 0% 0% 0.50)", 0, 0, 0, 127, true },
+ { "hsla(360,100,100,1.0)", 360, 100, 100, 255, true },
+ { "hsla(360, 100, 100, 1.0)", 360, 100, 100, 255, true },
+ { "hsla(360, 100%, 100%, 1.00)", 360, 100, 100, 255, true },
+ { "hsla(360 100% 100% 1.00)", 360, 100, 100, 255, true },
+ { "hsla(20, 10, 10, 0.24)", 20, 10, 10, 61, true },
+ { "hsla(100, 0, 50, 0.8)", 100, 0, 50, 204, true },
+ { "hsla(269, 50, 0, .6)", 269, 50, 0, 153, true }, };
+ Object[][] invalidValues = { { "hsla(361,0,0,0)", 0, 0, 0, 0, false },
+ { "hsla(0.0, 0, 0, 0)", 0, 0, 0, 0, false },
+ { "hsla(0,0%,0%, 1.1)", 0, 0, 0, 0, false },
+ { "hsla(0 0 0 0.009 )", 0, 0, 0, 0, false },
+ { "hsla(0 0% -100% 0.50)", 0, 0, 0, 0, false },
+ { "hsla(360,1000,100,1.0)", 0, 0, 0, 0, false },
+ { "hsla(0, 100, 100, 2.0)", 0, 0, 0, 0, false },
+ { "hsla(360, 100%, 100%, 10.00)", 0, 0, 0, 0, false },
+ { "hsl a(360 100% 100% 1.)", 0, 0, 0, 0, false },
+ { "hsla(20, -10, 10, 0.24)", 0, 0, 0, 0, false },
+ { "hsla(400, 0, 50, 0.8)", 0, 0, 0, 0, false },
+ { "hsla(200, 50, 0, 0.996)", 0, 0, 0, 0, false },
+ { "hsla 200, 50, 0, 0.9", 0, 0, 0, 0, false },
+ { "hsla(0,0,0,0.)", 0, 0, 0, 0, false } };
+
+ ArrayList<Object[]> values = new ArrayList<>();
+ Collections.addAll(values, validValues);
+ Collections.addAll(values, invalidValues);
+
+ return values;
+ }
+
+ @Test
+ public void testHSLAData() {
+ Matcher m = ColorUtil.HSLA_PATTERN.matcher(input);
+ boolean matches = m.matches();
+ if (expectedMatches) {
+ Color expectedColor = new Color(Color.HSLtoRGB(expectedHue,
+ expectedSaturation, expectedLight));
+ expectedColor.setAlpha(expectedAlpha);
+ Color c1 = ColorUtil.getHSLAPatternColor(m);
+ assertTrue(expectedColor.equals(c1));
+ } else {
+ assertTrue(!matches);
+ }
+ }
+
+}
diff --git a/server/src/test/java/com/vaadin/tests/server/component/colorpicker/HSLPatternParsingTest.java b/server/src/test/java/com/vaadin/tests/server/component/colorpicker/HSLPatternParsingTest.java
new file mode 100644
index 0000000000..738388a70d
--- /dev/null
+++ b/server/src/test/java/com/vaadin/tests/server/component/colorpicker/HSLPatternParsingTest.java
@@ -0,0 +1,89 @@
+package com.vaadin.tests.server.component.colorpicker;
+
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.regex.Matcher;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+import com.vaadin.shared.ui.colorpicker.Color;
+import com.vaadin.ui.components.colorpicker.ColorUtil;
+
+@RunWith(value = Parameterized.class)
+public class HSLPatternParsingTest {
+
+ @Parameter(value = 0)
+ public String input;
+
+ @Parameter(value = 1)
+ public Color expectedColor;
+
+ @Parameter(value = 2)
+ public boolean expectedMatches;
+
+ @Parameters(name = "{index}: testHSLData({0}) = ({1},{2})")
+ public static Collection<Object[]> hsldata() {
+ Object[][] validValues = {
+ { "hsl(0,0,0)", new Color(Color.HSLtoRGB(0, 0, 0)), true },
+ { "hsl(0, 0, 0)", new Color(Color.HSLtoRGB(0, 0, 0)), true },
+ { "hsl(0,0%,0% )", new Color(Color.HSLtoRGB(0, 0, 0)), true },
+ { "hsl(0 0 0)", new Color(Color.HSLtoRGB(0, 0, 0)), true },
+ { "hsl(0 0% 0%)", new Color(Color.HSLtoRGB(0, 0, 0)), true },
+ { "hsl(360,100,100)", new Color(Color.HSLtoRGB(360, 100, 100)),
+ true },
+ { "hsl(360, 100, 100)",
+ new Color(Color.HSLtoRGB(360, 100, 100)), true },
+ { "hsl(360, 100%, 100%)",
+ new Color(Color.HSLtoRGB(360, 100, 100)), true },
+ { "hsl(360 100% 100%)",
+ new Color(Color.HSLtoRGB(360, 100, 100)), true },
+ { "hsl(20, 10, 10)", new Color(Color.HSLtoRGB(20, 10, 10)),
+ true },
+ { "hsl(100, 0, 50)", new Color(Color.HSLtoRGB(100, 0, 50)),
+ true },
+ { "hsl(200, 50, 0)", new Color(Color.HSLtoRGB(200, 50, 0)),
+ true },
+ { "hsl(200, 50, 05)", new Color(Color.HSLtoRGB(200, 50, 5)),
+ true } };
+ Object[][] invalidValues = { { "hsl(361,0,0)", null, false },
+ { "hsl(-0, 0, 0)", null, false },
+ { "hsl (100%,0%,0% )", null, false },
+ { "hsl(0 101 0)", null, false },
+ { "hsl(0 0% -99%)", null, false },
+ { "hsl(360,100,10 0)", null, false },
+ { "hsl(360, 100, 101)", null, false },
+ { "hsl(360, 110%, 100%)", null, false },
+ { "hsl(3600 100% 100%)", null, false },
+ { "hs l(420, 10, 10)", null, false },
+ { "hsl(100, 0, 5,0)", null, false },
+ { "hsla(200, 50, 0)", null, false },
+ { "hsl(0,0,0", null, false }, { "rgb\\(\\.*", null, false },
+ { "hsl(\\.*)", null, false }, { "#\\d.*", null, false },
+ { "", null, false } };
+ ArrayList<Object[]> values = new ArrayList<>();
+ Collections.addAll(values, validValues);
+ Collections.addAll(values, invalidValues);
+
+ return values;
+ }
+
+ @Test
+ public void testHSLData() {
+ Matcher m = ColorUtil.HSL_PATTERN.matcher(input);
+ boolean matches = m.matches();
+ if (expectedMatches) {
+ Color c1 = ColorUtil.getHSLPatternColor(m);
+ assertTrue(expectedColor.equals(c1));
+ } else {
+ assertTrue(!matches);
+ }
+ }
+
+}
diff --git a/server/src/test/java/com/vaadin/tests/server/component/colorpicker/HexPatternParsingTest.java b/server/src/test/java/com/vaadin/tests/server/component/colorpicker/HexPatternParsingTest.java
new file mode 100644
index 0000000000..a79e928ddf
--- /dev/null
+++ b/server/src/test/java/com/vaadin/tests/server/component/colorpicker/HexPatternParsingTest.java
@@ -0,0 +1,76 @@
+package com.vaadin.tests.server.component.colorpicker;
+
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.regex.Matcher;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+import com.vaadin.shared.ui.colorpicker.Color;
+import com.vaadin.ui.components.colorpicker.ColorUtil;
+
+@RunWith(value = Parameterized.class)
+public class HexPatternParsingTest {
+
+ @Parameter(value = 0)
+ public String input;
+
+ @Parameter(value = 1)
+ public int expectedRed;
+ @Parameter(value = 2)
+ public int expectedGreen;
+ @Parameter(value = 3)
+ public int expectedBlue;
+
+ @Parameter(value = 4)
+ public boolean expectedMatches;
+
+ @Parameters(name = "{index}: textValidHEX({0}) = ({1},{2},{3},{4})")
+ public static Collection<Object[]> hexdata() {
+ Object[][] validValues = { { "#000000", 0, 0, 0, true },
+ { "#ffffff", 255, 255, 255, true },
+ { "#FF00ff", 255, 0, 255, true }, { "#aa90e3",170,144,227, true },
+ { "#016953", 1, 105, 83, true },
+ { "#bC64D0", 188, 100, 208, true },
+ { "#F100FF", 241, 0, 255, true },
+ { "#F0E9a5", 240, 233, 165, true },
+ { "#990077", 153, 0, 119, true } };
+ Object[][] invalidValues = { { "#0000000", 0, 0, 0, false },
+ { "#ffgfff", 0, 0, 0, false }, { "#FF10f", 0, 0, 0, false },
+ { "#aa9", 0, 0, 0, false }, { "#03", 0, 0, 0, false },
+ { "#aab3c4c", 0, 0, 0, false }, { "#6010", 0, 0, 0, false },
+ { "#CCCC", 0, 0, 0, false }, { "#9", 0, 0, 0, false },
+ { "#10 10 10", 0, 0, 0, false }, { "101010", 0, 0, 0, false },
+ { "#10101q", 0, 0, 0, false },
+ { "\\s%\\d[0-9]", 0, 0, 0, false },
+ { "#\\d.*", 0, 0, 0, false }, { "rgb\\(\\.*", 0, 0, 0, false },
+ { "#\\d\\d\\d", 0, 0, 0, false }, { "#\\d.*", 0, 0, 0, false },
+ { "", 0, 0, 0, false }, { "hsl(25,25,25)", 0, 0, 0, false } };
+ ArrayList<Object[]> values = new ArrayList<>();
+ Collections.addAll(values, validValues);
+ Collections.addAll(values, invalidValues);
+
+ return values;
+ }
+
+ @Test
+ public void testValidHEX() {
+ Matcher m = ColorUtil.HEX_PATTERN.matcher(input);
+ boolean matches = m.matches();
+ if (expectedMatches) {
+ Color c = new Color(expectedRed, expectedGreen, expectedBlue);
+ Color c1 = ColorUtil.getHexPatternColor(m);
+ assertTrue(c.equals(c1));
+ } else {
+ assertTrue(!matches);
+ }
+ }
+
+}
diff --git a/server/src/test/java/com/vaadin/tests/server/component/colorpicker/RGBAPatternParsingTest.java b/server/src/test/java/com/vaadin/tests/server/component/colorpicker/RGBAPatternParsingTest.java
new file mode 100644
index 0000000000..71ea7c7d7b
--- /dev/null
+++ b/server/src/test/java/com/vaadin/tests/server/component/colorpicker/RGBAPatternParsingTest.java
@@ -0,0 +1,92 @@
+package com.vaadin.tests.server.component.colorpicker;
+
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.regex.Matcher;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+import com.vaadin.shared.ui.colorpicker.Color;
+import com.vaadin.ui.components.colorpicker.ColorUtil;
+
+@RunWith(value = Parameterized.class)
+public class RGBAPatternParsingTest {
+
+ @Parameter(value = 0)
+ public String input;
+
+ @Parameter(value = 1)
+ public int expectedRed;
+ @Parameter(value = 2)
+ public int expectedGreen;
+ @Parameter(value = 3)
+ public int expectedBlue;
+ @Parameter(value = 4)
+ public int expectedAlpha;
+
+ @Parameter(value = 5)
+ public boolean expectedMatches;
+
+ @Parameters(name = "{index}: testRGBAData({0}) = ({1},{2},{3},{4},{5})")
+ public static Collection<Object[]> rgbdata() {
+ Object[][] validValues = { { "rgba(0,0,0,0)", 0, 0, 0, 0, true },
+ { "RGBA(0, 0, 0, 0 )", 0, 0, 0, 0, true },
+ { "rgba(0 0 0 0.00)", 0, 0, 0, 0, true },
+ { "rgba(1 1 1 1.00)", 1, 1, 1, 255, true },
+ { "rgba(0 100 200 0.50)", 0, 100, 200, 127, true },
+ { "rgba(255,255,255,1.0)", 255, 255, 255, 255, true },
+ { "rgba(255, 255, 255, 1.0)", 255, 255, 255, 255, true },
+ { "rgba(255 255 255 0)", 255, 255, 255, 0, true },
+ { "rgba(1, 10, 100, 0.00)", 1, 10, 100, 0, true } };
+ Object[][] invalidValues = { { "rgba(256,0,0,0)", 0, 0, 0, 0, false },
+ { "rgba(0, 256, 0, -0 )", 0, 0, 0, 0, false },
+ { "rgba(0,0,10.0, 00)", 0, 0, 0, 0, false },
+ { "rgba(0 0 0 2.00)", 0, 0, 0, 0, false },
+ { "rgba(0 -99 0 0.50)", 0, 0, 0, 0, false },
+ { "rgba(0,255%,255,1.0)", 0, 0, 0, 0, false },
+ { "rgba(255, 255, 255, 1.05)", 0, 0, 0, 0, false },
+ { "rgba(255, 255, 255, 1.50)", 0, 0, 0, 0, false },
+ { "rgb a(255 255 0.005)", 0, 0, 0, 0, false },
+ { "rgba(163, 256, 1000, 0.24)", 0, 0, 0, 0, false },
+ { "rgba(100, 0.5, 250, 0.8)", 0, 0, 0, 0, false },
+ { "rgba(, 50, 0, 0.6)", 0, 0, 0, 0, false },
+ { "rgba(200, 50, 0, 10.6)", 0, 0, 0, 0, false },
+ { "rgba 200, 50, 0, 1.", 0, 0, 0, 0, false },
+ { "rgba(0,0,0,0.)", 0, 0, 0, 0, false },
+ { "rgb(200, 50, 0)", 0, 0, 0, 0, false },
+ { "hsla,0(10,0,0)", 0, 0, 0, 0, false },
+ { "rgba(\\s.*\\d[0-9])", 0, 0, 0, 0, false },
+ { "rgba(\\.*,255,255, 0)", 0, 0, 0, 0, false },
+ { "#\\d.*", 0, 0, 0, 0, false }, { "", 0, 0, 0, 0, false },
+ { "rgba(\\d,\\d,\\d,0.0)", 0, 0, 0, 0, false },
+ { "^rgba\\( \\.*)", 0, 0, 0, 0, false } };
+
+ ArrayList<Object[]> values = new ArrayList<>();
+ Collections.addAll(values, validValues);
+ Collections.addAll(values, invalidValues);
+
+ return values;
+ }
+
+ @Test
+ public void testRGBAData() {
+ Matcher m = ColorUtil.RGBA_PATTERN.matcher(input);
+ boolean matches = m.matches();
+ if (expectedMatches) {
+ Color expectedColor = new Color(expectedRed, expectedGreen,
+ expectedBlue, expectedAlpha);
+ Color c1 = ColorUtil.getRGBAPatternColor(m);
+
+ assertTrue(expectedColor.equals(c1));
+ } else {
+ assertTrue(!matches);
+ }
+ }
+}
diff --git a/server/src/test/java/com/vaadin/tests/server/component/colorpicker/RGBPatternParsingTest.java b/server/src/test/java/com/vaadin/tests/server/component/colorpicker/RGBPatternParsingTest.java
new file mode 100644
index 0000000000..f853663faa
--- /dev/null
+++ b/server/src/test/java/com/vaadin/tests/server/component/colorpicker/RGBPatternParsingTest.java
@@ -0,0 +1,87 @@
+package com.vaadin.tests.server.component.colorpicker;
+
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.regex.Matcher;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+import com.vaadin.shared.ui.colorpicker.Color;
+import com.vaadin.ui.components.colorpicker.ColorUtil;
+
+@RunWith(value = Parameterized.class)
+public class RGBPatternParsingTest {
+
+ @Parameter(value = 0)
+ public String input;
+
+ @Parameter(value = 1)
+ public int expectedRed;
+ @Parameter(value = 2)
+ public int expectedGreen;
+ @Parameter(value = 3)
+ public int expectedBlue;
+
+ @Parameter(value = 4)
+ public boolean expectedMatches;
+
+ @Parameters(name = "{index}: testRGBData({0}) = ({1},{2},{3},{4})")
+ public static Collection<Object[]> rgbdata() {
+ Object[][] validValues = { { "rgb(0,0,0)", 0, 0, 0, true },
+ { "rgb(0, 0, 0)", 0, 0, 0, true },
+ { "rgb(0 0 0)", 0, 0, 0, true },
+ { "rgb(1 1 1)", 1, 1, 1, true },
+ { "rgb(0 100 255)", 0, 100, 255, true },
+ { "rgb(255,255,255)", 255, 255, 255, true },
+ { "RGB(255, 255, 255 )", 255, 255, 255, true },
+ { "rgb(255 255 255)", 255, 255, 255, true },
+ { "rgb(1, 10, 100)", 1, 10, 100, true } };
+ Object[][] invalidValues = { { "rgb(,0,0)", 0, 0, 0, false },
+ { "rgb(0, 0, 0, )", 0, 0, 0, false },
+ { "rgb(0.0,0,0)", 0, 0, 0, false },
+ { "rgb( 0 0 -1 )", 0, 0, 0, false },
+ { "rgb(1 00)", 0, 0, 0, false },
+ { "rgb(255,255,255.)", 0, 0, 0, false },
+ { "r gb(255, 256, 255)", 0, 0, 0, false },
+ { "rgb( 255, 255, 256 )", 0, 0, 0, false },
+ { "rgb(163, 2%, 210)", 0, 0, 0, false },
+ { "rGb(000)", 0, 0, 0, false },
+ { "rgb(255255255)", 0, 0, 0, false },
+ { "rGBA(255,255,255)", 0, 0, 0, false },
+ { "rgb 255 255 255)", 0, 0, 0, false },
+ { "255, 255, 0", 0, 0, 0, false },
+ { "hsl(10,0,0)", 0, 0, 0, false },
+ { "\\s%\\d[0-9]", 0, 0, 0, false },
+ { "rgb(\\.*,255,255)", 0, 0, 0, false },
+ { "#\\d.*", 0, 0, 0, false }, { "", 0, 0, 0, false },
+ { "rgb(\\d,\\d,\\d)", 0, 0, 0, false },
+ { "^rgb\\( \\.*)", 0, 0, 0, false } };
+
+ ArrayList<Object[]> values = new ArrayList<>();
+ Collections.addAll(values, validValues);
+ Collections.addAll(values, invalidValues);
+
+ return values;
+ }
+
+ @Test
+ public void testRGBData() {
+ Matcher m = ColorUtil.RGB_PATTERN.matcher(input);
+ boolean matches = m.matches();
+ if (expectedMatches) {
+ Color expectedColor = new Color(expectedRed, expectedGreen,
+ expectedBlue);
+ Color c1 = ColorUtil.getRGBPatternColor(m);
+ assertTrue(expectedColor.equals(c1));
+ } else {
+ assertTrue(!matches);
+ }
+ }
+}