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.

GridAsMultiSelectInBinderTest.java 8.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. package com.vaadin.data;
  2. import static org.junit.Assert.assertEquals;
  3. import static org.junit.Assert.assertFalse;
  4. import static org.junit.Assert.assertSame;
  5. import static org.junit.Assert.assertTrue;
  6. import java.util.ArrayList;
  7. import java.util.Arrays;
  8. import java.util.Collections;
  9. import java.util.LinkedHashSet;
  10. import java.util.List;
  11. import java.util.Set;
  12. import java.util.concurrent.atomic.AtomicReference;
  13. import java.util.stream.Collectors;
  14. import java.util.stream.Stream;
  15. import org.junit.Before;
  16. import org.junit.Test;
  17. import com.vaadin.tests.data.bean.BeanWithEnums;
  18. import com.vaadin.tests.data.bean.Sex;
  19. import com.vaadin.tests.data.bean.TestEnum;
  20. import com.vaadin.ui.Grid;
  21. import com.vaadin.ui.Grid.SelectionMode;
  22. import com.vaadin.ui.MultiSelect;
  23. import com.vaadin.ui.components.grid.MultiSelectionModelImpl;
  24. public class GridAsMultiSelectInBinderTest
  25. extends BinderTestBase<Binder<BeanWithEnums>, BeanWithEnums> {
  26. public class TestEnumSetToStringConverter
  27. implements Converter<Set<TestEnum>, String> {
  28. @Override
  29. public Result<String> convertToModel(Set<TestEnum> value,
  30. ValueContext context) {
  31. return Result.ok(value.stream().map(TestEnum::name)
  32. .collect(Collectors.joining(",")));
  33. }
  34. @Override
  35. public Set<TestEnum> convertToPresentation(String value,
  36. ValueContext context) {
  37. return Stream.of(value.split(","))
  38. .filter(string -> !string.isEmpty()).map(TestEnum::valueOf)
  39. .collect(Collectors.toSet());
  40. }
  41. }
  42. private class CustomMultiSelectModel extends MultiSelectionModelImpl<Sex> {
  43. @Override
  44. public void updateSelection(Set<Sex> addedItems, Set<Sex> removedItems,
  45. boolean userOriginated) {
  46. super.updateSelection(addedItems, removedItems, userOriginated);
  47. }
  48. }
  49. private Binder<AtomicReference<String>> converterBinder = new Binder<>();
  50. private Grid<TestEnum> grid;
  51. private MultiSelect<TestEnum> select;
  52. @Before
  53. public void setUp() {
  54. binder = new Binder<>();
  55. item = new BeanWithEnums();
  56. grid = new Grid<>();
  57. grid.setItems(TestEnum.values());
  58. grid.setSelectionMode(SelectionMode.MULTI);
  59. select = grid.asMultiSelect();
  60. converterBinder.forField(select)
  61. .withConverter(new TestEnumSetToStringConverter())
  62. .bind(AtomicReference::get, AtomicReference::set);
  63. }
  64. @Test(expected = IllegalStateException.class)
  65. public void boundGridInBinder_selectionModelChanged_throws() {
  66. grid.setSelectionMode(SelectionMode.SINGLE);
  67. select.select(TestEnum.ONE);
  68. }
  69. @Test
  70. public void beanBound_bindSelectByShortcut_selectionUpdated() {
  71. item.setEnums(Collections.singleton(TestEnum.ONE));
  72. binder.setBean(item);
  73. binder.bind(select, BeanWithEnums::getEnums, BeanWithEnums::setEnums);
  74. assertEquals(Collections.singleton(TestEnum.ONE),
  75. select.getSelectedItems());
  76. }
  77. @Test
  78. public void beanBound_bindSelect_selectionUpdated() {
  79. item.setEnums(Collections.singleton(TestEnum.TWO));
  80. binder.setBean(item);
  81. binder.forField(select).bind(BeanWithEnums::getEnums,
  82. BeanWithEnums::setEnums);
  83. assertEquals(Collections.singleton(TestEnum.TWO),
  84. select.getSelectedItems());
  85. }
  86. @Test
  87. public void selectBound_bindBeanWithoutEnums_selectedItemNotPresent() {
  88. bindEnum();
  89. assertTrue(select.getSelectedItems().isEmpty());
  90. }
  91. @Test
  92. public void selectBound_bindBean_selectionUpdated() {
  93. item.setEnums(Collections.singleton(TestEnum.ONE));
  94. bindEnum();
  95. assertEquals(Collections.singleton(TestEnum.ONE),
  96. select.getSelectedItems());
  97. }
  98. @Test
  99. public void bound_setSelection_beanValueUpdated() {
  100. bindEnum();
  101. select.select(TestEnum.TWO);
  102. assertEquals(Collections.singleton(TestEnum.TWO), item.getEnums());
  103. }
  104. @Test
  105. public void bound_setSelection_beanValueIsACopy() {
  106. bindEnum();
  107. select.select(TestEnum.TWO);
  108. Set<TestEnum> enums = item.getEnums();
  109. binder.setBean(new BeanWithEnums());
  110. select.select(TestEnum.ONE);
  111. assertEquals(Collections.singleton(TestEnum.TWO), enums);
  112. }
  113. @Test
  114. public void bound_deselect_beanValueUpdatedToNull() {
  115. item.setEnums(Collections.singleton(TestEnum.ONE));
  116. bindEnum();
  117. select.deselect(TestEnum.ONE);
  118. assertTrue(item.getEnums().isEmpty());
  119. }
  120. @Test
  121. public void unbound_changeSelection_beanValueNotUpdated() {
  122. item.setEnums(Collections.singleton(TestEnum.ONE));
  123. bindEnum();
  124. binder.removeBean();
  125. select.select(TestEnum.TWO);
  126. assertEquals(Collections.singleton(TestEnum.ONE), item.getEnums());
  127. }
  128. @Test
  129. public void withConverter_load_selectUpdated() {
  130. converterBinder.readBean(new AtomicReference<>("TWO"));
  131. assertEquals(Collections.singleton(TestEnum.TWO),
  132. select.getSelectedItems());
  133. }
  134. @Test
  135. public void withConverter_save_referenceUpdated() {
  136. select.select(TestEnum.ONE);
  137. select.select(TestEnum.TWO);
  138. AtomicReference<String> reference = new AtomicReference<>("");
  139. converterBinder.writeBeanIfValid(reference);
  140. assertEquals("ONE,TWO", reference.get());
  141. }
  142. @Test
  143. public void withValidator_validate_validatorUsed() {
  144. binder.forField(select)
  145. .withValidator(selection -> selection.size() % 2 == 1,
  146. "Must select odd number of items")
  147. .bind(BeanWithEnums::getEnums, BeanWithEnums::setEnums);
  148. binder.setBean(item);
  149. assertFalse(binder.validate().isOk());
  150. select.select(TestEnum.TWO);
  151. assertTrue(binder.validate().isOk());
  152. }
  153. @Test
  154. public void addValueChangeListener_selectionUpdated_eventTriggeredForMultiSelect() {
  155. CustomMultiSelectModel model = new CustomMultiSelectModel();
  156. Grid<Sex> grid = new Grid<Sex>() {
  157. {
  158. setSelectionModel(model);
  159. }
  160. };
  161. grid.setItems(Sex.values());
  162. MultiSelect<Sex> select = grid.asMultiSelect();
  163. List<Sex> selected = new ArrayList<>();
  164. List<Boolean> userOriginated = new ArrayList<>();
  165. select.addValueChangeListener(event -> {
  166. selected.addAll(event.getValue());
  167. userOriginated.add(event.isUserOriginated());
  168. assertSame(grid, event.getComponent());
  169. // cannot compare that the event source is the select since a new
  170. // MultiSelect wrapper object has been created for the event
  171. assertEquals(select.getValue(), event.getValue());
  172. });
  173. select.select(Sex.UNKNOWN);
  174. assertEquals(Arrays.asList(Sex.UNKNOWN), selected);
  175. model.updateSelection(new LinkedHashSet<>(Arrays.asList(Sex.MALE)),
  176. Collections.emptySet(), true); // simulate client side selection
  177. assertEquals(Arrays.asList(Sex.UNKNOWN, Sex.UNKNOWN, Sex.MALE),
  178. selected);
  179. selected.clear();
  180. select.select(Sex.MALE); // NOOP
  181. assertEquals(Arrays.asList(), selected);
  182. selected.clear();
  183. // client side deselect
  184. model.updateSelection(Collections.emptySet(),
  185. new LinkedHashSet<>(Arrays.asList(Sex.UNKNOWN)), true);
  186. assertEquals(Arrays.asList(Sex.MALE), selected);
  187. selected.clear();
  188. select.deselect(Sex.UNKNOWN); // NOOP
  189. assertEquals(Arrays.asList(), selected);
  190. selected.clear();
  191. select.deselect(Sex.FEMALE, Sex.MALE); // partly NOOP
  192. assertEquals(Arrays.asList(), selected);
  193. model.selectItems(Sex.FEMALE, Sex.MALE);
  194. assertEquals(Arrays.asList(Sex.FEMALE, Sex.MALE), selected);
  195. selected.clear();
  196. model.updateSelection(new LinkedHashSet<>(Arrays.asList(Sex.FEMALE)),
  197. Collections.emptySet(), true); // client side NOOP
  198. assertEquals(Arrays.asList(), selected);
  199. assertEquals(Arrays.asList(false, true, true, false, false),
  200. userOriginated);
  201. }
  202. protected void bindEnum() {
  203. binder.forField(select).bind(BeanWithEnums::getEnums,
  204. BeanWithEnums::setEnums);
  205. binder.setBean(item);
  206. }
  207. }