aboutsummaryrefslogtreecommitdiffstats
path: root/server/src/test
diff options
context:
space:
mode:
authorPekka Hyvönen <pekka@vaadin.com>2016-11-11 09:41:43 +0200
committerVaadin Code Review <review@vaadin.com>2016-11-29 10:18:11 +0000
commitf2d8f812efa067b4baa7e27c0ea76f7596b291e6 (patch)
tree8e35e6c4eef4ffc5f8006d30989914da1deeab1b /server/src/test
parent13443562ccbd633ceb561bb87893014f65437ad1 (diff)
downloadvaadin-framework-f2d8f812efa067b4baa7e27c0ea76f7596b291e6.tar.gz
vaadin-framework-f2d8f812efa067b4baa7e27c0ea76f7596b291e6.zip
Add MultiSelect support for Grid
Still missing following things coming in next patches: - select all checkbox - firing an event when data provider is changed in grid - read only selection models for grid Part 1 for vaadin/framework8-issues#232 Change-Id: Ib2c7c81a838f43cb7c521a56d50139c91961f54a
Diffstat (limited to 'server/src/test')
-rw-r--r--server/src/test/java/com/vaadin/data/GridAsMultiSelectInBinder.java270
-rw-r--r--server/src/test/java/com/vaadin/data/GridAsSingleSelectInBinder.java14
-rw-r--r--server/src/test/java/com/vaadin/tests/components/grid/GridMultiSelectionModelTest.java543
-rw-r--r--server/src/test/java/com/vaadin/tests/components/grid/GridSingleSelectionModelTest.java113
4 files changed, 911 insertions, 29 deletions
diff --git a/server/src/test/java/com/vaadin/data/GridAsMultiSelectInBinder.java b/server/src/test/java/com/vaadin/data/GridAsMultiSelectInBinder.java
new file mode 100644
index 0000000000..e31b2ab188
--- /dev/null
+++ b/server/src/test/java/com/vaadin/data/GridAsMultiSelectInBinder.java
@@ -0,0 +1,270 @@
+package com.vaadin.data;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.data.util.converter.Converter;
+import com.vaadin.data.util.converter.ValueContext;
+import com.vaadin.tests.data.bean.BeanWithEnums;
+import com.vaadin.tests.data.bean.Sex;
+import com.vaadin.tests.data.bean.TestEnum;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.MultiSelect;
+import com.vaadin.ui.components.grid.MultiSelectionModelImpl;
+import com.vaadin.ui.components.grid.SingleSelectionModelImpl;
+
+public class GridAsMultiSelectInBinder
+ extends BinderTestBase<Binder<BeanWithEnums>, BeanWithEnums> {
+ public class TestEnumSetToStringConverter
+ implements Converter<Set<TestEnum>, String> {
+ @Override
+ public Result<String> convertToModel(Set<TestEnum> value,
+ ValueContext context) {
+ return Result.ok(value.stream().map(TestEnum::name)
+ .collect(Collectors.joining(",")));
+ }
+
+ @Override
+ public Set<TestEnum> convertToPresentation(String value,
+ ValueContext context) {
+ return Stream.of(value.split(","))
+ .filter(string -> !string.isEmpty()).map(TestEnum::valueOf)
+ .collect(Collectors.toSet());
+ }
+ }
+
+ private class CustomMultiSelectModel extends MultiSelectionModelImpl<Sex> {
+
+ public CustomMultiSelectModel(Grid<Sex> grid) {
+ super(grid);
+ }
+
+ @Override
+ public void updateSelection(Set<Sex> addedItems, Set<Sex> removedItems,
+ boolean userOriginated) {
+ super.updateSelection(addedItems, removedItems, userOriginated);
+ }
+
+ }
+
+ private Binder<AtomicReference<String>> converterBinder = new Binder<>();
+ private Grid<TestEnum> grid;
+ private MultiSelect<TestEnum> select;
+
+ @Before
+ public void setUp() {
+ binder = new Binder<>();
+ item = new BeanWithEnums();
+ grid = new Grid<>();
+ grid.setItems(TestEnum.values());
+ grid.setSelectionModel(new MultiSelectionModelImpl<>(grid));
+ select = grid.asMultiSelect();
+
+ converterBinder.forField(select)
+ .withConverter(new TestEnumSetToStringConverter())
+ .bind(AtomicReference::get, AtomicReference::set);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void boundGridInBinder_selectionModelChanged_throws() {
+ grid.setSelectionModel(new SingleSelectionModelImpl<>(grid));
+
+ select.select(TestEnum.ONE);
+ }
+
+ @Test
+ public void beanBound_bindSelectByShortcut_selectionUpdated() {
+ item.setEnums(Collections.singleton(TestEnum.ONE));
+ binder.setBean(item);
+ binder.bind(select, BeanWithEnums::getEnums, BeanWithEnums::setEnums);
+
+ assertEquals(Collections.singleton(TestEnum.ONE),
+ select.getSelectedItems());
+ }
+
+ @Test
+ public void beanBound_bindSelect_selectionUpdated() {
+ item.setEnums(Collections.singleton(TestEnum.TWO));
+ binder.setBean(item);
+ binder.forField(select).bind(BeanWithEnums::getEnums,
+ BeanWithEnums::setEnums);
+
+ assertEquals(Collections.singleton(TestEnum.TWO),
+ select.getSelectedItems());
+ }
+
+ @Test
+ public void selectBound_bindBeanWithoutEnums_selectedItemNotPresent() {
+ bindEnum();
+
+ assertTrue(select.getSelectedItems().isEmpty());
+ }
+
+ @Test
+ public void selectBound_bindBean_selectionUpdated() {
+ item.setEnums(Collections.singleton(TestEnum.ONE));
+ bindEnum();
+
+ assertEquals(Collections.singleton(TestEnum.ONE),
+ select.getSelectedItems());
+ }
+
+ @Test
+ public void bound_setSelection_beanValueUpdated() {
+ bindEnum();
+
+ select.select(TestEnum.TWO);
+
+ assertEquals(Collections.singleton(TestEnum.TWO), item.getEnums());
+ }
+
+ @Test
+ public void bound_setSelection_beanValueIsACopy() {
+ bindEnum();
+
+ select.select(TestEnum.TWO);
+
+ Set<TestEnum> enums = item.getEnums();
+
+ binder.setBean(new BeanWithEnums());
+ select.select(TestEnum.ONE);
+
+ assertEquals(Collections.singleton(TestEnum.TWO), enums);
+ }
+
+ @Test
+ public void bound_deselect_beanValueUpdatedToNull() {
+ item.setEnums(Collections.singleton(TestEnum.ONE));
+ bindEnum();
+
+ select.deselect(TestEnum.ONE);
+
+ assertTrue(item.getEnums().isEmpty());
+ }
+
+ @Test
+ public void unbound_changeSelection_beanValueNotUpdated() {
+ item.setEnums(Collections.singleton(TestEnum.ONE));
+ bindEnum();
+ binder.removeBean();
+
+ select.select(TestEnum.TWO);
+
+ assertEquals(Collections.singleton(TestEnum.ONE), item.getEnums());
+ }
+
+ @Test
+ public void withConverter_load_selectUpdated() {
+ converterBinder.readBean(new AtomicReference<>("TWO"));
+
+ assertEquals(Collections.singleton(TestEnum.TWO),
+ select.getSelectedItems());
+ }
+
+ @Test
+ public void withConverter_save_referenceUpdated() {
+ select.select(TestEnum.ONE);
+ select.select(TestEnum.TWO);
+
+ AtomicReference<String> reference = new AtomicReference<>("");
+ converterBinder.writeBeanIfValid(reference);
+
+ assertEquals("ONE,TWO", reference.get());
+ }
+
+ @Test
+ public void withValidator_validate_validatorUsed() {
+ binder.forField(select)
+ .withValidator(selection -> selection.size() % 2 == 1,
+ "Must select odd number of items")
+ .bind(BeanWithEnums::getEnums, BeanWithEnums::setEnums);
+ binder.setBean(item);
+
+ assertFalse(binder.validate().isOk());
+
+ select.select(TestEnum.TWO);
+
+ assertTrue(binder.validate().isOk());
+ }
+
+ @Test
+ public void addValueChangeListener_selectionUpdated_eventTriggeredForMultiSelect() {
+ Grid<Sex> grid = new Grid<>();
+ CustomMultiSelectModel model = new CustomMultiSelectModel(grid);
+ grid.setSelectionModel(model);
+ grid.setItems(Sex.values());
+ MultiSelect<Sex> select = grid.asMultiSelect();
+
+ List<Sex> selected = new ArrayList<>();
+ List<Boolean> userOriginated = new ArrayList<>();
+ select.addValueChangeListener(event -> {
+ selected.addAll(event.getValue());
+ userOriginated.add(event.isUserOriginated());
+ assertSame(grid, event.getComponent());
+ // cannot compare that the event source is the select since a new
+ // MultiSelect wrapper object has been created for the event
+
+ assertEquals(select.getValue(), event.getValue());
+ });
+
+ select.select(Sex.UNKNOWN);
+
+ assertEquals(Arrays.asList(Sex.UNKNOWN), selected);
+
+ model.updateSelection(new LinkedHashSet<>(Arrays.asList(Sex.MALE)),
+ Collections.emptySet(), true); // simulate client side selection
+ assertEquals(Arrays.asList(Sex.UNKNOWN, Sex.UNKNOWN, Sex.MALE),
+ selected);
+ selected.clear();
+
+ select.select(Sex.MALE); // NOOP
+ assertEquals(Arrays.asList(), selected);
+ selected.clear();
+
+ model.updateSelection(Collections.emptySet(),
+ new LinkedHashSet<>(Arrays.asList(Sex.UNKNOWN)), true); // client
+ // side
+ // deselect
+ assertEquals(Arrays.asList(Sex.MALE), selected);
+ selected.clear();
+
+ select.deselect(Sex.UNKNOWN); // NOOP
+ assertEquals(Arrays.asList(), selected);
+ selected.clear();
+
+ select.deselect(Sex.FEMALE, Sex.MALE); // partly NOOP
+ assertEquals(Arrays.asList(), selected);
+
+ model.selectItems(Sex.FEMALE, Sex.MALE);
+ assertEquals(Arrays.asList(Sex.FEMALE, Sex.MALE), selected);
+ selected.clear();
+
+ model.updateSelection(new LinkedHashSet<>(Arrays.asList(Sex.FEMALE)),
+ Collections.emptySet(), true); // client side NOOP
+ assertEquals(Arrays.asList(), selected);
+
+ assertEquals(Arrays.asList(false, true, true, false, false),
+ userOriginated);
+ }
+
+ protected void bindEnum() {
+ binder.forField(select).bind(BeanWithEnums::getEnums,
+ BeanWithEnums::setEnums);
+ binder.setBean(item);
+ }
+}
diff --git a/server/src/test/java/com/vaadin/data/GridAsSingleSelectInBinder.java b/server/src/test/java/com/vaadin/data/GridAsSingleSelectInBinder.java
index 7b34c78f25..cf649384e0 100644
--- a/server/src/test/java/com/vaadin/data/GridAsSingleSelectInBinder.java
+++ b/server/src/test/java/com/vaadin/data/GridAsSingleSelectInBinder.java
@@ -16,7 +16,8 @@ import com.vaadin.tests.data.bean.Person;
import com.vaadin.tests.data.bean.Sex;
import com.vaadin.ui.Grid;
import com.vaadin.ui.SingleSelect;
-import com.vaadin.ui.components.grid.SingleSelectionModel;
+import com.vaadin.ui.components.grid.MultiSelectionModelImpl;
+import com.vaadin.ui.components.grid.SingleSelectionModelImpl;
public class GridAsSingleSelectInBinder
extends BinderTestBase<Binder<Person>, Person> {
@@ -29,7 +30,7 @@ public class GridAsSingleSelectInBinder
}
}
- private class CustomSingleSelectModel extends SingleSelectionModel<Sex> {
+ private class CustomSingleSelectModel extends SingleSelectionModelImpl<Sex> {
public CustomSingleSelectModel(Grid<Sex> grid) {
super(grid);
@@ -52,6 +53,13 @@ public class GridAsSingleSelectInBinder
select = grid.asSingleSelect();
}
+ @Test(expected = IllegalStateException.class)
+ public void boundGridInBinder_selectionModelChanged_throws() {
+ grid.setSelectionModel(new MultiSelectionModelImpl<>(grid));
+
+ select.setValue(Sex.MALE);
+ }
+
@Test
public void personBound_bindSelectByShortcut_selectionUpdated() {
item.setSex(Sex.FEMALE);
@@ -117,8 +125,6 @@ public class GridAsSingleSelectInBinder
@Test
public void addValueChangeListener_selectionUpdated_eventTriggeredForSelect() {
- binder = new Binder<>();
- item = new Person();
GridWithCustomSingleSelectionModel grid = new GridWithCustomSingleSelectionModel();
CustomSingleSelectModel model = new CustomSingleSelectModel(grid);
grid.setSelectionModel(model);
diff --git a/server/src/test/java/com/vaadin/tests/components/grid/GridMultiSelectionModelTest.java b/server/src/test/java/com/vaadin/tests/components/grid/GridMultiSelectionModelTest.java
new file mode 100644
index 0000000000..d7a087be54
--- /dev/null
+++ b/server/src/test/java/com/vaadin/tests/components/grid/GridMultiSelectionModelTest.java
@@ -0,0 +1,543 @@
+package com.vaadin.tests.components.grid;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.easymock.Capture;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import com.vaadin.data.HasValue.ValueChangeEvent;
+import com.vaadin.event.selection.SingleSelectionEvent;
+import com.vaadin.event.selection.SingleSelectionListener;
+import com.vaadin.server.data.provider.bov.Person;
+import com.vaadin.shared.Registration;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.GridSelectionModel;
+import com.vaadin.ui.components.grid.MultiSelectionModelImpl;
+import com.vaadin.ui.components.grid.SingleSelectionModelImpl;
+
+import elemental.json.JsonObject;
+
+public class GridMultiSelectionModelTest {
+
+ public static final Person PERSON_C = new Person("c", 3);
+ public static final Person PERSON_B = new Person("b", 2);
+ public static final Person PERSON_A = new Person("a", 1);
+
+ private Grid<Person> grid;
+ private MultiSelectionModelImpl<Person> selectionModel;
+ private Capture<List<Person>> currentSelectionCapture;
+ private Capture<List<Person>> oldSelectionCapture;
+ private AtomicInteger events;
+
+ public static class CustomMultiSelectionModel
+ extends MultiSelectionModelImpl<String> {
+ public final Map<String, Boolean> generatedData = new LinkedHashMap<>();
+
+ public CustomMultiSelectionModel(Grid<String> grid) {
+ super(grid);
+ }
+
+ @Override
+ public void generateData(String item, JsonObject jsonObject) {
+ super.generateData(item, jsonObject);
+ // capture updated row
+ generatedData.put(item, isSelected(item));
+ }
+
+ }
+
+ @Before
+ public void setUp() {
+ grid = new Grid<>();
+ selectionModel = new MultiSelectionModelImpl<>(grid);
+ grid.setSelectionModel(selectionModel);
+ grid.setItems(PERSON_A, PERSON_B, PERSON_C);
+
+ currentSelectionCapture = new Capture<>();
+ oldSelectionCapture = new Capture<>();
+ events = new AtomicInteger();
+
+ selectionModel.addSelectionListener(event -> {
+ currentSelectionCapture
+ .setValue(new ArrayList<>(event.getNewSelection()));
+ oldSelectionCapture
+ .setValue(new ArrayList<>(event.getOldSelection()));
+ events.incrementAndGet();
+ });
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void selectionModelChanged_usingPreviousSelectionModel_throws() {
+ grid.setSelectionModel(new SingleSelectionModelImpl<>(grid));
+
+ selectionModel.select(PERSON_A);
+ }
+
+ @Test
+ public void changingSelectionModel_firesSelectionEvent() {
+ Grid<String> customGrid = new Grid<>();
+ customGrid.setSelectionModel(new MultiSelectionModelImpl<>(customGrid));
+ customGrid.setItems("Foo", "Bar", "Baz");
+
+ List<String> selectionChanges = new ArrayList<>();
+ Capture<List<String>> oldSelectionCapture = new Capture<>();
+ ((MultiSelectionModelImpl<String>) customGrid.getSelectionModel())
+ .addSelectionListener(e -> {
+ selectionChanges.addAll(e.getValue());
+ oldSelectionCapture
+ .setValue(new ArrayList<>(e.getOldSelection()));
+ });
+
+ customGrid.getSelectionModel().select("Foo");
+ assertEquals(Arrays.asList("Foo"), selectionChanges);
+ selectionChanges.clear();
+
+ customGrid.getSelectionModel().select("Bar");
+ assertEquals("Foo",
+ customGrid.getSelectionModel().getFirstSelectedItem().get());
+ assertEquals(Arrays.asList("Foo", "Bar"), selectionChanges);
+ selectionChanges.clear();
+
+ customGrid.setSelectionModel(new SingleSelectionModelImpl<>(customGrid));
+ assertFalse(customGrid.getSelectionModel().getFirstSelectedItem()
+ .isPresent());
+ assertEquals(Arrays.asList(), selectionChanges);
+ assertEquals(Arrays.asList("Foo", "Bar"),
+ oldSelectionCapture.getValue());
+ }
+
+ @Test
+ public void serverSideSelection_GridChangingSelectionModel_sendsUpdatedRowsToClient() {
+ Grid<String> customGrid = new Grid<>();
+ customGrid.setItems("Foo", "Bar", "Baz");
+
+ CustomMultiSelectionModel customModel = new CustomMultiSelectionModel(
+ customGrid);
+ customGrid.setSelectionModel(customModel);
+ customGrid.getDataCommunicator().beforeClientResponse(true);
+
+ Assert.assertFalse("Item should have been updated as selected",
+ customModel.generatedData.get("Foo"));
+ Assert.assertFalse("Item should have been updated as NOT selected",
+ customModel.generatedData.get("Bar"));
+ Assert.assertFalse("Item should have been updated as NOT selected",
+ customModel.generatedData.get("Baz"));
+
+ customModel.generatedData.clear();
+
+ customGrid.getSelectionModel().select("Foo");
+ customGrid.getDataCommunicator().beforeClientResponse(false);
+
+ Assert.assertTrue("Item should have been updated as selected",
+ customModel.generatedData.get("Foo"));
+ Assert.assertFalse("Item should have NOT been updated",
+ customModel.generatedData.containsKey("Bar"));
+ Assert.assertFalse("Item should have NOT been updated",
+ customModel.generatedData.containsKey("Baz"));
+
+ customModel.generatedData.clear();
+
+ customModel.updateSelection(asSet("Bar"), asSet("Foo"));
+ customGrid.getDataCommunicator().beforeClientResponse(false);
+
+ Assert.assertFalse("Item should have been updated as NOT selected",
+ customModel.generatedData.get("Foo"));
+ Assert.assertTrue("Item should have been updated as selected",
+ customModel.generatedData.get("Bar"));
+ Assert.assertFalse("Item should have NOT been updated",
+ customModel.generatedData.containsKey("Baz"));
+
+ // switch to single to cause event
+ customModel.generatedData.clear();
+ customGrid.setSelectionModel(new SingleSelectionModelImpl<>(customGrid));
+ customGrid.getDataCommunicator().beforeClientResponse(false);
+
+ // changing selection model should trigger row updates, but the old
+ // selection model is not triggered as it has been removed
+ Assert.assertTrue(customModel.generatedData.isEmpty()); // not triggered
+ }
+
+ @Test
+ public void select_gridWithStrings() {
+ Grid<String> gridWithStrings = new Grid<>();
+ gridWithStrings
+ .setSelectionModel(new MultiSelectionModelImpl<>(gridWithStrings));
+ gridWithStrings.setItems("Foo", "Bar", "Baz");
+
+ GridSelectionModel<String> model = gridWithStrings.getSelectionModel();
+ Assert.assertFalse(model.isSelected("Foo"));
+
+ model.select("Foo");
+ Assert.assertTrue(model.isSelected("Foo"));
+ Assert.assertEquals(Optional.of("Foo"), model.getFirstSelectedItem());
+
+ model.select("Bar");
+ Assert.assertTrue(model.isSelected("Foo"));
+ Assert.assertTrue(model.isSelected("Bar"));
+ Assert.assertEquals(Arrays.asList("Foo", "Bar"),
+ new ArrayList<>(model.getSelectedItems()));
+
+ model.deselect("Bar");
+ Assert.assertFalse(model.isSelected("Bar"));
+ Assert.assertTrue(model.getFirstSelectedItem().isPresent());
+ Assert.assertEquals(Arrays.asList("Foo"),
+ new ArrayList<>(model.getSelectedItems()));
+ }
+
+ @Test
+ public void select() {
+ selectionModel.select(PERSON_B);
+
+ assertEquals(PERSON_B,
+ selectionModel.getFirstSelectedItem().orElse(null));
+ assertEquals(Optional.of(PERSON_B),
+ selectionModel.getFirstSelectedItem());
+
+ assertFalse(selectionModel.isSelected(PERSON_A));
+ assertTrue(selectionModel.isSelected(PERSON_B));
+ assertFalse(selectionModel.isSelected(PERSON_C));
+
+ assertEquals(Arrays.asList(PERSON_B),
+ currentSelectionCapture.getValue());
+
+ selectionModel.select(PERSON_A);
+ assertEquals(PERSON_B,
+ selectionModel.getFirstSelectedItem().orElse(null));
+
+ assertTrue(selectionModel.isSelected(PERSON_A));
+ assertTrue(selectionModel.isSelected(PERSON_B));
+ assertFalse(selectionModel.isSelected(PERSON_C));
+
+ assertEquals(Arrays.asList(PERSON_B, PERSON_A),
+ currentSelectionCapture.getValue());
+ assertEquals(2, events.get());
+ }
+
+ @Test
+ public void deselect() {
+ selectionModel.select(PERSON_B);
+ selectionModel.deselect(PERSON_B);
+
+ assertFalse(selectionModel.getFirstSelectedItem().isPresent());
+
+ assertFalse(selectionModel.isSelected(PERSON_A));
+ assertFalse(selectionModel.isSelected(PERSON_B));
+ assertFalse(selectionModel.isSelected(PERSON_C));
+
+ assertEquals(Arrays.asList(), currentSelectionCapture.getValue());
+ assertEquals(2, events.get());
+ }
+
+ @Test
+ public void selectItems() {
+ selectionModel.selectItems(PERSON_C, PERSON_B);
+
+ assertEquals(PERSON_C,
+ selectionModel.getFirstSelectedItem().orElse(null));
+ assertEquals(Optional.of(PERSON_C),
+ selectionModel.getFirstSelectedItem());
+
+ assertFalse(selectionModel.isSelected(PERSON_A));
+ assertTrue(selectionModel.isSelected(PERSON_B));
+ assertTrue(selectionModel.isSelected(PERSON_C));
+
+ assertEquals(Arrays.asList(PERSON_C, PERSON_B),
+ currentSelectionCapture.getValue());
+
+ selectionModel.selectItems(PERSON_A, PERSON_C); // partly NOOP
+ assertTrue(selectionModel.isSelected(PERSON_A));
+ assertTrue(selectionModel.isSelected(PERSON_B));
+ assertTrue(selectionModel.isSelected(PERSON_C));
+
+ assertEquals(Arrays.asList(PERSON_C, PERSON_B, PERSON_A),
+ currentSelectionCapture.getValue());
+ assertEquals(2, events.get());
+ }
+
+ @Test
+ public void deselectItems() {
+ selectionModel.selectItems(PERSON_C, PERSON_A, PERSON_B);
+
+ selectionModel.deselectItems(PERSON_A);
+ assertEquals(PERSON_C,
+ selectionModel.getFirstSelectedItem().orElse(null));
+ assertEquals(Optional.of(PERSON_C),
+ selectionModel.getFirstSelectedItem());
+
+ assertFalse(selectionModel.isSelected(PERSON_A));
+ assertTrue(selectionModel.isSelected(PERSON_B));
+ assertTrue(selectionModel.isSelected(PERSON_C));
+
+ assertEquals(Arrays.asList(PERSON_C, PERSON_B),
+ currentSelectionCapture.getValue());
+
+ selectionModel.deselectItems(PERSON_A, PERSON_B, PERSON_C);
+ assertNull(selectionModel.getFirstSelectedItem().orElse(null));
+ assertEquals(Optional.empty(), selectionModel.getFirstSelectedItem());
+
+ assertFalse(selectionModel.isSelected(PERSON_A));
+ assertFalse(selectionModel.isSelected(PERSON_B));
+ assertFalse(selectionModel.isSelected(PERSON_C));
+
+ assertEquals(Arrays.asList(), currentSelectionCapture.getValue());
+ assertEquals(3, events.get());
+ }
+
+ @Test
+ public void selectionEvent_newSelection_oldSelection() {
+ selectionModel.selectItems(PERSON_C, PERSON_A, PERSON_B);
+
+ assertEquals(Arrays.asList(PERSON_C, PERSON_A, PERSON_B),
+ currentSelectionCapture.getValue());
+ assertEquals(Arrays.asList(), oldSelectionCapture.getValue());
+
+ selectionModel.deselect(PERSON_A);
+
+ assertEquals(Arrays.asList(PERSON_C, PERSON_B),
+ currentSelectionCapture.getValue());
+ assertEquals(Arrays.asList(PERSON_C, PERSON_A, PERSON_B),
+ oldSelectionCapture.getValue());
+
+ selectionModel.deselectItems(PERSON_A, PERSON_B, PERSON_C);
+ assertEquals(Arrays.asList(), currentSelectionCapture.getValue());
+ assertEquals(Arrays.asList(PERSON_C, PERSON_B),
+ oldSelectionCapture.getValue());
+
+ selectionModel.selectItems(PERSON_A);
+ assertEquals(Arrays.asList(PERSON_A),
+ currentSelectionCapture.getValue());
+ assertEquals(Arrays.asList(), oldSelectionCapture.getValue());
+
+ selectionModel.updateSelection(
+ new LinkedHashSet<>(Arrays.asList(PERSON_B, PERSON_C)),
+ new LinkedHashSet<>(Arrays.asList(PERSON_A)));
+ assertEquals(Arrays.asList(PERSON_B, PERSON_C),
+ currentSelectionCapture.getValue());
+ assertEquals(Arrays.asList(PERSON_A), oldSelectionCapture.getValue());
+
+ selectionModel.deselectAll();
+ assertEquals(Arrays.asList(), currentSelectionCapture.getValue());
+ assertEquals(Arrays.asList(PERSON_B, PERSON_C),
+ oldSelectionCapture.getValue());
+
+ selectionModel.select(PERSON_C);
+ assertEquals(Arrays.asList(PERSON_C),
+ currentSelectionCapture.getValue());
+ assertEquals(Arrays.asList(), oldSelectionCapture.getValue());
+
+ selectionModel.deselect(PERSON_C);
+ assertEquals(Arrays.asList(), currentSelectionCapture.getValue());
+ assertEquals(Arrays.asList(PERSON_C), oldSelectionCapture.getValue());
+ }
+
+ @Test
+ public void deselectAll() {
+ selectionModel.selectItems(PERSON_A, PERSON_C, PERSON_B);
+
+ assertTrue(selectionModel.isSelected(PERSON_A));
+ assertTrue(selectionModel.isSelected(PERSON_B));
+ assertTrue(selectionModel.isSelected(PERSON_C));
+ assertEquals(Arrays.asList(PERSON_A, PERSON_C, PERSON_B),
+ currentSelectionCapture.getValue());
+ assertEquals(1, events.get());
+
+ selectionModel.deselectAll();
+ assertFalse(selectionModel.isSelected(PERSON_A));
+ assertFalse(selectionModel.isSelected(PERSON_B));
+ assertFalse(selectionModel.isSelected(PERSON_C));
+ assertEquals(Arrays.asList(), currentSelectionCapture.getValue());
+ assertEquals(Arrays.asList(PERSON_A, PERSON_C, PERSON_B),
+ oldSelectionCapture.getValue());
+ assertEquals(2, events.get());
+
+ selectionModel.select(PERSON_C);
+ assertFalse(selectionModel.isSelected(PERSON_A));
+ assertFalse(selectionModel.isSelected(PERSON_B));
+ assertTrue(selectionModel.isSelected(PERSON_C));
+ assertEquals(Arrays.asList(PERSON_C),
+ currentSelectionCapture.getValue());
+ assertEquals(Arrays.asList(), oldSelectionCapture.getValue());
+ assertEquals(3, events.get());
+
+ selectionModel.deselectAll();
+ assertFalse(selectionModel.isSelected(PERSON_A));
+ assertFalse(selectionModel.isSelected(PERSON_B));
+ assertFalse(selectionModel.isSelected(PERSON_C));
+ assertEquals(Arrays.asList(), currentSelectionCapture.getValue());
+ assertEquals(Arrays.asList(PERSON_C), oldSelectionCapture.getValue());
+ assertEquals(4, events.get());
+
+ selectionModel.deselectAll();
+ assertEquals(4, events.get());
+ }
+
+ @Test
+ public void updateSelection() {
+ selectionModel.updateSelection(asSet(PERSON_A), Collections.emptySet());
+
+ assertTrue(selectionModel.isSelected(PERSON_A));
+ assertFalse(selectionModel.isSelected(PERSON_B));
+ assertFalse(selectionModel.isSelected(PERSON_C));
+ assertEquals(Arrays.asList(PERSON_A),
+ currentSelectionCapture.getValue());
+ assertEquals(1, events.get());
+
+ selectionModel.updateSelection(asSet(PERSON_B), asSet(PERSON_A));
+
+ assertFalse(selectionModel.isSelected(PERSON_A));
+ assertTrue(selectionModel.isSelected(PERSON_B));
+ assertFalse(selectionModel.isSelected(PERSON_C));
+ assertEquals(Arrays.asList(PERSON_B),
+ currentSelectionCapture.getValue());
+ assertEquals(Arrays.asList(PERSON_A), oldSelectionCapture.getValue());
+ assertEquals(2, events.get());
+
+ selectionModel.updateSelection(asSet(PERSON_B), asSet(PERSON_A)); // NOOP
+
+ assertFalse(selectionModel.isSelected(PERSON_A));
+ assertTrue(selectionModel.isSelected(PERSON_B));
+ assertFalse(selectionModel.isSelected(PERSON_C));
+ assertEquals(Arrays.asList(PERSON_B),
+ currentSelectionCapture.getValue());
+ assertEquals(Arrays.asList(PERSON_A), oldSelectionCapture.getValue());
+ assertEquals(2, events.get());
+
+ selectionModel.updateSelection(asSet(PERSON_A, PERSON_C),
+ asSet(PERSON_A)); // partly NOOP
+
+ assertFalse(selectionModel.isSelected(PERSON_A));
+ assertTrue(selectionModel.isSelected(PERSON_B));
+ assertTrue(selectionModel.isSelected(PERSON_C));
+ assertEquals(Arrays.asList(PERSON_B, PERSON_C),
+ currentSelectionCapture.getValue());
+ assertEquals(Arrays.asList(PERSON_B), oldSelectionCapture.getValue());
+ assertEquals(3, events.get());
+
+ selectionModel.updateSelection(asSet(PERSON_B, PERSON_A),
+ asSet(PERSON_B)); // partly NOOP
+
+ assertTrue(selectionModel.isSelected(PERSON_A));
+ assertTrue(selectionModel.isSelected(PERSON_B));
+ assertTrue(selectionModel.isSelected(PERSON_C));
+ assertEquals(Arrays.asList(PERSON_B, PERSON_C, PERSON_A),
+ currentSelectionCapture.getValue());
+ assertEquals(Arrays.asList(PERSON_B, PERSON_C),
+ oldSelectionCapture.getValue());
+ assertEquals(4, events.get());
+
+ selectionModel.updateSelection(asSet(),
+ asSet(PERSON_B, PERSON_A, PERSON_C));
+
+ assertFalse(selectionModel.isSelected(PERSON_A));
+ assertFalse(selectionModel.isSelected(PERSON_B));
+ assertFalse(selectionModel.isSelected(PERSON_C));
+ assertEquals(Arrays.asList(), currentSelectionCapture.getValue());
+ assertEquals(Arrays.asList(PERSON_B, PERSON_C, PERSON_A),
+ oldSelectionCapture.getValue());
+ assertEquals(5, events.get());
+ }
+
+ private <T> Set<T> asSet(@SuppressWarnings("unchecked") T... people) {
+ return new LinkedHashSet<>(Arrays.asList(people));
+ }
+
+ @Test
+ public void selectTwice() {
+ selectionModel.select(PERSON_C);
+ selectionModel.select(PERSON_C);
+
+ assertEquals(PERSON_C,
+ selectionModel.getFirstSelectedItem().orElse(null));
+
+ assertFalse(selectionModel.isSelected(PERSON_A));
+ assertFalse(selectionModel.isSelected(PERSON_B));
+ assertTrue(selectionModel.isSelected(PERSON_C));
+
+ assertEquals(Optional.of(PERSON_C),
+ selectionModel.getFirstSelectedItem());
+
+ assertEquals(Arrays.asList(PERSON_C),
+ currentSelectionCapture.getValue());
+ assertEquals(1, events.get());
+ }
+
+ @Test
+ public void deselectTwice() {
+ selectionModel.select(PERSON_C);
+ assertEquals(Arrays.asList(PERSON_C),
+ currentSelectionCapture.getValue());
+ assertEquals(1, events.get());
+
+ selectionModel.deselect(PERSON_C);
+
+ assertFalse(selectionModel.getFirstSelectedItem().isPresent());
+ assertFalse(selectionModel.isSelected(PERSON_C));
+ assertEquals(Arrays.asList(), currentSelectionCapture.getValue());
+ assertEquals(2, events.get());
+
+ selectionModel.deselect(PERSON_C);
+
+ assertFalse(selectionModel.getFirstSelectedItem().isPresent());
+ assertFalse(selectionModel.isSelected(PERSON_A));
+ assertFalse(selectionModel.isSelected(PERSON_B));
+ assertFalse(selectionModel.isSelected(PERSON_C));
+ assertEquals(Arrays.asList(), currentSelectionCapture.getValue());
+ assertEquals(2, events.get());
+ }
+
+ @SuppressWarnings({ "serial" })
+ @Test
+ public void addValueChangeListener() {
+ AtomicReference<SingleSelectionListener<String>> selectionListener = new AtomicReference<>();
+ Registration registration = Mockito.mock(Registration.class);
+ Grid<String> grid = new Grid<>();
+ grid.setItems("foo", "bar");
+ String value = "foo";
+ SingleSelectionModelImpl<String> select = new SingleSelectionModelImpl<String>(
+ grid) {
+ @Override
+ public Registration addSelectionListener(
+ SingleSelectionListener<String> listener) {
+ selectionListener.set(listener);
+ return registration;
+ }
+
+ @Override
+ public Optional<String> getSelectedItem() {
+ return Optional.of(value);
+ }
+ };
+
+ AtomicReference<ValueChangeEvent<?>> event = new AtomicReference<>();
+ Registration actualRegistration = select.addSelectionListener(evt -> {
+ Assert.assertNull(event.get());
+ event.set(evt);
+ });
+ Assert.assertSame(registration, actualRegistration);
+
+ selectionListener.get().accept(new SingleSelectionEvent<>(grid,
+ select.asSingleSelect(), true));
+
+ Assert.assertEquals(grid, event.get().getComponent());
+ Assert.assertEquals(value, event.get().getValue());
+ Assert.assertTrue(event.get().isUserOriginated());
+ }
+}
diff --git a/server/src/test/java/com/vaadin/tests/components/grid/GridSingleSelectionModelTest.java b/server/src/test/java/com/vaadin/tests/components/grid/GridSingleSelectionModelTest.java
index 67b35c5208..17b409c1a6 100644
--- a/server/src/test/java/com/vaadin/tests/components/grid/GridSingleSelectionModelTest.java
+++ b/server/src/test/java/com/vaadin/tests/components/grid/GridSingleSelectionModelTest.java
@@ -6,7 +6,9 @@ import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
@@ -20,62 +22,124 @@ import com.vaadin.event.selection.SingleSelectionEvent;
import com.vaadin.event.selection.SingleSelectionListener;
import com.vaadin.server.data.provider.bov.Person;
import com.vaadin.shared.Registration;
-import com.vaadin.shared.data.DataCommunicatorClientRpc;
import com.vaadin.ui.Grid;
import com.vaadin.ui.Grid.GridSelectionModel;
-import com.vaadin.ui.components.grid.SingleSelectionModel;
+import com.vaadin.ui.components.grid.MultiSelectionModelImpl;
+import com.vaadin.ui.components.grid.SingleSelectionModelImpl;
+
+import elemental.json.JsonObject;
public class GridSingleSelectionModelTest {
public static final Person PERSON_C = new Person("c", 3);
public static final Person PERSON_B = new Person("b", 2);
public static final Person PERSON_A = new Person("a", 1);
- public static final String RPC_INTERFACE = DataCommunicatorClientRpc.class
- .getName();
- private class CustomSelectionModelGrid extends Grid<String> {
- public void switchSelectionModel() {
- // just switch selection model to cause event
- setSelectionModel(new SingleSelectionModel(this));
+ public static class CustomSingleSelectionModel
+ extends SingleSelectionModelImpl<String> {
+ public final Map<String, Boolean> generatedData = new LinkedHashMap<>();
+
+ public CustomSingleSelectionModel(Grid<String> grid) {
+ super(grid);
}
+
+ @Override
+ public void generateData(String item, JsonObject jsonObject) {
+ super.generateData(item, jsonObject);
+ // capture updated row
+ generatedData.put(item, isSelected(item));
+ }
+
}
private List<Person> selectionChanges;
private Grid<Person> grid;
- private SingleSelectionModel<Person> selectionModel;
+ private SingleSelectionModelImpl<Person> selectionModel;
@Before
public void setUp() {
grid = new Grid<>();
grid.setItems(PERSON_A, PERSON_B, PERSON_C);
- selectionModel = (SingleSelectionModel<Person>) grid
+ selectionModel = (SingleSelectionModelImpl<Person>) grid
.getSelectionModel();
selectionChanges = new ArrayList<>();
- selectionModel.addSelectionChangeListener(
- e -> selectionChanges.add(e.getValue()));
+ selectionModel
+ .addSelectionListener(e -> selectionChanges.add(e.getValue()));
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void selectionModelChanged_usingPreviousSelectionModel_throws() {
+ grid.setSelectionModel(new MultiSelectionModelImpl<>(grid));
+
+ selectionModel.select(PERSON_A);
}
@Test
- public void testGridChangingSelectionModel_firesSelectionChangeEvent() {
- CustomSelectionModelGrid customGrid = new CustomSelectionModelGrid();
+ public void gridChangingSelectionModel_firesSelectionChangeEvent() {
+ Grid<String> customGrid = new Grid<>();
customGrid.setItems("Foo", "Bar", "Baz");
List<String> selectionChanges = new ArrayList<>();
- ((SingleSelectionModel<String>) customGrid.getSelectionModel())
- .addSelectionChangeListener(
- e -> selectionChanges.add(e.getValue()));
+ ((SingleSelectionModelImpl<String>) customGrid.getSelectionModel())
+ .addSelectionListener(e -> selectionChanges.add(e.getValue()));
customGrid.getSelectionModel().select("Foo");
assertEquals("Foo",
customGrid.getSelectionModel().getFirstSelectedItem().get());
assertEquals(Arrays.asList("Foo"), selectionChanges);
- customGrid.switchSelectionModel();
+ customGrid
+ .setSelectionModel(new CustomSingleSelectionModel(customGrid));
assertEquals(Arrays.asList("Foo", null), selectionChanges);
}
@Test
+ public void serverSideSelection_GridChangingSelectionModel_sendsUpdatedRowsToClient() {
+ Grid<String> customGrid = new Grid<>();
+ customGrid.setItems("Foo", "Bar", "Baz");
+
+ CustomSingleSelectionModel customModel = new CustomSingleSelectionModel(
+ customGrid);
+ customGrid.setSelectionModel(customModel);
+
+ customGrid.getDataCommunicator().beforeClientResponse(true);
+
+ Assert.assertFalse("Item should have been updated as selected",
+ customModel.generatedData.get("Foo"));
+ Assert.assertFalse("Item should have been updated as NOT selected",
+ customModel.generatedData.get("Bar"));
+ Assert.assertFalse("Item should have been updated as NOT selected",
+ customModel.generatedData.get("Baz"));
+
+ customModel.generatedData.clear();
+
+ customGrid.getSelectionModel().select("Foo");
+ customGrid.getDataCommunicator().beforeClientResponse(false);
+
+ Assert.assertTrue("Item should have been updated as selected",
+ customModel.generatedData.get("Foo"));
+ Assert.assertFalse("Item should have NOT been updated",
+ customModel.generatedData.containsKey("Bar"));
+ Assert.assertFalse("Item should have NOT been updated",
+ customModel.generatedData.containsKey("Baz"));
+
+ // switch to another selection model to cause event
+ customModel.generatedData.clear();
+ customGrid.setSelectionModel(new SingleSelectionModelImpl<>(customGrid));
+ customGrid.getDataCommunicator().beforeClientResponse(false);
+
+ // since the selection model has been removed, it is no longer a data
+ // generator for the data communicator, would need to verify somehow
+ // that row is not marked as selected anymore ? (done in UI tests)
+ Assert.assertTrue(customModel.generatedData.isEmpty()); // at least
+ // removed
+ // selection
+ // model is not
+ // triggered
+ }
+
+ @Test
public void testGridWithSingleSelection() {
Grid<String> gridWithStrings = new Grid<>();
gridWithStrings.setItems("Foo", "Bar", "Baz");
@@ -210,10 +274,10 @@ public class GridSingleSelectionModelTest {
Grid<String> grid = new Grid<>();
grid.setItems("foo", "bar");
String value = "foo";
- SingleSelectionModel<String> select = new SingleSelectionModel<String>(
+ SingleSelectionModelImpl<String> select = new SingleSelectionModelImpl<String>(
grid) {
@Override
- public Registration addSelectionChangeListener(
+ public Registration addSelectionListener(
SingleSelectionListener<String> listener) {
selectionListener.set(listener);
return registration;
@@ -226,11 +290,10 @@ public class GridSingleSelectionModelTest {
};
AtomicReference<ValueChangeEvent<?>> event = new AtomicReference<>();
- Registration actualRegistration = select
- .addSelectionChangeListener(evt -> {
- Assert.assertNull(event.get());
- event.set(evt);
- });
+ Registration actualRegistration = select.addSelectionListener(evt -> {
+ Assert.assertNull(event.get());
+ event.set(evt);
+ });
Assert.assertSame(registration, actualRegistration);
selectionListener.get().accept(new SingleSelectionEvent<>(grid,