package com.vaadin.tests.components.grid;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
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;
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.data.provider.bov.Person;
import com.vaadin.event.selection.SingleSelectionEvent;
import com.vaadin.event.selection.SingleSelectionListener;
import com.vaadin.shared.Registration;
import com.vaadin.ui.Grid;
import com.vaadin.ui.Grid.SelectionMode;
import com.vaadin.ui.components.grid.GridSelectionModel;
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 class CustomSingleSelectionModel
extends SingleSelectionModelImpl<String> {
public final Map<String, Boolean> generatedData = new LinkedHashMap<>();
@Override
public void generateData(String item, JsonObject jsonObject) {
super.generateData(item, jsonObject);
// capture updated row
generatedData.put(item, isSelected(item));
}
}
private static class TestSingleSelectionModel
extends SingleSelectionModelImpl<Object> {
public TestSingleSelectionModel() {
getState(false).selectionAllowed = false;
}
@Override
protected void setSelectedFromClient(String key) {
super.setSelectedFromClient(key);
}
}
private List<Person> selectionChanges;
private Grid<Person> grid;
private SingleSelectionModelImpl<Person> selectionModel;
@Before
public void setUp() {
grid = new Grid<>();
grid.setItems(PERSON_A, PERSON_B, PERSON_C);
selectionModel = (SingleSelectionModelImpl<Person>) grid
.getSelectionModel();
selectionChanges = new ArrayList<>();
selectionModel.addSingleSelectionListener(
e -> selectionChanges.add(e.getValue()));
}
@Test(expected = IllegalStateException.class)
public void throwExceptionWhenSelectionIsDisallowed() {
TestSingleSelectionModel model = new TestSingleSelectionModel();
model.setSelectedFromClient("foo");
}
@Test(expected = IllegalStateException.class)
public void selectionModelChanged_usingPreviousSelectionModel_throws() {
grid.setSelectionMode(SelectionMode.MULTI);
selectionModel.select(PERSON_A);
}
@Test
public void gridChangingSelectionModel_firesSelectionChangeEvent() {
Grid<String> customGrid = new Grid<>();
customGrid.setItems("Foo", "Bar", "Baz");
List<String> selectionChanges = new ArrayList<>();
List<String> oldSelectionValues = new ArrayList<>();
((SingleSelectionModelImpl<String>) customGrid.getSelectionModel())
.addSingleSelectionListener(e -> {
selectionChanges.add(e.getValue());
oldSelectionValues.add(e.getOldValue());
});
customGrid.getSelectionModel().select("Foo");
assertEquals("Foo",
customGrid.getSelectionModel().getFirstSelectedItem().get());
assertEquals(Arrays.asList("Foo"), selectionChanges);
assertEquals(Arrays.asList((String) null), oldSelectionValues);
customGrid.setSelectionMode(SelectionMode.MULTI);
assertEquals(Arrays.asList("Foo", null), selectionChanges);
assertEquals(Arrays.asList(null, "Foo"), oldSelectionValues);
}
@Test
public void serverSideSelection_GridChangingSelectionModel_sendsUpdatedRowsToClient() {
CustomSingleSelectionModel customModel = new CustomSingleSelectionModel();
Grid<String> customGrid = new Grid<String>() {
{
setSelectionModel(customModel);
}
};
customGrid.setItems("Foo", "Bar", "Baz");
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.setSelectionMode(SelectionMode.MULTI);
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");
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.assertFalse(model.isSelected("Foo"));
Assert.assertTrue(model.isSelected("Bar"));
model.deselect("Bar");
Assert.assertFalse(model.isSelected("Bar"));
Assert.assertFalse(model.getFirstSelectedItem().isPresent());
}
@Test
public void select_isSelected() {
selectionModel.select(PERSON_B);
assertTrue(selectionModel.getSelectedItem().isPresent());
assertEquals(PERSON_B, selectionModel.getSelectedItem().orElse(null));
assertFalse(selectionModel.isSelected(PERSON_A));
assertTrue(selectionModel.isSelected(PERSON_B));
assertFalse(selectionModel.isSelected(PERSON_C));
assertEquals(Optional.of(PERSON_B), selectionModel.getSelectedItem());
assertEquals(Arrays.asList(PERSON_B), selectionChanges);
}
@Test
public void selectDeselect() {
selectionModel.select(PERSON_B);
selectionModel.deselect(PERSON_B);
assertFalse(selectionModel.getSelectedItem().isPresent());
assertFalse(selectionModel.isSelected(PERSON_A));
assertFalse(selectionModel.isSelected(PERSON_B));
assertFalse(selectionModel.isSelected(PERSON_C));
assertFalse(selectionModel.getSelectedItem().isPresent());
assertEquals(Arrays.asList(PERSON_B, null), selectionChanges);
}
@Test
public void reselect() {
selectionModel.select(PERSON_B);
selectionModel.select(PERSON_C);
assertEquals(PERSON_C, selectionModel.getSelectedItem().orElse(null));
assertFalse(selectionModel.isSelected(PERSON_A));
assertFalse(selectionModel.isSelected(PERSON_B));
assertTrue(selectionModel.isSelected(PERSON_C));
assertEquals(Optional.of(PERSON_C), selectionModel.getSelectedItem());
assertEquals(Arrays.asList(PERSON_B, PERSON_C), selectionChanges);
}
@Test
public void selectTwice() {
selectionModel.select(PERSON_C);
selectionModel.select(PERSON_C);
assertEquals(PERSON_C, selectionModel.getSelectedItem().orElse(null));
assertFalse(selectionModel.isSelected(PERSON_A));
assertFalse(selectionModel.isSelected(PERSON_B));
assertTrue(selectionModel.isSelected(PERSON_C));
assertEquals(Optional.of(PERSON_C), selectionModel.getSelectedItem());
assertEquals(Arrays.asList(PERSON_C), selectionChanges);
}
@Test
public void deselectTwice() {
selectionModel.select(PERSON_C);
selectionModel.deselect(PERSON_C);
selectionModel.deselect(PERSON_C);
assertFalse(selectionModel.getSelectedItem().isPresent());
assertFalse(selectionModel.isSelected(PERSON_A));
assertFalse(selectionModel.isSelected(PERSON_B));
assertFalse(selectionModel.isSelected(PERSON_C));
assertFalse(selectionModel.getSelectedItem().isPresent());
assertEquals(Arrays.asList(PERSON_C, null), selectionChanges);
}
@Test
public void getSelectedItem() {
selectionModel.setSelectedItem(PERSON_B);
Assert.assertEquals(PERSON_B, selectionModel.getSelectedItem().get());
selectionModel.deselect(PERSON_B);
Assert.assertFalse(selectionModel.getSelectedItem().isPresent());
}
@Test
public void select_deselect_getSelectedItem() {
selectionModel.select(PERSON_C);
Assert.assertEquals(PERSON_C, selectionModel.getSelectedItem().get());
selectionModel.deselect(PERSON_C);
Assert.assertFalse(selectionModel.getSelectedItem().isPresent());
}
@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>() {
@Override
public Registration addSingleSelectionListener(
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
.addSingleSelectionListener(evt -> {
Assert.assertNull(event.get());
event.set(evt);
});
Assert.assertSame(registration, actualRegistration);
selectionListener.get().selectionChange(new SingleSelectionEvent<>(grid,
select.asSingleSelect(), null, true));
Assert.assertEquals(grid, event.get().getComponent());
Assert.assertEquals(value, event.get().getValue());
Assert.assertEquals(null, event.get().getOldValue());
Assert.assertTrue(event.get().isUserOriginated());
}
}