]> source.dussan.org Git - vaadin-framework.git/commitdiff
Show validation error selecting invalid date from DateField (#10013)
authorMarco Collovati <mcollovati@gmail.com>
Wed, 20 Sep 2017 05:32:04 +0000 (07:32 +0200)
committerHenri Sara <henri.sara@gmail.com>
Tue, 26 Sep 2017 15:24:43 +0000 (18:24 +0300)
Component error was cleared after selecting a date from
calendar popup, even if the date is invalid due to
validation errors or if user programmatically sets an UserError.

This change inverts the order of setValue() and setComponentError(null) in order
to preserve errors set by ValueChangeListeners (e.g. Binder validators).

Fixes #10011

server/src/main/java/com/vaadin/ui/AbstractDateField.java
uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldValidationError.java [new file with mode: 0644]
uitest/src/test/java/com/vaadin/tests/components/datefield/DateFieldValidationErrorTest.java [new file with mode: 0644]

index 2ad976a7fe1565845ce769c57506a8a7d3ddb480..bc6b5f49a8b1e15967faee9d87bfa9ab3fe365fd 100644 (file)
@@ -249,8 +249,8 @@ public abstract class AbstractDateField<T extends Temporal & TemporalAdjuster &
                 if (newDateString == null || newDateString.isEmpty()) {
                     uiHasValidDateString = true;
                     currentParseErrorMessage = null;
-                    setValue(newDate, true);
                     setComponentError(null);
+                    setValue(newDate, true);
                 } else {
                     if (variables.get("lastInvalidDateString") != null) {
                         Result<T> parsedDate = handleUnparsableDateString(
diff --git a/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldValidationError.java b/uitest/src/main/java/com/vaadin/tests/components/datefield/DateFieldValidationError.java
new file mode 100644 (file)
index 0000000..0bc9e14
--- /dev/null
@@ -0,0 +1,31 @@
+package com.vaadin.tests.components.datefield;
+
+import java.time.LocalDate;
+import java.util.Locale;
+
+import com.vaadin.annotations.Widgetset;
+import com.vaadin.data.Binder;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.components.AbstractTestUI;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.DateField;
+import com.vaadin.ui.Notification;
+
+@Widgetset("com.vaadin.DefaultWidgetSet")
+public class DateFieldValidationError extends AbstractTestUI {
+
+    @Override
+    protected void setup(VaadinRequest request) {
+        DateField df = new DateField();
+        df.setLocale(Locale.US);
+        Binder<Void> binder = new Binder<>();
+        binder.forField(df)
+            .withValidator(localDate -> localDate != null && localDate.isAfter(LocalDate.now()), "Invalid date")
+            .bind(v -> LocalDate.now(), (v, t) -> {
+            /* NO-OP */
+            });
+        addComponent(df);
+        addComponent(new Button("Validate", e -> Notification.show(binder.validate().isOk() ? "OK" : "Fail")));
+    }
+
+}
diff --git a/uitest/src/test/java/com/vaadin/tests/components/datefield/DateFieldValidationErrorTest.java b/uitest/src/test/java/com/vaadin/tests/components/datefield/DateFieldValidationErrorTest.java
new file mode 100644 (file)
index 0000000..6bfa1d2
--- /dev/null
@@ -0,0 +1,57 @@
+package com.vaadin.tests.components.datefield;
+
+import java.time.LocalDate;
+
+import com.vaadin.testbench.elements.DateFieldElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.ui.ExpectedConditions;
+
+public class DateFieldValidationErrorTest extends MultiBrowserTest {
+
+    @Test
+    public void testComponentErrorShouldBeShownWhenEnteringInvalidDate() throws InterruptedException {
+        openTestURL();
+        DateFieldElement dateField = $(DateFieldElement.class).first();
+        dateField.getInputElement().click();
+        dateField.getInputElement().sendKeys("01/01/01", Keys.TAB);
+
+        assertHasErrorMessage(dateField);
+    }
+
+    @Test
+    public void testComponentErrorShouldBeShownWhenSelectingInvalidDate() throws InterruptedException {
+        openTestURL();
+        DateFieldElement dateField = $(DateFieldElement.class).first();
+        dateField.setDate(LocalDate.now());
+        dateField.openPopup();
+        waitUntil(ExpectedConditions.visibilityOfElementLocated(By.className("v-datefield-popup")));
+
+        WebElement popup = findElement(com.vaadin.testbench.By.className("v-datefield-popup"));
+        // select day before today
+        WebElement popupBody = popup.findElement(By.className("v-datefield-calendarpanel"));
+        popupBody.sendKeys(Keys.ARROW_LEFT, Keys.ENTER);
+
+        // move focus away otherwise tooltip is not shown
+        WebElement inputElement = dateField.getInputElement();
+        inputElement.click();
+        inputElement.sendKeys(Keys.TAB);
+
+        assertHasErrorMessage(dateField);
+    }
+
+    private void assertHasErrorMessage(DateFieldElement dateField) {
+        waitForElementPresent(By.className("v-errorindicator"));
+        dateField.showTooltip();
+        waitUntil(driver -> "Invalid date".equals(getTooltipErrorElement().getText()));
+    }
+
+    @Override
+    protected boolean requireWindowFocusForIE() {
+        return true;
+    }
+
+}