Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

BinderConverterValidatorTest.java 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  1. /*
  2. * Copyright 2000-2016 Vaadin Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.vaadin.data;
  17. import static org.junit.Assert.assertEquals;
  18. import static org.junit.Assert.assertFalse;
  19. import static org.junit.Assert.assertNotNull;
  20. import static org.junit.Assert.assertNull;
  21. import static org.junit.Assert.assertTrue;
  22. import java.util.List;
  23. import java.util.concurrent.atomic.AtomicBoolean;
  24. import org.junit.Assert;
  25. import org.junit.Before;
  26. import org.junit.Test;
  27. import com.vaadin.data.Binder.Binding;
  28. import com.vaadin.data.Binder.BindingBuilder;
  29. import com.vaadin.data.util.converter.StringToIntegerConverter;
  30. import com.vaadin.data.util.converter.ValueContext;
  31. import com.vaadin.data.validator.NotEmptyValidator;
  32. import com.vaadin.server.AbstractErrorMessage;
  33. import com.vaadin.server.ErrorMessage;
  34. import com.vaadin.server.SerializablePredicate;
  35. import com.vaadin.server.UserError;
  36. import com.vaadin.tests.data.bean.Person;
  37. import com.vaadin.ui.Label;
  38. import com.vaadin.ui.TextField;
  39. public class BinderConverterValidatorTest
  40. extends BinderTestBase<Binder<Person>, Person> {
  41. private static class StatusBean {
  42. private String status;
  43. public String getStatus() {
  44. return status;
  45. }
  46. public void setStatus(String status) {
  47. this.status = status;
  48. }
  49. }
  50. @Before
  51. public void setUp() {
  52. binder = new Binder<>();
  53. item = new Person();
  54. item.setFirstName("Johannes");
  55. item.setAge(32);
  56. }
  57. @Test
  58. public void validate_notBound_noErrors() {
  59. BinderValidationStatus<Person> status = binder.validate();
  60. assertTrue(status.isOk());
  61. }
  62. @Test
  63. public void bound_validatorsAreOK_noErrors() {
  64. BindingBuilder<Person, String> binding = binder.forField(nameField);
  65. binding.withValidator(Validator.alwaysPass()).bind(Person::getFirstName,
  66. Person::setFirstName);
  67. nameField.setComponentError(new UserError(""));
  68. BinderValidationStatus<Person> status = binder.validate();
  69. assertTrue(status.isOk());
  70. assertNull(nameField.getComponentError());
  71. }
  72. @SuppressWarnings("serial")
  73. @Test
  74. public void bound_validatorsFail_errors() {
  75. BindingBuilder<Person, String> binding = binder.forField(nameField);
  76. binding.withValidator(Validator.alwaysPass());
  77. String msg1 = "foo";
  78. String msg2 = "bar";
  79. binding.withValidator((String value,
  80. ValueContext context) -> ValidationResult.error(msg1));
  81. binding.withValidator(value -> false, msg2);
  82. binding.bind(Person::getFirstName, Person::setFirstName);
  83. BinderValidationStatus<Person> status = binder.validate();
  84. List<ValidationStatus<?>> errors = status.getFieldValidationErrors();
  85. assertEquals(1, errors.size());
  86. ValidationStatus<?> validationStatus = errors.stream().findFirst()
  87. .get();
  88. String msg = validationStatus.getMessage().get();
  89. assertEquals(msg1, msg);
  90. HasValue<?> field = validationStatus.getField();
  91. assertEquals(nameField, field);
  92. ErrorMessage componentError = nameField.getComponentError();
  93. assertNotNull(componentError);
  94. assertEquals("foo",
  95. ((AbstractErrorMessage) componentError).getMessage());
  96. }
  97. @Test
  98. public void validatorForSuperTypeCanBeUsed() {
  99. // Validates that a validator for a super type can be used, e.g.
  100. // validator for Number can be used on a Double
  101. TextField salaryField = new TextField();
  102. Validator<Number> positiveNumberValidator = (value, context) -> {
  103. if (value.doubleValue() >= 0) {
  104. return ValidationResult.ok();
  105. } else {
  106. return ValidationResult.error(NEGATIVE_ERROR_MESSAGE);
  107. }
  108. };
  109. binder.forField(salaryField)
  110. .withConverter(Double::valueOf, String::valueOf)
  111. .withValidator(positiveNumberValidator)
  112. .bind(Person::getSalaryDouble, Person::setSalaryDouble);
  113. Person person = new Person();
  114. binder.setBean(person);
  115. salaryField.setValue("10");
  116. assertEquals(10, person.getSalaryDouble(), 0);
  117. salaryField.setValue("-1"); // Does not pass validator
  118. assertEquals(10, person.getSalaryDouble(), 0);
  119. }
  120. @Test
  121. public void convertInitialValue() {
  122. bindAgeWithValidatorConverterValidator();
  123. assertEquals("32", ageField.getValue());
  124. }
  125. @Test
  126. public void convertToModelValidAge() {
  127. bindAgeWithValidatorConverterValidator();
  128. ageField.setValue("33");
  129. assertEquals(33, item.getAge());
  130. }
  131. @Test
  132. public void convertToModelNegativeAgeFailsOnFirstValidator() {
  133. bindAgeWithValidatorConverterValidator();
  134. ageField.setValue("");
  135. assertEquals(32, item.getAge());
  136. assertValidationErrors(binder.validate(), EMPTY_ERROR_MESSAGE);
  137. }
  138. private void assertValidationErrors(
  139. List<ValidationStatus<?>> validationErrors,
  140. String... errorMessages) {
  141. assertEquals(errorMessages.length, validationErrors.size());
  142. for (int i = 0; i < errorMessages.length; i++) {
  143. assertEquals(errorMessages[i],
  144. validationErrors.get(i).getMessage().get());
  145. }
  146. }
  147. private void assertValidationErrors(BinderValidationStatus<Person> status,
  148. String... errorMessages) {
  149. assertValidationErrors(status.getFieldValidationErrors(),
  150. errorMessages);
  151. }
  152. @Test
  153. public void convertToModelConversionFails() {
  154. bindAgeWithValidatorConverterValidator();
  155. ageField.setValue("abc");
  156. assertEquals(32, item.getAge());
  157. assertValidationErrors(binder.validate(), NOT_NUMBER_ERROR_MESSAGE);
  158. }
  159. @Test
  160. public void convertToModelNegativeAgeFailsOnIntegerValidator() {
  161. bindAgeWithValidatorConverterValidator();
  162. ageField.setValue("-5");
  163. assertEquals(32, item.getAge());
  164. assertValidationErrors(binder.validate(), NEGATIVE_ERROR_MESSAGE);
  165. }
  166. @Test
  167. public void convertDataToField() {
  168. bindAgeWithValidatorConverterValidator();
  169. binder.getBean().get().setAge(12);
  170. binder.readBean(binder.getBean().get());
  171. assertEquals("12", ageField.getValue());
  172. }
  173. @Test
  174. public void convertNotValidatableDataToField() {
  175. bindAgeWithValidatorConverterValidator();
  176. binder.getBean().get().setAge(-12);
  177. binder.readBean(binder.getBean().get());
  178. assertEquals("-12", ageField.getValue());
  179. }
  180. @Test(expected = IllegalArgumentException.class)
  181. public void convertInvalidDataToField() {
  182. TextField field = new TextField();
  183. StatusBean bean = new StatusBean();
  184. bean.setStatus("1");
  185. Binder<StatusBean> binder = new Binder<>();
  186. BindingBuilder<StatusBean, String> binding = binder.forField(field)
  187. .withConverter(presentation -> {
  188. if (presentation.equals("OK")) {
  189. return "1";
  190. } else if (presentation.equals("NOTOK")) {
  191. return "2";
  192. }
  193. throw new IllegalArgumentException(
  194. "Value must be OK or NOTOK");
  195. }, model -> {
  196. if (model.equals("1")) {
  197. return "OK";
  198. } else if (model.equals("2")) {
  199. return "NOTOK";
  200. } else {
  201. throw new IllegalArgumentException(
  202. "Value in model must be 1 or 2");
  203. }
  204. });
  205. binding.bind(StatusBean::getStatus, StatusBean::setStatus);
  206. binder.setBean(bean);
  207. bean.setStatus("3");
  208. binder.readBean(bean);
  209. }
  210. @Test
  211. public void validate_failedBeanValidatorWithoutFieldValidators() {
  212. binder.forField(nameField).bind(Person::getFirstName,
  213. Person::setFirstName);
  214. String msg = "foo";
  215. binder.withValidator(Validator.from(bean -> false, msg));
  216. Person person = new Person();
  217. binder.setBean(person);
  218. List<ValidationStatus<?>> errors = binder.validate()
  219. .getFieldValidationErrors();
  220. assertEquals(0, errors.size());
  221. }
  222. @Test
  223. public void validate_failedBeanValidatorWithFieldValidator() {
  224. String msg = "foo";
  225. BindingBuilder<Person, String> binding = binder.forField(nameField)
  226. .withValidator(new NotEmptyValidator<>(msg));
  227. binding.bind(Person::getFirstName, Person::setFirstName);
  228. binder.withValidator(Validator.from(bean -> false, msg));
  229. Person person = new Person();
  230. binder.setBean(person);
  231. List<ValidationStatus<?>> errors = binder.validate()
  232. .getFieldValidationErrors();
  233. assertEquals(1, errors.size());
  234. ValidationStatus<?> error = errors.get(0);
  235. assertEquals(msg, error.getMessage().get());
  236. assertEquals(nameField, error.getField());
  237. }
  238. @Test
  239. public void validate_failedBothBeanValidatorAndFieldValidator() {
  240. String msg1 = "foo";
  241. BindingBuilder<Person, String> binding = binder.forField(nameField)
  242. .withValidator(new NotEmptyValidator<>(msg1));
  243. binding.bind(Person::getFirstName, Person::setFirstName);
  244. String msg2 = "bar";
  245. binder.withValidator(Validator.from(bean -> false, msg2));
  246. Person person = new Person();
  247. binder.setBean(person);
  248. List<ValidationStatus<?>> errors = binder.validate()
  249. .getFieldValidationErrors();
  250. assertEquals(1, errors.size());
  251. ValidationStatus<?> error = errors.get(0);
  252. assertEquals(msg1, error.getMessage().get());
  253. assertEquals(nameField, error.getField());
  254. }
  255. @Test
  256. public void validate_okBeanValidatorWithoutFieldValidators() {
  257. binder.forField(nameField).bind(Person::getFirstName,
  258. Person::setFirstName);
  259. String msg = "foo";
  260. binder.withValidator(Validator.from(bean -> true, msg));
  261. Person person = new Person();
  262. binder.setBean(person);
  263. assertFalse(binder.validate().hasErrors());
  264. assertTrue(binder.validate().isOk());
  265. }
  266. @Test
  267. public void binder_saveIfValid() {
  268. String msg1 = "foo";
  269. BindingBuilder<Person, String> binding = binder.forField(nameField)
  270. .withValidator(new NotEmptyValidator<>(msg1));
  271. binding.bind(Person::getFirstName, Person::setFirstName);
  272. String beanValidatorErrorMessage = "bar";
  273. binder.withValidator(
  274. Validator.from(bean -> false, beanValidatorErrorMessage));
  275. Person person = new Person();
  276. String firstName = "first name";
  277. person.setFirstName(firstName);
  278. binder.readBean(person);
  279. nameField.setValue("");
  280. assertFalse(binder.writeBeanIfValid(person));
  281. // check that field level-validation failed and bean is not updated
  282. assertEquals(firstName, person.getFirstName());
  283. nameField.setValue("new name");
  284. assertFalse(binder.writeBeanIfValid(person));
  285. // Bean is updated but reverted
  286. assertEquals(firstName, person.getFirstName());
  287. }
  288. @Test
  289. public void updateBoundField_bindingValdationFails_beanLevelValidationIsNotRun() {
  290. bindAgeWithValidatorConverterValidator();
  291. bindName();
  292. AtomicBoolean beanLevelValidationRun = new AtomicBoolean();
  293. binder.withValidator(Validator
  294. .from(bean -> beanLevelValidationRun.getAndSet(true), ""));
  295. ageField.setValue("not a number");
  296. assertFalse(beanLevelValidationRun.get());
  297. nameField.setValue("foo");
  298. assertFalse(beanLevelValidationRun.get());
  299. }
  300. @Test
  301. public void updateBoundField_bindingValdationSuccess_beanLevelValidationIsRun() {
  302. bindAgeWithValidatorConverterValidator();
  303. bindName();
  304. AtomicBoolean beanLevelValidationRun = new AtomicBoolean();
  305. binder.withValidator(Validator
  306. .from(bean -> beanLevelValidationRun.getAndSet(true), ""));
  307. ageField.setValue(String.valueOf(12));
  308. assertTrue(beanLevelValidationRun.get());
  309. }
  310. @Test
  311. public void binderHasChanges() throws ValidationException {
  312. binder.forField(nameField)
  313. .withValidator(Validator.from(name -> !"".equals(name),
  314. "Name can't be empty"))
  315. .bind(Person::getFirstName, Person::setFirstName);
  316. assertFalse(binder.hasChanges());
  317. binder.setBean(item);
  318. assertFalse(binder.hasChanges());
  319. // Bound binder + valid user changes: hasChanges == false
  320. nameField.setValue("foo");
  321. assertFalse(binder.hasChanges());
  322. nameField.setValue("bar");
  323. binder.writeBeanIfValid(new Person());
  324. assertFalse(binder.hasChanges());
  325. // Bound binder + invalid user changes: hasChanges() == true
  326. nameField.setValue("");
  327. binder.writeBeanIfValid(new Person());
  328. assertTrue(binder.hasChanges());
  329. // Read bean resets hasChanges
  330. binder.readBean(item);
  331. assertFalse(binder.hasChanges());
  332. // Removing a bound bean resets hasChanges
  333. nameField.setValue("");
  334. assertTrue(binder.hasChanges());
  335. binder.removeBean();
  336. assertFalse(binder.hasChanges());
  337. // Unbound binder + valid user changes: hasChanges() == true
  338. nameField.setValue("foo");
  339. assertTrue(binder.hasChanges());
  340. // successful writeBean resets hasChanges to false
  341. binder.writeBeanIfValid(new Person());
  342. assertFalse(binder.hasChanges());
  343. // Unbound binder + invalid user changes: hasChanges() == true
  344. nameField.setValue("");
  345. assertTrue(binder.hasChanges());
  346. // unsuccessful writeBean doesn't affect hasChanges
  347. nameField.setValue("");
  348. binder.writeBeanIfValid(new Person());
  349. assertTrue(binder.hasChanges());
  350. }
  351. @Test(expected = ValidationException.class)
  352. public void save_fieldValidationErrors() throws ValidationException {
  353. Binder<Person> binder = new Binder<>();
  354. String msg = "foo";
  355. binder.forField(nameField).withValidator(new NotEmptyValidator<>(msg))
  356. .bind(Person::getFirstName, Person::setFirstName);
  357. Person person = new Person();
  358. String firstName = "foo";
  359. person.setFirstName(firstName);
  360. nameField.setValue("");
  361. try {
  362. binder.writeBean(person);
  363. } finally {
  364. // Bean should not have been updated
  365. Assert.assertEquals(firstName, person.getFirstName());
  366. }
  367. }
  368. @Test(expected = ValidationException.class)
  369. public void save_beanValidationErrors() throws ValidationException {
  370. Binder<Person> binder = new Binder<>();
  371. binder.forField(nameField).withValidator(new NotEmptyValidator<>("a"))
  372. .bind(Person::getFirstName, Person::setFirstName);
  373. binder.withValidator(Validator.from(person -> false, "b"));
  374. Person person = new Person();
  375. nameField.setValue("foo");
  376. try {
  377. binder.writeBean(person);
  378. } finally {
  379. // Bean should have been updated for item validation but reverted
  380. Assert.assertNull(person.getFirstName());
  381. }
  382. }
  383. @Test
  384. public void save_fieldsAndBeanLevelValidation() throws ValidationException {
  385. binder.forField(nameField).withValidator(new NotEmptyValidator<>("a"))
  386. .bind(Person::getFirstName, Person::setFirstName);
  387. binder.withValidator(
  388. Validator.from(person -> person.getLastName() != null, "b"));
  389. Person person = new Person();
  390. person.setLastName("bar");
  391. nameField.setValue("foo");
  392. binder.writeBean(person);
  393. Assert.assertEquals(nameField.getValue(), person.getFirstName());
  394. Assert.assertEquals("bar", person.getLastName());
  395. }
  396. @Test
  397. public void saveIfValid_fieldValidationErrors() {
  398. String msg = "foo";
  399. binder.forField(nameField).withValidator(new NotEmptyValidator<>(msg))
  400. .bind(Person::getFirstName, Person::setFirstName);
  401. Person person = new Person();
  402. person.setFirstName("foo");
  403. nameField.setValue("");
  404. Assert.assertFalse(binder.writeBeanIfValid(person));
  405. Assert.assertEquals("foo", person.getFirstName());
  406. }
  407. @Test
  408. public void saveIfValid_noValidationErrors() {
  409. String msg = "foo";
  410. binder.forField(nameField).withValidator(new NotEmptyValidator<>(msg))
  411. .bind(Person::getFirstName, Person::setFirstName);
  412. Person person = new Person();
  413. person.setFirstName("foo");
  414. nameField.setValue("bar");
  415. Assert.assertTrue(binder.writeBeanIfValid(person));
  416. Assert.assertEquals("bar", person.getFirstName());
  417. }
  418. @Test
  419. public void saveIfValid_beanValidationErrors() {
  420. Binder<Person> binder = new Binder<>();
  421. binder.forField(nameField).bind(Person::getFirstName,
  422. Person::setFirstName);
  423. String msg = "foo";
  424. binder.withValidator(Validator.from(
  425. prsn -> prsn.getAddress() != null || prsn.getEmail() != null,
  426. msg));
  427. Person person = new Person();
  428. person.setFirstName("foo");
  429. nameField.setValue("");
  430. Assert.assertFalse(binder.writeBeanIfValid(person));
  431. Assert.assertEquals("foo", person.getFirstName());
  432. }
  433. @Test
  434. public void save_null_beanIsUpdated() throws ValidationException {
  435. Binder<Person> binder = new Binder<>();
  436. binder.forField(nameField).withConverter(fieldValue -> {
  437. if ("null".equals(fieldValue)) {
  438. return null;
  439. } else {
  440. return fieldValue;
  441. }
  442. }, model -> {
  443. return model;
  444. }).bind(Person::getFirstName, Person::setFirstName);
  445. Person person = new Person();
  446. person.setFirstName("foo");
  447. nameField.setValue("null");
  448. binder.writeBean(person);
  449. Assert.assertNull(person.getFirstName());
  450. }
  451. @Test
  452. public void save_validationErrors_exceptionContainsErrors()
  453. throws ValidationException {
  454. String msg = "foo";
  455. BindingBuilder<Person, String> nameBinding = binder.forField(nameField)
  456. .withValidator(new NotEmptyValidator<>(msg));
  457. nameBinding.bind(Person::getFirstName, Person::setFirstName);
  458. BindingBuilder<Person, Integer> ageBinding = binder.forField(ageField)
  459. .withConverter(stringToInteger).withValidator(notNegative);
  460. ageBinding.bind(Person::getAge, Person::setAge);
  461. Person person = new Person();
  462. nameField.setValue("");
  463. ageField.setValue("-1");
  464. try {
  465. binder.writeBean(person);
  466. Assert.fail();
  467. } catch (ValidationException exception) {
  468. List<ValidationStatus<?>> validationErrors = exception
  469. .getFieldValidationErrors();
  470. Assert.assertEquals(2, validationErrors.size());
  471. ValidationStatus<?> error = validationErrors.get(0);
  472. Assert.assertEquals(nameField, error.getField());
  473. Assert.assertEquals(msg, error.getMessage().get());
  474. error = validationErrors.get(1);
  475. Assert.assertEquals(ageField, error.getField());
  476. Assert.assertEquals(NEGATIVE_ERROR_MESSAGE,
  477. error.getMessage().get());
  478. }
  479. }
  480. @Test
  481. public void binderBindAndLoad_clearsErrors() {
  482. BindingBuilder<Person, String> binding = binder.forField(nameField)
  483. .withValidator(notEmpty);
  484. binding.bind(Person::getFirstName, Person::setFirstName);
  485. binder.withValidator(bean -> !bean.getFirstName().contains("error"),
  486. "error");
  487. Person person = new Person();
  488. person.setFirstName("");
  489. binder.setBean(person);
  490. // initial value is invalid but no error
  491. Assert.assertNull(nameField.getComponentError());
  492. // make error show
  493. nameField.setValue("foo");
  494. nameField.setValue("");
  495. Assert.assertNotNull(nameField.getComponentError());
  496. // bind to another person to see that error is cleared
  497. person = new Person();
  498. person.setFirstName("");
  499. binder.setBean(person);
  500. // error has been cleared
  501. Assert.assertNull(nameField.getComponentError());
  502. // make show error
  503. nameField.setValue("foo");
  504. nameField.setValue("");
  505. Assert.assertNotNull(nameField.getComponentError());
  506. // load should also clear error
  507. binder.readBean(person);
  508. Assert.assertNull(nameField.getComponentError());
  509. // bind a new field that has invalid value in bean
  510. TextField lastNameField = new TextField();
  511. person.setLastName("");
  512. BindingBuilder<Person, String> binding2 = binder.forField(lastNameField)
  513. .withValidator(notEmpty);
  514. binding2.bind(Person::getLastName, Person::setLastName);
  515. // should not have error shown
  516. Assert.assertNull(lastNameField.getComponentError());
  517. // add status label to show bean level error
  518. Label statusLabel = new Label();
  519. binder.setStatusLabel(statusLabel);
  520. nameField.setValue("error");
  521. // no error shown yet because second field validation doesn't pass
  522. Assert.assertEquals("", statusLabel.getValue());
  523. // make second field validation pass to get bean validation error
  524. lastNameField.setValue("foo");
  525. Assert.assertEquals("error", statusLabel.getValue());
  526. // reload bean to clear error
  527. binder.readBean(person);
  528. Assert.assertEquals("", statusLabel.getValue());
  529. // reset() should clear all errors and status label
  530. nameField.setValue("");
  531. lastNameField.setValue("");
  532. Assert.assertNotNull(nameField.getComponentError());
  533. Assert.assertNotNull(lastNameField.getComponentError());
  534. statusLabel.setComponentError(new UserError("ERROR"));
  535. binder.removeBean();
  536. Assert.assertNull(nameField.getComponentError());
  537. Assert.assertNull(lastNameField.getComponentError());
  538. Assert.assertEquals("", statusLabel.getValue());
  539. }
  540. @Test
  541. public void binderLoad_withCrossFieldValidation_clearsErrors() {
  542. TextField lastNameField = new TextField();
  543. final SerializablePredicate<String> lengthPredicate = v -> v
  544. .length() > 2;
  545. BindingBuilder<Person, String> firstNameBinding = binder
  546. .forField(nameField).withValidator(lengthPredicate, "length");
  547. firstNameBinding.bind(Person::getFirstName, Person::setFirstName);
  548. Binding<Person, String> lastNameBinding = binder.forField(lastNameField)
  549. .withValidator(v -> !nameField.getValue().isEmpty()
  550. || lengthPredicate.test(v), "err")
  551. .withValidator(lengthPredicate, "length")
  552. .bind(Person::getLastName, Person::setLastName);
  553. // this will be triggered as a new bean is bound with binder.bind(),
  554. // causing a validation error to be visible until reset is done
  555. nameField.addValueChangeListener(v -> lastNameBinding.validate());
  556. Person person = new Person();
  557. binder.setBean(person);
  558. Assert.assertNull(nameField.getComponentError());
  559. Assert.assertNull(lastNameField.getComponentError());
  560. nameField.setValue("x");
  561. Assert.assertNotNull(nameField.getComponentError());
  562. Assert.assertNotNull(lastNameField.getComponentError());
  563. binder.setBean(person);
  564. Assert.assertNull(nameField.getComponentError());
  565. Assert.assertNull(lastNameField.getComponentError());
  566. }
  567. protected void bindName() {
  568. binder.bind(nameField, Person::getFirstName, Person::setFirstName);
  569. binder.setBean(item);
  570. }
  571. protected void bindAgeWithValidatorConverterValidator() {
  572. binder.forField(ageField).withValidator(notEmpty)
  573. .withConverter(stringToInteger).withValidator(notNegative)
  574. .bind(Person::getAge, Person::setAge);
  575. binder.setBean(item);
  576. }
  577. @Test(expected = ValidationException.class)
  578. public void save_beanValidationErrorsWithConverter()
  579. throws ValidationException {
  580. Binder<Person> binder = new Binder<>();
  581. binder.forField(ageField)
  582. .withConverter(new StringToIntegerConverter("Can't convert"))
  583. .bind(Person::getAge, Person::setAge);
  584. binder.withValidator(Validator.from(person -> false, "b"));
  585. Person person = new Person();
  586. ageField.setValue("1");
  587. try {
  588. binder.writeBean(person);
  589. } finally {
  590. // Bean should have been updated for item validation but reverted
  591. Assert.assertEquals(0, person.getAge());
  592. }
  593. }
  594. }