You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BinderConverterValidatorTest.java 24KB

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