/*
* Copyright 2000-2014 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.vaadin.ui;
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.Collection;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicReference;
import org.jsoup.nodes.Element;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import com.vaadin.data.HasDataProvider;
import com.vaadin.data.HasValue.ValueChangeEvent;
import com.vaadin.data.provider.DataProvider;
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.shared.data.DataCommunicatorClientRpc;
import com.vaadin.ui.declarative.DesignContext;
/**
* Test for {@link AbstractSingleSelect} and {@link AbstractSingleSelection}
*
* @author Vaadin Ltd
*/
public class AbstractSingleSelectTest {
private List<Person> selectionChanges;
private List<Person> oldSelections;
private static class PersonListing extends AbstractSingleSelect<Person>
implements HasDataProvider<Person> {
@Override
protected Element writeItem(Element design, Person item,
DesignContext context) {
return null;
}
@Override
protected void readItems(Element design, DesignContext context) {
}
@Override
public DataProvider<Person, ?> getDataProvider() {
return internalGetDataProvider();
}
@Override
public void setDataProvider(DataProvider<Person, ?> dataProvider) {
internalSetDataProvider(dataProvider);
}
}
@Before
public void initListing() {
listing = new PersonListing();
listing.setItems(PERSON_A, PERSON_B, PERSON_C);
selectionChanges = new ArrayList<>();
oldSelections = new ArrayList<>();
listing.addSelectionListener(e -> selectionChanges.add(e.getValue()));
listing.addSelectionListener(e -> oldSelections.add(e.getOldValue()));
}
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 PersonListing listing;
@Test
public void select() {
listing.setValue(PERSON_B);
assertTrue(listing.getSelectedItem().isPresent());
assertEquals(PERSON_B, listing.getSelectedItem().orElse(null));
assertFalse(listing.isSelected(PERSON_A));
assertTrue(listing.isSelected(PERSON_B));
assertFalse(listing.isSelected(PERSON_C));
assertEquals(Optional.of(PERSON_B), listing.getSelectedItem());
assertEquals(Arrays.asList(PERSON_B), selectionChanges);
verifyValueChanges();
}
@Test
public void selectDeselect() {
listing.setValue(PERSON_B);
listing.setValue(null);
assertFalse(listing.getSelectedItem().isPresent());
assertFalse(listing.isSelected(PERSON_A));
assertFalse(listing.isSelected(PERSON_B));
assertFalse(listing.isSelected(PERSON_C));
assertFalse(listing.getSelectedItem().isPresent());
assertEquals(Arrays.asList(PERSON_B, null), selectionChanges);
verifyValueChanges();
}
@Test
public void reselect() {
listing.setValue(PERSON_B);
listing.setValue(PERSON_C);
assertEquals(PERSON_C, listing.getSelectedItem().orElse(null));
assertFalse(listing.isSelected(PERSON_A));
assertFalse(listing.isSelected(PERSON_B));
assertTrue(listing.isSelected(PERSON_C));
assertEquals(Optional.of(PERSON_C), listing.getSelectedItem());
assertEquals(Arrays.asList(PERSON_B, PERSON_C), selectionChanges);
verifyValueChanges();
}
@Test
public void selectTwice() {
listing.setValue(PERSON_C);
listing.setValue(PERSON_C);
assertEquals(PERSON_C, listing.getSelectedItem().orElse(null));
assertFalse(listing.isSelected(PERSON_A));
assertFalse(listing.isSelected(PERSON_B));
assertTrue(listing.isSelected(PERSON_C));
assertEquals(Optional.of(PERSON_C), listing.getSelectedItem());
assertEquals(Arrays.asList(PERSON_C), selectionChanges);
verifyValueChanges();
}
@Test
public void deselectTwice() {
listing.setValue(PERSON_C);
listing.setValue(null);
listing.setValue(null);
assertFalse(listing.getSelectedItem().isPresent());
assertFalse(listing.isSelected(PERSON_A));
assertFalse(listing.isSelected(PERSON_B));
assertFalse(listing.isSelected(PERSON_C));
assertFalse(listing.getSelectedItem().isPresent());
assertEquals(Arrays.asList(PERSON_C, null), selectionChanges);
verifyValueChanges();
}
@Test
public void getValue() {
listing.setSelectedItem(PERSON_B);
Assert.assertEquals(PERSON_B, listing.getValue());
listing.setValue(null);
Assert.assertNull(listing.getValue());
verifyValueChanges();
}
@Test
@SuppressWarnings({ "rawtypes" })
public void getValue_isDelegatedTo_getSelectedItem() {
AbstractSingleSelect select = Mockito.mock(AbstractSingleSelect.class);
Optional selected = Optional.of(new Object());
Mockito.when(select.getSelectedItem()).thenReturn(selected);
Mockito.doCallRealMethod().when(select).getValue();
Assert.assertSame(selected.get(), select.getValue());
selected = Optional.empty();
Mockito.when(select.getSelectedItem()).thenReturn(selected);
Assert.assertNull(select.getValue());
}
@Test
public void setValue() {
listing.setValue(PERSON_C);
Assert.assertEquals(PERSON_C, listing.getSelectedItem().get());
listing.setValue(null);
Assert.assertFalse(listing.getSelectedItem().isPresent());
verifyValueChanges();
}
@Test
@SuppressWarnings({ "rawtypes", "unchecked" })
public void setValue_isDelegatedTo_setSelectedItem() {
AbstractSingleSelect select = Mockito.mock(AbstractSingleSelect.class);
Mockito.doCallRealMethod().when(select).setValue(Mockito.any());
Object value = new Object();
select.setValue(value);
Mockito.verify(select).setSelectedItem(value);
select.setValue(null);
Mockito.verify(select).setSelectedItem(null);
}
@SuppressWarnings("serial")
@Test
public void addValueChangeListener() {
AtomicReference<SingleSelectionListener<String>> selectionListener = new AtomicReference<>();
Registration registration = Mockito.mock(Registration.class);
String value = "foo";
AbstractSingleSelect<String> select = new AbstractSingleSelect<String>() {
@Override
public Registration addSelectionListener(
SingleSelectionListener<String> listener) {
selectionListener.set(listener);
return registration;
}
@Override
public String getValue() {
return value;
}
@Override
protected Element writeItem(Element design, String item,
DesignContext context) {
return null;
}
@Override
protected void readItems(Element design, DesignContext context) {
}
@Override
public void setItems(Collection<String> items) {
throw new UnsupportedOperationException(
"Not needed in this test");
}
@Override
public DataProvider<String, ?> getDataProvider() {
return null;
}
};
AtomicReference<ValueChangeEvent<?>> event = new AtomicReference<>();
Registration actualRegistration = select.addValueChangeListener(evt -> {
Assert.assertNull(event.get());
event.set(evt);
});
Assert.assertSame(registration, actualRegistration);
selectionListener.get().selectionChange(
new SingleSelectionEvent<>(select, value, true));
Assert.assertEquals(select, event.get().getComponent());
Assert.assertEquals(value, event.get().getOldValue());
Assert.assertEquals(value, event.get().getValue());
Assert.assertTrue(event.get().isUserOriginated());
}
private void verifyValueChanges() {
if (oldSelections.size() > 0) {
assertEquals(null, oldSelections.get(0));
assertEquals(selectionChanges.size(), oldSelections.size());
for (int i = 0; i < oldSelections.size() - 1; i++) {
assertEquals(selectionChanges.get(i), oldSelections.get(i + 1));
}
}
}
}