]> source.dussan.org Git - vaadin-framework.git/commitdiff
Set DateField value only if it passes range check (#11887)
authorTatu Lund <tatu@vaadin.com>
Wed, 8 Apr 2020 09:17:11 +0000 (12:17 +0300)
committerGitHub <noreply@github.com>
Wed, 8 Apr 2020 09:17:11 +0000 (12:17 +0300)
Fixes #11108

server/src/main/java/com/vaadin/ui/AbstractDateField.java
server/src/test/java/com/vaadin/ui/DateFieldTestCase.java
uitest/src/test/java/com/vaadin/tests/components/datefield/DateFieldBinderCrossValidationTest.java
uitest/src/test/java/com/vaadin/tests/components/datefield/DateFieldFaultyInputNotValidTest.java

index c252655e446506102a3516afaec11aa12132a76d..9c5d9bb656cddd8591948dea076e2e47d046cd6b 100644 (file)
@@ -297,7 +297,10 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster &
      * validate. If {@code startDate} is set to {@code null}, any value before
      * {@code endDate} will be accepted by the range
      * <p>
-     * Note: Negative, i.e. BC dates are not supported
+     * Note: Negative, i.e. BC dates are not supported.
+     * <p>
+     * Note: It's usually recommended to use only one of the following at the same
+     * time: Range validator with Binder or DateField's setRangeStart check.
      *
      * @param startDate
      *            - the allowed range's start date
@@ -359,6 +362,9 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster &
      * date (taking the resolution into account), the component will not
      * validate. If {@code endDate} is set to {@code null}, any value after
      * {@code startDate} will be accepted by the range.
+     * <p>
+     * Note: It's usually recommended to use only one of the following at the same
+     * time: Range validator with Binder or DateField's setRangeEnd check.
      *
      * @param endDate
      *            the allowed range's end date (inclusive, based on the current
@@ -618,27 +624,38 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster &
      *
      * @param value
      *            the new value, may be {@code null}
+     * @throws IllegalArgumentException
+     *            if the value is not within range bounds
      */
     @Override
     public void setValue(T value) {
-        currentErrorMessage = null;
-        /*
-         * First handle special case when the client side component have a date
-         * string but value is null (e.g. unparsable date string typed in by the
-         * user). No value changes should happen, but we need to do some
-         * internal housekeeping.
-         */
-        if (value == null && !getState(false).parsable) {
+        RangeValidator<T> validator = getRangeValidator();
+        ValidationResult result = validator.apply(value,
+                new ValueContext(this, this));
+
+        if (result.isError()) {
+            throw new IllegalArgumentException(
+                    "value is not within acceptable range");
+        } else {
+            currentErrorMessage = null;
             /*
-             * Side-effects of doSetValue clears possible previous strings and
-             * flags about invalid input.
+             * First handle special case when the client side component has a date
+             * string but value is null (e.g. unparsable date string typed in by the
+             * user). No value changes should happen, but we need to do some
+             * internal housekeeping.
              */
-            doSetValue(null);
-
-            markAsDirty();
-            return;
+            if (value == null && !getState(false).parsable) {
+                /*
+                 * Side-effects of doSetValue clears possible previous strings and
+                 * flags about invalid input.
+                 */
+                doSetValue(null);
+
+                markAsDirty();
+                return;
+            }
+            super.setValue(value);
         }
-        super.setValue(value);
     }
 
     /**
@@ -785,8 +802,8 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster &
     @Override
     protected void doSetValue(T value) {
 
-        this.value = value;
         // Also set the internal dateString
+        this.value = value;
         if (value == null) {
             value = getEmptyValue();
         }
index f50141df6627d10bf1ab3a588d9eda26c0ad1a9f..026388d6238ad6a77b51a2d7fe8a79ab296c4bb1 100644 (file)
@@ -10,12 +10,17 @@ import java.time.LocalDate;
 
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.Rule;
+import org.junit.rules.ExpectedException;
 
 public class DateFieldTestCase {
 
     private AbstractLocalDateField dateField;
     private LocalDate date;
 
+    @Rule
+    public transient ExpectedException exceptionRule = ExpectedException.none();
+
     @Before
     public void setup() {
         dateField = new AbstractLocalDateField() {
@@ -39,9 +44,11 @@ public class DateFieldTestCase {
 
     @Test
     public void belowRangeStartIsNotAcceptedAsValue() {
+        LocalDate currentDate = dateField.getValue();
         dateField.setRangeStart(date);
+        exceptionRule.expect(IllegalArgumentException.class);
         dateField.setValue(date.minusDays(1));
-        assertNotNull(dateField.getComponentError());
+        assertThat(dateField.getValue(), is(currentDate));
     }
 
     @Test
@@ -60,8 +67,10 @@ public class DateFieldTestCase {
 
     @Test
     public void aboveRangeEndIsNotAcceptedAsValue() {
+        LocalDate currentDate = dateField.getValue();
         dateField.setRangeEnd(date);
+        exceptionRule.expect(IllegalArgumentException.class);
         dateField.setValue(date.plusDays(1));
-        assertNotNull(dateField.getComponentError());
+        assertThat(dateField.getValue(), is(currentDate));
     }
 }
index efbbf3f999fa51104decc20bc9187c331a486f9b..4a47f3786a2a9b426e115cdc4eecebf69952a55e 100644 (file)
@@ -30,6 +30,8 @@ public class DateFieldBinderCrossValidationTest extends SingleBrowserTest {
         fromFieldText.sendKeys("2019/01/01", Keys.ENTER);
         toFieldText.sendKeys("2018/02/02", Keys.ENTER);
 
+        sleep(200);
+
         assertEquals("Error message should contain the information",
                 EXPECTED_ERROR, label.getText());
 
index 3a3b6cd069142b1e4016c34864fa75b9d5a8ebe7..87cb115ae5a4ff1a745f9820765b187798d6a3bc 100644 (file)
@@ -6,7 +6,9 @@ import java.time.LocalDate;
 
 import org.junit.Test;
 import org.openqa.selenium.By;
+import org.openqa.selenium.Keys;
 import org.openqa.selenium.interactions.Actions;
+import org.openqa.selenium.WebElement;
 
 import com.vaadin.testbench.elements.ButtonElement;
 import com.vaadin.testbench.elements.DateFieldElement;
@@ -46,6 +48,7 @@ public class DateFieldFaultyInputNotValidTest extends SingleBrowserTest {
     public void testDateOutOfRange() {
         openTestURL();
         DateFieldElement dateField = $(DateFieldElement.class).first();
+        WebElement dateFieldText = dateField.findElement(By.tagName("input"));
         dateField.setDate(LocalDate.now());
 
         $(ButtonElement.class).first().click();
@@ -53,7 +56,7 @@ public class DateFieldFaultyInputNotValidTest extends SingleBrowserTest {
                 $(NotificationElement.class).first().getText());
         $(NotificationElement.class).first().close();
 
-        dateField.setDate(LocalDate.now().minusDays(7));
+        dateFieldText.sendKeys(LocalDate.now().minusDays(7).toString(), Keys.ENTER);
 
         $(ButtonElement.class).first().click();
         assertEquals("Last week should not be ok", "Fail",