diff options
author | Pekka Hyvönen <pekka@vaadin.com> | 2016-09-12 12:05:19 +0300 |
---|---|---|
committer | Vaadin Code Review <review@vaadin.com> | 2016-09-12 13:07:22 +0000 |
commit | 28f5c845793be9a0db3f2acef914a68ccc91ce80 (patch) | |
tree | 42ba7c5cffc7de3a2412ffbd3cc6fa3605ddb606 /server/src/test | |
parent | 363dce92ae948aa7912007bb024c980de820851f (diff) | |
download | vaadin-framework-28f5c845793be9a0db3f2acef914a68ccc91ce80.tar.gz vaadin-framework-28f5c845793be9a0db3f2acef914a68ccc91ce80.zip |
Refactor Binder Status Handling API
BinderStatusHandler is now triggered only once per validation.
Unified ValidationError and BinderResult into BinderValidationStatus.
Renamed ValidationStatusChangeEvent into ValidationStatus.
Unified handler names for validation status.
Next patch will fix resetting of field errors on reset.
Change-Id: I9536d554d781fe599fbd7e5bcb5a9ffebe675ca0
Diffstat (limited to 'server/src/test')
3 files changed, 327 insertions, 180 deletions
diff --git a/server/src/test/java/com/vaadin/data/BeanBinderTest.java b/server/src/test/java/com/vaadin/data/BeanBinderTest.java index 1788c3a9e8..84a414edf1 100644 --- a/server/src/test/java/com/vaadin/data/BeanBinderTest.java +++ b/server/src/test/java/com/vaadin/data/BeanBinderTest.java @@ -163,9 +163,10 @@ public class BeanBinderTest { } private void assertInvalid(HasValue<?> field, String message) { - List<ValidationError<?>> errors = binder.validate(); + BinderValidationStatus<?> status = binder.validate(); + List<ValidationStatus<?>> errors = status.getFieldValidationErrors(); assertEquals(1, errors.size()); - assertSame(field, errors.get(0).getField().get()); - assertEquals(message, errors.get(0).getMessage()); + assertSame(field, errors.get(0).getField()); + assertEquals(message, errors.get(0).getMessage().get()); } } diff --git a/server/src/test/java/com/vaadin/data/BinderBookOfVaadinTest.java b/server/src/test/java/com/vaadin/data/BinderBookOfVaadinTest.java index 6861903132..d11a0ed6da 100644 --- a/server/src/test/java/com/vaadin/data/BinderBookOfVaadinTest.java +++ b/server/src/test/java/com/vaadin/data/BinderBookOfVaadinTest.java @@ -27,12 +27,14 @@ import org.junit.Before; import org.junit.Test; import com.vaadin.data.Binder.Binding; +import com.vaadin.data.ValidationStatus.Status; import com.vaadin.data.util.converter.Converter; import com.vaadin.data.util.converter.StringToIntegerConverter; import com.vaadin.data.validator.EmailValidator; import com.vaadin.server.AbstractErrorMessage; import com.vaadin.ui.Button; import com.vaadin.ui.Label; +import com.vaadin.ui.Notification; import com.vaadin.ui.PopupDateField; import com.vaadin.ui.Slider; import com.vaadin.ui.TextField; @@ -140,6 +142,30 @@ public class BinderBookOfVaadinTest { } @Test + public void loadingFromBusinessObjects() { + // this test is just to make sure the code snippet in the book compiles + binder.load(new BookPerson(1969, 50000)); + + BinderValidationStatus<BookPerson> status = binder.validate(); + + if (status.hasErrors()) { + Notification.show("Validation error count: " + + status.getValidationErrors().size()); + } + } + + @Test + public void handlingCheckedException() { + // another test just to verify that book examples actually compile + try { + binder.save(new BookPerson(2000, 50000)); + } catch (ValidationException e) { + Notification.show("Validation error count: " + + e.getValidationErrors().size()); + } + } + + @Test public void simpleEmailValidator() { binder.forField(field) // Explicit validator instance @@ -148,16 +174,16 @@ public class BinderBookOfVaadinTest { .bind(BookPerson::getEmail, BookPerson::setEmail); field.setValue("not-email"); - List<ValidationError<?>> errors = binder.validate(); - Assert.assertEquals(1, errors.size()); + BinderValidationStatus<?> status = binder.validate(); + Assert.assertEquals(1, status.getFieldValidationErrors().size()); Assert.assertEquals("This doesn't look like a valid email address", - errors.get(0).getMessage()); + status.getFieldValidationErrors().get(0).getMessage().get()); Assert.assertEquals("This doesn't look like a valid email address", ((AbstractErrorMessage) field.getErrorMessage()).getMessage()); field.setValue("abc@vaadin.com"); - errors = binder.validate(); - Assert.assertEquals(0, errors.size()); + status = binder.validate(); + Assert.assertEquals(0, status.getBeanValidationErrors().size()); Assert.assertNull(field.getErrorMessage()); } @@ -170,16 +196,16 @@ public class BinderBookOfVaadinTest { .bind(BookPerson::getLastName, BookPerson::setLastName); field.setValue("a"); - List<ValidationError<?>> errors = binder.validate(); - Assert.assertEquals(1, errors.size()); + BinderValidationStatus<?> status = binder.validate(); + Assert.assertEquals(1, status.getFieldValidationErrors().size()); Assert.assertEquals("Last name must contain at least three characters", - errors.get(0).getMessage()); + status.getFieldValidationErrors().get(0).getMessage().get()); Assert.assertEquals("Last name must contain at least three characters", ((AbstractErrorMessage) field.getErrorMessage()).getMessage()); field.setValue("long last name"); - errors = binder.validate(); - Assert.assertEquals(0, errors.size()); + status = binder.validate(); + Assert.assertEquals(0, status.getFieldValidationErrors().size()); Assert.assertNull(field.getErrorMessage()); } @@ -194,25 +220,25 @@ public class BinderBookOfVaadinTest { .bind(BookPerson::getEmail, BookPerson::setEmail); field.setValue("not-email"); - List<ValidationError<?>> errors = binder.validate(); + BinderValidationStatus<?> status = binder.validate(); // Only one error per field should be reported - Assert.assertEquals(1, errors.size()); + Assert.assertEquals(1, status.getFieldValidationErrors().size()); Assert.assertEquals("This doesn't look like a valid email address", - errors.get(0).getMessage()); + status.getFieldValidationErrors().get(0).getMessage().get()); Assert.assertEquals("This doesn't look like a valid email address", ((AbstractErrorMessage) field.getErrorMessage()).getMessage()); field.setValue("abc@vaadin.com"); - errors = binder.validate(); - Assert.assertEquals(1, errors.size()); + status = binder.validate(); + Assert.assertEquals(1, status.getFieldValidationErrors().size()); Assert.assertEquals("Only acme.com email addresses are allowed", - errors.get(0).getMessage()); + status.getFieldValidationErrors().get(0).getMessage().get()); Assert.assertEquals("Only acme.com email addresses are allowed", ((AbstractErrorMessage) field.getErrorMessage()).getMessage()); field.setValue("abc@acme.com"); - errors = binder.validate(); - Assert.assertEquals(0, errors.size()); + status = binder.validate(); + Assert.assertEquals(0, status.getFieldValidationErrors().size()); Assert.assertNull(field.getErrorMessage()); } @@ -296,32 +322,32 @@ public class BinderBookOfVaadinTest { departing.setValue(before); returning.setValue(after); - List<ValidationError<?>> errors = binder.validate(); - Assert.assertTrue(errors.isEmpty()); + BinderValidationStatus<Trip> status = binder.validate(); + Assert.assertTrue(status.getBeanValidationErrors().isEmpty()); Assert.assertNull(departing.getComponentError()); Assert.assertNull(returning.getComponentError()); // update returning => validation is done against this field returning.setValue(past); - errors = binder.validate(); + status = binder.validate(); - Assert.assertFalse(errors.isEmpty()); + Assert.assertFalse(status.getFieldValidationErrors().isEmpty()); Assert.assertNotNull(returning.getComponentError()); Assert.assertNull(departing.getComponentError()); // set correct value back returning.setValue(before); - errors = binder.validate(); + status = binder.validate(); - Assert.assertTrue(errors.isEmpty()); + Assert.assertTrue(status.getFieldValidationErrors().isEmpty()); Assert.assertNull(departing.getComponentError()); Assert.assertNull(returning.getComponentError()); // update departing => validation is done because of listener added departing.setValue(after); - errors = binder.validate(); + status = binder.validate(); - Assert.assertFalse(errors.isEmpty()); + Assert.assertFalse(status.getFieldValidationErrors().isEmpty()); Assert.assertNotNull(returning.getComponentError()); Assert.assertNull(departing.getComponentError()); @@ -351,7 +377,7 @@ public class BinderBookOfVaadinTest { departing.setValue(before); returning.setValue(after); - Result<Date> result = returnBinding.validate(); + ValidationStatus<Date> result = returnBinding.validate(); Assert.assertFalse(result.isError()); Assert.assertNull(departing.getComponentError()); @@ -402,17 +428,16 @@ public class BinderBookOfVaadinTest { @Test public void withBindingStatusChangeHandlerExample() { Label nameStatus = new Label(); - AtomicReference<ValidationStatusChangeEvent> event = new AtomicReference<>(); + AtomicReference<ValidationStatus<?>> statusCapture = new AtomicReference<>(); String msg = "Full name must contain at least three characters"; binder.forField(field).withValidator(name -> name.length() >= 3, msg) - .withStatusChangeHandler(statusChange -> { + .withStatusHandler(statusChange -> { nameStatus.setValue(statusChange.getMessage().orElse("")); // Only show the label when validation has failed - boolean error = statusChange - .getStatus() == ValidationStatus.ERROR; + boolean error = statusChange.getStatus() == Status.ERROR; nameStatus.setVisible(error); - event.set(statusChange); + statusCapture.set(statusChange); }).bind(BookPerson::getLastName, BookPerson::setLastName); field.setValue("aa"); @@ -420,22 +445,22 @@ public class BinderBookOfVaadinTest { Assert.assertTrue(nameStatus.isVisible()); Assert.assertEquals(msg, nameStatus.getValue()); - Assert.assertNotNull(event.get()); - ValidationStatusChangeEvent evt = event.get(); - Assert.assertEquals(ValidationStatus.ERROR, evt.getStatus()); - Assert.assertEquals(msg, evt.getMessage().get()); - Assert.assertEquals(field, evt.getSource()); + Assert.assertNotNull(statusCapture.get()); + ValidationStatus<?> status = statusCapture.get(); + Assert.assertEquals(Status.ERROR, status.getStatus()); + Assert.assertEquals(msg, status.getMessage().get()); + Assert.assertEquals(field, status.getField()); field.setValue("foo"); binder.validate(); Assert.assertFalse(nameStatus.isVisible()); Assert.assertEquals("", nameStatus.getValue()); - Assert.assertNotNull(event.get()); - evt = event.get(); - Assert.assertEquals(ValidationStatus.OK, evt.getStatus()); - Assert.assertFalse(evt.getMessage().isPresent()); - Assert.assertEquals(field, evt.getSource()); + Assert.assertNotNull(statusCapture.get()); + status = statusCapture.get(); + Assert.assertEquals(Status.OK, status.getStatus()); + Assert.assertFalse(status.getMessage().isPresent()); + Assert.assertEquals(field, status.getField()); } @Test @@ -495,17 +520,18 @@ public class BinderBookOfVaadinTest { .bind(BookPerson::getYearOfBirth, BookPerson::setYearOfBirth); yearOfBirthField.setValue("abc"); - Assert.assertEquals("Doesn't look like a year", - binder.validate().get(0).getMessage()); + Assert.assertEquals("Doesn't look like a year", binder.validate() + .getFieldValidationErrors().get(0).getMessage().get()); yearOfBirthField.setValue("abcd"); - Assert.assertEquals("Must enter a number", - binder.validate().get(0).getMessage()); + Assert.assertEquals("Must enter a number", binder.validate() + .getFieldValidationErrors().get(0).getMessage().get()); yearOfBirthField.setValue("1200"); Assert.assertEquals("Person must be born in the 20th century", - binder.validate().get(0).getMessage()); + binder.validate().getFieldValidationErrors().get(0).getMessage() + .get()); yearOfBirthField.setValue("1950"); - Assert.assertTrue(binder.validate().isEmpty()); + Assert.assertFalse(binder.validate().hasErrors()); BookPerson person = new BookPerson(1500, 12); binder.save(person); Assert.assertEquals(1950, person.getYearOfBirth()); @@ -546,15 +572,17 @@ public class BinderBookOfVaadinTest { binder.bind(p); yearOfBirthField.setValue("abc"); - Assert.assertEquals("Please enter a number", - binder.validate().get(0).getMessage()); + Assert.assertTrue(binder.validate().hasErrors()); + Assert.assertEquals("Please enter a number", binder.validate() + .getFieldValidationErrors().get(0).getMessage().get()); yearOfBirthField.setValue("123"); - Assert.assertTrue(binder.validate().isEmpty()); + Assert.assertTrue(binder.validate().isOk()); p.setYearOfBirth(12500); binder.load(p); Assert.assertEquals("12500", yearOfBirthField.getValue()); + Assert.assertTrue(binder.validate().isOk()); } @Test @@ -582,25 +610,30 @@ public class BinderBookOfVaadinTest { // first bean validator fails and passes error message to status label yearOfBirth.setValue("2001"); - List<ValidationError<?>> errors = binder.validate(); - Assert.assertEquals(1, errors.size()); - Assert.assertEquals(errors.get(0).getMessage(), message); + BinderValidationStatus<?> status = binder.validate(); + Assert.assertEquals(0, status.getFieldValidationErrors().size()); + Assert.assertEquals(1, status.getBeanValidationErrors().size()); + Assert.assertEquals( + status.getBeanValidationErrors().get(0).getMessage().get(), + message); Assert.assertEquals(message, formStatusLabel.getValue()); // value is correct, status label is cleared yearOfBirth.setValue("1999"); - errors = binder.validate(); - Assert.assertEquals(0, errors.size()); + status = binder.validate(); + Assert.assertFalse(status.hasErrors()); Assert.assertEquals("", formStatusLabel.getValue()); // both bean validators fail, should be two error messages chained yearOfBirth.setValue("2000"); - errors = binder.validate(); - Assert.assertEquals(2, errors.size()); + status = binder.validate(); + Assert.assertEquals(2, status.getBeanValidationResults().size()); + Assert.assertEquals(0, status.getFieldValidationErrors().size()); + Assert.assertEquals(2, status.getBeanValidationErrors().size()); // only first error is shown Assert.assertEquals(message, formStatusLabel.getValue()); @@ -612,21 +645,17 @@ public class BinderBookOfVaadinTest { BinderStatusHandler defaultHandler = binder.getStatusHandler(); - binder.setStatusHandler(results -> { - String errorMessage = results.stream() - // Ignore confirmation messages - .filter(BinderResult::isError) - // Ignore messages that belong to a specific field - .filter(error -> !error.getField().isPresent()) - // Create a string out of the remaining messages - .map(Result::getMessage).map(o -> o.get()) - .collect(Collectors.joining("\n")); - + binder.setStatusHandler(status -> { + // create an error message on failed bean level validations + List<Result<?>> errors = status.getBeanValidationErrors(); + String errorMessage = errors.stream().map(Result::getMessage) + .map(o -> o.get()).collect(Collectors.joining("\n")); + // show error in a label formStatusLabel.setValue(errorMessage); formStatusLabel.setVisible(!errorMessage.isEmpty()); // Let the default handler show messages for each field - defaultHandler.accept(results); + defaultHandler.accept(status); }); final String bindingMessage = "uneven"; @@ -648,34 +677,41 @@ public class BinderBookOfVaadinTest { // first binding validation fails, no bean level validation is done yearOfBirth.setValue("2001"); - List<ValidationError<?>> errors = binder.validate(); - Assert.assertEquals(1, errors.size()); - Assert.assertEquals(errors.get(0).getMessage(), bindingMessage); + BinderValidationStatus<?> status = binder.validate(); + Assert.assertEquals(1, status.getFieldValidationErrors().size()); + Assert.assertEquals(bindingMessage, + status.getFieldValidationErrors().get(0).getMessage().get()); Assert.assertEquals("", formStatusLabel.getValue()); // first bean validator fails and passes error message to status label yearOfBirth.setValue("2002"); - errors = binder.validate(); - Assert.assertEquals(1, errors.size()); - Assert.assertEquals(errors.get(0).getMessage(), message); + status = binder.validate(); + Assert.assertEquals(0, status.getFieldValidationErrors().size()); + Assert.assertEquals(1, status.getBeanValidationErrors().size()); + Assert.assertEquals(message, + status.getBeanValidationErrors().get(0).getMessage().get()); Assert.assertEquals(message, formStatusLabel.getValue()); // value is correct, status label is cleared yearOfBirth.setValue("1998"); - errors = binder.validate(); - Assert.assertEquals(0, errors.size()); + status = binder.validate(); + Assert.assertTrue(status.isOk()); + Assert.assertFalse(status.hasErrors()); + Assert.assertEquals(0, status.getFieldValidationErrors().size()); + Assert.assertEquals(0, status.getBeanValidationErrors().size()); Assert.assertEquals("", formStatusLabel.getValue()); // both bean validators fail, should be two error messages chained yearOfBirth.setValue("2000"); - errors = binder.validate(); - Assert.assertEquals(2, errors.size()); + status = binder.validate(); + Assert.assertEquals(0, status.getFieldValidationErrors().size()); + Assert.assertEquals(2, status.getBeanValidationErrors().size()); Assert.assertEquals(message + "\n" + message2, formStatusLabel.getValue()); diff --git a/server/src/test/java/com/vaadin/data/BinderTest.java b/server/src/test/java/com/vaadin/data/BinderTest.java index 4b69fdf50e..0a82b527bb 100644 --- a/server/src/test/java/com/vaadin/data/BinderTest.java +++ b/server/src/test/java/com/vaadin/data/BinderTest.java @@ -5,17 +5,15 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertSame; import java.util.List; -import java.util.Optional; -import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; -import java.util.stream.Collectors; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import com.vaadin.data.Binder.Binding; +import com.vaadin.data.ValidationStatus.Status; import com.vaadin.data.util.converter.Converter; import com.vaadin.data.validator.NotEmptyValidator; import com.vaadin.server.AbstractErrorMessage; @@ -27,6 +25,8 @@ import com.vaadin.ui.TextField; public class BinderTest { + private static final String EMPTY_ERROR_MESSAGE = "Value cannot be empty"; + private static class StatusBean { private String status; @@ -48,7 +48,7 @@ public class BinderTest { Person p = new Person(); Validator<String> notEmpty = Validator.from(val -> !val.isEmpty(), - "Value cannot be empty"); + EMPTY_ERROR_MESSAGE); Converter<String, Integer> stringToInteger = Converter.from( Integer::valueOf, String::valueOf, e -> "Value must be a number"); Validator<Integer> notNegative = Validator.from(x -> x >= 0, @@ -327,18 +327,17 @@ public class BinderTest { binder.save(person); Assert.fail(); } catch (ValidationException exception) { - List<ValidationError<?>> validationErrors = exception - .getValidationError(); + List<ValidationStatus<?>> validationErrors = exception + .getFieldValidationErrors(); Assert.assertEquals(2, validationErrors.size()); - ValidationError<?> error = validationErrors.get(0); - Assert.assertEquals(nameField, error.getField().get()); - Assert.assertEquals(msg, error.getMessage()); - Assert.assertEquals("", error.getValue()); + ValidationStatus<?> error = validationErrors.get(0); + Assert.assertEquals(nameField, error.getField()); + Assert.assertEquals(msg, error.getMessage().get()); error = validationErrors.get(1); - Assert.assertEquals(ageField, error.getField().get()); - Assert.assertEquals("Value must be positive", error.getMessage()); - Assert.assertEquals(ageField.getValue(), error.getValue()); + Assert.assertEquals(ageField, error.getField()); + Assert.assertEquals("Value must be positive", + error.getMessage().get()); } } @@ -375,9 +374,9 @@ public class BinderTest { public void validate_notBound_noErrors() { Binder<Person> binder = new Binder<>(); - List<ValidationError<?>> errors = binder.validate(); + BinderValidationStatus<Person> status = binder.validate(); - Assert.assertTrue(errors.isEmpty()); + Assert.assertTrue(status.isOk()); } @Test @@ -388,9 +387,9 @@ public class BinderTest { Person::setFirstName); nameField.setComponentError(new UserError("")); - List<ValidationError<?>> errors = binder.validate(); + BinderValidationStatus<Person> status = binder.validate(); - Assert.assertTrue(errors.isEmpty()); + Assert.assertTrue(status.isOk()); Assert.assertNull(nameField.getComponentError()); } @@ -411,19 +410,19 @@ public class BinderTest { binding.withValidator(value -> false, msg2); binding.bind(Person::getFirstName, Person::setFirstName); - List<ValidationError<?>> errors = binder.validate(); + BinderValidationStatus<Person> status = binder.validate(); + List<ValidationStatus<?>> errors = status.getFieldValidationErrors(); Assert.assertEquals(1, errors.size()); - Set<String> errorMessages = errors.stream() - .map(ValidationError::getMessage).collect(Collectors.toSet()); - Assert.assertTrue(errorMessages.contains(msg1)); + ValidationStatus<?> validationStatus = errors.stream().findFirst() + .get(); + String msg = validationStatus.getMessage().get(); + Assert.assertEquals(msg1, msg); + + HasValue<?> field = validationStatus.getField(); - Set<?> fields = errors.stream().map(ValidationError::getField) - .filter(Optional::isPresent).map(Optional::get) - .collect(Collectors.toSet()); - Assert.assertEquals(1, fields.size()); - Assert.assertTrue(fields.contains(nameField)); + Assert.assertEquals(nameField, field); ErrorMessage componentError = nameField.getComponentError(); Assert.assertNotNull(componentError); @@ -490,19 +489,25 @@ public class BinderTest { ageField.setValue(""); assertEquals(32, p.getAge()); - assertValidationErrors(binder.validate(), "Value cannot be empty"); + assertValidationErrors(binder.validate(), EMPTY_ERROR_MESSAGE); } private void assertValidationErrors( - List<ValidationError<?>> validationErrors, + List<ValidationStatus<?>> validationErrors, String... errorMessages) { Assert.assertEquals(errorMessages.length, validationErrors.size()); for (int i = 0; i < errorMessages.length; i++) { Assert.assertEquals(errorMessages[i], - validationErrors.get(i).getMessage()); + validationErrors.get(i).getMessage().get()); } } + private void assertValidationErrors(BinderValidationStatus<Person> status, + String... errorMessages) { + assertValidationErrors(status.getFieldValidationErrors(), + errorMessages); + } + @Test public void convertToModelConversionFails() { bindAgeWithValidatorConverterValidator(); @@ -571,11 +576,11 @@ public class BinderTest { @Test public void bindingWithStatusChangeHandler_handlerGetsEvents() { - AtomicReference<ValidationStatusChangeEvent> event = new AtomicReference<>(); + AtomicReference<ValidationStatus<?>> statusCapture = new AtomicReference<>(); Binding<Person, String, String> binding = binder.forField(nameField) - .withValidator(notEmpty).withStatusChangeHandler(evt -> { - Assert.assertNull(event.get()); - event.set(evt); + .withValidator(notEmpty).withStatusHandler(evt -> { + Assert.assertNull(statusCapture.get()); + statusCapture.set(evt); }); binding.bind(Person::getFirstName, Person::setFirstName); @@ -585,30 +590,30 @@ public class BinderTest { // message binder.validate(); - Assert.assertNotNull(event.get()); - ValidationStatusChangeEvent evt = event.get(); - Assert.assertEquals(ValidationStatus.ERROR, evt.getStatus()); - Assert.assertEquals("Value cannot be empty", evt.getMessage().get()); - Assert.assertEquals(nameField, evt.getSource()); + Assert.assertNotNull(statusCapture.get()); + ValidationStatus<?> evt = statusCapture.get(); + Assert.assertEquals(Status.ERROR, evt.getStatus()); + Assert.assertEquals(EMPTY_ERROR_MESSAGE, evt.getMessage().get()); + Assert.assertEquals(nameField, evt.getField()); nameField.setValue("foo"); - event.set(null); + statusCapture.set(null); // Second validation succeeds => should be event with OK status and // no message binder.validate(); - evt = event.get(); + evt = statusCapture.get(); Assert.assertNotNull(evt); - Assert.assertEquals(ValidationStatus.OK, evt.getStatus()); + Assert.assertEquals(Status.OK, evt.getStatus()); Assert.assertFalse(evt.getMessage().isPresent()); - Assert.assertEquals(nameField, evt.getSource()); + Assert.assertEquals(nameField, evt.getField()); } @Test public void bindingWithStatusChangeHandler_defaultStatusChangeHandlerIsReplaced() { Binding<Person, String, String> binding = binder.forField(nameField) - .withValidator(notEmpty).withStatusChangeHandler(evt -> { + .withValidator(notEmpty).withStatusHandler(evt -> { }); binding.bind(Person::getFirstName, Person::setFirstName); @@ -639,7 +644,7 @@ public class BinderTest { binding.validate(); Assert.assertTrue(label.isVisible()); - Assert.assertEquals("Value cannot be empty", label.getValue()); + Assert.assertEquals(EMPTY_ERROR_MESSAGE, label.getValue()); nameField.setValue("foo"); @@ -677,7 +682,7 @@ public class BinderTest { .withValidator(notEmpty); binding.bind(Person::getFirstName, Person::setFirstName); - binding.withStatusChangeHandler(evt -> Assert.fail()); + binding.withStatusHandler(evt -> Assert.fail()); } @Test(expected = IllegalStateException.class) @@ -697,7 +702,7 @@ public class BinderTest { Binding<Person, String, String> binding = binder.forField(nameField); - binding.withStatusChangeHandler(event -> { + binding.withStatusHandler(event -> { }); binding.withStatusLabel(label); @@ -711,7 +716,7 @@ public class BinderTest { binding.withStatusLabel(label); - binding.withStatusChangeHandler(event -> { + binding.withStatusHandler(event -> { }); } @@ -720,10 +725,10 @@ public class BinderTest { Binding<Person, String, String> binding = binder.forField(nameField); - binding.withStatusChangeHandler(event -> { + binding.withStatusHandler(event -> { }); - binding.withStatusChangeHandler(event -> { + binding.withStatusHandler(event -> { }); } @@ -738,9 +743,9 @@ public class BinderTest { Person person = new Person(); binder.bind(person); - List<ValidationError<?>> errors = binder.validate(); - Assert.assertEquals(1, errors.size()); - Assert.assertFalse(errors.get(0).getField().isPresent()); + List<ValidationStatus<?>> errors = binder.validate() + .getFieldValidationErrors(); + Assert.assertEquals(0, errors.size()); } @Test @@ -756,12 +761,12 @@ public class BinderTest { Person person = new Person(); binder.bind(person); - List<ValidationError<?>> errors = binder.validate(); + List<ValidationStatus<?>> errors = binder.validate() + .getFieldValidationErrors(); Assert.assertEquals(1, errors.size()); - ValidationError<?> error = errors.get(0); - Assert.assertEquals(msg, error.getMessage()); - Assert.assertTrue(error.getField().isPresent()); - Assert.assertEquals(nameField.getValue(), error.getValue()); + ValidationStatus<?> error = errors.get(0); + Assert.assertEquals(msg, error.getMessage().get()); + Assert.assertEquals(nameField, error.getField()); } @Test @@ -778,14 +783,14 @@ public class BinderTest { Person person = new Person(); binder.bind(person); - List<ValidationError<?>> errors = binder.validate(); + List<ValidationStatus<?>> errors = binder.validate() + .getFieldValidationErrors(); Assert.assertEquals(1, errors.size()); - ValidationError<?> error = errors.get(0); + ValidationStatus<?> error = errors.get(0); - Assert.assertEquals(msg1, error.getMessage()); - Assert.assertEquals(nameField, error.getField().get()); - Assert.assertEquals(nameField.getValue(), error.getValue()); + Assert.assertEquals(msg1, error.getMessage().get()); + Assert.assertEquals(nameField, error.getField()); } @Test @@ -799,8 +804,8 @@ public class BinderTest { Person person = new Person(); binder.bind(person); - List<ValidationError<?>> errors = binder.validate(); - Assert.assertEquals(0, errors.size()); + Assert.assertFalse(binder.validate().hasErrors()); + Assert.assertTrue(binder.validate().isOk()); } @Test @@ -863,15 +868,105 @@ public class BinderTest { } @Test - public void binderWithStatusChangeHandler_handlerGetsEvents() { - AtomicReference<List<BinderResult<?, ?>>> resultsCapture = new AtomicReference<>(); + public void binderWithStatusHandler_fieldValidationNoBeanValidation_handlerGetsStatusUpdates() { + AtomicReference<BinderValidationStatus<?>> statusCapture = new AtomicReference<>(); binder.forField(nameField).withValidator(notEmpty) - .withStatusChangeHandler(evt -> { + .withStatusHandler(evt -> { Assert.fail( "Using a custom status change handler so no change should end up here"); }).bind(Person::getFirstName, Person::setFirstName); binder.forField(ageField).withConverter(stringToInteger) - .withValidator(notNegative).withStatusChangeHandler(evt -> { + .withValidator(notNegative).withStatusHandler(evt -> { + Assert.fail( + "Using a custom status change handler so no change should end up here"); + }).bind(Person::getAge, Person::setAge); + + binder.setStatusHandler(r -> { + statusCapture.set(r); + }); + binder.bind(p); + Assert.assertNull(nameField.getComponentError()); + + nameField.setValue(""); + ageField.setValue("5"); + + // First binding validation fails => should be result with ERROR status + // and message + BinderValidationStatus<Person> status2 = binder.validate(); + BinderValidationStatus<?> status = statusCapture.get(); + Assert.assertSame(status2, status); + + Assert.assertNull(nameField.getComponentError()); + + List<ValidationStatus<?>> bindingStatuses = status + .getFieldValidationStatuses(); + Assert.assertNotNull(bindingStatuses); + Assert.assertEquals(1, status.getFieldValidationErrors().size()); + Assert.assertEquals(2, bindingStatuses.size()); + + ValidationStatus<?> r = bindingStatuses.get(0); + Assert.assertTrue(r.isError()); + Assert.assertEquals(EMPTY_ERROR_MESSAGE, r.getMessage().get()); + Assert.assertEquals(nameField, r.getField()); + + r = bindingStatuses.get(1); + Assert.assertFalse(r.isError()); + Assert.assertFalse(r.getMessage().isPresent()); + Assert.assertEquals(ageField, r.getField()); + + Assert.assertEquals(0, status.getBeanValidationResults().size()); + Assert.assertEquals(0, status.getBeanValidationErrors().size()); + + nameField.setValue("foo"); + ageField.setValue(""); + + statusCapture.set(null); + // Second validation succeeds => should be result with OK status and + // no message, and error result for age + binder.validate(); + + status = statusCapture.get(); + bindingStatuses = status.getFieldValidationStatuses(); + Assert.assertEquals(1, status.getFieldValidationErrors().size()); + Assert.assertEquals(2, bindingStatuses.size()); + + r = bindingStatuses.get(0); + Assert.assertFalse(r.isError()); + Assert.assertFalse(r.getMessage().isPresent()); + Assert.assertEquals(nameField, r.getField()); + + r = bindingStatuses.get(1); + Assert.assertTrue(r.isError()); + Assert.assertEquals("Value must be a number", r.getMessage().get()); + Assert.assertEquals(ageField, r.getField()); + + Assert.assertEquals(0, status.getBeanValidationResults().size()); + Assert.assertEquals(0, status.getBeanValidationErrors().size()); + + statusCapture.set(null); + // binding validations pass, binder validation fails + ageField.setValue("0"); + binder.validate(); + + status = statusCapture.get(); + bindingStatuses = status.getFieldValidationStatuses(); + Assert.assertEquals(0, status.getFieldValidationErrors().size()); + Assert.assertEquals(2, bindingStatuses.size()); + + Assert.assertEquals(0, status.getBeanValidationResults().size()); + Assert.assertEquals(0, status.getBeanValidationErrors().size()); + } + + @Test + public void binderWithStatusHandler_fieldAndBeanLevelValidation_handlerGetsStatusUpdates() { + AtomicReference<BinderValidationStatus<?>> statusCapture = new AtomicReference<>(); + binder.forField(nameField).withValidator(notEmpty) + .withStatusHandler(evt -> { + Assert.fail( + "Using a custom status change handler so no change should end up here"); + }).bind(Person::getFirstName, Person::setFirstName); + binder.forField(ageField).withConverter(stringToInteger) + .withValidator(notNegative).withStatusHandler(evt -> { Assert.fail( "Using a custom status change handler so no change should end up here"); }).bind(Person::getAge, Person::setAge); @@ -881,7 +976,7 @@ public class BinderTest { : Result.error("Need first name and age")); binder.setStatusHandler(r -> { - resultsCapture.set(r); + statusCapture.set(r); }); binder.bind(p); Assert.assertNull(nameField.getComponentError()); @@ -891,65 +986,78 @@ public class BinderTest { // First binding validation fails => should be result with ERROR status // and message - binder.validate(); + BinderValidationStatus<Person> status2 = binder.validate(); + BinderValidationStatus<?> status = statusCapture.get(); + Assert.assertSame(status2, status); Assert.assertNull(nameField.getComponentError()); - List<BinderResult<?, ?>> results = resultsCapture.get(); - Assert.assertNotNull(results); - Assert.assertEquals(2, results.size()); + List<ValidationStatus<?>> bindingStatuses = status + .getFieldValidationStatuses(); + Assert.assertNotNull(bindingStatuses); + Assert.assertEquals(1, status.getFieldValidationErrors().size()); + Assert.assertEquals(2, bindingStatuses.size()); - BinderResult<?, ?> r = results.get(0); + ValidationStatus<?> r = bindingStatuses.get(0); Assert.assertTrue(r.isError()); - Assert.assertEquals("Value cannot be empty", r.getMessage().get()); - Assert.assertEquals(nameField, r.getField().get()); + Assert.assertEquals(EMPTY_ERROR_MESSAGE, r.getMessage().get()); + Assert.assertEquals(nameField, r.getField()); - r = results.get(1); + r = bindingStatuses.get(1); Assert.assertFalse(r.isError()); Assert.assertFalse(r.getMessage().isPresent()); - Assert.assertEquals(ageField, r.getField().get()); + Assert.assertEquals(ageField, r.getField()); + + Assert.assertEquals(0, status.getBeanValidationResults().size()); + Assert.assertEquals(0, status.getBeanValidationErrors().size()); nameField.setValue("foo"); ageField.setValue(""); - resultsCapture.set(null); + statusCapture.set(null); // Second validation succeeds => should be result with OK status and // no message, and error result for age binder.validate(); - results = resultsCapture.get(); - Assert.assertNotNull(results); - Assert.assertEquals(2, results.size()); + status = statusCapture.get(); + bindingStatuses = status.getFieldValidationStatuses(); + Assert.assertEquals(1, status.getFieldValidationErrors().size()); + Assert.assertEquals(2, bindingStatuses.size()); - r = results.get(0); + r = bindingStatuses.get(0); Assert.assertFalse(r.isError()); Assert.assertFalse(r.getMessage().isPresent()); - Assert.assertEquals(nameField, r.getField().get()); + Assert.assertEquals(nameField, r.getField()); - r = results.get(1); + r = bindingStatuses.get(1); Assert.assertTrue(r.isError()); Assert.assertEquals("Value must be a number", r.getMessage().get()); - Assert.assertEquals(ageField, r.getField().get()); + Assert.assertEquals(ageField, r.getField()); + + Assert.assertEquals(0, status.getBeanValidationResults().size()); + Assert.assertEquals(0, status.getBeanValidationErrors().size()); - resultsCapture.set(null); + statusCapture.set(null); // binding validations pass, binder validation fails ageField.setValue("0"); binder.validate(); - results = resultsCapture.get(); - Assert.assertNotNull(results); - Assert.assertEquals(1, results.size()); + status = statusCapture.get(); + bindingStatuses = status.getFieldValidationStatuses(); + Assert.assertEquals(0, status.getFieldValidationErrors().size()); + Assert.assertEquals(2, bindingStatuses.size()); - r = results.get(0); - Assert.assertTrue(r.isError()); - Assert.assertTrue(r.getMessage().isPresent()); - Assert.assertFalse(r.getField().isPresent()); + Assert.assertEquals(1, status.getBeanValidationResults().size()); + Assert.assertEquals(1, status.getBeanValidationErrors().size()); + + Assert.assertEquals("Need first name and age", + status.getBeanValidationErrors().get(0).getMessage().get()); } @Test public void binderWithStatusChangeHandler_defaultStatusChangeHandlerIsReplaced() { Binding<Person, String, String> binding = binder.forField(nameField) - .withValidator(notEmpty).withStatusChangeHandler(evt -> { + .withValidator(notEmpty).withStatusHandler(evt -> { }); binding.bind(Person::getFirstName, Person::setFirstName); @@ -991,7 +1099,7 @@ public class BinderTest { .withValidator(notEmpty); binding.bind(Person::getFirstName, Person::setFirstName); - binding.withStatusChangeHandler(evt -> Assert.fail()); + binding.withStatusHandler(evt -> Assert.fail()); } @Test(expected = IllegalStateException.class) @@ -1038,7 +1146,7 @@ public class BinderTest { @Test public void binderWithStatusChangeHandler_replaceHandler() { - AtomicReference<List<BinderResult<?, ?>>> capture = new AtomicReference<>(); + AtomicReference<BinderValidationStatus<?>> capture = new AtomicReference<>(); Binding<Person, String, String> binding = binder.forField(nameField); binding.bind(Person::getFirstName, Person::setFirstName); @@ -1054,9 +1162,11 @@ public class BinderTest { nameField.setValue("foo"); binder.validate(); - List<BinderResult<?, ?>> results = capture.get(); + List<ValidationStatus<?>> results = capture.get() + .getFieldValidationStatuses(); Assert.assertNotNull(results); Assert.assertEquals(1, results.size()); + Assert.assertFalse(results.get(0).isError()); } @Test |