aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenis Anisimov <denis@vaadin.com>2016-08-16 16:09:35 +0300
committerVaadin Code Review <review@vaadin.com>2016-08-17 07:48:06 +0000
commitc91703aff22b3ef8adaf86afb82c50a344f1ab76 (patch)
tree672a3b62f755c23e70bb8e9e632339a9df8b3b24
parenta5575a9252f4e502624079c65c7080e741846692 (diff)
downloadvaadin-framework-c91703aff22b3ef8adaf86afb82c50a344f1ab76.tar.gz
vaadin-framework-c91703aff22b3ef8adaf86afb82c50a344f1ab76.zip
Test that cross field validation works as expected (#33).
Test for cross field validation from Book of Vaadin. Change-Id: Ida338bd79456332b3a359217ea7b9900a1408153
-rw-r--r--documentation/datamodel/datamodel-forms.asciidoc12
-rw-r--r--server/src/main/java/com/vaadin/data/Binder.java14
-rw-r--r--server/src/test/java/com/vaadin/data/BinderBookOfVaadinTest.java70
3 files changed, 88 insertions, 8 deletions
diff --git a/documentation/datamodel/datamodel-forms.asciidoc b/documentation/datamodel/datamodel-forms.asciidoc
index 3bea6f857c..8acbffdd7a 100644
--- a/documentation/datamodel/datamodel-forms.asciidoc
+++ b/documentation/datamodel/datamodel-forms.asciidoc
@@ -205,15 +205,13 @@ PopupDateField departing = new PopupDateField("Departing");
PopupDateField returning = new PopupDateField("Returning");
// Store return date binding so we can revalidate it later
-FieldBinding<Trip, LocalDate> returnBinding = binder
- .forField(returning)
- .withValidator(
- returnDate -> !returnDate.isBefore(departing.getValue()),
- "Cannot return before departing")
- .bind(Trip::getReturnDate, Trip::setReturnDate);
+Binding<Trip, Date, Date> returnBinding = binder.forField(returning)
+ .withValidator(returnDate -> !returnDate.before(departing.getValue()),
+ "Cannot return before departing");
+returnBinding.bind(Trip::getReturnDate, Trip::setReturnDate);
// Revalidate return date when departure date changes
-departing.onChange(newValue -> returnBinding.validate());
+departing.addValueChangeListener(event -> returnBinding.validate());
----
== Converting User Input
diff --git a/server/src/main/java/com/vaadin/data/Binder.java b/server/src/main/java/com/vaadin/data/Binder.java
index 8c637118d6..5ce80d2c0b 100644
--- a/server/src/main/java/com/vaadin/data/Binder.java
+++ b/server/src/main/java/com/vaadin/data/Binder.java
@@ -262,6 +262,17 @@ public class Binder<BEAN> implements Serializable {
*/
public HasValue<FIELDVALUE> getField();
+ /**
+ * Validates the field value and returns a {@code Result} instance
+ * representing the outcome of the validation.
+ *
+ * @see Binder#validate()
+ * @see Validator#apply(Object)
+ *
+ * @return the validation result.
+ */
+ public Result<TARGET> validate();
+
}
/**
@@ -372,7 +383,8 @@ public class Binder<BEAN> implements Serializable {
.addValueChangeListener(e -> storeFieldValue(bean));
}
- private Result<TARGET> validate() {
+ @Override
+ public Result<TARGET> validate() {
FIELDVALUE fieldValue = field.getValue();
Result<TARGET> dataValue = converterValidatorChain.convertToModel(
fieldValue, ((AbstractComponent) field).getLocale());
diff --git a/server/src/test/java/com/vaadin/data/BinderBookOfVaadinTest.java b/server/src/test/java/com/vaadin/data/BinderBookOfVaadinTest.java
index 74cec124a6..6fcfe61ce3 100644
--- a/server/src/test/java/com/vaadin/data/BinderBookOfVaadinTest.java
+++ b/server/src/test/java/com/vaadin/data/BinderBookOfVaadinTest.java
@@ -15,6 +15,8 @@
*/
package com.vaadin.data;
+import java.util.Calendar;
+import java.util.Date;
import java.util.List;
import org.junit.Assert;
@@ -26,6 +28,7 @@ import com.vaadin.data.util.converter.StringToIntegerConverter;
import com.vaadin.data.validator.EmailValidator;
import com.vaadin.server.AbstractErrorMessage;
import com.vaadin.ui.AbstractField;
+import com.vaadin.ui.PopupDateField;
import com.vaadin.ui.Slider;
/**
@@ -95,6 +98,18 @@ public class BinderBookOfVaadinTest {
}
+ public static class Trip {
+ private Date returnDate;
+
+ public Date getReturnDate() {
+ return returnDate;
+ }
+
+ public void setReturnDate(Date returnDate) {
+ this.returnDate = returnDate;
+ }
+ }
+
private Binder<BookPerson> binder;
private TextField field;
@@ -238,4 +253,59 @@ public class BinderBookOfVaadinTest {
yearOfBirthField.getComponentError().getFormattedHtmlMessage());
}
+ @Test
+ public void crossFieldValidation() {
+ Binder<Trip> binder = new Binder<>();
+ PopupDateField departing = new PopupDateField("Departing");
+ PopupDateField returning = new PopupDateField("Returning");
+
+ Binding<Trip, Date, Date> returnBinding = binder.forField(returning)
+ .withValidator(
+ returnDate -> !returnDate.before(departing.getValue()),
+ "Cannot return before departing");
+
+ returnBinding.bind(Trip::getReturnDate, Trip::setReturnDate);
+ departing.addValueChangeListener(event -> returnBinding.validate());
+
+ Calendar calendar = Calendar.getInstance();
+ Date past = calendar.getTime();
+ calendar.add(1, Calendar.DAY_OF_YEAR);
+ Date before = calendar.getTime();
+ calendar.add(1, Calendar.DAY_OF_YEAR);
+ Date after = calendar.getTime();
+
+ departing.setValue(before);
+ returning.setValue(after);
+
+ List<ValidationError<?>> errors = binder.validate();
+ Assert.assertTrue(errors.isEmpty());
+ Assert.assertNull(departing.getComponentError());
+ Assert.assertNull(returning.getComponentError());
+
+ // update returning => validation is done against this field
+ returning.setValue(past);
+ errors = binder.validate();
+
+ Assert.assertFalse(errors.isEmpty());
+ Assert.assertNotNull(returning.getComponentError());
+ Assert.assertNull(departing.getComponentError());
+
+ // set correct value back
+ returning.setValue(before);
+ errors = binder.validate();
+
+ Assert.assertTrue(errors.isEmpty());
+ Assert.assertNull(departing.getComponentError());
+ Assert.assertNull(returning.getComponentError());
+
+ // update departing => validation is done because of listener added
+ departing.setValue(after);
+ errors = binder.validate();
+
+ Assert.assertFalse(errors.isEmpty());
+ Assert.assertNotNull(returning.getComponentError());
+ Assert.assertNull(departing.getComponentError());
+
+ }
+
}