diff options
author | Artur Signell <artur@vaadin.com> | 2016-08-18 18:04:59 +0300 |
---|---|---|
committer | Artur Signell <artur@vaadin.com> | 2016-08-20 00:08:44 +0300 |
commit | 6e0f2efe996cfd3b38c960e04cbced0a91215cf0 (patch) | |
tree | 9eafac7107b3d34d8d1e9bc7631a1debad4fd720 /compatibility-server/src/test | |
parent | 016a2ceb86f771a3902ace98d9fe56351c0efdf2 (diff) | |
download | vaadin-framework-6e0f2efe996cfd3b38c960e04cbced0a91215cf0.tar.gz vaadin-framework-6e0f2efe996cfd3b38c960e04cbced0a91215cf0.zip |
Move FieldGroup and Vaadin 7 Grid to compatibility package
Change-Id: I9aaef478e0b67462641239802b924b8461cb9225
Diffstat (limited to 'compatibility-server/src/test')
63 files changed, 12139 insertions, 0 deletions
diff --git a/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/BeanFieldGroupTest.java b/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/BeanFieldGroupTest.java new file mode 100644 index 0000000000..3333cd7744 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/BeanFieldGroupTest.java @@ -0,0 +1,70 @@ +/* + * Copyright 2012 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.data.fieldgroup; + +import org.junit.Assert; +import org.junit.Test; + +public class BeanFieldGroupTest { + + class Main { + private String mainField; + + public String getMainField() { + return mainField; + } + + public void setMainField(String mainField) { + this.mainField = mainField; + } + + } + + class Sub1 extends Main { + private Integer sub1Field; + + public Integer getSub1Field() { + return sub1Field; + } + + public void setSub1Field(Integer sub1Field) { + this.sub1Field = sub1Field; + } + + } + + class Sub2 extends Sub1 { + private boolean sub2field; + + public boolean isSub2field() { + return sub2field; + } + + public void setSub2field(boolean sub2field) { + this.sub2field = sub2field; + } + + } + + @Test + public void propertyTypeWithoutItem() { + BeanFieldGroup<Sub2> s = new BeanFieldGroup<BeanFieldGroupTest.Sub2>( + Sub2.class); + Assert.assertEquals(boolean.class, s.getPropertyType("sub2field")); + Assert.assertEquals(Integer.class, s.getPropertyType("sub1Field")); + Assert.assertEquals(String.class, s.getPropertyType("mainField")); + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactoryTest.java b/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactoryTest.java new file mode 100644 index 0000000000..93aa1350b0 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/DefaultFieldGroupFieldFactoryTest.java @@ -0,0 +1,125 @@ +/* + * Copyright 2000-2016 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.data.fieldgroup; + +import java.lang.reflect.Constructor; +import java.util.Date; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.fieldgroup.DefaultFieldGroupFieldFactory; +import com.vaadin.ui.AbstractSelect; +import com.vaadin.ui.ComboBox; +import com.vaadin.ui.ListSelect; +import com.vaadin.v7.ui.LegacyDateField; +import com.vaadin.v7.ui.LegacyField; +import com.vaadin.v7.ui.LegacyInlineDateField; +import com.vaadin.v7.ui.LegacyPopupDateField; +import com.vaadin.v7.ui.LegacyTextField; + +public class DefaultFieldGroupFieldFactoryTest { + + private DefaultFieldGroupFieldFactory fieldFactory; + + @Before + public void setupFieldFactory() { + fieldFactory = DefaultFieldGroupFieldFactory.get(); + } + + @Test + public void noPublicConstructor() { + Class<DefaultFieldGroupFieldFactory> clazz = DefaultFieldGroupFieldFactory.class; + Constructor<?>[] constructors = clazz.getConstructors(); + Assert.assertEquals( + "DefaultFieldGroupFieldFactory contains public constructors", 0, + constructors.length); + } + + @Test + public void testSameInstance() { + DefaultFieldGroupFieldFactory factory1 = DefaultFieldGroupFieldFactory + .get(); + DefaultFieldGroupFieldFactory factory2 = DefaultFieldGroupFieldFactory + .get(); + Assert.assertTrue( + "DefaultFieldGroupFieldFactory.get() method returns different instances", + factory1 == factory2); + Assert.assertNotNull( + "DefaultFieldGroupFieldFactory.get() method returns null", + factory1); + } + + @Test + public void testDateGenerationForPopupDateField() { + LegacyField f = fieldFactory.createField(Date.class, + LegacyDateField.class); + Assert.assertNotNull(f); + Assert.assertEquals(LegacyPopupDateField.class, f.getClass()); + } + + @Test + public void testDateGenerationForInlineDateField() { + LegacyField f = fieldFactory.createField(Date.class, + LegacyInlineDateField.class); + Assert.assertNotNull(f); + Assert.assertEquals(LegacyInlineDateField.class, f.getClass()); + } + + @Test + public void testDateGenerationForTextField() { + LegacyField f = fieldFactory.createField(Date.class, + LegacyTextField.class); + Assert.assertNotNull(f); + Assert.assertEquals(LegacyTextField.class, f.getClass()); + } + + @Test + public void testDateGenerationForField() { + LegacyField f = fieldFactory.createField(Date.class, LegacyField.class); + Assert.assertNotNull(f); + Assert.assertEquals(LegacyPopupDateField.class, f.getClass()); + } + + public enum SomeEnum { + FOO, BAR; + } + + @Test + public void testEnumComboBox() { + LegacyField f = fieldFactory.createField(SomeEnum.class, + ComboBox.class); + Assert.assertNotNull(f); + Assert.assertEquals(ComboBox.class, f.getClass()); + } + + @Test + public void testEnumAnySelect() { + LegacyField f = fieldFactory.createField(SomeEnum.class, + AbstractSelect.class); + Assert.assertNotNull(f); + Assert.assertEquals(ListSelect.class, f.getClass()); + } + + @Test + public void testEnumAnyField() { + LegacyField f = fieldFactory.createField(SomeEnum.class, + LegacyField.class); + Assert.assertNotNull(f); + Assert.assertEquals(ListSelect.class, f.getClass()); + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/FieldGroupDateTest.java b/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/FieldGroupDateTest.java new file mode 100644 index 0000000000..e270211abf --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/FieldGroupDateTest.java @@ -0,0 +1,97 @@ +/* + * Copyright 2000-2016 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.data.fieldgroup; + +import java.util.Date; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.util.BeanItem; +import com.vaadin.v7.ui.LegacyField; +import com.vaadin.v7.ui.LegacyPopupDateField; + +public class FieldGroupDateTest { + + private FieldGroup fieldGroup; + + public class TestBean { + private Date javaDate; + private java.sql.Date sqlDate; + + public TestBean(Date javaDate, java.sql.Date sqlDate) { + super(); + this.javaDate = javaDate; + this.sqlDate = sqlDate; + } + + public java.sql.Date getSqlDate() { + return sqlDate; + } + + public void setSqlDate(java.sql.Date sqlDate) { + this.sqlDate = sqlDate; + } + + public Date getJavaDate() { + return javaDate; + } + + public void setJavaDate(Date date) { + javaDate = date; + } + } + + @SuppressWarnings("deprecation") + @Before + public void setup() { + fieldGroup = new FieldGroup(); + fieldGroup.setItemDataSource(new BeanItem<TestBean>(new TestBean( + new Date(2010, 5, 7), new java.sql.Date(2011, 6, 8)))); + } + + @Test + public void testBuildAndBindDate() { + LegacyField f = fieldGroup.buildAndBind("javaDate"); + Assert.assertNotNull(f); + Assert.assertEquals(LegacyPopupDateField.class, f.getClass()); + } + + @Test + public void testBuildAndBindSqlDate() { + LegacyField f = fieldGroup.buildAndBind("sqlDate"); + Assert.assertNotNull(f); + Assert.assertEquals(LegacyPopupDateField.class, f.getClass()); + } + + @Test + public void clearFields() { + LegacyPopupDateField sqlDate = new LegacyPopupDateField(); + LegacyPopupDateField javaDate = new LegacyPopupDateField(); + fieldGroup.bind(sqlDate, "sqlDate"); + fieldGroup.bind(javaDate, "javaDate"); + + Assert.assertEquals(new Date(2010, 5, 7), javaDate.getValue()); + Assert.assertEquals(new Date(2011, 6, 8), sqlDate.getValue()); + + fieldGroup.clear(); + Assert.assertEquals(null, javaDate.getValue()); + Assert.assertEquals(null, sqlDate.getValue()); + + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/FieldGroupExceptionTest.java b/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/FieldGroupExceptionTest.java new file mode 100644 index 0000000000..4622f0960e --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/FieldGroupExceptionTest.java @@ -0,0 +1,33 @@ +/* + * Copyright 2000-2016 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.data.fieldgroup; + +import org.junit.Test; + +import com.vaadin.data.fieldgroup.FieldGroup.CommitException; +import com.vaadin.v7.ui.LegacyPopupDateField; + +public class FieldGroupExceptionTest { + + @Test(expected = CommitException.class) + public void testUnboundCommitException() throws CommitException { + FieldGroup fieldGroup = new FieldGroup(); + LegacyPopupDateField dateField = new LegacyPopupDateField(); + fieldGroup.bind(dateField, "date"); + fieldGroup.commit(); + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/FieldGroupTest.java b/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/FieldGroupTest.java new file mode 100644 index 0000000000..c0039fc4fb --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/fieldgroup/FieldGroupTest.java @@ -0,0 +1,96 @@ +package com.vaadin.data.fieldgroup; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsNull.nullValue; +import static org.mockito.Mockito.mock; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.Property; +import com.vaadin.data.Property.Transactional; +import com.vaadin.data.util.BeanItem; +import com.vaadin.data.util.TransactionalPropertyWrapper; +import com.vaadin.v7.ui.LegacyField; +import com.vaadin.v7.ui.LegacyTextField; + +public class FieldGroupTest { + + private FieldGroup sut; + private LegacyField field; + + @Before + public void setup() { + sut = new FieldGroup(); + field = mock(LegacyField.class); + } + + @Test + public void fieldIsBound() { + sut.bind(field, "foobar"); + + assertThat(sut.getField("foobar"), is(field)); + } + + @Test(expected = FieldGroup.BindException.class) + public void cannotBindToAlreadyBoundProperty() { + sut.bind(field, "foobar"); + sut.bind(mock(LegacyField.class), "foobar"); + } + + @Test(expected = FieldGroup.BindException.class) + public void cannotBindNullField() { + sut.bind(null, "foobar"); + } + + public void canUnbindWithoutItem() { + sut.bind(field, "foobar"); + + sut.unbind(field); + assertThat(sut.getField("foobar"), is(nullValue())); + } + + @Test + public void wrapInTransactionalProperty_provideCustomImpl_customTransactionalWrapperIsUsed() { + Bean bean = new Bean(); + FieldGroup group = new FieldGroup() { + @Override + protected <T> Transactional<T> wrapInTransactionalProperty( + Property<T> itemProperty) { + return new TransactionalPropertyImpl(itemProperty); + } + }; + group.setItemDataSource(new BeanItem<Bean>(bean)); + LegacyTextField field = new LegacyTextField(); + group.bind(field, "name"); + + Property propertyDataSource = field.getPropertyDataSource(); + Assert.assertTrue( + "Custom implementation of transactional property " + + "has not been used", + propertyDataSource instanceof TransactionalPropertyImpl); + } + + public static class TransactionalPropertyImpl<T> + extends TransactionalPropertyWrapper<T> { + + public TransactionalPropertyImpl(Property<T> wrappedProperty) { + super(wrappedProperty); + } + + } + + public static class Bean { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/AbstractBeanContainerTestBase.java b/compatibility-server/src/test/java/com/vaadin/data/util/AbstractBeanContainerTestBase.java new file mode 100644 index 0000000000..4a9e4f9891 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/AbstractBeanContainerTestBase.java @@ -0,0 +1,77 @@ +package com.vaadin.data.util; + +/** + * Automated test for {@link AbstractBeanContainer}. + * + * Only a limited subset of the functionality is tested here, the rest in tests + * of subclasses including {@link BeanItemContainer} and {@link BeanContainer}. + */ +public abstract class AbstractBeanContainerTestBase + extends AbstractInMemoryContainerTestBase { + + public static class Person { + private String name; + + public Person(String name) { + setName(name); + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + } + + public static class ClassName { + // field names match constants in parent test class + private String fullyQualifiedName; + private String simpleName; + private String reverseFullyQualifiedName; + private Integer idNumber; + + public ClassName(String fullyQualifiedName, Integer idNumber) { + this.fullyQualifiedName = fullyQualifiedName; + simpleName = AbstractContainerTestBase + .getSimpleName(fullyQualifiedName); + reverseFullyQualifiedName = reverse(fullyQualifiedName); + this.idNumber = idNumber; + } + + public String getFullyQualifiedName() { + return fullyQualifiedName; + } + + public void setFullyQualifiedName(String fullyQualifiedName) { + this.fullyQualifiedName = fullyQualifiedName; + } + + public String getSimpleName() { + return simpleName; + } + + public void setSimpleName(String simpleName) { + this.simpleName = simpleName; + } + + public String getReverseFullyQualifiedName() { + return reverseFullyQualifiedName; + } + + public void setReverseFullyQualifiedName( + String reverseFullyQualifiedName) { + this.reverseFullyQualifiedName = reverseFullyQualifiedName; + } + + public Integer getIdNumber() { + return idNumber; + } + + public void setIdNumber(Integer idNumber) { + this.idNumber = idNumber; + } + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/AbstractContainerTestBase.java b/compatibility-server/src/test/java/com/vaadin/data/util/AbstractContainerTestBase.java new file mode 100644 index 0000000000..955b609735 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/AbstractContainerTestBase.java @@ -0,0 +1,866 @@ +package com.vaadin.data.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.junit.Assert; + +import com.vaadin.data.Container; +import com.vaadin.data.Container.Filterable; +import com.vaadin.data.Container.ItemSetChangeEvent; +import com.vaadin.data.Container.ItemSetChangeListener; +import com.vaadin.data.Container.Ordered; +import com.vaadin.data.Container.Sortable; +import com.vaadin.data.Item; +import com.vaadin.data.util.filter.SimpleStringFilter; + +public abstract class AbstractContainerTestBase { + + /** + * Helper class for testing e.g. listeners expecting events to be fired. + */ + protected abstract static class AbstractEventCounter { + private int eventCount = 0; + private int lastAssertedEventCount = 0; + + /** + * Increment the event count. To be called by subclasses e.g. from a + * listener method. + */ + protected void increment() { + ++eventCount; + } + + /** + * Check that no one event has occurred since the previous assert call. + */ + public void assertNone() { + Assert.assertEquals(lastAssertedEventCount, eventCount); + } + + /** + * Check that exactly one event has occurred since the previous assert + * call. + */ + public void assertOnce() { + Assert.assertEquals(++lastAssertedEventCount, eventCount); + } + + /** + * Reset the counter and the expected count. + */ + public void reset() { + eventCount = 0; + lastAssertedEventCount = 0; + } + } + + /** + * Test class for counting item set change events and verifying they have + * been received. + */ + protected static class ItemSetChangeCounter extends AbstractEventCounter + implements ItemSetChangeListener { + + @Override + public void containerItemSetChange(ItemSetChangeEvent event) { + increment(); + } + + } + + // #6043: for items that have been filtered out, Container interface does + // not specify what to return from getItem() and getContainerProperty(), so + // need checkGetItemNull parameter for the test to be usable for most + // current containers + protected void validateContainer(Container container, + Object expectedFirstItemId, Object expectedLastItemId, + Object itemIdInSet, Object itemIdNotInSet, boolean checkGetItemNull, + int expectedSize) { + Container.Indexed indexed = null; + if (container instanceof Container.Indexed) { + indexed = (Container.Indexed) container; + } + + List<Object> itemIdList = new ArrayList<Object>(container.getItemIds()); + + // size() + assertEquals(expectedSize, container.size()); + assertEquals(expectedSize, itemIdList.size()); + + // first item, last item + Object first = itemIdList.get(0); + Object last = itemIdList.get(itemIdList.size() - 1); + + assertEquals(expectedFirstItemId, first); + assertEquals(expectedLastItemId, last); + + // containsId + assertFalse(container.containsId(itemIdNotInSet)); + assertTrue(container.containsId(itemIdInSet)); + + // getItem + if (checkGetItemNull) { + assertNull(container.getItem(itemIdNotInSet)); + } + assertNotNull(container.getItem(itemIdInSet)); + + // getContainerProperty + for (Object propId : container.getContainerPropertyIds()) { + if (checkGetItemNull) { + assertNull( + container.getContainerProperty(itemIdNotInSet, propId)); + } + assertNotNull(container.getContainerProperty(itemIdInSet, propId)); + } + + if (indexed != null) { + // firstItemId + assertEquals(first, indexed.firstItemId()); + + // lastItemId + assertEquals(last, indexed.lastItemId()); + + // nextItemId + assertEquals(itemIdList.get(1), indexed.nextItemId(first)); + + // prevItemId + assertEquals(itemIdList.get(itemIdList.size() - 2), + indexed.prevItemId(last)); + + // isFirstId + assertTrue(indexed.isFirstId(first)); + assertFalse(indexed.isFirstId(last)); + + // isLastId + assertTrue(indexed.isLastId(last)); + assertFalse(indexed.isLastId(first)); + + // indexOfId + assertEquals(0, indexed.indexOfId(first)); + assertEquals(expectedSize - 1, indexed.indexOfId(last)); + + // getIdByIndex + assertEquals(indexed.getIdByIndex(0), first); + assertEquals(indexed.getIdByIndex(expectedSize - 1), last); + + } + + // getItemProperty + Assert.assertNull( + container.getItem(itemIdInSet).getItemProperty("notinset")); + + } + + protected static final Object FULLY_QUALIFIED_NAME = "fullyQualifiedName"; + protected static final Object SIMPLE_NAME = "simpleName"; + protected static final Object REVERSE_FULLY_QUALIFIED_NAME = "reverseFullyQualifiedName"; + protected static final Object ID_NUMBER = "idNumber"; + + protected void testBasicContainerOperations(Container container) { + initializeContainer(container); + + // Basic container + validateContainer(container, sampleData[0], + sampleData[sampleData.length - 1], sampleData[10], "abc", true, + sampleData.length); + + validateRemovingItems(container); + validateAddItem(container); + if (container instanceof Container.Indexed) { + validateAddItemAt((Container.Indexed) container); + } + if (container instanceof Container.Ordered) { + validateAddItemAfter((Container.Ordered) container); + } + + } + + protected void validateRemovingItems(Container container) { + int sizeBeforeRemoving = container.size(); + + List<Object> itemIdList = new ArrayList<Object>(container.getItemIds()); + // There should be at least four items in the list + Object first = itemIdList.get(0); + Object middle = itemIdList.get(2); + Object last = itemIdList.get(itemIdList.size() - 1); + + container.removeItem(first); + container.removeItem(middle); // Middle now that first has been removed + container.removeItem(last); + + assertEquals(sizeBeforeRemoving - 3, container.size()); + + container.removeAllItems(); + + assertEquals(0, container.size()); + } + + protected void validateAddItem(Container container) { + try { + container.removeAllItems(); + + Object id = container.addItem(); + Assert.assertTrue(container.containsId(id)); + Assert.assertNotNull(container.getItem(id)); + + Item item = container.addItem("foo"); + Assert.assertNotNull(item); + Assert.assertTrue(container.containsId("foo")); + Assert.assertEquals(item, container.getItem("foo")); + + // Add again + Item item2 = container.addItem("foo"); + Assert.assertNull(item2); + + // Null is not a valid itemId + Assert.assertNull(container.addItem(null)); + } catch (UnsupportedOperationException e) { + // Ignore contains which do not support addItem* + } + } + + protected void validateAddItemAt(Container.Indexed container) { + try { + container.removeAllItems(); + + Object id = container.addItemAt(0); + Assert.assertTrue(container.containsId(id)); + Assert.assertEquals(id, container.getIdByIndex(0)); + Assert.assertNotNull(container.getItem(id)); + + Item item = container.addItemAt(0, "foo"); + Assert.assertNotNull(item); + Assert.assertTrue(container.containsId("foo")); + Assert.assertEquals(item, container.getItem("foo")); + Assert.assertEquals("foo", container.getIdByIndex(0)); + + Item itemAtEnd = container.addItemAt(2, "atend"); + Assert.assertNotNull(itemAtEnd); + Assert.assertTrue(container.containsId("atend")); + Assert.assertEquals(itemAtEnd, container.getItem("atend")); + Assert.assertEquals("atend", container.getIdByIndex(2)); + + // Add again + Item item2 = container.addItemAt(0, "foo"); + Assert.assertNull(item2); + } catch (UnsupportedOperationException e) { + // Ignore contains which do not support addItem* + } + } + + protected void validateAddItemAfter(Container.Ordered container) { + if (container instanceof AbstractBeanContainer) { + // Doesn't work as bean container requires beans + return; + } + + try { + container.removeAllItems(); + + Assert.assertNotNull(container.addItem(0)); + + Item item = container.addItemAfter(null, "foo"); + Assert.assertNotNull(item); + Assert.assertTrue(container.containsId("foo")); + Assert.assertEquals(item, container.getItem("foo")); + Assert.assertEquals("foo", + container.getItemIds().iterator().next()); + + Item itemAtEnd = container.addItemAfter(0, "atend"); + Assert.assertNotNull(itemAtEnd); + Assert.assertTrue(container.containsId("atend")); + Assert.assertEquals(itemAtEnd, container.getItem("atend")); + Iterator<?> i = container.getItemIds().iterator(); + i.next(); + i.next(); + Assert.assertEquals("atend", i.next()); + + // Add again + Assert.assertNull(container.addItemAfter(null, "foo")); + Assert.assertNull(container.addItemAfter("atend", "foo")); + Assert.assertNull(container.addItemAfter("nonexistant", "123123")); + } catch (UnsupportedOperationException e) { + // Ignore contains which do not support addItem* + } + } + + protected void testContainerOrdered(Container.Ordered container) { + // addItem with empty container + Object id = container.addItem(); + assertOrderedContents(container, id); + Item item = container.getItem(id); + assertNotNull(item); + + // addItemAfter with empty container + container.removeAllItems(); + assertOrderedContents(container); + id = container.addItemAfter(null); + assertOrderedContents(container, id); + item = container.getItem(id); + assertNotNull(item); + + // Add a new item before the first + // addItemAfter + Object newFirstId = container.addItemAfter(null); + assertOrderedContents(container, newFirstId, id); + + // addItemAfter(Object) + Object newSecondItemId = container.addItemAfter(newFirstId); + // order is now: newFirstId, newSecondItemId, id + assertOrderedContents(container, newFirstId, newSecondItemId, id); + + // addItemAfter(Object,Object) + String fourthId = "id of the fourth item"; + Item fourth = container.addItemAfter(newFirstId, fourthId); + // order is now: newFirstId, fourthId, newSecondItemId, id + assertNotNull(fourth); + assertEquals(fourth, container.getItem(fourthId)); + assertOrderedContents(container, newFirstId, fourthId, newSecondItemId, + id); + + // addItemAfter(Object,Object) + Object fifthId = new Object(); + Item fifth = container.addItemAfter(null, fifthId); + // order is now: fifthId, newFirstId, fourthId, newSecondItemId, id + assertNotNull(fifth); + assertEquals(fifth, container.getItem(fifthId)); + assertOrderedContents(container, fifthId, newFirstId, fourthId, + newSecondItemId, id); + + // addItemAfter(Object,Object) + Object sixthId = new Object(); + Item sixth = container.addItemAfter(id, sixthId); + // order is now: fifthId, newFirstId, fourthId, newSecondItemId, id, + // sixthId + assertNotNull(sixth); + assertEquals(sixth, container.getItem(sixthId)); + assertOrderedContents(container, fifthId, newFirstId, fourthId, + newSecondItemId, id, sixthId); + + // Test order after removing first item 'fifthId' + container.removeItem(fifthId); + // order is now: newFirstId, fourthId, newSecondItemId, id, sixthId + assertOrderedContents(container, newFirstId, fourthId, newSecondItemId, + id, sixthId); + + // Test order after removing last item 'sixthId' + container.removeItem(sixthId); + // order is now: newFirstId, fourthId, newSecondItemId, id + assertOrderedContents(container, newFirstId, fourthId, newSecondItemId, + id); + + // Test order after removing item from the middle 'fourthId' + container.removeItem(fourthId); + // order is now: newFirstId, newSecondItemId, id + assertOrderedContents(container, newFirstId, newSecondItemId, id); + + // Delete remaining items + container.removeItem(newFirstId); + container.removeItem(newSecondItemId); + container.removeItem(id); + assertOrderedContents(container); + + Object finalItem = container.addItem(); + assertOrderedContents(container, finalItem); + } + + private void assertOrderedContents(Ordered container, Object... ids) { + assertEquals(ids.length, container.size()); + for (int i = 0; i < ids.length - 1; i++) { + assertNotNull("The item id should not be null", ids[i]); + } + if (ids.length == 0) { + assertNull("The first id is wrong", container.firstItemId()); + assertNull("The last id is wrong", container.lastItemId()); + return; + } + + assertEquals("The first id is wrong", ids[0], container.firstItemId()); + assertEquals("The last id is wrong", ids[ids.length - 1], + container.lastItemId()); + + // isFirstId & isLastId + assertTrue(container.isFirstId(container.firstItemId())); + assertTrue(container.isLastId(container.lastItemId())); + + // nextId + Object ref = container.firstItemId(); + for (int i = 1; i < ids.length; i++) { + Object next = container.nextItemId(ref); + assertEquals("The id after " + ref + " is wrong", ids[i], next); + ref = next; + } + assertNull("The last id should not have a next id", + container.nextItemId(ids[ids.length - 1])); + assertNull(container.nextItemId("not-in-container")); + + // prevId + ref = container.lastItemId(); + for (int i = ids.length - 2; i >= 0; i--) { + Object prev = container.prevItemId(ref); + assertEquals("The id before " + ref + " is wrong", ids[i], prev); + ref = prev; + } + assertNull("The first id should not have a prev id", + container.prevItemId(ids[0])); + assertNull(container.prevItemId("not-in-container")); + + } + + protected void testContainerIndexed(Container.Indexed container, + Object itemId, int itemPosition, boolean testAddEmptyItemAt, + Object newItemId, boolean testAddItemAtWithId) { + initializeContainer(container); + + // indexOfId + Assert.assertEquals(itemPosition, container.indexOfId(itemId)); + + // getIdByIndex + Assert.assertEquals(itemId, container.getIdByIndex(itemPosition)); + + // addItemAt + if (testAddEmptyItemAt) { + Object addedId = container.addItemAt(itemPosition); + Assert.assertEquals(itemPosition, container.indexOfId(addedId)); + Assert.assertEquals(itemPosition + 1, container.indexOfId(itemId)); + Assert.assertEquals(addedId, container.getIdByIndex(itemPosition)); + Assert.assertEquals(itemId, + container.getIdByIndex(itemPosition + 1)); + + Object newFirstId = container.addItemAt(0); + Assert.assertEquals(0, container.indexOfId(newFirstId)); + Assert.assertEquals(itemPosition + 2, container.indexOfId(itemId)); + Assert.assertEquals(newFirstId, container.firstItemId()); + Assert.assertEquals(newFirstId, container.getIdByIndex(0)); + Assert.assertEquals(itemId, + container.getIdByIndex(itemPosition + 2)); + + Object newLastId = container.addItemAt(container.size()); + Assert.assertEquals(container.size() - 1, + container.indexOfId(newLastId)); + Assert.assertEquals(itemPosition + 2, container.indexOfId(itemId)); + Assert.assertEquals(newLastId, container.lastItemId()); + Assert.assertEquals(newLastId, + container.getIdByIndex(container.size() - 1)); + Assert.assertEquals(itemId, + container.getIdByIndex(itemPosition + 2)); + + Assert.assertTrue(container.removeItem(addedId)); + Assert.assertTrue(container.removeItem(newFirstId)); + Assert.assertTrue(container.removeItem(newLastId)); + + Assert.assertFalse( + "Removing non-existing item should indicate failure", + container.removeItem(addedId)); + } + + // addItemAt + if (testAddItemAtWithId) { + container.addItemAt(itemPosition, newItemId); + Assert.assertEquals(itemPosition, container.indexOfId(newItemId)); + Assert.assertEquals(itemPosition + 1, container.indexOfId(itemId)); + Assert.assertEquals(newItemId, + container.getIdByIndex(itemPosition)); + Assert.assertEquals(itemId, + container.getIdByIndex(itemPosition + 1)); + Assert.assertTrue(container.removeItem(newItemId)); + Assert.assertFalse(container.containsId(newItemId)); + + container.addItemAt(0, newItemId); + Assert.assertEquals(0, container.indexOfId(newItemId)); + Assert.assertEquals(itemPosition + 1, container.indexOfId(itemId)); + Assert.assertEquals(newItemId, container.firstItemId()); + Assert.assertEquals(newItemId, container.getIdByIndex(0)); + Assert.assertEquals(itemId, + container.getIdByIndex(itemPosition + 1)); + Assert.assertTrue(container.removeItem(newItemId)); + Assert.assertFalse(container.containsId(newItemId)); + + container.addItemAt(container.size(), newItemId); + Assert.assertEquals(container.size() - 1, + container.indexOfId(newItemId)); + Assert.assertEquals(itemPosition, container.indexOfId(itemId)); + Assert.assertEquals(newItemId, container.lastItemId()); + Assert.assertEquals(newItemId, + container.getIdByIndex(container.size() - 1)); + Assert.assertEquals(itemId, container.getIdByIndex(itemPosition)); + Assert.assertTrue(container.removeItem(newItemId)); + Assert.assertFalse(container.containsId(newItemId)); + } + } + + protected void testContainerFiltering(Container.Filterable container) { + initializeContainer(container); + + // Filter by "contains ab" + SimpleStringFilter filter1 = new SimpleStringFilter( + FULLY_QUALIFIED_NAME, "ab", false, false); + container.addContainerFilter(filter1); + + assertTrue(container.getContainerFilters().size() == 1); + assertEquals(filter1, + container.getContainerFilters().iterator().next()); + + validateContainer(container, "com.vaadin.data.BufferedValidatable", + "com.vaadin.ui.TabSheet", + "com.vaadin.terminal.gwt.client.Focusable", + "com.vaadin.data.Buffered", isFilteredOutItemNull(), 20); + + // Filter by "contains da" (reversed as ad here) + container.removeAllContainerFilters(); + + assertTrue(container.getContainerFilters().isEmpty()); + + SimpleStringFilter filter2 = new SimpleStringFilter( + REVERSE_FULLY_QUALIFIED_NAME, "ad", false, false); + container.addContainerFilter(filter2); + + assertTrue(container.getContainerFilters().size() == 1); + assertEquals(filter2, + container.getContainerFilters().iterator().next()); + + validateContainer(container, "com.vaadin.data.Buffered", + "com.vaadin.server.ComponentSizeValidator", + "com.vaadin.data.util.IndexedContainer", + "com.vaadin.terminal.gwt.client.ui.VUriFragmentUtility", + isFilteredOutItemNull(), 37); + } + + /** + * Override in subclasses to return false if the container getItem() method + * returns a non-null value for an item that has been filtered out. + * + * @return + */ + protected boolean isFilteredOutItemNull() { + return true; + } + + protected void testContainerSortingAndFiltering( + Container.Sortable sortable) { + Filterable filterable = (Filterable) sortable; + + initializeContainer(sortable); + + // Filter by "contains ab" + filterable.addContainerFilter(new SimpleStringFilter( + FULLY_QUALIFIED_NAME, "ab", false, false)); + + // Must be able to sort based on PROP1 for this test + assertTrue(sortable.getSortableContainerPropertyIds() + .contains(FULLY_QUALIFIED_NAME)); + + sortable.sort(new Object[] { FULLY_QUALIFIED_NAME }, + new boolean[] { true }); + + validateContainer(sortable, "com.vaadin.data.BufferedValidatable", + "com.vaadin.ui.TableFieldFactory", + "com.vaadin.ui.TableFieldFactory", + "com.vaadin.data.util.BeanItem", isFilteredOutItemNull(), 20); + } + + protected void testContainerSorting(Container.Filterable container) { + Container.Sortable sortable = (Sortable) container; + + initializeContainer(container); + + // Must be able to sort based on PROP1 for this test + assertTrue(sortable.getSortableContainerPropertyIds() + .contains(FULLY_QUALIFIED_NAME)); + assertTrue(sortable.getSortableContainerPropertyIds() + .contains(REVERSE_FULLY_QUALIFIED_NAME)); + + sortable.sort(new Object[] { FULLY_QUALIFIED_NAME }, + new boolean[] { true }); + + validateContainer(container, "com.vaadin.Application", + "org.vaadin.test.LastClass", + "com.vaadin.server.ApplicationResource", "blah", true, + sampleData.length); + + sortable.sort(new Object[] { REVERSE_FULLY_QUALIFIED_NAME }, + new boolean[] { true }); + + validateContainer(container, "com.vaadin.server.ApplicationPortlet2", + "com.vaadin.data.util.ObjectProperty", + "com.vaadin.ui.BaseFieldFactory", "blah", true, + sampleData.length); + + } + + protected void initializeContainer(Container container) { + Assert.assertTrue(container.removeAllItems()); + Object[] propertyIds = container.getContainerPropertyIds().toArray(); + for (Object propertyId : propertyIds) { + container.removeContainerProperty(propertyId); + } + + container.addContainerProperty(FULLY_QUALIFIED_NAME, String.class, ""); + container.addContainerProperty(SIMPLE_NAME, String.class, ""); + container.addContainerProperty(REVERSE_FULLY_QUALIFIED_NAME, + String.class, null); + container.addContainerProperty(ID_NUMBER, Integer.class, null); + + for (int i = 0; i < sampleData.length; i++) { + String id = sampleData[i]; + Item item = container.addItem(id); + + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(sampleData[i]); + item.getItemProperty(SIMPLE_NAME) + .setValue(getSimpleName(sampleData[i])); + item.getItemProperty(REVERSE_FULLY_QUALIFIED_NAME) + .setValue(reverse(sampleData[i])); + item.getItemProperty(ID_NUMBER).setValue(i); + } + } + + protected static String getSimpleName(String name) { + if (name.contains(".")) { + return name.substring(name.lastIndexOf('.') + 1); + } else { + return name; + } + } + + protected static String reverse(String string) { + return new StringBuilder(string).reverse().toString(); + } + + protected final String[] sampleData = { + "com.vaadin.annotations.AutoGenerated", "com.vaadin.Application", + "com.vaadin.data.Buffered", "com.vaadin.data.BufferedValidatable", + "com.vaadin.data.Container", "com.vaadin.data.Item", + "com.vaadin.data.Property", "com.vaadin.data.util.BeanItem", + "com.vaadin.data.util.BeanItemContainer", + "com.vaadin.data.util.ContainerHierarchicalWrapper", + "com.vaadin.data.util.ContainerOrderedWrapper", + "com.vaadin.data.util.DefaultItemSorter", + "com.vaadin.data.util.FilesystemContainer", + "com.vaadin.data.util.Filter", + "com.vaadin.data.util.HierarchicalContainer", + "com.vaadin.data.util.IndexedContainer", + "com.vaadin.data.util.ItemSorter", + "com.vaadin.data.util.MethodProperty", + "com.vaadin.data.util.ObjectProperty", + "com.vaadin.data.util.PropertyFormatter", + "com.vaadin.data.util.PropertysetItem", + "com.vaadin.data.util.QueryContainer", + "com.vaadin.data.util.TextFileProperty", + "com.vaadin.data.Validatable", + "com.vaadin.data.validator.AbstractStringValidator", + "com.vaadin.data.validator.AbstractValidator", + "com.vaadin.data.validator.CompositeValidator", + "com.vaadin.data.validator.DoubleValidator", + "com.vaadin.data.validator.EmailValidator", + "com.vaadin.data.validator.IntegerValidator", + "com.vaadin.data.validator.NullValidator", + "com.vaadin.data.validator.RegexpValidator", + "com.vaadin.data.validator.StringLengthValidator", + "com.vaadin.data.Validator", "com.vaadin.event.Action", + "com.vaadin.event.ComponentEventListener", + "com.vaadin.event.EventRouter", "com.vaadin.event.FieldEvents", + "com.vaadin.event.ItemClickEvent", "com.vaadin.event.LayoutEvents", + "com.vaadin.event.ListenerMethod", + "com.vaadin.event.MethodEventSource", + "com.vaadin.event.MouseEvents", "com.vaadin.event.ShortcutAction", + "com.vaadin.launcher.DemoLauncher", + "com.vaadin.launcher.DevelopmentServerLauncher", + "com.vaadin.launcher.util.BrowserLauncher", + "com.vaadin.service.ApplicationContext", + "com.vaadin.service.FileTypeResolver", + "com.vaadin.server.ApplicationResource", + "com.vaadin.server.ClassResource", + "com.vaadin.server.CompositeErrorMessage", + "com.vaadin.server.DownloadStream", + "com.vaadin.server.ErrorMessage", + "com.vaadin.server.ExternalResource", + "com.vaadin.server.FileResource", + "com.vaadin.terminal.gwt.client.ApplicationConfiguration", + "com.vaadin.terminal.gwt.client.ApplicationConnection", + "com.vaadin.terminal.gwt.client.BrowserInfo", + "com.vaadin.terminal.gwt.client.ClientExceptionHandler", + "com.vaadin.terminal.gwt.client.ComponentDetail", + "com.vaadin.terminal.gwt.client.ComponentDetailMap", + "com.vaadin.terminal.gwt.client.ComponentLocator", + "com.vaadin.terminal.gwt.client.Console", + "com.vaadin.terminal.gwt.client.Container", + "com.vaadin.terminal.gwt.client.ContainerResizedListener", + "com.vaadin.terminal.gwt.client.CSSRule", + "com.vaadin.terminal.gwt.client.DateTimeService", + "com.vaadin.terminal.gwt.client.DefaultWidgetSet", + "com.vaadin.terminal.gwt.client.Focusable", + "com.vaadin.terminal.gwt.client.HistoryImplIEVaadin", + "com.vaadin.terminal.gwt.client.LocaleNotLoadedException", + "com.vaadin.terminal.gwt.client.LocaleService", + "com.vaadin.terminal.gwt.client.MouseEventDetails", + "com.vaadin.terminal.gwt.client.NullConsole", + "com.vaadin.terminal.gwt.client.Paintable", + "com.vaadin.terminal.gwt.client.RenderInformation", + "com.vaadin.terminal.gwt.client.RenderSpace", + "com.vaadin.terminal.gwt.client.StyleConstants", + "com.vaadin.terminal.gwt.client.TooltipInfo", + "com.vaadin.terminal.gwt.client.ui.Action", + "com.vaadin.terminal.gwt.client.ui.ActionOwner", + "com.vaadin.terminal.gwt.client.ui.AlignmentInfo", + "com.vaadin.terminal.gwt.client.ui.CalendarEntry", + "com.vaadin.terminal.gwt.client.ui.ClickEventHandler", + "com.vaadin.terminal.gwt.client.ui.Field", + "com.vaadin.terminal.gwt.client.ui.Icon", + "com.vaadin.terminal.gwt.client.ui.layout.CellBasedLayout", + "com.vaadin.terminal.gwt.client.ui.layout.ChildComponentContainer", + "com.vaadin.terminal.gwt.client.ui.layout.Margins", + "com.vaadin.terminal.gwt.client.ui.LayoutClickEventHandler", + "com.vaadin.terminal.gwt.client.ui.MenuBar", + "com.vaadin.terminal.gwt.client.ui.MenuItem", + "com.vaadin.terminal.gwt.client.ui.richtextarea.VRichTextToolbar", + "com.vaadin.terminal.gwt.client.ui.ShortcutActionHandler", + "com.vaadin.terminal.gwt.client.ui.SubPartAware", + "com.vaadin.terminal.gwt.client.ui.Table", + "com.vaadin.terminal.gwt.client.ui.TreeAction", + "com.vaadin.terminal.gwt.client.ui.TreeImages", + "com.vaadin.terminal.gwt.client.ui.VAbsoluteLayout", + "com.vaadin.terminal.gwt.client.ui.VAccordion", + "com.vaadin.terminal.gwt.client.ui.VButton", + "com.vaadin.terminal.gwt.client.ui.VCalendarPanel", + "com.vaadin.terminal.gwt.client.ui.VCheckBox", + "com.vaadin.terminal.gwt.client.ui.VContextMenu", + "com.vaadin.terminal.gwt.client.ui.VCssLayout", + "com.vaadin.terminal.gwt.client.ui.VCustomComponent", + "com.vaadin.terminal.gwt.client.ui.VCustomLayout", + "com.vaadin.terminal.gwt.client.ui.VDateField", + "com.vaadin.terminal.gwt.client.ui.VDateFieldCalendar", + "com.vaadin.terminal.gwt.client.ui.VEmbedded", + "com.vaadin.terminal.gwt.client.ui.VFilterSelect", + "com.vaadin.terminal.gwt.client.ui.VForm", + "com.vaadin.terminal.gwt.client.ui.VFormLayout", + "com.vaadin.terminal.gwt.client.ui.VGridLayout", + "com.vaadin.terminal.gwt.client.ui.VHorizontalLayout", + "com.vaadin.terminal.gwt.client.ui.VLabel", + "com.vaadin.terminal.gwt.client.ui.VLink", + "com.vaadin.terminal.gwt.client.ui.VListSelect", + "com.vaadin.terminal.gwt.client.ui.VMarginInfo", + "com.vaadin.terminal.gwt.client.ui.VMenuBar", + "com.vaadin.terminal.gwt.client.ui.VNativeButton", + "com.vaadin.terminal.gwt.client.ui.VNativeSelect", + "com.vaadin.terminal.gwt.client.ui.VNotification", + "com.vaadin.terminal.gwt.client.ui.VOptionGroup", + "com.vaadin.terminal.gwt.client.ui.VOptionGroupBase", + "com.vaadin.terminal.gwt.client.ui.VOrderedLayout", + "com.vaadin.terminal.gwt.client.ui.VOverlay", + "com.vaadin.terminal.gwt.client.ui.VPanel", + "com.vaadin.terminal.gwt.client.ui.VPasswordField", + "com.vaadin.terminal.gwt.client.ui.VPopupCalendar", + "com.vaadin.terminal.gwt.client.ui.VPopupView", + "com.vaadin.terminal.gwt.client.ui.VProgressIndicator", + "com.vaadin.terminal.gwt.client.ui.VRichTextArea", + "com.vaadin.terminal.gwt.client.ui.VScrollTable", + "com.vaadin.terminal.gwt.client.ui.VSlider", + "com.vaadin.terminal.gwt.client.ui.VSplitPanel", + "com.vaadin.terminal.gwt.client.ui.VSplitPanelHorizontal", + "com.vaadin.terminal.gwt.client.ui.VSplitPanelVertical", + "com.vaadin.terminal.gwt.client.ui.VTablePaging", + "com.vaadin.terminal.gwt.client.ui.VTabsheet", + "com.vaadin.terminal.gwt.client.ui.VTabsheetBase", + "com.vaadin.terminal.gwt.client.ui.VTabsheetPanel", + "com.vaadin.terminal.gwt.client.ui.VTextArea", + "com.vaadin.terminal.gwt.client.ui.VTextField", + "com.vaadin.terminal.gwt.client.ui.VTextualDate", + "com.vaadin.terminal.gwt.client.ui.VTime", + "com.vaadin.terminal.gwt.client.ui.VTree", + "com.vaadin.terminal.gwt.client.ui.VTwinColSelect", + "com.vaadin.terminal.gwt.client.ui.VUnknownComponent", + "com.vaadin.terminal.gwt.client.ui.VUpload", + "com.vaadin.terminal.gwt.client.ui.VUriFragmentUtility", + "com.vaadin.terminal.gwt.client.ui.VVerticalLayout", + "com.vaadin.terminal.gwt.client.ui.VView", + "com.vaadin.terminal.gwt.client.ui.VWindow", + "com.vaadin.terminal.gwt.client.UIDL", + "com.vaadin.terminal.gwt.client.Util", + "com.vaadin.terminal.gwt.client.ValueMap", + "com.vaadin.terminal.gwt.client.VCaption", + "com.vaadin.terminal.gwt.client.VCaptionWrapper", + "com.vaadin.terminal.gwt.client.VDebugConsole", + "com.vaadin.terminal.gwt.client.VErrorMessage", + "com.vaadin.terminal.gwt.client.VTooltip", + "com.vaadin.terminal.gwt.client.VUIDLBrowser", + "com.vaadin.terminal.gwt.client.WidgetMap", + "com.vaadin.terminal.gwt.client.WidgetSet", + "com.vaadin.server.AbstractApplicationPortlet", + "com.vaadin.server.AbstractApplicationServlet", + "com.vaadin.server.AbstractCommunicationManager", + "com.vaadin.server.AbstractWebApplicationContext", + "com.vaadin.server.ApplicationPortlet", + "com.vaadin.server.ApplicationPortlet2", + "com.vaadin.server.ApplicationRunnerServlet", + "com.vaadin.server.ApplicationServlet", + "com.vaadin.server.ChangeVariablesErrorEvent", + "com.vaadin.server.CommunicationManager", + "com.vaadin.server.ComponentSizeValidator", + "com.vaadin.server.Constants", + "com.vaadin.server.GAEApplicationServlet", + "com.vaadin.server.HttpServletRequestListener", + "com.vaadin.server.HttpUploadStream", + "com.vaadin.server.JsonPaintTarget", + "com.vaadin.server.PortletApplicationContext", + "com.vaadin.server.PortletApplicationContext2", + "com.vaadin.server.PortletCommunicationManager", + "com.vaadin.server.PortletRequestListener", + "com.vaadin.server.RestrictedRenderResponse", + "com.vaadin.server.SessionExpiredException", + "com.vaadin.server.SystemMessageException", + "com.vaadin.server.WebApplicationContext", + "com.vaadin.server.WebBrowser", + "com.vaadin.server.widgetsetutils.ClassPathExplorer", + "com.vaadin.server.widgetsetutils.WidgetMapGenerator", + "com.vaadin.server.widgetsetutils.WidgetSetBuilder", + "com.vaadin.server.KeyMapper", "com.vaadin.server.Paintable", + "com.vaadin.server.PaintException", "com.vaadin.server.PaintTarget", + "com.vaadin.server.ParameterHandler", "com.vaadin.server.Resource", + "com.vaadin.server.Scrollable", "com.vaadin.server.Sizeable", + "com.vaadin.server.StreamResource", "com.vaadin.server.SystemError", + "com.vaadin.server.Terminal", "com.vaadin.server.ThemeResource", + "com.vaadin.server.UploadStream", "com.vaadin.server.URIHandler", + "com.vaadin.server.UserError", "com.vaadin.server.VariableOwner", + "com.vaadin.tools.ReflectTools", + "com.vaadin.tools.WidgetsetCompiler", + "com.vaadin.ui.AbsoluteLayout", "com.vaadin.ui.AbstractComponent", + "com.vaadin.ui.AbstractComponentContainer", + "com.vaadin.ui.AbstractField", "com.vaadin.ui.AbstractLayout", + "com.vaadin.ui.AbstractOrderedLayout", + "com.vaadin.ui.AbstractSelect", "com.vaadin.ui.Accordion", + "com.vaadin.ui.Alignment", "com.vaadin.ui.AlignmentUtils", + "com.vaadin.ui.BaseFieldFactory", "com.vaadin.ui.Button", + "com.vaadin.ui.CheckBox", "com.vaadin.ui.ClientWidget", + "com.vaadin.ui.ComboBox", "com.vaadin.ui.Component", + "com.vaadin.ui.ComponentContainer", "com.vaadin.ui.CssLayout", + "com.vaadin.ui.CustomComponent", "com.vaadin.ui.CustomLayout", + "com.vaadin.ui.DateField", "com.vaadin.ui.DefaultFieldFactory", + "com.vaadin.ui.Embedded", "com.vaadin.ui.ExpandLayout", + "com.vaadin.ui.Field", "com.vaadin.ui.FieldFactory", + "com.vaadin.ui.Form", "com.vaadin.ui.FormFieldFactory", + "com.vaadin.ui.FormLayout", "com.vaadin.ui.GridLayout", + "com.vaadin.ui.HorizontalLayout", "com.vaadin.ui.InlineDateField", + "com.vaadin.ui.Label", "com.vaadin.ui.Layout", "com.vaadin.ui.Link", + "com.vaadin.ui.ListSelect", "com.vaadin.ui.LoginForm", + "com.vaadin.ui.MenuBar", "com.vaadin.ui.NativeButton", + "com.vaadin.ui.NativeSelect", "com.vaadin.ui.OptionGroup", + "com.vaadin.ui.OrderedLayout", "com.vaadin.ui.Panel", + "com.vaadin.ui.PopupDateField", "com.vaadin.ui.PopupView", + "com.vaadin.ui.ProgressIndicator", "com.vaadin.ui.RichTextArea", + "com.vaadin.ui.Select", "com.vaadin.ui.Slider", + "com.vaadin.ui.SplitPanel", "com.vaadin.ui.Table", + "com.vaadin.ui.TableFieldFactory", "com.vaadin.ui.TabSheet", + "com.vaadin.ui.TextField", "com.vaadin.ui.Tree", + "com.vaadin.ui.TwinColSelect", "com.vaadin.ui.Upload", + "com.vaadin.ui.UriFragmentUtility", "com.vaadin.ui.VerticalLayout", + "com.vaadin.ui.Window", "com.vaadin.util.SerializerHelper", + "org.vaadin.test.LastClass" }; +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/AbstractHierarchicalContainerTestBase.java b/compatibility-server/src/test/java/com/vaadin/data/util/AbstractHierarchicalContainerTestBase.java new file mode 100644 index 0000000000..f3eda74100 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/AbstractHierarchicalContainerTestBase.java @@ -0,0 +1,289 @@ +package com.vaadin.data.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.Collection; + +import com.vaadin.data.Container; +import com.vaadin.data.Container.Hierarchical; +import com.vaadin.data.Container.Sortable; +import com.vaadin.data.Item; + +public abstract class AbstractHierarchicalContainerTestBase + extends AbstractContainerTestBase { + + /** + * @param container + * The container to validate + * @param expectedFirstItemId + * Expected first item id + * @param expectedLastItemId + * Expected last item id + * @param itemIdInSet + * An item id that is in the container + * @param itemIdNotInSet + * An item id that is not in the container + * @param checkGetItemNull + * true if getItem() should return null for itemIdNotInSet, false + * to skip the check (container.containsId() is checked in any + * case) + * @param expectedSize + * Expected number of items in the container. Not related to + * hierarchy. + * @param expectedTraversalSize + * Expected number of items found when traversing from the roots + * down to all available nodes. + * @param expectedRootSize + * Expected number of root items + * @param rootsHaveChildren + * true if all roots have children, false otherwise (skips some + * asserts) + */ + protected void validateHierarchicalContainer(Hierarchical container, + Object expectedFirstItemId, Object expectedLastItemId, + Object itemIdInSet, Object itemIdNotInSet, boolean checkGetItemNull, + int expectedSize, int expectedRootSize, boolean rootsHaveChildren) { + + validateContainer(container, expectedFirstItemId, expectedLastItemId, + itemIdInSet, itemIdNotInSet, checkGetItemNull, expectedSize); + + // rootItemIds + Collection<?> rootIds = container.rootItemIds(); + assertEquals(expectedRootSize, rootIds.size()); + + for (Object rootId : rootIds) { + // All roots must be in container + assertTrue(container.containsId(rootId)); + + // All roots must have no parent + assertNull(container.getParent(rootId)); + + // all roots must be roots + assertTrue(container.isRoot(rootId)); + + if (rootsHaveChildren) { + // all roots have children allowed in this case + assertTrue(container.areChildrenAllowed(rootId)); + + // all roots have children in this case + Collection<?> children = container.getChildren(rootId); + assertNotNull(rootId + " should have children", children); + assertTrue(rootId + " should have children", + (children.size() > 0)); + // getParent + for (Object childId : children) { + assertEquals(container.getParent(childId), rootId); + } + + } + } + + // isRoot should return false for unknown items + assertFalse(container.isRoot(itemIdNotInSet)); + + // hasChildren should return false for unknown items + assertFalse(container.hasChildren(itemIdNotInSet)); + + // areChildrenAllowed should return false for unknown items + assertFalse(container.areChildrenAllowed(itemIdNotInSet)); + + // removeItem of unknown items should return false + assertFalse(container.removeItem(itemIdNotInSet)); + + assertEquals(expectedSize, countNodes(container)); + + validateHierarchy(container); + } + + private int countNodes(Hierarchical container) { + int totalNodes = 0; + for (Object rootId : container.rootItemIds()) { + totalNodes += countNodes(container, rootId); + } + + return totalNodes; + } + + private int countNodes(Hierarchical container, Object itemId) { + int nodes = 1; // This + Collection<?> children = container.getChildren(itemId); + if (children != null) { + for (Object id : children) { + nodes += countNodes(container, id); + } + } + + return nodes; + } + + private void validateHierarchy(Hierarchical container) { + for (Object rootId : container.rootItemIds()) { + validateHierarchy(container, rootId, null); + } + } + + private void validateHierarchy(Hierarchical container, Object itemId, + Object parentId) { + Collection<?> children = container.getChildren(itemId); + + // getParent + assertEquals(container.getParent(itemId), parentId); + + if (!container.areChildrenAllowed(itemId)) { + // If no children is allowed the item should have no children + assertFalse(container.hasChildren(itemId)); + assertTrue(children == null || children.size() == 0); + + return; + } + if (children != null) { + for (Object id : children) { + validateHierarchy(container, id, itemId); + } + } + } + + protected void testHierarchicalContainer(Container.Hierarchical container) { + initializeContainer(container); + + int packages = 21 + 3; + int expectedSize = sampleData.length + packages; + validateHierarchicalContainer(container, "com", + "org.vaadin.test.LastClass", + "com.vaadin.server.ApplicationResource", "blah", true, + expectedSize, 2, true); + + } + + protected void testHierarchicalSorting(Container.Hierarchical container) { + Container.Sortable sortable = (Sortable) container; + + initializeContainer(container); + + // Must be able to sort based on PROP1 and PROP2 for this test + assertTrue(sortable.getSortableContainerPropertyIds() + .contains(FULLY_QUALIFIED_NAME)); + assertTrue(sortable.getSortableContainerPropertyIds() + .contains(REVERSE_FULLY_QUALIFIED_NAME)); + + sortable.sort(new Object[] { FULLY_QUALIFIED_NAME }, + new boolean[] { true }); + + int packages = 21 + 3; + int expectedSize = sampleData.length + packages; + validateHierarchicalContainer(container, "com", + "org.vaadin.test.LastClass", + "com.vaadin.server.ApplicationResource", "blah", true, + expectedSize, 2, true); + + sortable.sort(new Object[] { REVERSE_FULLY_QUALIFIED_NAME }, + new boolean[] { true }); + + validateHierarchicalContainer(container, + "com.vaadin.server.ApplicationPortlet2", + "com.vaadin.data.util.ObjectProperty", + "com.vaadin.server.ApplicationResource", "blah", true, + expectedSize, 2, true); + + } + + protected void initializeContainer(Container.Hierarchical container) { + container.removeAllItems(); + Object[] propertyIds = container.getContainerPropertyIds().toArray(); + for (Object propertyId : propertyIds) { + container.removeContainerProperty(propertyId); + } + + container.addContainerProperty(FULLY_QUALIFIED_NAME, String.class, ""); + container.addContainerProperty(SIMPLE_NAME, String.class, ""); + container.addContainerProperty(REVERSE_FULLY_QUALIFIED_NAME, + String.class, null); + container.addContainerProperty(ID_NUMBER, Integer.class, null); + + for (int i = 0; i < sampleData.length; i++) { + String id = sampleData[i]; + + // Add path as parent + String paths[] = id.split("\\."); + String path = paths[0]; + // Adds "com" and other items multiple times so should return null + // for all but the first time + if (container.addItem(path) != null) { + assertTrue(container.setChildrenAllowed(path, false)); + Item item = container.getItem(path); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(path); + item.getItemProperty(SIMPLE_NAME).setValue(getSimpleName(path)); + item.getItemProperty(REVERSE_FULLY_QUALIFIED_NAME) + .setValue(reverse(path)); + item.getItemProperty(ID_NUMBER).setValue(1); + } + for (int j = 1; j < paths.length; j++) { + String parent = path; + path = path + "." + paths[j]; + + // Adds "com" and other items multiple times so should return + // null for all but the first time + if (container.addItem(path) != null) { + assertTrue(container.setChildrenAllowed(path, false)); + + Item item = container.getItem(path); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(path); + item.getItemProperty(SIMPLE_NAME) + .setValue(getSimpleName(path)); + item.getItemProperty(REVERSE_FULLY_QUALIFIED_NAME) + .setValue(reverse(path)); + item.getItemProperty(ID_NUMBER).setValue(1); + + } + assertTrue(container.setChildrenAllowed(parent, true)); + assertTrue("Failed to set " + parent + " as parent for " + path, + container.setParent(path, parent)); + } + + Item item = container.getItem(id); + assertNotNull(item); + String parent = id.substring(0, id.lastIndexOf('.')); + assertTrue(container.setParent(id, parent)); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(sampleData[i]); + item.getItemProperty(SIMPLE_NAME) + .setValue(getSimpleName(sampleData[i])); + item.getItemProperty(REVERSE_FULLY_QUALIFIED_NAME) + .setValue(reverse(sampleData[i])); + item.getItemProperty(ID_NUMBER).setValue(i % 2); + } + } + + protected void testRemoveHierarchicalWrapperSubtree( + Container.Hierarchical container) { + initializeContainer(container); + + // remove root item + removeItemRecursively(container, "org"); + + int packages = 21 + 3 - 3; + int expectedSize = sampleData.length + packages - 1; + + validateContainer(container, "com", "com.vaadin.util.SerializerHelper", + "com.vaadin.server.ApplicationResource", "blah", true, + expectedSize); + + // rootItemIds + Collection<?> rootIds = container.rootItemIds(); + assertEquals(1, rootIds.size()); + } + + private void removeItemRecursively(Container.Hierarchical container, + Object itemId) { + if (container instanceof ContainerHierarchicalWrapper) { + ((ContainerHierarchicalWrapper) container) + .removeItemRecursively("org"); + } else { + HierarchicalContainer.removeItemRecursively(container, itemId); + } + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/AbstractInMemoryContainerTestBase.java b/compatibility-server/src/test/java/com/vaadin/data/util/AbstractInMemoryContainerTestBase.java new file mode 100644 index 0000000000..3858504bc7 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/AbstractInMemoryContainerTestBase.java @@ -0,0 +1,6 @@ +package com.vaadin.data.util; + +public abstract class AbstractInMemoryContainerTestBase + extends AbstractContainerTestBase { + +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/BeanContainerTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/BeanContainerTest.java new file mode 100644 index 0000000000..bdf6ba1958 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/BeanContainerTest.java @@ -0,0 +1,516 @@ +package com.vaadin.data.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.Container; +import com.vaadin.data.Item; +import com.vaadin.data.util.AbstractBeanContainer.BeanIdResolver; + +public class BeanContainerTest extends AbstractBeanContainerTestBase { + + protected static class PersonNameResolver + implements BeanIdResolver<String, Person> { + + @Override + public String getIdForBean(Person bean) { + return bean != null ? bean.getName() : null; + } + + } + + protected static class NullResolver + implements BeanIdResolver<String, Person> { + + @Override + public String getIdForBean(Person bean) { + return null; + } + + } + + private Map<String, ClassName> nameToBean = new LinkedHashMap<String, ClassName>(); + + private BeanContainer<String, ClassName> getContainer() { + return new BeanContainer<String, ClassName>(ClassName.class); + } + + @Before + public void setUp() { + nameToBean.clear(); + + for (int i = 0; i < sampleData.length; i++) { + ClassName className = new ClassName(sampleData[i], i); + nameToBean.put(sampleData[i], className); + } + } + + @Override + @SuppressWarnings("unchecked") + protected void initializeContainer(Container container) { + BeanContainer<String, ClassName> beanItemContainer = (BeanContainer<String, ClassName>) container; + + beanItemContainer.removeAllItems(); + + for (Entry<String, ClassName> entry : nameToBean.entrySet()) { + beanItemContainer.addItem(entry.getKey(), entry.getValue()); + } + } + + @Override + protected boolean isFilteredOutItemNull() { + return false; + } + + @Test + public void testGetType_existingProperty_typeReturned() { + BeanContainer<String, ClassName> container = getContainer(); + Assert.assertEquals( + "Unexpected type is returned for property 'simpleName'", + String.class, container.getType("simpleName")); + } + + @Test + public void testGetType_notExistingProperty_nullReturned() { + BeanContainer<String, ClassName> container = getContainer(); + Assert.assertNull("Not null type is returned for property ''", + container.getType("")); + } + + @Test + public void testBasicOperations() { + testBasicContainerOperations(getContainer()); + } + + @Test + public void testFiltering() { + testContainerFiltering(getContainer()); + } + + @Test + public void testSorting() { + testContainerSorting(getContainer()); + } + + @Test + public void testSortingAndFiltering() { + testContainerSortingAndFiltering(getContainer()); + } + + // duplicated from parent class and modified - adding items to + // BeanContainer differs from other containers + @Test + public void testContainerOrdered() { + BeanContainer<String, String> container = new BeanContainer<String, String>( + String.class); + + String id = "test1"; + + Item item = container.addItem(id, "value"); + assertNotNull(item); + + assertEquals(id, container.firstItemId()); + assertEquals(id, container.lastItemId()); + + // isFirstId + assertTrue(container.isFirstId(id)); + assertTrue(container.isFirstId(container.firstItemId())); + // isLastId + assertTrue(container.isLastId(id)); + assertTrue(container.isLastId(container.lastItemId())); + + // Add a new item before the first + // addItemAfter + String newFirstId = "newFirst"; + item = container.addItemAfter(null, newFirstId, "newFirstValue"); + assertNotNull(item); + assertNotNull(container.getItem(newFirstId)); + + // isFirstId + assertTrue(container.isFirstId(newFirstId)); + assertTrue(container.isFirstId(container.firstItemId())); + // isLastId + assertTrue(container.isLastId(id)); + assertTrue(container.isLastId(container.lastItemId())); + + // nextItemId + assertEquals(id, container.nextItemId(newFirstId)); + assertNull(container.nextItemId(id)); + assertNull(container.nextItemId("not-in-container")); + + // prevItemId + assertEquals(newFirstId, container.prevItemId(id)); + assertNull(container.prevItemId(newFirstId)); + assertNull(container.prevItemId("not-in-container")); + + // addItemAfter(IDTYPE, IDTYPE, BT) + String newSecondItemId = "newSecond"; + item = container.addItemAfter(newFirstId, newSecondItemId, + "newSecondValue"); + // order is now: newFirstId, newSecondItemId, id + assertNotNull(item); + assertNotNull(container.getItem(newSecondItemId)); + assertEquals(id, container.nextItemId(newSecondItemId)); + assertEquals(newFirstId, container.prevItemId(newSecondItemId)); + + // addItemAfter(IDTYPE, IDTYPE, BT) + String fourthId = "id of the fourth item"; + Item fourth = container.addItemAfter(newFirstId, fourthId, + "fourthValue"); + // order is now: newFirstId, fourthId, newSecondItemId, id + assertNotNull(fourth); + assertEquals(fourth, container.getItem(fourthId)); + assertEquals(newSecondItemId, container.nextItemId(fourthId)); + assertEquals(newFirstId, container.prevItemId(fourthId)); + + // addItemAfter(IDTYPE, IDTYPE, BT) + String fifthId = "fifth"; + Item fifth = container.addItemAfter(null, fifthId, "fifthValue"); + // order is now: fifthId, newFirstId, fourthId, newSecondItemId, id + assertNotNull(fifth); + assertEquals(fifth, container.getItem(fifthId)); + assertEquals(newFirstId, container.nextItemId(fifthId)); + assertNull(container.prevItemId(fifthId)); + + } + + // TODO test Container.Indexed interface operation - testContainerIndexed()? + + @Test + public void testAddItemAt() { + BeanContainer<String, String> container = new BeanContainer<String, String>( + String.class); + + container.addItem("id1", "value1"); + // id1 + container.addItemAt(0, "id2", "value2"); + // id2, id1 + container.addItemAt(1, "id3", "value3"); + // id2, id3, id1 + container.addItemAt(container.size(), "id4", "value4"); + // id2, id3, id1, id4 + + assertNull(container.addItemAt(-1, "id5", "value5")); + assertNull(container.addItemAt(container.size() + 1, "id6", "value6")); + + assertEquals(4, container.size()); + assertEquals("id2", container.getIdByIndex(0)); + assertEquals("id3", container.getIdByIndex(1)); + assertEquals("id1", container.getIdByIndex(2)); + assertEquals("id4", container.getIdByIndex(3)); + } + + @Test + public void testUnsupportedMethods() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + container.addItem("John", new Person("John")); + + try { + container.addItem(); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addItem(null); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addItemAfter(null, null); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addItemAfter(new Person("Jane")); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addItemAt(0); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addItemAt(0, new Person("Jane")); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addContainerProperty("lastName", String.class, ""); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + assertEquals(1, container.size()); + } + + @Test + public void testRemoveContainerProperty() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + container.setBeanIdResolver(new PersonNameResolver()); + container.addBean(new Person("John")); + + Assert.assertEquals("John", + container.getContainerProperty("John", "name").getValue()); + Assert.assertTrue(container.removeContainerProperty("name")); + Assert.assertNull(container.getContainerProperty("John", "name")); + + Assert.assertNotNull(container.getItem("John")); + // property removed also from item + Assert.assertNull(container.getItem("John").getItemProperty("name")); + } + + @Test + public void testAddNullBeans() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + + assertNull(container.addItem("id1", null)); + assertNull(container.addItemAfter(null, "id2", null)); + assertNull(container.addItemAt(0, "id3", null)); + + assertEquals(0, container.size()); + } + + @Test + public void testAddNullId() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + + Person john = new Person("John"); + + assertNull(container.addItem(null, john)); + assertNull(container.addItemAfter(null, null, john)); + assertNull(container.addItemAt(0, null, john)); + + assertEquals(0, container.size()); + } + + @Test + public void testEmptyContainer() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + + assertNull(container.firstItemId()); + assertNull(container.lastItemId()); + + assertEquals(0, container.size()); + + // could test more about empty container + } + + @Test + public void testAddBeanWithoutResolver() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + + try { + container.addBean(new Person("John")); + Assert.fail(); + } catch (IllegalStateException e) { + // should get exception + } + try { + container.addBeanAfter(null, new Person("Jane")); + Assert.fail(); + } catch (IllegalStateException e) { + // should get exception + } + try { + container.addBeanAt(0, new Person("Jack")); + Assert.fail(); + } catch (IllegalStateException e) { + // should get exception + } + try { + container + .addAll(Arrays.asList(new Person[] { new Person("Jack") })); + Assert.fail(); + } catch (IllegalStateException e) { + // should get exception + } + + assertEquals(0, container.size()); + } + + @Test + public void testAddAllWithNullItemId() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + // resolver that returns null as item id + container.setBeanIdResolver( + new BeanIdResolver<String, AbstractBeanContainerTestBase.Person>() { + + @Override + public String getIdForBean(Person bean) { + return bean.getName(); + } + }); + + List<Person> persons = new ArrayList<Person>(); + persons.add(new Person("John")); + persons.add(new Person("Marc")); + persons.add(new Person(null)); + persons.add(new Person("foo")); + + try { + container.addAll(persons); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + + container.removeAllItems(); + persons.remove(2); + container.addAll(persons); + assertEquals(3, container.size()); + } + + @Test + public void testAddBeanWithNullResolver() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + // resolver that returns null as item id + container.setBeanIdResolver(new NullResolver()); + + try { + container.addBean(new Person("John")); + Assert.fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + try { + container.addBeanAfter(null, new Person("Jane")); + Assert.fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + try { + container.addBeanAt(0, new Person("Jack")); + Assert.fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + + assertEquals(0, container.size()); + } + + @Test + public void testAddBeanWithResolver() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + container.setBeanIdResolver(new PersonNameResolver()); + + assertNotNull(container.addBean(new Person("John"))); + assertNotNull(container.addBeanAfter(null, new Person("Jane"))); + assertNotNull(container.addBeanAt(0, new Person("Jack"))); + + container.addAll(Arrays.asList( + new Person[] { new Person("Jill"), new Person("Joe") })); + + assertTrue(container.containsId("John")); + assertTrue(container.containsId("Jane")); + assertTrue(container.containsId("Jack")); + assertTrue(container.containsId("Jill")); + assertTrue(container.containsId("Joe")); + assertEquals(3, container.indexOfId("Jill")); + assertEquals(4, container.indexOfId("Joe")); + assertEquals(5, container.size()); + } + + @Test + public void testAddNullBeansWithResolver() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + container.setBeanIdResolver(new PersonNameResolver()); + + assertNull(container.addBean(null)); + assertNull(container.addBeanAfter(null, null)); + assertNull(container.addBeanAt(0, null)); + + assertEquals(0, container.size()); + } + + @Test + public void testAddBeanWithPropertyResolver() { + BeanContainer<String, Person> container = new BeanContainer<String, Person>( + Person.class); + container.setBeanIdProperty("name"); + + assertNotNull(container.addBean(new Person("John"))); + assertNotNull(container.addBeanAfter(null, new Person("Jane"))); + assertNotNull(container.addBeanAt(0, new Person("Jack"))); + + container.addAll(Arrays.asList( + new Person[] { new Person("Jill"), new Person("Joe") })); + + assertTrue(container.containsId("John")); + assertTrue(container.containsId("Jane")); + assertTrue(container.containsId("Jack")); + assertTrue(container.containsId("Jill")); + assertTrue(container.containsId("Joe")); + assertEquals(3, container.indexOfId("Jill")); + assertEquals(4, container.indexOfId("Joe")); + assertEquals(5, container.size()); + } + + @Test + public void testAddNestedContainerProperty() { + BeanContainer<String, NestedMethodPropertyTest.Person> container = new BeanContainer<String, NestedMethodPropertyTest.Person>( + NestedMethodPropertyTest.Person.class); + container.setBeanIdProperty("name"); + + container.addBean(new NestedMethodPropertyTest.Person("John", + new NestedMethodPropertyTest.Address("Ruukinkatu 2-4", 20540))); + + assertTrue(container.addNestedContainerProperty("address.street")); + assertEquals("Ruukinkatu 2-4", container + .getContainerProperty("John", "address.street").getValue()); + } + + @Test + public void testNestedContainerPropertyWithNullBean() { + BeanContainer<String, NestedMethodPropertyTest.Person> container = new BeanContainer<String, NestedMethodPropertyTest.Person>( + NestedMethodPropertyTest.Person.class); + container.setBeanIdProperty("name"); + + container.addBean(new NestedMethodPropertyTest.Person("John", null)); + assertTrue(container + .addNestedContainerProperty("address.postalCodeObject")); + assertTrue(container.addNestedContainerProperty("address.street")); + // the nested properties added with allowNullBean setting should return + // null + assertNull(container.getContainerProperty("John", "address.street") + .getValue()); + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/BeanItemContainerGenerator.java b/compatibility-server/src/test/java/com/vaadin/data/util/BeanItemContainerGenerator.java new file mode 100644 index 0000000000..a5bdcc7cf9 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/BeanItemContainerGenerator.java @@ -0,0 +1,150 @@ +package com.vaadin.data.util; + +import java.util.Date; +import java.util.concurrent.atomic.AtomicLong; + +public class BeanItemContainerGenerator { + + public static class PortableRandom { + private final static long multiplier = 0x5DEECE66DL; + private final static long addend = 0xBL; + private final static long mask = (1L << 48) - 1; + private AtomicLong seed; + + public PortableRandom(long seed) { + this.seed = new AtomicLong(0L); + setSeed(seed); + } + + synchronized public void setSeed(long seed) { + seed = (seed ^ multiplier) & mask; + this.seed.set(seed); + } + + public int nextInt(int n) { + if (n <= 0) { + throw new IllegalArgumentException("n must be positive"); + } + + if ((n & -n) == n) { + return (int) ((n * (long) next(31)) >> 31); + } + + int bits, val; + do { + bits = next(31); + val = bits % n; + } while (bits - val + (n - 1) < 0); + return val; + } + + protected int next(int bits) { + long oldseed, nextseed; + AtomicLong seed = this.seed; + do { + oldseed = seed.get(); + nextseed = (oldseed * multiplier + addend) & mask; + } while (!seed.compareAndSet(oldseed, nextseed)); + return (int) (nextseed >>> (48 - bits)); + } + + public boolean nextBoolean() { + return next(1) != 0; + } + + } + + public static BeanItemContainer<TestBean> createContainer(int size) { + return createContainer(size, new Date().getTime()); + } + + public static BeanItemContainer<TestBean> createContainer(int size, + long seed) { + + BeanItemContainer<TestBean> container = new BeanItemContainer<TestBean>( + TestBean.class); + PortableRandom r = new PortableRandom(seed); + for (int i = 0; i < size; i++) { + container.addBean(new TestBean(r)); + } + + return container; + + } + + public static class TestBean { + private String name, address, city, country; + private int age, shoesize; + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public int getShoesize() { + return shoesize; + } + + public void setShoesize(int shoesize) { + this.shoesize = shoesize; + } + + public TestBean(PortableRandom r) { + age = r.nextInt(100) + 5; + shoesize = r.nextInt(10) + 35; + name = createRandomString(r, r.nextInt(5) + 5); + address = createRandomString(r, r.nextInt(15) + 5) + " " + + r.nextInt(100) + 1; + city = createRandomString(r, r.nextInt(7) + 3); + if (r.nextBoolean()) { + country = createRandomString(r, r.nextInt(4) + 4); + } + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getCountry() { + return country; + } + + public void setCountry(String country) { + this.country = country; + } + + } + + public static String createRandomString(PortableRandom r, int len) { + StringBuilder b = new StringBuilder(); + for (int i = 0; i < len; i++) { + b.append((char) (r.nextInt('z' - 'a') + 'a')); + } + + return b.toString(); + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/BeanItemContainerSortTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/BeanItemContainerSortTest.java new file mode 100644 index 0000000000..4f4e35258f --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/BeanItemContainerSortTest.java @@ -0,0 +1,166 @@ +package com.vaadin.data.util; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.junit.Assert; +import org.junit.Test; + +public class BeanItemContainerSortTest { + public class Person { + private String name; + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + private int age; + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + } + + public class Parent extends Person { + private Set<Person> children = new HashSet<Person>(); + + public void setChildren(Set<Person> children) { + this.children = children; + } + + public Set<Person> getChildren() { + return children; + } + } + + String[] names = new String[] { "Antti", "Ville", "Sirkka", "Jaakko", + "Pekka", "John" }; + int[] ages = new int[] { 10, 20, 50, 12, 64, 67 }; + String[] sortedByAge = new String[] { names[0], names[3], names[1], + names[2], names[4], names[5] }; + + public BeanItemContainer<Person> getContainer() { + BeanItemContainer<Person> bc = new BeanItemContainer<Person>( + Person.class); + for (int i = 0; i < names.length; i++) { + Person p = new Person(); + p.setName(names[i]); + p.setAge(ages[i]); + bc.addBean(p); + } + return bc; + + } + + public BeanItemContainer<Parent> getParentContainer() { + BeanItemContainer<Parent> bc = new BeanItemContainer<Parent>( + Parent.class); + for (int i = 0; i < names.length; i++) { + Parent p = new Parent(); + p.setName(names[i]); + p.setAge(ages[i]); + bc.addBean(p); + } + return bc; + } + + @Test + public void testSort() { + testSort(true); + } + + public void testSort(boolean b) { + BeanItemContainer<Person> container = getContainer(); + container.sort(new Object[] { "name" }, new boolean[] { b }); + + List<String> asList = Arrays.asList(names); + Collections.sort(asList); + if (!b) { + Collections.reverse(asList); + } + + int i = 0; + for (String string : asList) { + Person idByIndex = container.getIdByIndex(i++); + Assert.assertTrue(container.containsId(idByIndex)); + Assert.assertEquals(string, idByIndex.getName()); + } + } + + @Test + public void testReverseSort() { + testSort(false); + } + + @Test + public void primitiveSorting() { + BeanItemContainer<Person> container = getContainer(); + container.sort(new Object[] { "age" }, new boolean[] { true }); + + int i = 0; + for (String string : sortedByAge) { + Person idByIndex = container.getIdByIndex(i++); + Assert.assertTrue(container.containsId(idByIndex)); + Assert.assertEquals(string, idByIndex.getName()); + } + } + + @Test + public void customSorting() { + BeanItemContainer<Person> container = getContainer(); + + // custom sorter using the reverse order + container.setItemSorter(new DefaultItemSorter() { + @Override + public int compare(Object o1, Object o2) { + return -super.compare(o1, o2); + } + }); + + container.sort(new Object[] { "age" }, new boolean[] { true }); + + int i = container.size() - 1; + for (String string : sortedByAge) { + Person idByIndex = container.getIdByIndex(i--); + Assert.assertTrue(container.containsId(idByIndex)); + Assert.assertEquals(string, idByIndex.getName()); + } + } + + @Test + public void testGetSortableProperties() { + BeanItemContainer<Person> container = getContainer(); + + Collection<?> sortablePropertyIds = container + .getSortableContainerPropertyIds(); + Assert.assertEquals(2, sortablePropertyIds.size()); + Assert.assertTrue(sortablePropertyIds.contains("name")); + Assert.assertTrue(sortablePropertyIds.contains("age")); + } + + @Test + public void testGetNonSortableProperties() { + BeanItemContainer<Parent> container = getParentContainer(); + + Assert.assertEquals(3, container.getContainerPropertyIds().size()); + + Collection<?> sortablePropertyIds = container + .getSortableContainerPropertyIds(); + Assert.assertEquals(2, sortablePropertyIds.size()); + Assert.assertTrue(sortablePropertyIds.contains("name")); + Assert.assertTrue(sortablePropertyIds.contains("age")); + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/BeanItemContainerTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/BeanItemContainerTest.java new file mode 100644 index 0000000000..19b0835fd6 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/BeanItemContainerTest.java @@ -0,0 +1,997 @@ +package com.vaadin.data.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.easymock.Capture; +import org.easymock.EasyMock; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.Container; +import com.vaadin.data.Container.Indexed.ItemAddEvent; +import com.vaadin.data.Container.Indexed.ItemRemoveEvent; +import com.vaadin.data.Container.ItemSetChangeListener; +import com.vaadin.data.Item; +import com.vaadin.data.util.NestedMethodPropertyTest.Address; +import com.vaadin.data.util.filter.Compare; + +/** + * Test basic functionality of BeanItemContainer. + * + * Most sorting related tests are in {@link BeanItemContainerSortTest}. + */ +public class BeanItemContainerTest extends AbstractBeanContainerTestBase { + + // basics from the common container test + + private Map<String, ClassName> nameToBean = new LinkedHashMap<String, ClassName>(); + + private BeanItemContainer<ClassName> getContainer() { + return new BeanItemContainer<ClassName>(ClassName.class); + } + + @Before + public void setUp() { + nameToBean.clear(); + + for (int i = 0; i < sampleData.length; i++) { + ClassName className = new ClassName(sampleData[i], i); + nameToBean.put(sampleData[i], className); + } + } + + @Override + @SuppressWarnings("unchecked") + protected void initializeContainer(Container container) { + BeanItemContainer<ClassName> beanItemContainer = (BeanItemContainer<ClassName>) container; + + beanItemContainer.removeAllItems(); + + Iterator<ClassName> it = nameToBean.values().iterator(); + while (it.hasNext()) { + beanItemContainer.addBean(it.next()); + } + } + + @Override + protected void validateContainer(Container container, + Object expectedFirstItemId, Object expectedLastItemId, + Object itemIdInSet, Object itemIdNotInSet, boolean checkGetItemNull, + int expectedSize) { + Object notInSet = nameToBean.get(itemIdNotInSet); + if (notInSet == null && itemIdNotInSet != null) { + notInSet = new ClassName(String.valueOf(itemIdNotInSet), 9999); + } + super.validateContainer(container, nameToBean.get(expectedFirstItemId), + nameToBean.get(expectedLastItemId), nameToBean.get(itemIdInSet), + notInSet, checkGetItemNull, expectedSize); + } + + @Override + protected boolean isFilteredOutItemNull() { + return false; + } + + @Test + public void testGetType_existingProperty_typeReturned() { + BeanItemContainer<ClassName> container = getContainer(); + Assert.assertEquals( + "Unexpected type is returned for property 'simpleName'", + String.class, container.getType("simpleName")); + } + + @Test + public void testGetType_notExistingProperty_nullReturned() { + BeanItemContainer<ClassName> container = getContainer(); + Assert.assertNull("Not null type is returned for property ''", + container.getType("")); + } + + @Test + public void testBasicOperations() { + testBasicContainerOperations(getContainer()); + } + + @Test + public void testFiltering() { + testContainerFiltering(getContainer()); + } + + @Test + public void testSorting() { + testContainerSorting(getContainer()); + } + + @Test + public void testSortingAndFiltering() { + testContainerSortingAndFiltering(getContainer()); + } + + // duplicated from parent class and modified - adding items to + // BeanItemContainer differs from other containers + @Test + public void testContainerOrdered() { + BeanItemContainer<String> container = new BeanItemContainer<String>( + String.class); + + String id = "test1"; + + Item item = container.addBean(id); + assertNotNull(item); + + assertEquals(id, container.firstItemId()); + assertEquals(id, container.lastItemId()); + + // isFirstId + assertTrue(container.isFirstId(id)); + assertTrue(container.isFirstId(container.firstItemId())); + // isLastId + assertTrue(container.isLastId(id)); + assertTrue(container.isLastId(container.lastItemId())); + + // Add a new item before the first + // addItemAfter + String newFirstId = "newFirst"; + item = container.addItemAfter(null, newFirstId); + assertNotNull(item); + assertNotNull(container.getItem(newFirstId)); + + // isFirstId + assertTrue(container.isFirstId(newFirstId)); + assertTrue(container.isFirstId(container.firstItemId())); + // isLastId + assertTrue(container.isLastId(id)); + assertTrue(container.isLastId(container.lastItemId())); + + // nextItemId + assertEquals(id, container.nextItemId(newFirstId)); + assertNull(container.nextItemId(id)); + assertNull(container.nextItemId("not-in-container")); + + // prevItemId + assertEquals(newFirstId, container.prevItemId(id)); + assertNull(container.prevItemId(newFirstId)); + assertNull(container.prevItemId("not-in-container")); + + // addItemAfter(Object) + String newSecondItemId = "newSecond"; + item = container.addItemAfter(newFirstId, newSecondItemId); + // order is now: newFirstId, newSecondItemId, id + assertNotNull(item); + assertNotNull(container.getItem(newSecondItemId)); + assertEquals(id, container.nextItemId(newSecondItemId)); + assertEquals(newFirstId, container.prevItemId(newSecondItemId)); + + // addItemAfter(Object,Object) + String fourthId = "id of the fourth item"; + Item fourth = container.addItemAfter(newFirstId, fourthId); + // order is now: newFirstId, fourthId, newSecondItemId, id + assertNotNull(fourth); + assertEquals(fourth, container.getItem(fourthId)); + assertEquals(newSecondItemId, container.nextItemId(fourthId)); + assertEquals(newFirstId, container.prevItemId(fourthId)); + + // addItemAfter(Object,Object) + Object fifthId = "fifth"; + Item fifth = container.addItemAfter(null, fifthId); + // order is now: fifthId, newFirstId, fourthId, newSecondItemId, id + assertNotNull(fifth); + assertEquals(fifth, container.getItem(fifthId)); + assertEquals(newFirstId, container.nextItemId(fifthId)); + assertNull(container.prevItemId(fifthId)); + + } + + @Test + public void testContainerIndexed() { + testContainerIndexed(getContainer(), nameToBean.get(sampleData[2]), 2, + false, new ClassName("org.vaadin.test.Test", 8888), true); + } + + @SuppressWarnings("deprecation") + @Test + public void testCollectionConstructors() { + List<ClassName> classNames = new ArrayList<ClassName>(); + classNames.add(new ClassName("a.b.c.Def", 1)); + classNames.add(new ClassName("a.b.c.Fed", 2)); + classNames.add(new ClassName("b.c.d.Def", 3)); + + // note that this constructor is problematic, users should use the + // version that + // takes the bean class as a parameter + BeanItemContainer<ClassName> container = new BeanItemContainer<ClassName>( + classNames); + + Assert.assertEquals(3, container.size()); + Assert.assertEquals(classNames.get(0), container.firstItemId()); + Assert.assertEquals(classNames.get(1), container.getIdByIndex(1)); + Assert.assertEquals(classNames.get(2), container.lastItemId()); + + BeanItemContainer<ClassName> container2 = new BeanItemContainer<ClassName>( + ClassName.class, classNames); + + Assert.assertEquals(3, container2.size()); + Assert.assertEquals(classNames.get(0), container2.firstItemId()); + Assert.assertEquals(classNames.get(1), container2.getIdByIndex(1)); + Assert.assertEquals(classNames.get(2), container2.lastItemId()); + } + + // this only applies to the collection constructor with no type parameter + @SuppressWarnings("deprecation") + @Test + public void testEmptyCollectionConstructor() { + try { + new BeanItemContainer<ClassName>((Collection<ClassName>) null); + Assert.fail( + "Initializing BeanItemContainer from a null collection should not work!"); + } catch (IllegalArgumentException e) { + // success + } + try { + new BeanItemContainer<ClassName>(new ArrayList<ClassName>()); + Assert.fail( + "Initializing BeanItemContainer from an empty collection should not work!"); + } catch (IllegalArgumentException e) { + // success + } + } + + @Test + public void testItemSetChangeListeners() { + BeanItemContainer<ClassName> container = getContainer(); + ItemSetChangeCounter counter = new ItemSetChangeCounter(); + container.addListener(counter); + + ClassName cn1 = new ClassName("com.example.Test", 1111); + ClassName cn2 = new ClassName("com.example.Test2", 2222); + + initializeContainer(container); + counter.reset(); + container.addBean(cn1); + counter.assertOnce(); + + initializeContainer(container); + counter.reset(); + container.addItem(cn1); + counter.assertOnce(); + // no notification if already in container + container.addItem(cn1); + counter.assertNone(); + container.addItem(cn2); + counter.assertOnce(); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(null, cn1); + counter.assertOnce(); + Assert.assertEquals("com.example.Test", + container.getContainerProperty(container.firstItemId(), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(container.firstItemId(), cn1); + counter.assertOnce(); + Assert.assertEquals("com.example.Test", + container.getContainerProperty(container.getIdByIndex(1), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(container.lastItemId(), cn1); + counter.assertOnce(); + Assert.assertEquals("com.example.Test", + container.getContainerProperty(container.lastItemId(), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAt(0, cn1); + counter.assertOnce(); + Assert.assertEquals("com.example.Test", + container.getContainerProperty(container.firstItemId(), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAt(1, cn1); + counter.assertOnce(); + Assert.assertEquals("com.example.Test", + container.getContainerProperty(container.getIdByIndex(1), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAt(container.size(), cn1); + counter.assertOnce(); + Assert.assertEquals("com.example.Test", + container.getContainerProperty(container.lastItemId(), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.removeItem(nameToBean.get(sampleData[0])); + counter.assertOnce(); + + initializeContainer(container); + counter.reset(); + // no notification for removing a non-existing item + container.removeItem(cn1); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.removeAllItems(); + counter.assertOnce(); + // already empty + container.removeAllItems(); + counter.assertNone(); + + } + + @Test + public void testItemSetChangeListenersFiltering() { + BeanItemContainer<ClassName> container = getContainer(); + ItemSetChangeCounter counter = new ItemSetChangeCounter(); + container.addListener(counter); + + ClassName cn1 = new ClassName("com.example.Test", 1111); + ClassName cn2 = new ClassName("com.example.Test2", 2222); + ClassName other = new ClassName("com.example.Other", 3333); + + // simply adding or removing container filters should cause event + // (content changes) + + initializeContainer(container); + counter.reset(); + container.addContainerFilter(SIMPLE_NAME, "a", true, false); + counter.assertOnce(); + container.removeContainerFilters(SIMPLE_NAME); + counter.assertOnce(); + + initializeContainer(container); + counter.reset(); + container.addContainerFilter(SIMPLE_NAME, "a", true, false); + counter.assertOnce(); + container.removeAllContainerFilters(); + counter.assertOnce(); + + // perform operations while filtering container + + initializeContainer(container); + counter.reset(); + container.addContainerFilter(FULLY_QUALIFIED_NAME, "Test", true, false); + counter.assertOnce(); + + // passes filter + container.addBean(cn1); + counter.assertOnce(); + + // passes filter but already in the container + container.addBean(cn1); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + + // passes filter + container.addItem(cn1); + counter.assertOnce(); + // already in the container + container.addItem(cn1); + counter.assertNone(); + container.addItem(cn2); + counter.assertOnce(); + // does not pass filter + container.addItem(other); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(null, cn1); + counter.assertOnce(); + Assert.assertEquals("com.example.Test", + container.getContainerProperty(container.firstItemId(), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(container.firstItemId(), cn1); + counter.assertOnce(); + Assert.assertEquals("com.example.Test", + container.getContainerProperty(container.getIdByIndex(1), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(container.lastItemId(), cn1); + counter.assertOnce(); + Assert.assertEquals("com.example.Test", + container.getContainerProperty(container.lastItemId(), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAt(0, cn1); + counter.assertOnce(); + Assert.assertEquals("com.example.Test", + container.getContainerProperty(container.firstItemId(), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAt(1, cn1); + counter.assertOnce(); + Assert.assertEquals("com.example.Test", + container.getContainerProperty(container.getIdByIndex(1), + FULLY_QUALIFIED_NAME).getValue()); + + initializeContainer(container); + counter.reset(); + container.addItemAt(container.size(), cn1); + counter.assertOnce(); + Assert.assertEquals("com.example.Test", + container.getContainerProperty(container.lastItemId(), + FULLY_QUALIFIED_NAME).getValue()); + + // does not pass filter + // note: testAddRemoveWhileFiltering() checks position for these after + // removing filter etc, here concentrating on listeners + + initializeContainer(container); + counter.reset(); + container.addItemAfter(null, other); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(container.firstItemId(), other); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(container.lastItemId(), other); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.addItemAt(0, other); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.addItemAt(1, other); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.addItemAt(container.size(), other); + counter.assertNone(); + + // passes filter + + initializeContainer(container); + counter.reset(); + container.addItem(cn1); + counter.assertOnce(); + container.removeItem(cn1); + counter.assertOnce(); + + // does not pass filter + + initializeContainer(container); + counter.reset(); + // not visible + container.removeItem(nameToBean.get(sampleData[0])); + counter.assertNone(); + + container.removeAllItems(); + counter.assertOnce(); + // no visible items + container.removeAllItems(); + counter.assertNone(); + } + + @Test + public void testAddRemoveWhileFiltering() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + + Person john = new Person("John"); + Person jane = new Person("Jane"); + Person matthew = new Person("Matthew"); + + Person jack = new Person("Jack"); + Person michael = new Person("Michael"); + Person william = new Person("William"); + Person julia = new Person("Julia"); + Person george = new Person("George"); + Person mark = new Person("Mark"); + + container.addBean(john); + container.addBean(jane); + container.addBean(matthew); + + assertEquals(3, container.size()); + // john, jane, matthew + + container.addContainerFilter("name", "j", true, true); + + assertEquals(2, container.size()); + // john, jane, (matthew) + + // add a bean that passes the filter + container.addBean(jack); + assertEquals(3, container.size()); + assertEquals(jack, container.lastItemId()); + // john, jane, (matthew), jack + + // add beans that do not pass the filter + container.addBean(michael); + // john, jane, (matthew), jack, (michael) + container.addItemAfter(null, william); + // (william), john, jane, (matthew), jack, (michael) + + // add after an item that is shown + container.addItemAfter(john, george); + // (william), john, (george), jane, (matthew), jack, (michael) + assertEquals(3, container.size()); + assertEquals(john, container.firstItemId()); + + // add after an item that is not shown does nothing + container.addItemAfter(william, julia); + // (william), john, (george), jane, (matthew), jack, (michael) + assertEquals(3, container.size()); + assertEquals(john, container.firstItemId()); + + container.addItemAt(1, julia); + // (william), john, julia, (george), jane, (matthew), jack, (michael) + + container.addItemAt(2, mark); + // (william), john, julia, (mark), (george), jane, (matthew), jack, + // (michael) + + container.removeItem(matthew); + // (william), john, julia, (mark), (george), jane, jack, (michael) + + assertEquals(4, container.size()); + assertEquals(jack, container.lastItemId()); + + container.removeContainerFilters("name"); + + assertEquals(8, container.size()); + assertEquals(william, container.firstItemId()); + assertEquals(john, container.nextItemId(william)); + assertEquals(julia, container.nextItemId(john)); + assertEquals(mark, container.nextItemId(julia)); + assertEquals(george, container.nextItemId(mark)); + assertEquals(jane, container.nextItemId(george)); + assertEquals(jack, container.nextItemId(jane)); + assertEquals(michael, container.lastItemId()); + } + + @Test + public void testRefilterOnPropertyModification() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + + Person john = new Person("John"); + Person jane = new Person("Jane"); + Person matthew = new Person("Matthew"); + + container.addBean(john); + container.addBean(jane); + container.addBean(matthew); + + assertEquals(3, container.size()); + // john, jane, matthew + + container.addContainerFilter("name", "j", true, true); + + assertEquals(2, container.size()); + // john, jane, (matthew) + + // #6053 currently, modification of an item that is not visible does not + // trigger refiltering - should it? + // matthew.setName("Julia"); + // assertEquals(3, container.size()); + // john, jane, julia + + john.setName("Mark"); + assertEquals(2, container.size()); + // (mark), jane, julia + + container.removeAllContainerFilters(); + + assertEquals(3, container.size()); + } + + @Test + public void testAddAll() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + + Person john = new Person("John"); + Person jane = new Person("Jane"); + Person matthew = new Person("Matthew"); + + container.addBean(john); + container.addBean(jane); + container.addBean(matthew); + + assertEquals(3, container.size()); + // john, jane, matthew + + Person jack = new Person("Jack"); + Person michael = new Person("Michael"); + + // addAll + container.addAll(Arrays.asList(jack, michael)); + // john, jane, matthew, jack, michael + + assertEquals(5, container.size()); + assertEquals(jane, container.nextItemId(john)); + assertEquals(matthew, container.nextItemId(jane)); + assertEquals(jack, container.nextItemId(matthew)); + assertEquals(michael, container.nextItemId(jack)); + } + + @Test + public void testUnsupportedMethods() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + container.addBean(new Person("John")); + + try { + container.addItem(); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addItemAfter(new Person("Jane")); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addItemAt(0); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + try { + container.addContainerProperty("lastName", String.class, ""); + Assert.fail(); + } catch (UnsupportedOperationException e) { + // should get exception + } + + assertEquals(1, container.size()); + } + + @Test + public void testRemoveContainerProperty() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + Person john = new Person("John"); + container.addBean(john); + + Assert.assertEquals("John", + container.getContainerProperty(john, "name").getValue()); + Assert.assertTrue(container.removeContainerProperty("name")); + Assert.assertNull(container.getContainerProperty(john, "name")); + + Assert.assertNotNull(container.getItem(john)); + // property removed also from item + Assert.assertNull(container.getItem(john).getItemProperty("name")); + } + + @Test + public void testAddNullBean() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + Person john = new Person("John"); + container.addBean(john); + + assertNull(container.addItem(null)); + assertNull(container.addItemAfter(null, null)); + assertNull(container.addItemAfter(john, null)); + assertNull(container.addItemAt(0, null)); + + assertEquals(1, container.size()); + } + + @Test + public void testBeanIdResolver() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + Person john = new Person("John"); + + assertSame(john, container.getBeanIdResolver().getIdForBean(john)); + } + + @Test(expected = IllegalArgumentException.class) + public void testNullBeanClass() { + new BeanItemContainer<Object>((Class<Object>) null); + } + + @Test + public void testAddNestedContainerProperty() { + BeanItemContainer<NestedMethodPropertyTest.Person> container = new BeanItemContainer<NestedMethodPropertyTest.Person>( + NestedMethodPropertyTest.Person.class); + + NestedMethodPropertyTest.Person john = new NestedMethodPropertyTest.Person( + "John", + new NestedMethodPropertyTest.Address("Ruukinkatu 2-4", 20540)); + container.addBean(john); + + assertTrue(container.addNestedContainerProperty("address.street")); + assertEquals("Ruukinkatu 2-4", container + .getContainerProperty(john, "address.street").getValue()); + } + + @Test + public void testNestedContainerPropertyWithNullBean() { + BeanItemContainer<NestedMethodPropertyTest.Person> container = new BeanItemContainer<NestedMethodPropertyTest.Person>( + NestedMethodPropertyTest.Person.class); + NestedMethodPropertyTest.Person john = new NestedMethodPropertyTest.Person( + "John", null); + assertNotNull(container.addBean(john)); + assertTrue(container + .addNestedContainerProperty("address.postalCodeObject")); + assertTrue(container.addNestedContainerProperty("address.street")); + // the nested properties should return null + assertNull(container.getContainerProperty(john, "address.street") + .getValue()); + } + + @Test + public void testItemAddedEvent() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + Person bean = new Person("John"); + ItemSetChangeListener addListener = createListenerMockFor(container); + addListener.containerItemSetChange(EasyMock.isA(ItemAddEvent.class)); + EasyMock.replay(addListener); + + container.addItem(bean); + + EasyMock.verify(addListener); + } + + @Test + public void testItemAddedEvent_AddedItem() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + Person bean = new Person("John"); + ItemSetChangeListener addListener = createListenerMockFor(container); + Capture<ItemAddEvent> capturedEvent = captureAddEvent(addListener); + EasyMock.replay(addListener); + + container.addItem(bean); + + assertEquals(bean, capturedEvent.getValue().getFirstItemId()); + } + + @Test + public void testItemAddedEvent_addItemAt_IndexOfAddedItem() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + Person bean = new Person("John"); + container.addItem(bean); + ItemSetChangeListener addListener = createListenerMockFor(container); + Capture<ItemAddEvent> capturedEvent = captureAddEvent(addListener); + EasyMock.replay(addListener); + + container.addItemAt(1, new Person("")); + + assertEquals(1, capturedEvent.getValue().getFirstIndex()); + } + + @Test + public void testItemAddedEvent_addItemAfter_IndexOfAddedItem() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + Person bean = new Person("John"); + container.addItem(bean); + ItemSetChangeListener addListener = createListenerMockFor(container); + Capture<ItemAddEvent> capturedEvent = captureAddEvent(addListener); + EasyMock.replay(addListener); + + container.addItemAfter(bean, new Person("")); + + assertEquals(1, capturedEvent.getValue().getFirstIndex()); + } + + @Test + public void testItemAddedEvent_amountOfAddedItems() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + ItemSetChangeListener addListener = createListenerMockFor(container); + Capture<ItemAddEvent> capturedEvent = captureAddEvent(addListener); + EasyMock.replay(addListener); + List<Person> beans = Arrays.asList(new Person("Jack"), + new Person("John")); + + container.addAll(beans); + + assertEquals(2, capturedEvent.getValue().getAddedItemsCount()); + } + + @Test + public void testItemAddedEvent_someItemsAreFiltered_amountOfAddedItemsIsReducedByAmountOfFilteredItems() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + ItemSetChangeListener addListener = createListenerMockFor(container); + Capture<ItemAddEvent> capturedEvent = captureAddEvent(addListener); + EasyMock.replay(addListener); + List<Person> beans = Arrays.asList(new Person("Jack"), + new Person("John")); + container.addFilter(new Compare.Equal("name", "John")); + + container.addAll(beans); + + assertEquals(1, capturedEvent.getValue().getAddedItemsCount()); + } + + @Test + public void testItemAddedEvent_someItemsAreFiltered_addedItemIsTheFirstVisibleItem() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + Person bean = new Person("John"); + ItemSetChangeListener addListener = createListenerMockFor(container); + Capture<ItemAddEvent> capturedEvent = captureAddEvent(addListener); + EasyMock.replay(addListener); + List<Person> beans = Arrays.asList(new Person("Jack"), bean); + container.addFilter(new Compare.Equal("name", "John")); + + container.addAll(beans); + + assertEquals(bean, capturedEvent.getValue().getFirstItemId()); + } + + @Test + public void testItemRemovedEvent() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + Person bean = new Person("John"); + container.addItem(bean); + ItemSetChangeListener removeListener = createListenerMockFor(container); + removeListener + .containerItemSetChange(EasyMock.isA(ItemRemoveEvent.class)); + EasyMock.replay(removeListener); + + container.removeItem(bean); + + EasyMock.verify(removeListener); + } + + @Test + public void testItemRemovedEvent_RemovedItem() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + Person bean = new Person("John"); + container.addItem(bean); + ItemSetChangeListener removeListener = createListenerMockFor(container); + Capture<ItemRemoveEvent> capturedEvent = captureRemoveEvent( + removeListener); + EasyMock.replay(removeListener); + + container.removeItem(bean); + + assertEquals(bean, capturedEvent.getValue().getFirstItemId()); + } + + @Test + public void testItemRemovedEvent_indexOfRemovedItem() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + container.addItem(new Person("Jack")); + Person secondBean = new Person("John"); + container.addItem(secondBean); + ItemSetChangeListener removeListener = createListenerMockFor(container); + Capture<ItemRemoveEvent> capturedEvent = captureRemoveEvent( + removeListener); + EasyMock.replay(removeListener); + + container.removeItem(secondBean); + + assertEquals(1, capturedEvent.getValue().getFirstIndex()); + } + + @Test + public void testItemRemovedEvent_amountOfRemovedItems() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class); + container.addItem(new Person("Jack")); + container.addItem(new Person("John")); + ItemSetChangeListener removeListener = createListenerMockFor(container); + Capture<ItemRemoveEvent> capturedEvent = captureRemoveEvent( + removeListener); + EasyMock.replay(removeListener); + + container.removeAllItems(); + + assertEquals(2, capturedEvent.getValue().getRemovedItemsCount()); + } + + private Capture<ItemAddEvent> captureAddEvent( + ItemSetChangeListener addListener) { + Capture<ItemAddEvent> capturedEvent = new Capture<ItemAddEvent>(); + addListener.containerItemSetChange(EasyMock.capture(capturedEvent)); + return capturedEvent; + } + + private Capture<ItemRemoveEvent> captureRemoveEvent( + ItemSetChangeListener removeListener) { + Capture<ItemRemoveEvent> capturedEvent = new Capture<ItemRemoveEvent>(); + removeListener.containerItemSetChange(EasyMock.capture(capturedEvent)); + return capturedEvent; + } + + private ItemSetChangeListener createListenerMockFor( + BeanItemContainer<Person> container) { + ItemSetChangeListener listener = EasyMock + .createNiceMock(ItemSetChangeListener.class); + container.addItemSetChangeListener(listener); + return listener; + } + + @Test + public void testAddNestedContainerBeanBeforeData() { + BeanItemContainer<NestedMethodPropertyTest.Person> container = new BeanItemContainer<NestedMethodPropertyTest.Person>( + NestedMethodPropertyTest.Person.class); + + container.addNestedContainerBean("address"); + + assertTrue( + container.getContainerPropertyIds().contains("address.street")); + + NestedMethodPropertyTest.Person john = new NestedMethodPropertyTest.Person( + "John", new Address("streetname", 12345)); + container.addBean(john); + + assertTrue(container.getItem(john).getItemPropertyIds() + .contains("address.street")); + assertEquals("streetname", container.getItem(john) + .getItemProperty("address.street").getValue()); + + } + + @Test + public void testAddNestedContainerBeanAfterData() { + BeanItemContainer<NestedMethodPropertyTest.Person> container = new BeanItemContainer<NestedMethodPropertyTest.Person>( + NestedMethodPropertyTest.Person.class); + + NestedMethodPropertyTest.Person john = new NestedMethodPropertyTest.Person( + "John", new Address("streetname", 12345)); + container.addBean(john); + + container.addNestedContainerBean("address"); + + assertTrue( + container.getContainerPropertyIds().contains("address.street")); + assertTrue(container.getItem(john).getItemPropertyIds() + .contains("address.street")); + assertEquals("streetname", container.getItem(john) + .getItemProperty("address.street").getValue()); + + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/BeanItemTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/BeanItemTest.java new file mode 100644 index 0000000000..1bbe74818c --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/BeanItemTest.java @@ -0,0 +1,389 @@ +package com.vaadin.data.util; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.data.Property; + +/** + * Test BeanItem specific features. + * + * Only public API is tested, not the methods with package visibility. + * + * See also {@link PropertySetItemTest}, which tests the base class. + */ +public class BeanItemTest { + + @SuppressWarnings("unused") + protected static class MySuperClass { + private int superPrivate = 1; + private int superPrivate2 = 2; + protected double superProtected = 3.0; + private double superProtected2 = 4.0; + public boolean superPublic = true; + private boolean superPublic2 = true; + + public int getSuperPrivate() { + return superPrivate; + } + + public void setSuperPrivate(int superPrivate) { + this.superPrivate = superPrivate; + } + + public double getSuperProtected() { + return superProtected; + } + + public void setSuperProtected(double superProtected) { + this.superProtected = superProtected; + } + + public boolean isSuperPublic() { + return superPublic; + } + + public void setSuperPublic(boolean superPublic) { + this.superPublic = superPublic; + } + + } + + protected static class MyClass extends MySuperClass { + private String name; + public int value = 123; + + public MyClass(String name) { + this.name = name; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setNoField(String name) { + } + + public String getNoField() { + return "no field backing this setter"; + } + + public String getName2() { + return name; + } + } + + protected static class MyClass2 extends MyClass { + public MyClass2(String name) { + super(name); + } + + @Override + public void setName(String name) { + super.setName(name + "2"); + } + + @Override + public String getName() { + return super.getName() + "2"; + } + + @Override + public String getName2() { + return super.getName(); + } + + public void setName2(String name) { + super.setName(name); + } + } + + protected static interface MySuperInterface { + public int getSuper1(); + + public void setSuper1(int i); + + public int getOverride(); + } + + protected static interface MySuperInterface2 { + public int getSuper2(); + } + + protected static class Generic<T> { + + public T getProperty() { + return null; + } + + public void setProperty(T t) { + throw new UnsupportedOperationException(); + } + } + + protected static class SubClass extends Generic<String> { + + @Override + // Has a bridged method + public String getProperty() { + return ""; + } + + @Override + // Has a bridged method + public void setProperty(String t) { + } + } + + protected static interface MySubInterface + extends MySuperInterface, MySuperInterface2 { + public int getSub(); + + public void setSub(int i); + + @Override + public int getOverride(); + + public void setOverride(int i); + } + + @Test + public void testGetProperties() { + BeanItem<MySuperClass> item = new BeanItem<MySuperClass>( + new MySuperClass()); + + Collection<?> itemPropertyIds = item.getItemPropertyIds(); + Assert.assertEquals(3, itemPropertyIds.size()); + Assert.assertTrue(itemPropertyIds.contains("superPrivate")); + Assert.assertTrue(itemPropertyIds.contains("superProtected")); + Assert.assertTrue(itemPropertyIds.contains("superPublic")); + } + + @Test + public void testGetSuperClassProperties() { + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1")); + + Collection<?> itemPropertyIds = item.getItemPropertyIds(); + Assert.assertEquals(6, itemPropertyIds.size()); + Assert.assertTrue(itemPropertyIds.contains("superPrivate")); + Assert.assertTrue(itemPropertyIds.contains("superProtected")); + Assert.assertTrue(itemPropertyIds.contains("superPublic")); + Assert.assertTrue(itemPropertyIds.contains("name")); + Assert.assertTrue(itemPropertyIds.contains("noField")); + Assert.assertTrue(itemPropertyIds.contains("name2")); + } + + @Test + public void testOverridingProperties() { + BeanItem<MyClass2> item = new BeanItem<MyClass2>(new MyClass2("bean2")); + + Collection<?> itemPropertyIds = item.getItemPropertyIds(); + Assert.assertEquals(6, itemPropertyIds.size()); + + Assert.assertTrue(MyClass2.class.equals(item.getBean().getClass())); + + // check that name2 accessed via MyClass2, not MyClass + Assert.assertFalse(item.getItemProperty("name2").isReadOnly()); + } + + @Test + public void testGetInterfaceProperties() throws SecurityException, + NoSuchMethodException, IllegalArgumentException, + IllegalAccessException, InvocationTargetException { + Method method = BeanItem.class + .getDeclaredMethod("getPropertyDescriptors", Class.class); + method.setAccessible(true); + LinkedHashMap<String, VaadinPropertyDescriptor<Class>> propertyDescriptors = (LinkedHashMap<String, VaadinPropertyDescriptor<Class>>) method + .invoke(null, MySuperInterface.class); + + Assert.assertEquals(2, propertyDescriptors.size()); + Assert.assertTrue(propertyDescriptors.containsKey("super1")); + Assert.assertTrue(propertyDescriptors.containsKey("override")); + + MethodProperty<?> property = (MethodProperty<?>) propertyDescriptors + .get("override").createProperty(getClass()); + Assert.assertTrue(property.isReadOnly()); + } + + @Test + public void testGetSuperInterfaceProperties() throws SecurityException, + NoSuchMethodException, IllegalArgumentException, + IllegalAccessException, InvocationTargetException { + Method method = BeanItem.class + .getDeclaredMethod("getPropertyDescriptors", Class.class); + method.setAccessible(true); + LinkedHashMap<String, VaadinPropertyDescriptor<Class>> propertyDescriptors = (LinkedHashMap<String, VaadinPropertyDescriptor<Class>>) method + .invoke(null, MySubInterface.class); + + Assert.assertEquals(4, propertyDescriptors.size()); + Assert.assertTrue(propertyDescriptors.containsKey("sub")); + Assert.assertTrue(propertyDescriptors.containsKey("super1")); + Assert.assertTrue(propertyDescriptors.containsKey("super2")); + Assert.assertTrue(propertyDescriptors.containsKey("override")); + + MethodProperty<?> property = (MethodProperty<?>) propertyDescriptors + .get("override").createProperty(getClass()); + Assert.assertFalse(property.isReadOnly()); + } + + @Test + public void testPropertyExplicitOrder() { + Collection<String> ids = new ArrayList<String>(); + ids.add("name"); + ids.add("superPublic"); + ids.add("name2"); + ids.add("noField"); + + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1"), + ids); + + Iterator<?> it = item.getItemPropertyIds().iterator(); + Assert.assertEquals("name", it.next()); + Assert.assertEquals("superPublic", it.next()); + Assert.assertEquals("name2", it.next()); + Assert.assertEquals("noField", it.next()); + Assert.assertFalse(it.hasNext()); + } + + @Test + public void testPropertyExplicitOrder2() { + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1"), + new String[] { "name", "superPublic", "name2", "noField" }); + + Iterator<?> it = item.getItemPropertyIds().iterator(); + Assert.assertEquals("name", it.next()); + Assert.assertEquals("superPublic", it.next()); + Assert.assertEquals("name2", it.next()); + Assert.assertEquals("noField", it.next()); + Assert.assertFalse(it.hasNext()); + } + + @Test + public void testPropertyBadPropertyName() { + Collection<String> ids = new ArrayList<String>(); + ids.add("name3"); + ids.add("name"); + + // currently silently ignores non-existent properties + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1"), + ids); + + Iterator<?> it = item.getItemPropertyIds().iterator(); + Assert.assertEquals("name", it.next()); + Assert.assertFalse(it.hasNext()); + } + + @Test + public void testRemoveProperty() { + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1")); + + Collection<?> itemPropertyIds = item.getItemPropertyIds(); + Assert.assertEquals(6, itemPropertyIds.size()); + + item.removeItemProperty("name2"); + Assert.assertEquals(5, itemPropertyIds.size()); + Assert.assertFalse(itemPropertyIds.contains("name2")); + } + + @Test + public void testRemoveSuperProperty() { + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1")); + + Collection<?> itemPropertyIds = item.getItemPropertyIds(); + Assert.assertEquals(6, itemPropertyIds.size()); + + item.removeItemProperty("superPrivate"); + Assert.assertEquals(5, itemPropertyIds.size()); + Assert.assertFalse(itemPropertyIds.contains("superPrivate")); + } + + @Test + public void testPropertyTypes() { + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1")); + + Assert.assertTrue(Integer.class + .equals(item.getItemProperty("superPrivate").getType())); + Assert.assertTrue(Double.class + .equals(item.getItemProperty("superProtected").getType())); + Assert.assertTrue(Boolean.class + .equals(item.getItemProperty("superPublic").getType())); + Assert.assertTrue( + String.class.equals(item.getItemProperty("name").getType())); + } + + @Test + public void testPropertyReadOnly() { + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1")); + + Assert.assertFalse(item.getItemProperty("name").isReadOnly()); + Assert.assertTrue(item.getItemProperty("name2").isReadOnly()); + } + + @Test + public void testCustomProperties() throws Exception { + LinkedHashMap<String, VaadinPropertyDescriptor<MyClass>> propertyDescriptors = new LinkedHashMap<String, VaadinPropertyDescriptor<MyClass>>(); + propertyDescriptors.put("myname", + new MethodPropertyDescriptor<BeanItemTest.MyClass>("myname", + MyClass.class, + MyClass.class.getDeclaredMethod("getName"), + MyClass.class.getDeclaredMethod("setName", + String.class))); + MyClass instance = new MyClass("bean1"); + Constructor<BeanItem> constructor = BeanItem.class + .getDeclaredConstructor(Object.class, Map.class); + constructor.setAccessible(true); + BeanItem<MyClass> item = constructor.newInstance(instance, + propertyDescriptors); + + Assert.assertEquals(1, item.getItemPropertyIds().size()); + Assert.assertEquals("bean1", item.getItemProperty("myname").getValue()); + } + + @Test + public void testAddRemoveProperty() throws Exception { + MethodPropertyDescriptor<BeanItemTest.MyClass> pd = new MethodPropertyDescriptor<BeanItemTest.MyClass>( + "myname", MyClass.class, + MyClass.class.getDeclaredMethod("getName"), + MyClass.class.getDeclaredMethod("setName", String.class)); + + BeanItem<MyClass> item = new BeanItem<MyClass>(new MyClass("bean1")); + + Assert.assertEquals(6, item.getItemPropertyIds().size()); + Assert.assertEquals(null, item.getItemProperty("myname")); + + item.addItemProperty("myname", pd.createProperty(item.getBean())); + Assert.assertEquals(7, item.getItemPropertyIds().size()); + Assert.assertEquals("bean1", item.getItemProperty("myname").getValue()); + item.removeItemProperty("myname"); + Assert.assertEquals(6, item.getItemPropertyIds().size()); + Assert.assertEquals(null, item.getItemProperty("myname")); + } + + @Test + public void testOverridenGenericMethods() { + BeanItem<SubClass> item = new BeanItem<SubClass>(new SubClass()); + + Property<?> property = item.getItemProperty("property"); + Assert.assertEquals("Unexpected class for property type", String.class, + property.getType()); + + Assert.assertEquals("Unexpected property value", "", + property.getValue()); + + // Should not be exception + property.setValue(null); + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/ContainerHierarchicalWrapperTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/ContainerHierarchicalWrapperTest.java new file mode 100644 index 0000000000..e41f751bfd --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/ContainerHierarchicalWrapperTest.java @@ -0,0 +1,26 @@ +package com.vaadin.data.util; + +import org.junit.Test; + +public class ContainerHierarchicalWrapperTest + extends AbstractHierarchicalContainerTestBase { + + @Test + public void testBasicOperations() { + testBasicContainerOperations( + new ContainerHierarchicalWrapper(new IndexedContainer())); + } + + @Test + public void testHierarchicalContainer() { + testHierarchicalContainer( + new ContainerHierarchicalWrapper(new IndexedContainer())); + } + + @Test + public void testRemoveSubtree() { + testRemoveHierarchicalWrapperSubtree( + new ContainerHierarchicalWrapper(new IndexedContainer())); + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/ContainerOrderedWrapperTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/ContainerOrderedWrapperTest.java new file mode 100644 index 0000000000..c3a8b2c4f9 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/ContainerOrderedWrapperTest.java @@ -0,0 +1,107 @@ +package com.vaadin.data.util; + +import java.util.Collection; + +import org.junit.Test; + +import com.vaadin.data.Container; +import com.vaadin.data.Item; +import com.vaadin.data.Property; + +public class ContainerOrderedWrapperTest extends AbstractContainerTestBase { + + // This class is needed to get an implementation of container + // which is not an implementation of Ordered interface. + private class NotOrderedContainer implements Container { + + private IndexedContainer container; + + public NotOrderedContainer() { + container = new IndexedContainer(); + } + + @Override + public Item getItem(Object itemId) { + return container.getItem(itemId); + } + + @Override + public Collection<?> getContainerPropertyIds() { + return container.getContainerPropertyIds(); + } + + @Override + public Collection<?> getItemIds() { + return container.getItemIds(); + } + + @Override + public Property getContainerProperty(Object itemId, Object propertyId) { + return container.getContainerProperty(itemId, propertyId); + } + + @Override + public Class<?> getType(Object propertyId) { + return container.getType(propertyId); + } + + @Override + public int size() { + return container.size(); + } + + @Override + public boolean containsId(Object itemId) { + return container.containsId(itemId); + } + + @Override + public Item addItem(Object itemId) + throws UnsupportedOperationException { + return container.addItem(itemId); + } + + @Override + public Object addItem() throws UnsupportedOperationException { + return container.addItem(); + } + + @Override + public boolean removeItem(Object itemId) + throws UnsupportedOperationException { + return container.removeItem(itemId); + } + + @Override + public boolean addContainerProperty(Object propertyId, Class<?> type, + Object defaultValue) throws UnsupportedOperationException { + return container.addContainerProperty(propertyId, type, + defaultValue); + } + + @Override + public boolean removeContainerProperty(Object propertyId) + throws UnsupportedOperationException { + return container.removeContainerProperty(propertyId); + } + + @Override + public boolean removeAllItems() throws UnsupportedOperationException { + return container.removeAllItems(); + } + + } + + @Test + public void testBasicOperations() { + testBasicContainerOperations( + new ContainerOrderedWrapper(new NotOrderedContainer())); + } + + @Test + public void testOrdered() { + testContainerOrdered( + new ContainerOrderedWrapper(new NotOrderedContainer())); + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/ContainerSizeAssertTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/ContainerSizeAssertTest.java new file mode 100644 index 0000000000..58cb2b1d27 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/ContainerSizeAssertTest.java @@ -0,0 +1,59 @@ +/* + * Copyright 2000-2016 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.data.util; + +import org.junit.Test; + +import com.vaadin.data.Container; +import com.vaadin.ui.Table; + +public class ContainerSizeAssertTest { + + @Test(expected = AssertionError.class) + public void testNegativeSizeAssert() { + Table table = createAttachedTable(); + + table.setContainerDataSource(createNegativeSizeContainer()); + } + + @Test + public void testZeroSizeNoAssert() { + Table table = createAttachedTable(); + + table.setContainerDataSource(new IndexedContainer()); + } + + private Container createNegativeSizeContainer() { + return new IndexedContainer() { + @Override + public int size() { + return -1; + } + }; + } + + private Table createAttachedTable() { + return new Table() { + private boolean initialized = true; + + @Override + public boolean isAttached() { + // This returns false until the super constructor has finished + return initialized; + } + }; + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/ContainerSortingTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/ContainerSortingTest.java new file mode 100644 index 0000000000..1c4dc1de5e --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/ContainerSortingTest.java @@ -0,0 +1,222 @@ +package com.vaadin.data.util; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import org.junit.Test; + +import com.vaadin.data.Container; +import com.vaadin.data.Item; +import com.vaadin.tests.util.TestUtil; + +public class ContainerSortingTest { + + private static final String ITEM_DATA_MINUS2_NULL = "Data -2 null"; + private static final String ITEM_DATA_MINUS2 = "Data -2"; + private static final String ITEM_DATA_MINUS1 = "Data -1"; + private static final String ITEM_DATA_MINUS1_NULL = "Data -1 null"; + private static final String ITEM_ANOTHER_NULL = "Another null"; + private static final String ITEM_STRING_2 = "String 2"; + private static final String ITEM_STRING_NULL2 = "String null"; + private static final String ITEM_STRING_1 = "String 1"; + + private static final String PROPERTY_INTEGER_NULL2 = "integer-null"; + private static final String PROPERTY_INTEGER_NOT_NULL = "integer-not-null"; + private static final String PROPERTY_STRING_NULL = "string-null"; + private static final String PROPERTY_STRING_ID = "string-not-null"; + + @Test + public void testEmptyFilteredIndexedContainer() { + IndexedContainer ic = new IndexedContainer(); + + addProperties(ic); + populate(ic); + + ic.addContainerFilter(PROPERTY_STRING_ID, "aasdfasdfasdf", true, false); + ic.sort(new Object[] { PROPERTY_STRING_ID }, new boolean[] { true }); + + } + + @Test + public void testFilteredIndexedContainer() { + IndexedContainer ic = new IndexedContainer(); + + addProperties(ic); + populate(ic); + + ic.addContainerFilter(PROPERTY_STRING_ID, "a", true, false); + ic.sort(new Object[] { PROPERTY_STRING_ID }, new boolean[] { true }); + verifyOrder(ic, + new String[] { ITEM_ANOTHER_NULL, ITEM_DATA_MINUS1, + ITEM_DATA_MINUS1_NULL, ITEM_DATA_MINUS2, + ITEM_DATA_MINUS2_NULL, }); + } + + @Test + public void testIndexedContainer() { + IndexedContainer ic = new IndexedContainer(); + + addProperties(ic); + populate(ic); + + ic.sort(new Object[] { PROPERTY_STRING_ID }, new boolean[] { true }); + verifyOrder(ic, new String[] { ITEM_ANOTHER_NULL, ITEM_DATA_MINUS1, + ITEM_DATA_MINUS1_NULL, ITEM_DATA_MINUS2, ITEM_DATA_MINUS2_NULL, + ITEM_STRING_1, ITEM_STRING_2, ITEM_STRING_NULL2 }); + + ic.sort(new Object[] { PROPERTY_INTEGER_NOT_NULL, + PROPERTY_INTEGER_NULL2, PROPERTY_STRING_ID }, + new boolean[] { true, false, true }); + verifyOrder(ic, new String[] { ITEM_DATA_MINUS2, ITEM_DATA_MINUS2_NULL, + ITEM_DATA_MINUS1, ITEM_DATA_MINUS1_NULL, ITEM_ANOTHER_NULL, + ITEM_STRING_NULL2, ITEM_STRING_1, ITEM_STRING_2 }); + + ic.sort(new Object[] { PROPERTY_INTEGER_NOT_NULL, + PROPERTY_INTEGER_NULL2, PROPERTY_STRING_ID }, + new boolean[] { true, true, true }); + verifyOrder(ic, new String[] { ITEM_DATA_MINUS2_NULL, ITEM_DATA_MINUS2, + ITEM_DATA_MINUS1_NULL, ITEM_DATA_MINUS1, ITEM_ANOTHER_NULL, + ITEM_STRING_NULL2, ITEM_STRING_1, ITEM_STRING_2 }); + + } + + @Test + public void testHierarchicalContainer() { + HierarchicalContainer hc = new HierarchicalContainer(); + populateContainer(hc); + hc.sort(new Object[] { "name" }, new boolean[] { true }); + verifyOrder(hc, + new String[] { "Audi", "C++", "Call of Duty", "Cars", "English", + "Fallout", "Finnish", "Ford", "Games", "Java", + "Might and Magic", "Natural languages", "PHP", + "Programming languages", "Python", "Red Alert", + "Swedish", "Toyota", "Volvo" }); + TestUtil.assertArrays(hc.rootItemIds().toArray(), + new Integer[] { nameToId.get("Cars"), nameToId.get("Games"), + nameToId.get("Natural languages"), + nameToId.get("Programming languages") }); + TestUtil.assertArrays(hc.getChildren(nameToId.get("Games")).toArray(), + new Integer[] { nameToId.get("Call of Duty"), + nameToId.get("Fallout"), + nameToId.get("Might and Magic"), + nameToId.get("Red Alert") }); + } + + private static void populateContainer(HierarchicalContainer container) { + container.addContainerProperty("name", String.class, null); + + addItem(container, "Games", null); + addItem(container, "Call of Duty", "Games"); + addItem(container, "Might and Magic", "Games"); + addItem(container, "Fallout", "Games"); + addItem(container, "Red Alert", "Games"); + + addItem(container, "Cars", null); + addItem(container, "Toyota", "Cars"); + addItem(container, "Volvo", "Cars"); + addItem(container, "Audi", "Cars"); + addItem(container, "Ford", "Cars"); + + addItem(container, "Natural languages", null); + addItem(container, "Swedish", "Natural languages"); + addItem(container, "English", "Natural languages"); + addItem(container, "Finnish", "Natural languages"); + + addItem(container, "Programming languages", null); + addItem(container, "C++", "Programming languages"); + addItem(container, "PHP", "Programming languages"); + addItem(container, "Java", "Programming languages"); + addItem(container, "Python", "Programming languages"); + + } + + private static int index = 0; + private static Map<String, Integer> nameToId = new HashMap<String, Integer>(); + private static Map<Integer, String> idToName = new HashMap<Integer, String>(); + + public static void addItem(IndexedContainer container, String string, + String parent) { + nameToId.put(string, index); + idToName.put(index, string); + + Item item = container.addItem(index); + item.getItemProperty("name").setValue(string); + + if (parent != null && container instanceof HierarchicalContainer) { + ((HierarchicalContainer) container).setParent(index, + nameToId.get(parent)); + } + + index++; + } + + private void verifyOrder(Container.Sortable ic, Object[] idOrder) { + int size = ic.size(); + Object[] actual = new Object[size]; + Iterator<?> i = ic.getItemIds().iterator(); + int index = 0; + while (i.hasNext()) { + Object o = i.next(); + if (o.getClass() == Integer.class + && idOrder[index].getClass() == String.class) { + o = idToName.get(o); + } + actual[index++] = o; + } + + TestUtil.assertArrays(actual, idOrder); + + } + + private void populate(IndexedContainer ic) { + addItem(ic, ITEM_STRING_1, ITEM_STRING_1, 1, 1); + addItem(ic, ITEM_STRING_NULL2, null, 0, null); + addItem(ic, ITEM_STRING_2, ITEM_STRING_2, 2, 2); + addItem(ic, ITEM_ANOTHER_NULL, null, 0, null); + addItem(ic, ITEM_DATA_MINUS1, ITEM_DATA_MINUS1, -1, -1); + addItem(ic, ITEM_DATA_MINUS1_NULL, null, -1, null); + addItem(ic, ITEM_DATA_MINUS2, ITEM_DATA_MINUS2, -2, -2); + addItem(ic, ITEM_DATA_MINUS2_NULL, null, -2, null); + } + + private Item addItem(Container ic, String id, String string_null, + int integer, Integer integer_null) { + Item i = ic.addItem(id); + i.getItemProperty(PROPERTY_STRING_ID).setValue(id); + i.getItemProperty(PROPERTY_STRING_NULL).setValue(string_null); + i.getItemProperty(PROPERTY_INTEGER_NOT_NULL).setValue(integer); + i.getItemProperty(PROPERTY_INTEGER_NULL2).setValue(integer_null); + + return i; + } + + private void addProperties(IndexedContainer ic) { + ic.addContainerProperty("id", String.class, null); + ic.addContainerProperty(PROPERTY_STRING_ID, String.class, ""); + ic.addContainerProperty(PROPERTY_STRING_NULL, String.class, null); + ic.addContainerProperty(PROPERTY_INTEGER_NULL2, Integer.class, null); + ic.addContainerProperty(PROPERTY_INTEGER_NOT_NULL, Integer.class, 0); + ic.addContainerProperty("comparable-null", Integer.class, 0); + } + + public class MyObject implements Comparable<MyObject> { + private String data; + + @Override + public int compareTo(MyObject o) { + if (o == null) { + return 1; + } + + if (o.data == null) { + return data == null ? 0 : 1; + } else if (data == null) { + return -1; + } else { + return data.compareTo(o.data); + } + } + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/FileSystemContainerTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/FileSystemContainerTest.java new file mode 100644 index 0000000000..992b265702 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/FileSystemContainerTest.java @@ -0,0 +1,16 @@ +package com.vaadin.data.util; + +import java.io.File; + +import org.junit.Assert; +import org.junit.Test; + +public class FileSystemContainerTest { + + @Test + public void nonExistingDirectory() { + FilesystemContainer fsc = new FilesystemContainer( + new File("/non/existing")); + Assert.assertTrue(fsc.getItemIds().isEmpty()); + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/GeneratedPropertyContainerBasicTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/GeneratedPropertyContainerBasicTest.java new file mode 100644 index 0000000000..11335314f0 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/GeneratedPropertyContainerBasicTest.java @@ -0,0 +1,596 @@ +package com.vaadin.data.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.List; + +import org.easymock.Capture; +import org.easymock.EasyMock; +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.data.Container; +import com.vaadin.data.Container.Indexed.ItemAddEvent; +import com.vaadin.data.Container.Indexed.ItemRemoveEvent; +import com.vaadin.data.Container.ItemSetChangeListener; +import com.vaadin.data.Container.ItemSetChangeNotifier; +import com.vaadin.data.Item; +import com.vaadin.data.util.filter.SimpleStringFilter; + +public class GeneratedPropertyContainerBasicTest + extends AbstractInMemoryContainerTestBase { + + @Test + public void testBasicOperations() { + testBasicContainerOperations(createContainer()); + } + + private GeneratedPropertyContainer createContainer() { + return new GeneratedPropertyContainer(new IndexedContainer()); + } + + @Test + public void testFiltering() { + testContainerFiltering(createContainer()); + } + + @Test + public void testSorting() { + testContainerSorting(createContainer()); + } + + @Test + public void testSortingAndFiltering() { + testContainerSortingAndFiltering(createContainer()); + } + + @Test + public void testContainerOrdered() { + testContainerOrdered(createContainer()); + } + + @Test + public void testContainerIndexed() { + testContainerIndexed(createContainer(), sampleData[2], 2, true, + "newItemId", true); + } + + @Test + public void testItemSetChangeListeners() { + GeneratedPropertyContainer container = createContainer(); + ItemSetChangeCounter counter = new ItemSetChangeCounter(); + container.addListener(counter); + + String id1 = "id1"; + String id2 = "id2"; + String id3 = "id3"; + + initializeContainer(container); + counter.reset(); + container.addItem(); + counter.assertOnce(); + container.addItem(id1); + counter.assertOnce(); + + initializeContainer(container); + counter.reset(); + container.addItemAt(0); + counter.assertOnce(); + container.addItemAt(0, id1); + counter.assertOnce(); + container.addItemAt(0, id2); + counter.assertOnce(); + container.addItemAt(container.size(), id3); + counter.assertOnce(); + // no notification if already in container + container.addItemAt(0, id1); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(null); + counter.assertOnce(); + container.addItemAfter(null, id1); + counter.assertOnce(); + container.addItemAfter(id1); + counter.assertOnce(); + container.addItemAfter(id1, id2); + counter.assertOnce(); + container.addItemAfter(container.firstItemId()); + counter.assertOnce(); + container.addItemAfter(container.lastItemId()); + counter.assertOnce(); + container.addItemAfter(container.lastItemId(), id3); + counter.assertOnce(); + // no notification if already in container + container.addItemAfter(0, id1); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.removeItem(sampleData[0]); + counter.assertOnce(); + + initializeContainer(container); + counter.reset(); + // no notification for removing a non-existing item + container.removeItem(id1); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.removeAllItems(); + counter.assertOnce(); + // already empty + container.removeAllItems(); + counter.assertNone(); + + } + + @Test + public void testAddRemoveContainerFilter() { + GeneratedPropertyContainer container = createContainer(); + ItemSetChangeCounter counter = new ItemSetChangeCounter(); + container.addListener(counter); + + // simply adding or removing container filters should cause events + // (content changes) + + initializeContainer(container); + counter.reset(); + SimpleStringFilter filter = new SimpleStringFilter(SIMPLE_NAME, "a", + true, false); + container.addContainerFilter(filter); + counter.assertOnce(); + container.removeContainerFilter(filter); + counter.assertOnce(); + container.addContainerFilter( + new SimpleStringFilter(SIMPLE_NAME, "a", true, false)); + counter.assertOnce(); + container.removeAllContainerFilters(); + counter.assertOnce(); + } + + // TODO other tests should check positions after removing filter etc, + // here concentrating on listeners + @Test + public void testItemSetChangeListenersFiltering() { + Container.Indexed container = createContainer(); + ItemSetChangeCounter counter = new ItemSetChangeCounter(); + ((GeneratedPropertyContainer) container).addListener(counter); + + counter.reset(); + ((Container.Filterable) container) + .addContainerFilter(new SimpleStringFilter(FULLY_QUALIFIED_NAME, + "Test", true, false)); + // no real change, so no notification required + counter.assertNone(); + + String id1 = "com.example.Test1"; + String id2 = "com.example.Test2"; + String id3 = "com.example.Other"; + + // perform operations while filtering container + + Item item; + + initializeContainer(container); + counter.reset(); + // passes filter + item = container.addItem(id1); + // no event if filtered out + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1); + counter.assertOnce(); + // passes filter but already in the container + item = container.addItem(id1); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + // passes filter after change + item = container.addItemAt(0, id1); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1); + counter.assertOnce(); + item = container.addItemAt(container.size(), id2); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id2); + counter.assertOnce(); + // passes filter but already in the container + item = container.addItemAt(0, id1); + counter.assertNone(); + item = container.addItemAt(container.size(), id2); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + // passes filter + item = container.addItemAfter(null, id1); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1); + counter.assertOnce(); + item = container.addItemAfter(container.lastItemId(), id2); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id2); + counter.assertOnce(); + // passes filter but already in the container + item = container.addItemAfter(null, id1); + counter.assertNone(); + item = container.addItemAfter(container.lastItemId(), id2); + counter.assertNone(); + + // does not pass filter + + // TODO implement rest + + initializeContainer(container); + counter.reset(); + item = container.addItemAfter(null, id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + item = container.addItemAfter(container.firstItemId(), id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + item = container.addItemAfter(container.lastItemId(), id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + item = container.addItemAt(0, id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + item = container.addItemAt(1, id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + item = container.addItemAt(container.size(), id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + + // passes filter + + initializeContainer(container); + counter.reset(); + item = container.addItem(id1); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1); + counter.assertOnce(); + container.removeItem(id1); + counter.assertOnce(); + // already removed + container.removeItem(id1); + counter.assertNone(); + + item = container.addItem(id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + // not visible + container.removeItem(id3); + counter.assertNone(); + + // remove all + + initializeContainer(container); + item = container.addItem(id1); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1); + counter.reset(); + container.removeAllItems(); + counter.assertOnce(); + // no visible items + container.removeAllItems(); + counter.assertNone(); + } + + @Test + public void testItemAdd_idSequence() { + GeneratedPropertyContainer container = createContainer(); + Object itemId; + + itemId = container.addItem(); + assertEquals(Integer.valueOf(1), itemId); + + itemId = container.addItem(); + assertEquals(Integer.valueOf(2), itemId); + + itemId = container.addItemAfter(null); + assertEquals(Integer.valueOf(3), itemId); + + itemId = container.addItemAt(2); + assertEquals(Integer.valueOf(4), itemId); + } + + @Test + public void testItemAddRemove_idSequence() { + GeneratedPropertyContainer container = createContainer(); + Object itemId; + + itemId = container.addItem(); + assertEquals(Integer.valueOf(1), itemId); + + container.removeItem(itemId); + + itemId = container.addItem(); + assertEquals( + "Id sequence should continue from the previous value even if an item is removed", + Integer.valueOf(2), itemId); + } + + @Test + public void testItemAddedEvent() { + GeneratedPropertyContainer container = createContainer(); + ItemSetChangeListener addListener = createListenerMockFor(container); + addListener.containerItemSetChange(EasyMock.isA(ItemAddEvent.class)); + EasyMock.replay(addListener); + + container.addItem(); + + EasyMock.verify(addListener); + } + + @Test + public void testItemAddedEvent_AddedItem() { + GeneratedPropertyContainer container = createContainer(); + ItemSetChangeListener addListener = createListenerMockFor(container); + Capture<ItemAddEvent> capturedEvent = captureAddEvent(addListener); + EasyMock.replay(addListener); + + Object itemId = container.addItem(); + + assertEquals(itemId, capturedEvent.getValue().getFirstItemId()); + } + + @Test + public void testItemAddedEvent_IndexOfAddedItem() { + GeneratedPropertyContainer container = createContainer(); + ItemSetChangeListener addListener = createListenerMockFor(container); + container.addItem(); + Capture<ItemAddEvent> capturedEvent = captureAddEvent(addListener); + EasyMock.replay(addListener); + + Object itemId = container.addItemAt(1); + + assertEquals(1, capturedEvent.getValue().getFirstIndex()); + } + + @Test + public void testItemRemovedEvent() { + GeneratedPropertyContainer container = createContainer(); + Object itemId = container.addItem(); + ItemSetChangeListener removeListener = createListenerMockFor(container); + removeListener + .containerItemSetChange(EasyMock.isA(ItemRemoveEvent.class)); + EasyMock.replay(removeListener); + + container.removeItem(itemId); + + EasyMock.verify(removeListener); + } + + @Test + public void testItemRemovedEvent_RemovedItem() { + GeneratedPropertyContainer container = createContainer(); + Object itemId = container.addItem(); + ItemSetChangeListener removeListener = createListenerMockFor(container); + Capture<ItemRemoveEvent> capturedEvent = captureRemoveEvent( + removeListener); + EasyMock.replay(removeListener); + + container.removeItem(itemId); + + assertEquals(itemId, capturedEvent.getValue().getFirstItemId()); + } + + @Test + public void testItemRemovedEvent_indexOfRemovedItem() { + GeneratedPropertyContainer container = createContainer(); + container.addItem(); + Object secondItemId = container.addItem(); + ItemSetChangeListener removeListener = createListenerMockFor(container); + Capture<ItemRemoveEvent> capturedEvent = captureRemoveEvent( + removeListener); + EasyMock.replay(removeListener); + + container.removeItem(secondItemId); + + assertEquals(1, capturedEvent.getValue().getFirstIndex()); + } + + @Test + public void testItemRemovedEvent_amountOfRemovedItems() { + GeneratedPropertyContainer container = createContainer(); + container.addItem(); + container.addItem(); + ItemSetChangeListener removeListener = createListenerMockFor(container); + Capture<ItemRemoveEvent> capturedEvent = captureRemoveEvent( + removeListener); + EasyMock.replay(removeListener); + + container.removeAllItems(); + + assertEquals(2, capturedEvent.getValue().getRemovedItemsCount()); + } + + private Capture<ItemAddEvent> captureAddEvent( + ItemSetChangeListener addListener) { + Capture<ItemAddEvent> capturedEvent = new Capture<ItemAddEvent>(); + addListener.containerItemSetChange(EasyMock.capture(capturedEvent)); + return capturedEvent; + } + + private Capture<ItemRemoveEvent> captureRemoveEvent( + ItemSetChangeListener removeListener) { + Capture<ItemRemoveEvent> capturedEvent = new Capture<ItemRemoveEvent>(); + removeListener.containerItemSetChange(EasyMock.capture(capturedEvent)); + return capturedEvent; + } + + private ItemSetChangeListener createListenerMockFor( + ItemSetChangeNotifier container) { + ItemSetChangeListener listener = EasyMock + .createNiceMock(ItemSetChangeListener.class); + container.addItemSetChangeListener(listener); + return listener; + } + + // Ticket 8028 + @Test + public void testGetItemIdsRangeIndexOutOfBounds() { + GeneratedPropertyContainer ic = createContainer(); + try { + ic.getItemIds(-1, 10); + fail("Container returned items starting from index -1, something very wrong here!"); + } catch (IndexOutOfBoundsException e) { + // This is expected... + } catch (Exception e) { + // Should not happen! + fail("Container threw unspecified exception when fetching a range of items and the range started from -1"); + } + + } + + // Ticket 8028 + @Test + public void testGetItemIdsRangeIndexOutOfBounds2() { + GeneratedPropertyContainer ic = createContainer(); + ic.addItem(new Object()); + try { + ic.getItemIds(2, 1); + fail("Container returned items starting from index -1, something very wrong here!"); + } catch (IndexOutOfBoundsException e) { + // This is expected... + } catch (Exception e) { + // Should not happen! + fail("Container threw unspecified exception when fetching a out of bounds range of items"); + } + + } + + // Ticket 8028 + @Test + public void testGetItemIdsRangeZeroRange() { + GeneratedPropertyContainer ic = createContainer(); + ic.addItem(new Object()); + try { + List<Object> itemIds = (List<Object>) ic.getItemIds(1, 0); + + assertTrue( + "Container returned actual values when asking for 0 items...", + itemIds.isEmpty()); + } catch (Exception e) { + // Should not happen! + fail("Container threw unspecified exception when fetching 0 items..."); + } + + } + + // Ticket 8028 + @Test + public void testGetItemIdsRangeNegativeRange() { + GeneratedPropertyContainer ic = createContainer(); + ic.addItem(new Object()); + try { + List<Object> itemIds = (List<Object>) ic.getItemIds(1, -1); + + assertTrue( + "Container returned actual values when asking for -1 items...", + itemIds.isEmpty()); + } catch (IllegalArgumentException e) { + // this is expected + + } catch (Exception e) { + // Should not happen! + fail("Container threw unspecified exception when fetching -1 items..."); + } + + } + + // Ticket 8028 + @Test + public void testGetItemIdsRangeIndexOutOfBoundsDueToSizeChange() { + GeneratedPropertyContainer ic = createContainer(); + ic.addItem(new Object()); + Assert.assertEquals( + "Container returned too many items when the range was >> container size", + 1, ic.getItemIds(0, 10).size()); + } + + // Ticket 8028 + @Test + public void testGetItemIdsRangeBaseCase() { + GeneratedPropertyContainer ic = createContainer(); + String object1 = new String("Obj1"); + String object2 = new String("Obj2"); + String object3 = new String("Obj3"); + String object4 = new String("Obj4"); + String object5 = new String("Obj5"); + + ic.addItem(object1); + ic.addItem(object2); + ic.addItem(object3); + ic.addItem(object4); + ic.addItem(object5); + + try { + List<Object> itemIds = (List<Object>) ic.getItemIds(1, 2); + + assertTrue(itemIds.contains(object2)); + assertTrue(itemIds.contains(object3)); + assertEquals(2, itemIds.size()); + + } catch (Exception e) { + // Should not happen! + fail("Container threw exception when fetching a range of items "); + } + } + + // test getting non-existing property (#10445) + @Test + public void testNonExistingProperty() { + Container ic = createContainer(); + String object1 = new String("Obj1"); + ic.addItem(object1); + assertNull(ic.getContainerProperty(object1, "xyz")); + } + + // test getting null property id (#10445) + @Test + public void testNullPropertyId() { + Container ic = createContainer(); + String object1 = new String("Obj1"); + ic.addItem(object1); + assertNull(ic.getContainerProperty(object1, null)); + } + + @Override + protected void initializeContainer(Container container) { + if (container instanceof GeneratedPropertyContainer) { + super.initializeContainer(((GeneratedPropertyContainer) container) + .getWrappedContainer()); + } else { + super.initializeContainer(container); + } + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/GeneratedPropertyContainerTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/GeneratedPropertyContainerTest.java new file mode 100644 index 0000000000..1e34567439 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/GeneratedPropertyContainerTest.java @@ -0,0 +1,318 @@ +/* + * Copyright 2000-2016 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.data.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.Container.Indexed; +import com.vaadin.data.Container.ItemSetChangeEvent; +import com.vaadin.data.Container.ItemSetChangeListener; +import com.vaadin.data.Container.PropertySetChangeEvent; +import com.vaadin.data.Container.PropertySetChangeListener; +import com.vaadin.data.Item; +import com.vaadin.data.sort.SortOrder; +import com.vaadin.data.util.GeneratedPropertyContainer.GeneratedPropertyItem; +import com.vaadin.data.util.filter.Compare; +import com.vaadin.data.util.filter.UnsupportedFilterException; + +public class GeneratedPropertyContainerTest { + + GeneratedPropertyContainer container; + Indexed wrappedContainer; + private static double MILES_CONVERSION = 0.6214d; + + private class GeneratedPropertyListener + implements PropertySetChangeListener { + + private int callCount = 0; + + public int getCallCount() { + return callCount; + } + + @Override + public void containerPropertySetChange(PropertySetChangeEvent event) { + ++callCount; + assertEquals( + "Container for event was not GeneratedPropertyContainer", + event.getContainer(), container); + } + } + + private class GeneratedItemSetListener implements ItemSetChangeListener { + + private int callCount = 0; + + public int getCallCount() { + return callCount; + } + + @Override + public void containerItemSetChange(ItemSetChangeEvent event) { + ++callCount; + assertEquals( + "Container for event was not GeneratedPropertyContainer", + event.getContainer(), container); + } + } + + @Before + public void setUp() { + container = new GeneratedPropertyContainer(createContainer()); + } + + @Test + public void testSimpleGeneratedProperty() { + container.addGeneratedProperty("hello", + new PropertyValueGenerator<String>() { + + @Override + public String getValue(Item item, Object itemId, + Object propertyId) { + return "Hello World!"; + } + + @Override + public Class<String> getType() { + return String.class; + } + }); + + Object itemId = container.addItem(); + assertEquals("Expected value not in item.", + container.getItem(itemId).getItemProperty("hello").getValue(), + "Hello World!"); + } + + @Test + public void testSortableProperties() { + container.addGeneratedProperty("baz", + new PropertyValueGenerator<String>() { + + @Override + public String getValue(Item item, Object itemId, + Object propertyId) { + return item.getItemProperty("foo").getValue() + " " + + item.getItemProperty("bar").getValue(); + } + + @Override + public Class<String> getType() { + return String.class; + } + + @Override + public SortOrder[] getSortProperties(SortOrder order) { + SortOrder[] sortOrder = new SortOrder[1]; + sortOrder[0] = new SortOrder("bar", + order.getDirection()); + return sortOrder; + } + }); + + container.sort(new Object[] { "baz" }, new boolean[] { true }); + assertEquals("foo 0", container.getItem(container.getIdByIndex(0)) + .getItemProperty("baz").getValue()); + + container.sort(new Object[] { "baz" }, new boolean[] { false }); + assertEquals("foo 10", container.getItem(container.getIdByIndex(0)) + .getItemProperty("baz").getValue()); + } + + @Test + public void testOverrideSortableProperties() { + + assertTrue(container.getSortableContainerPropertyIds().contains("bar")); + + container.addGeneratedProperty("bar", + new PropertyValueGenerator<String>() { + + @Override + public String getValue(Item item, Object itemId, + Object propertyId) { + return item.getItemProperty("foo").getValue() + " " + + item.getItemProperty("bar").getValue(); + } + + @Override + public Class<String> getType() { + return String.class; + } + }); + + assertFalse( + container.getSortableContainerPropertyIds().contains("bar")); + } + + @Test + public void testFilterByMiles() { + container.addGeneratedProperty("miles", + new PropertyValueGenerator<Double>() { + + @Override + public Double getValue(Item item, Object itemId, + Object propertyId) { + return (Double) item.getItemProperty("km").getValue() + * MILES_CONVERSION; + } + + @Override + public Class<Double> getType() { + return Double.class; + } + + @Override + public Filter modifyFilter(Filter filter) + throws UnsupportedFilterException { + if (filter instanceof Compare.LessOrEqual) { + Double value = (Double) ((Compare.LessOrEqual) filter) + .getValue(); + value = value / MILES_CONVERSION; + return new Compare.LessOrEqual("km", value); + } + return super.modifyFilter(filter); + } + }); + + for (Object itemId : container.getItemIds()) { + Item item = container.getItem(itemId); + Double km = (Double) item.getItemProperty("km").getValue(); + Double miles = (Double) item.getItemProperty("miles").getValue(); + assertTrue(miles.equals(km * MILES_CONVERSION)); + } + + Filter filter = new Compare.LessOrEqual("miles", MILES_CONVERSION); + container.addContainerFilter(filter); + for (Object itemId : container.getItemIds()) { + Item item = container.getItem(itemId); + assertTrue("Item did not pass original filter.", + filter.passesFilter(itemId, item)); + } + + assertTrue(container.getContainerFilters().contains(filter)); + container.removeContainerFilter(filter); + assertFalse(container.getContainerFilters().contains(filter)); + + boolean allPass = true; + for (Object itemId : container.getItemIds()) { + Item item = container.getItem(itemId); + if (!filter.passesFilter(itemId, item)) { + allPass = false; + } + } + + if (allPass) { + fail("Removing filter did not introduce any previous filtered items"); + } + } + + @Test + public void testPropertySetChangeNotifier() { + GeneratedPropertyListener listener = new GeneratedPropertyListener(); + GeneratedPropertyListener removedListener = new GeneratedPropertyListener(); + container.addPropertySetChangeListener(listener); + container.addPropertySetChangeListener(removedListener); + + container.addGeneratedProperty("foo", + new PropertyValueGenerator<String>() { + + @Override + public String getValue(Item item, Object itemId, + Object propertyId) { + return ""; + } + + @Override + public Class<String> getType() { + return String.class; + } + }); + + // Adding property to wrapped container should cause an event + wrappedContainer.addContainerProperty("baz", String.class, ""); + container.removePropertySetChangeListener(removedListener); + container.removeGeneratedProperty("foo"); + + assertEquals("Listener was not called correctly.", 3, + listener.getCallCount()); + assertEquals("Removed listener was not called correctly.", 2, + removedListener.getCallCount()); + } + + @Test + public void testItemSetChangeNotifier() { + GeneratedItemSetListener listener = new GeneratedItemSetListener(); + container.addItemSetChangeListener(listener); + + container.sort(new Object[] { "foo" }, new boolean[] { true }); + container.sort(new Object[] { "foo" }, new boolean[] { false }); + + assertEquals("Listener was not called correctly.", 2, + listener.getCallCount()); + + } + + @Test + public void testRemoveProperty() { + container.removeContainerProperty("foo"); + assertFalse("Container contained removed property", + container.getContainerPropertyIds().contains("foo")); + assertTrue("Wrapped container did not contain removed property", + wrappedContainer.getContainerPropertyIds().contains("foo")); + + assertFalse(container.getItem(container.firstItemId()) + .getItemPropertyIds().contains("foo")); + + container.addContainerProperty("foo", null, null); + assertTrue("Container did not contain returned property", + container.getContainerPropertyIds().contains("foo")); + } + + @Test + public void testGetWrappedItem() { + Object itemId = wrappedContainer.getItemIds().iterator().next(); + Item wrappedItem = wrappedContainer.getItem(itemId); + GeneratedPropertyItem generatedPropertyItem = (GeneratedPropertyItem) container + .getItem(itemId); + assertEquals(wrappedItem, generatedPropertyItem.getWrappedItem()); + } + + private Indexed createContainer() { + wrappedContainer = new IndexedContainer(); + wrappedContainer.addContainerProperty("foo", String.class, "foo"); + wrappedContainer.addContainerProperty("bar", Integer.class, 0); + // km contains double values from 0.0 to 2.0 + wrappedContainer.addContainerProperty("km", Double.class, 0); + + for (int i = 0; i <= 10; ++i) { + Object itemId = wrappedContainer.addItem(); + Item item = wrappedContainer.getItem(itemId); + item.getItemProperty("foo").setValue("foo"); + item.getItemProperty("bar").setValue(i); + item.getItemProperty("km").setValue(i / 5.0d); + } + + return wrappedContainer; + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/HierarchicalContainerOrderedWrapperTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/HierarchicalContainerOrderedWrapperTest.java new file mode 100644 index 0000000000..54984f07ad --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/HierarchicalContainerOrderedWrapperTest.java @@ -0,0 +1,33 @@ +package com.vaadin.data.util; + +import org.junit.Test; + +public class HierarchicalContainerOrderedWrapperTest + extends AbstractHierarchicalContainerTestBase { + + private HierarchicalContainerOrderedWrapper createContainer() { + return new HierarchicalContainerOrderedWrapper( + new ContainerHierarchicalWrapper(new IndexedContainer())); + } + + @Test + public void testBasicOperations() { + testBasicContainerOperations(createContainer()); + } + + @Test + public void testHierarchicalContainer() { + testHierarchicalContainer(createContainer()); + } + + @Test + public void testContainerOrdered() { + testContainerOrdered(createContainer()); + } + + @Test + public void testRemoveSubtree() { + testRemoveHierarchicalWrapperSubtree(createContainer()); + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/HierarchicalContainerTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/HierarchicalContainerTest.java new file mode 100644 index 0000000000..7ab20ca3dd --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/HierarchicalContainerTest.java @@ -0,0 +1,286 @@ +package com.vaadin.data.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; + +import org.junit.Test; + +import com.vaadin.data.Container.Filter; +import com.vaadin.data.Item; + +public class HierarchicalContainerTest + extends AbstractHierarchicalContainerTestBase { + + @Test + public void testBasicOperations() { + testBasicContainerOperations(new HierarchicalContainer()); + } + + @Test + public void testFiltering() { + testContainerFiltering(new HierarchicalContainer()); + } + + @Test + public void testSorting() { + testContainerSorting(new HierarchicalContainer()); + } + + @Test + public void testOrdered() { + testContainerOrdered(new HierarchicalContainer()); + } + + @Test + public void testHierarchicalSorting() { + testHierarchicalSorting(new HierarchicalContainer()); + } + + @Test + public void testSortingAndFiltering() { + testContainerSortingAndFiltering(new HierarchicalContainer()); + } + + @Test + public void testRemovingItemsFromFilteredContainer() { + HierarchicalContainer container = new HierarchicalContainer(); + initializeContainer(container); + container.setIncludeParentsWhenFiltering(true); + container.addContainerFilter(FULLY_QUALIFIED_NAME, "ab", false, false); + Object p1 = container.getParent("com.vaadin.ui.TabSheet"); + assertEquals("com.vaadin.ui", p1); + + container.removeItem("com.vaadin.ui.TabSheet"); + // Parent for the removed item must be null because the item is no + // longer in the container + p1 = container.getParent("com.vaadin.ui.TabSheet"); + assertNull("Parent should be null, is " + p1, p1); + + container.removeAllItems(); + p1 = container.getParent("com.vaadin.terminal.gwt.client.Focusable"); + assertNull("Parent should be null, is " + p1, p1); + + } + + @Test + public void testParentWhenRemovingFilterFromContainer() { + HierarchicalContainer container = new HierarchicalContainer(); + initializeContainer(container); + container.setIncludeParentsWhenFiltering(true); + container.addContainerFilter(FULLY_QUALIFIED_NAME, "ab", false, false); + Object p1 = container.getParent("com.vaadin.ui.TabSheet"); + assertEquals("com.vaadin.ui", p1); + p1 = container + .getParent("com.vaadin.terminal.gwt.client.ui.VPopupCalendar"); + assertNull(p1); + container.removeAllContainerFilters(); + p1 = container + .getParent("com.vaadin.terminal.gwt.client.ui.VPopupCalendar"); + assertEquals("com.vaadin.terminal.gwt.client.ui", p1); + + } + + @Test + public void testChangeParentInFilteredContainer() { + HierarchicalContainer container = new HierarchicalContainer(); + initializeContainer(container); + container.setIncludeParentsWhenFiltering(true); + container.addContainerFilter(FULLY_QUALIFIED_NAME, "Tab", false, false); + + // Change parent of filtered item + Object p1 = container.getParent("com.vaadin.ui.TabSheet"); + assertEquals("com.vaadin.ui", p1); + container.setParent("com.vaadin.ui.TabSheet", "com.vaadin"); + p1 = container.getParent("com.vaadin.ui.TabSheet"); + assertEquals("com.vaadin", p1); + container.setParent("com.vaadin.ui.TabSheet", "com"); + p1 = container.getParent("com.vaadin.ui.TabSheet"); + assertEquals("com", p1); + container.setParent("com.vaadin.ui.TabSheet", null); + p1 = container.getParent("com.vaadin.ui.TabSheet"); + assertNull(p1); + + // root -> non-root + container.setParent("com.vaadin.ui.TabSheet", "com"); + p1 = container.getParent("com.vaadin.ui.TabSheet"); + assertEquals("com", p1); + + } + + @Test + public void testHierarchicalFilteringWithParents() { + HierarchicalContainer container = new HierarchicalContainer(); + initializeContainer(container); + container.setIncludeParentsWhenFiltering(true); + + // Filter by "contains ab" + container.addContainerFilter(FULLY_QUALIFIED_NAME, "ab", false, false); + + // 20 items match the filters and the have 8 parents that should also be + // included + // only one root "com" should exist + // filtered + int expectedSize = 29; + int expectedRoots = 1; + + validateHierarchicalContainer(container, "com", + "com.vaadin.ui.TabSheet", + "com.vaadin.terminal.gwt.client.Focusable", "blah", true, + expectedSize, expectedRoots, true); + + // only include .gwt.client classes + container.removeAllContainerFilters(); + container.addContainerFilter(FULLY_QUALIFIED_NAME, ".gwt.client.", + false, false); + + int packages = 6; + int classes = 112; + + expectedSize = packages + classes; + expectedRoots = 1; + + validateHierarchicalContainer(container, "com", + "com.vaadin.terminal.gwt.client.WidgetSet", + "com.vaadin.terminal.gwt.client.ui.VSplitPanelVertical", "blah", + true, expectedSize, expectedRoots, true); + + // Additionally remove all without 'm' in the simple name. + container.addContainerFilter(SIMPLE_NAME, "m", false, false); + + expectedSize = 7 + 18; + expectedRoots = 1; + + validateHierarchicalContainer(container, "com", + "com.vaadin.terminal.gwt.client.ui.VUriFragmentUtility", + "com.vaadin.terminal.gwt.client.ui.layout.ChildComponentContainer", + "blah", true, expectedSize, expectedRoots, true); + + } + + @Test + public void testRemoveLastChild() { + HierarchicalContainer c = new HierarchicalContainer(); + + c.addItem("root"); + assertEquals(false, c.hasChildren("root")); + + c.addItem("child"); + c.setParent("child", "root"); + assertEquals(true, c.hasChildren("root")); + + c.removeItem("child"); + assertFalse(c.containsId("child")); + assertNull(c.getChildren("root")); + assertNull(c.getChildren("child")); + assertFalse(c.hasChildren("child")); + assertFalse(c.hasChildren("root")); + } + + @Test + public void testRemoveLastChildFromFiltered() { + HierarchicalContainer c = new HierarchicalContainer(); + + c.addItem("root"); + assertEquals(false, c.hasChildren("root")); + + c.addItem("child"); + c.setParent("child", "root"); + assertEquals(true, c.hasChildren("root")); + + // Dummy filter that does not remove any items + c.addContainerFilter(new Filter() { + + @Override + public boolean passesFilter(Object itemId, Item item) + throws UnsupportedOperationException { + return true; + } + + @Override + public boolean appliesToProperty(Object propertyId) { + return true; + } + }); + c.removeItem("child"); + + assertFalse(c.containsId("child")); + assertNull(c.getChildren("root")); + assertNull(c.getChildren("child")); + assertFalse(c.hasChildren("child")); + assertFalse(c.hasChildren("root")); + } + + @Test + public void testHierarchicalFilteringWithoutParents() { + HierarchicalContainer container = new HierarchicalContainer(); + + initializeContainer(container); + container.setIncludeParentsWhenFiltering(false); + + // Filter by "contains ab" + container.addContainerFilter(SIMPLE_NAME, "ab", false, false); + + // 20 items match the filter. + // com.vaadin.data.BufferedValidatable + // com.vaadin.data.Validatable + // com.vaadin.terminal.gwt.client.Focusable + // com.vaadin.terminal.gwt.client.Paintable + // com.vaadin.terminal.gwt.client.ui.Table + // com.vaadin.terminal.gwt.client.ui.VLabel + // com.vaadin.terminal.gwt.client.ui.VScrollTable + // com.vaadin.terminal.gwt.client.ui.VTablePaging + // com.vaadin.terminal.gwt.client.ui.VTabsheet + // com.vaadin.terminal.gwt.client.ui.VTabsheetBase + // com.vaadin.terminal.gwt.client.ui.VTabsheetPanel + // com.vaadin.server.ChangeVariablesErrorEvent + // com.vaadin.server.Paintable + // com.vaadin.server.Scrollable + // com.vaadin.server.Sizeable + // com.vaadin.server.VariableOwner + // com.vaadin.ui.Label + // com.vaadin.ui.Table + // com.vaadin.ui.TableFieldFactory + // com.vaadin.ui.TabSheet + // all become roots. + int expectedSize = 20; + int expectedRoots = 20; + + validateHierarchicalContainer(container, + "com.vaadin.data.BufferedValidatable", "com.vaadin.ui.TabSheet", + "com.vaadin.terminal.gwt.client.ui.VTabsheetBase", "blah", true, + expectedSize, expectedRoots, false); + + // only include .gwt.client classes + container.removeAllContainerFilters(); + container.addContainerFilter(FULLY_QUALIFIED_NAME, ".gwt.client.", + false, false); + + int packages = 3; + int classes = 110; + + expectedSize = packages + classes; + expectedRoots = 35 + 1; // com.vaadin.terminal.gwt.client.ui + + // com.vaadin.terminal.gwt.client.* + + // Sorting is case insensitive + validateHierarchicalContainer(container, + "com.vaadin.terminal.gwt.client.ApplicationConfiguration", + "com.vaadin.terminal.gwt.client.WidgetSet", + "com.vaadin.terminal.gwt.client.ui.VOptionGroup", "blah", true, + expectedSize, expectedRoots, false); + + // Additionally remove all without 'P' in the simple name. + container.addContainerFilter(SIMPLE_NAME, "P", false, false); + + expectedSize = 13; + expectedRoots = expectedSize; + + validateHierarchicalContainer(container, + "com.vaadin.terminal.gwt.client.Paintable", + "com.vaadin.terminal.gwt.client.ui.VTabsheetPanel", + "com.vaadin.terminal.gwt.client.ui.VPopupCalendar", "blah", + true, expectedSize, expectedRoots, false); + + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/IndexedContainerTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/IndexedContainerTest.java new file mode 100644 index 0000000000..b19a425518 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/IndexedContainerTest.java @@ -0,0 +1,533 @@ +package com.vaadin.data.util; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.easymock.Capture; +import org.easymock.EasyMock; +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.data.Container.Indexed.ItemAddEvent; +import com.vaadin.data.Container.Indexed.ItemRemoveEvent; +import com.vaadin.data.Container.ItemSetChangeListener; +import com.vaadin.data.Item; + +public class IndexedContainerTest extends AbstractInMemoryContainerTestBase { + + @Test + public void testBasicOperations() { + testBasicContainerOperations(new IndexedContainer()); + } + + @Test + public void testFiltering() { + testContainerFiltering(new IndexedContainer()); + } + + @Test + public void testSorting() { + testContainerSorting(new IndexedContainer()); + } + + @Test + public void testSortingAndFiltering() { + testContainerSortingAndFiltering(new IndexedContainer()); + } + + @Test + public void testContainerOrdered() { + testContainerOrdered(new IndexedContainer()); + } + + @Test + public void testContainerIndexed() { + testContainerIndexed(new IndexedContainer(), sampleData[2], 2, true, + "newItemId", true); + } + + @Test + public void testItemSetChangeListeners() { + IndexedContainer container = new IndexedContainer(); + ItemSetChangeCounter counter = new ItemSetChangeCounter(); + container.addListener(counter); + + String id1 = "id1"; + String id2 = "id2"; + String id3 = "id3"; + + initializeContainer(container); + counter.reset(); + container.addItem(); + counter.assertOnce(); + container.addItem(id1); + counter.assertOnce(); + + initializeContainer(container); + counter.reset(); + container.addItemAt(0); + counter.assertOnce(); + container.addItemAt(0, id1); + counter.assertOnce(); + container.addItemAt(0, id2); + counter.assertOnce(); + container.addItemAt(container.size(), id3); + counter.assertOnce(); + // no notification if already in container + container.addItemAt(0, id1); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.addItemAfter(null); + counter.assertOnce(); + container.addItemAfter(null, id1); + counter.assertOnce(); + container.addItemAfter(id1); + counter.assertOnce(); + container.addItemAfter(id1, id2); + counter.assertOnce(); + container.addItemAfter(container.firstItemId()); + counter.assertOnce(); + container.addItemAfter(container.lastItemId()); + counter.assertOnce(); + container.addItemAfter(container.lastItemId(), id3); + counter.assertOnce(); + // no notification if already in container + container.addItemAfter(0, id1); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.removeItem(sampleData[0]); + counter.assertOnce(); + + initializeContainer(container); + counter.reset(); + // no notification for removing a non-existing item + container.removeItem(id1); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + container.removeAllItems(); + counter.assertOnce(); + // already empty + container.removeAllItems(); + counter.assertNone(); + + } + + @Test + public void testAddRemoveContainerFilter() { + IndexedContainer container = new IndexedContainer(); + ItemSetChangeCounter counter = new ItemSetChangeCounter(); + container.addListener(counter); + + // simply adding or removing container filters should cause events + // (content changes) + + initializeContainer(container); + counter.reset(); + container.addContainerFilter(SIMPLE_NAME, "a", true, false); + counter.assertOnce(); + container.removeContainerFilters(SIMPLE_NAME); + counter.assertOnce(); + container.addContainerFilter(SIMPLE_NAME, "a", true, false); + counter.assertOnce(); + container.removeAllContainerFilters(); + counter.assertOnce(); + } + + // TODO other tests should check positions after removing filter etc, + // here concentrating on listeners + @Test + public void testItemSetChangeListenersFiltering() { + IndexedContainer container = new IndexedContainer(); + ItemSetChangeCounter counter = new ItemSetChangeCounter(); + container.addListener(counter); + + counter.reset(); + container.addContainerFilter(FULLY_QUALIFIED_NAME, "Test", true, false); + // no real change, so no notification required + counter.assertNone(); + + String id1 = "com.example.Test1"; + String id2 = "com.example.Test2"; + String id3 = "com.example.Other"; + + // perform operations while filtering container + + Item item; + + initializeContainer(container); + counter.reset(); + // passes filter + item = container.addItem(id1); + // no event if filtered out + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1); + counter.assertOnce(); + // passes filter but already in the container + item = container.addItem(id1); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + // passes filter after change + item = container.addItemAt(0, id1); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1); + counter.assertOnce(); + item = container.addItemAt(container.size(), id2); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id2); + counter.assertOnce(); + // passes filter but already in the container + item = container.addItemAt(0, id1); + counter.assertNone(); + item = container.addItemAt(container.size(), id2); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + // passes filter + item = container.addItemAfter(null, id1); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1); + counter.assertOnce(); + item = container.addItemAfter(container.lastItemId(), id2); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id2); + counter.assertOnce(); + // passes filter but already in the container + item = container.addItemAfter(null, id1); + counter.assertNone(); + item = container.addItemAfter(container.lastItemId(), id2); + counter.assertNone(); + + // does not pass filter + + // TODO implement rest + + initializeContainer(container); + counter.reset(); + item = container.addItemAfter(null, id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + item = container.addItemAfter(container.firstItemId(), id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + item = container.addItemAfter(container.lastItemId(), id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + item = container.addItemAt(0, id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + item = container.addItemAt(1, id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + + initializeContainer(container); + counter.reset(); + item = container.addItemAt(container.size(), id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + + // passes filter + + initializeContainer(container); + counter.reset(); + item = container.addItem(id1); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1); + counter.assertOnce(); + container.removeItem(id1); + counter.assertOnce(); + // already removed + container.removeItem(id1); + counter.assertNone(); + + item = container.addItem(id3); + counter.assertNone(); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id3); + counter.assertNone(); + // not visible + container.removeItem(id3); + counter.assertNone(); + + // remove all + + initializeContainer(container); + item = container.addItem(id1); + item.getItemProperty(FULLY_QUALIFIED_NAME).setValue(id1); + counter.reset(); + container.removeAllItems(); + counter.assertOnce(); + // no visible items + container.removeAllItems(); + counter.assertNone(); + } + + @Test + public void testItemAdd_idSequence() { + IndexedContainer container = new IndexedContainer(); + Object itemId; + + itemId = container.addItem(); + assertEquals(Integer.valueOf(1), itemId); + + itemId = container.addItem(); + assertEquals(Integer.valueOf(2), itemId); + + itemId = container.addItemAfter(null); + assertEquals(Integer.valueOf(3), itemId); + + itemId = container.addItemAt(2); + assertEquals(Integer.valueOf(4), itemId); + } + + @Test + public void testItemAddRemove_idSequence() { + IndexedContainer container = new IndexedContainer(); + Object itemId; + + itemId = container.addItem(); + assertEquals(Integer.valueOf(1), itemId); + + container.removeItem(itemId); + + itemId = container.addItem(); + assertEquals( + "Id sequence should continue from the previous value even if an item is removed", + Integer.valueOf(2), itemId); + } + + @Test + public void testItemAddedEvent() { + IndexedContainer container = new IndexedContainer(); + ItemSetChangeListener addListener = createListenerMockFor(container); + addListener.containerItemSetChange(EasyMock.isA(ItemAddEvent.class)); + EasyMock.replay(addListener); + + container.addItem(); + + EasyMock.verify(addListener); + } + + @Test + public void testItemAddedEvent_AddedItem() { + IndexedContainer container = new IndexedContainer(); + ItemSetChangeListener addListener = createListenerMockFor(container); + Capture<ItemAddEvent> capturedEvent = captureAddEvent(addListener); + EasyMock.replay(addListener); + + Object itemId = container.addItem(); + + assertEquals(itemId, capturedEvent.getValue().getFirstItemId()); + } + + @Test + public void testItemAddedEvent_IndexOfAddedItem() { + IndexedContainer container = new IndexedContainer(); + ItemSetChangeListener addListener = createListenerMockFor(container); + container.addItem(); + Capture<ItemAddEvent> capturedEvent = captureAddEvent(addListener); + EasyMock.replay(addListener); + + Object itemId = container.addItemAt(1); + + assertEquals(1, capturedEvent.getValue().getFirstIndex()); + } + + @Test + public void testItemRemovedEvent() { + IndexedContainer container = new IndexedContainer(); + Object itemId = container.addItem(); + ItemSetChangeListener removeListener = createListenerMockFor(container); + removeListener + .containerItemSetChange(EasyMock.isA(ItemRemoveEvent.class)); + EasyMock.replay(removeListener); + + container.removeItem(itemId); + + EasyMock.verify(removeListener); + } + + @Test + public void testItemRemovedEvent_RemovedItem() { + IndexedContainer container = new IndexedContainer(); + Object itemId = container.addItem(); + ItemSetChangeListener removeListener = createListenerMockFor(container); + Capture<ItemRemoveEvent> capturedEvent = captureRemoveEvent( + removeListener); + EasyMock.replay(removeListener); + + container.removeItem(itemId); + + assertEquals(itemId, capturedEvent.getValue().getFirstItemId()); + } + + @Test + public void testItemRemovedEvent_indexOfRemovedItem() { + IndexedContainer container = new IndexedContainer(); + container.addItem(); + Object secondItemId = container.addItem(); + ItemSetChangeListener removeListener = createListenerMockFor(container); + Capture<ItemRemoveEvent> capturedEvent = captureRemoveEvent( + removeListener); + EasyMock.replay(removeListener); + + container.removeItem(secondItemId); + + assertEquals(1, capturedEvent.getValue().getFirstIndex()); + } + + @Test + public void testItemRemovedEvent_amountOfRemovedItems() { + IndexedContainer container = new IndexedContainer(); + container.addItem(); + container.addItem(); + ItemSetChangeListener removeListener = createListenerMockFor(container); + Capture<ItemRemoveEvent> capturedEvent = captureRemoveEvent( + removeListener); + EasyMock.replay(removeListener); + + container.removeAllItems(); + + assertEquals(2, capturedEvent.getValue().getRemovedItemsCount()); + } + + private Capture<ItemAddEvent> captureAddEvent( + ItemSetChangeListener addListener) { + Capture<ItemAddEvent> capturedEvent = new Capture<ItemAddEvent>(); + addListener.containerItemSetChange(EasyMock.capture(capturedEvent)); + return capturedEvent; + } + + private Capture<ItemRemoveEvent> captureRemoveEvent( + ItemSetChangeListener removeListener) { + Capture<ItemRemoveEvent> capturedEvent = new Capture<ItemRemoveEvent>(); + removeListener.containerItemSetChange(EasyMock.capture(capturedEvent)); + return capturedEvent; + } + + private ItemSetChangeListener createListenerMockFor( + IndexedContainer container) { + ItemSetChangeListener listener = EasyMock + .createNiceMock(ItemSetChangeListener.class); + container.addItemSetChangeListener(listener); + return listener; + } + + // Ticket 8028 + @Test(expected = IndexOutOfBoundsException.class) + public void testGetItemIdsRangeIndexOutOfBounds() { + IndexedContainer ic = new IndexedContainer(); + ic.getItemIds(-1, 10); + } + + // Ticket 8028 + @Test(expected = IndexOutOfBoundsException.class) + public void testGetItemIdsRangeIndexOutOfBounds2() { + IndexedContainer ic = new IndexedContainer(); + ic.addItem(new Object()); + ic.getItemIds(2, 1); + } + + // Ticket 8028 + @Test + public void testGetItemIdsRangeZeroRange() { + IndexedContainer ic = new IndexedContainer(); + ic.addItem(new Object()); + List<Object> itemIds = ic.getItemIds(1, 0); + + assertTrue( + "Container returned actual values when asking for 0 items...", + itemIds.isEmpty()); + } + + // Ticket 8028 + @Test(expected = IllegalArgumentException.class) + public void testGetItemIdsRangeNegativeRange() { + IndexedContainer ic = new IndexedContainer(); + ic.addItem(new Object()); + List<Object> itemIds = ic.getItemIds(1, -1); + + assertTrue( + "Container returned actual values when asking for -1 items...", + itemIds.isEmpty()); + } + + // Ticket 8028 + @Test + public void testGetItemIdsRangeIndexOutOfBoundsDueToSizeChange() { + IndexedContainer ic = new IndexedContainer(); + ic.addItem(new Object()); + Assert.assertEquals( + "Container returned too many items when the range was >> container size", + 1, ic.getItemIds(0, 10).size()); + } + + // Ticket 8028 + @Test + public void testGetItemIdsRangeBaseCase() { + IndexedContainer ic = new IndexedContainer(); + String object1 = new String("Obj1"); + String object2 = new String("Obj2"); + String object3 = new String("Obj3"); + String object4 = new String("Obj4"); + String object5 = new String("Obj5"); + + ic.addItem(object1); + ic.addItem(object2); + ic.addItem(object3); + ic.addItem(object4); + ic.addItem(object5); + + List<Object> itemIds = ic.getItemIds(1, 2); + + assertTrue(itemIds.contains(object2)); + assertTrue(itemIds.contains(object3)); + assertEquals(2, itemIds.size()); + } + + // test getting non-existing property (#10445) + @Test + public void testNonExistingProperty() { + IndexedContainer ic = new IndexedContainer(); + String object1 = new String("Obj1"); + ic.addItem(object1); + assertNull(ic.getContainerProperty(object1, "xyz")); + } + + // test getting null property id (#10445) + @Test + public void testNullPropertyId() { + IndexedContainer ic = new IndexedContainer(); + String object1 = new String("Obj1"); + ic.addItem(object1); + assertNull(ic.getContainerProperty(object1, null)); + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/MethodPropertyMemoryConsumptionTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/MethodPropertyMemoryConsumptionTest.java new file mode 100644 index 0000000000..6776021c24 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/MethodPropertyMemoryConsumptionTest.java @@ -0,0 +1,150 @@ +/* + * Copyright 2000-2016 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.data.util; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.lang.reflect.Field; + +import org.junit.Assert; +import org.junit.Test; + +/** + * Test for MethodProperty: don't allocate unnecessary Object arrays. + * + * @since 7.2 + * @author Vaadin Ltd + */ +public class MethodPropertyMemoryConsumptionTest { + + @Test + public void testSetArguments() + throws NoSuchFieldException, SecurityException, + IllegalArgumentException, IllegalAccessException { + TestBean bean = new TestBean(); + TestMethodProperty<String> property = new TestMethodProperty<String>( + bean, "name"); + Object[] getArgs = property.getGetArgs(); + Object[] setArgs = property.getSetArgs(); + + Field getArgsField = TestMethodProperty.class + .getDeclaredField("getArgs"); + getArgsField.setAccessible(true); + + Field setArgsField = TestMethodProperty.class + .getDeclaredField("setArgs"); + setArgsField.setAccessible(true); + + Assert.assertSame( + "setArguments method sets non-default instance" + + " of empty Object array for getArgs", + getArgsField.get(property), getArgs); + + Assert.assertSame( + "setArguments method sets non-default instance" + + " of empty Object array for setArgs", + setArgsField.get(property), setArgs); + } + + @Test + public void testDefaultCtor() { + TestBean bean = new TestBean(); + TestMethodProperty<String> property = new TestMethodProperty<String>( + bean, "name"); + + Object[] getArgs = property.getGetArgs(); + Object[] setArgs = property.getSetArgs(); + + TestBean otherBean = new TestBean(); + TestMethodProperty<String> otherProperty = new TestMethodProperty<String>( + otherBean, "name"); + Assert.assertSame( + "setArguments method uses different instance" + + " of empty Object array for getArgs", + getArgs, otherProperty.getGetArgs()); + Assert.assertSame( + "setArguments method uses different instance" + + " of empty Object array for setArgs", + setArgs, otherProperty.getSetArgs()); + } + + @Test + public void testDefaultArgsSerialization() + throws IOException, ClassNotFoundException { + TestBean bean = new TestBean(); + TestMethodProperty<String> property = new TestMethodProperty<String>( + bean, "name"); + + ByteArrayOutputStream sourceOutStream = new ByteArrayOutputStream(); + ObjectOutputStream outStream = new ObjectOutputStream(sourceOutStream); + outStream.writeObject(property); + + ObjectInputStream inputStream = new ObjectInputStream( + new ByteArrayInputStream(sourceOutStream.toByteArray())); + Object red = inputStream.readObject(); + TestMethodProperty<?> deserialized = (TestMethodProperty<?>) red; + + Assert.assertNotNull("Deseriliation doesn't call setArguments method", + deserialized.getGetArgs()); + Assert.assertNotNull("Deseriliation doesn't call setArguments method", + deserialized.getSetArgs()); + + } + + public static class TestMethodProperty<T> extends MethodProperty<T> { + + public TestMethodProperty(Object instance, String beanPropertyName) { + super(instance, beanPropertyName); + } + + @Override + public void setArguments(Object[] getArgs, Object[] setArgs, + int setArgumentIndex) { + super.setArguments(getArgs, setArgs, setArgumentIndex); + this.getArgs = getArgs; + this.setArgs = setArgs; + } + + Object[] getGetArgs() { + return getArgs; + } + + Object[] getSetArgs() { + return setArgs; + } + + private transient Object[] getArgs; + private transient Object[] setArgs; + } + + public static class TestBean implements Serializable { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/NestedMethodPropertyTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/NestedMethodPropertyTest.java new file mode 100644 index 0000000000..4a1e2a1784 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/NestedMethodPropertyTest.java @@ -0,0 +1,351 @@ +package com.vaadin.data.util; + +import static org.junit.Assert.assertNull; +import static org.junit.Assert.fail; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class NestedMethodPropertyTest { + + public static class Address implements Serializable { + private String street; + private int postalCodePrimitive; + private Integer postalCodeObject; + + public Address(String street, int postalCode) { + this.street = street; + postalCodePrimitive = postalCode; + postalCodeObject = postalCode; + } + + public void setStreet(String street) { + this.street = street; + } + + public String getStreet() { + return street; + } + + public void setPostalCodePrimitive(int postalCodePrimitive) { + this.postalCodePrimitive = postalCodePrimitive; + } + + public int getPostalCodePrimitive() { + return postalCodePrimitive; + } + + public void setPostalCodeObject(Integer postalCodeObject) { + this.postalCodeObject = postalCodeObject; + } + + public Integer getPostalCodeObject() { + return postalCodeObject; + } + + // read-only boolean property + public boolean isBoolean() { + return true; + } + } + + public static class Person implements Serializable { + private String name; + private Address address; + private int age; + + public Person(String name, Address address) { + this.name = name; + this.address = address; + } + + public Person(String name, Address address, int age) { + this.name = name; + this.address = address; + this.age = age; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setAddress(Address address) { + this.address = address; + } + + public Address getAddress() { + return address; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + } + + public static class Team implements Serializable { + private String name; + private Person manager; + + public Team(String name, Person manager) { + this.name = name; + this.manager = manager; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setManager(Person manager) { + this.manager = manager; + } + + public Person getManager() { + return manager; + } + } + + private Address oldMill; + private Person joonas; + private Team vaadin; + + @Before + public void setUp() { + oldMill = new Address("Ruukinkatu 2-4", 20540); + joonas = new Person("Joonas", oldMill); + vaadin = new Team("Vaadin", joonas); + } + + @Test + public void testSingleLevelNestedSimpleProperty() { + NestedMethodProperty<String> nameProperty = new NestedMethodProperty<String>( + vaadin, "name"); + + Assert.assertEquals(String.class, nameProperty.getType()); + Assert.assertEquals("Vaadin", nameProperty.getValue()); + } + + @Test + public void testSingleLevelNestedObjectProperty() { + NestedMethodProperty<Person> managerProperty = new NestedMethodProperty<Person>( + vaadin, "manager"); + + Assert.assertEquals(Person.class, managerProperty.getType()); + Assert.assertEquals(joonas, managerProperty.getValue()); + } + + @Test + public void testMultiLevelNestedProperty() { + NestedMethodProperty<String> managerNameProperty = new NestedMethodProperty<String>( + vaadin, "manager.name"); + NestedMethodProperty<Address> addressProperty = new NestedMethodProperty<Address>( + vaadin, "manager.address"); + NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>( + vaadin, "manager.address.street"); + NestedMethodProperty<Integer> postalCodePrimitiveProperty = new NestedMethodProperty<Integer>( + vaadin, "manager.address.postalCodePrimitive"); + NestedMethodProperty<Integer> postalCodeObjectProperty = new NestedMethodProperty<Integer>( + vaadin, "manager.address.postalCodeObject"); + NestedMethodProperty<Boolean> booleanProperty = new NestedMethodProperty<Boolean>( + vaadin, "manager.address.boolean"); + + Assert.assertEquals(String.class, managerNameProperty.getType()); + Assert.assertEquals("Joonas", managerNameProperty.getValue()); + + Assert.assertEquals(Address.class, addressProperty.getType()); + Assert.assertEquals(oldMill, addressProperty.getValue()); + + Assert.assertEquals(String.class, streetProperty.getType()); + Assert.assertEquals("Ruukinkatu 2-4", streetProperty.getValue()); + + Assert.assertEquals(Integer.class, + postalCodePrimitiveProperty.getType()); + Assert.assertEquals(Integer.valueOf(20540), + postalCodePrimitiveProperty.getValue()); + + Assert.assertEquals(Integer.class, postalCodeObjectProperty.getType()); + Assert.assertEquals(Integer.valueOf(20540), + postalCodeObjectProperty.getValue()); + + Assert.assertEquals(Boolean.class, booleanProperty.getType()); + Assert.assertEquals(Boolean.TRUE, booleanProperty.getValue()); + } + + @Test + public void testEmptyPropertyName() { + try { + new NestedMethodProperty<Object>(vaadin, ""); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + + try { + new NestedMethodProperty<Object>(vaadin, " "); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + } + + @Test + public void testInvalidPropertyName() { + try { + new NestedMethodProperty<Object>(vaadin, "."); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + try { + new NestedMethodProperty<Object>(vaadin, ".manager"); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + try { + new NestedMethodProperty<Object>(vaadin, "manager."); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + try { + new NestedMethodProperty<Object>(vaadin, "manager..name"); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + } + + @Test + public void testInvalidNestedPropertyName() { + try { + new NestedMethodProperty<Object>(vaadin, "member"); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + + try { + new NestedMethodProperty<Object>(vaadin, "manager.pet"); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + + try { + new NestedMethodProperty<Object>(vaadin, "manager.address.city"); + fail(); + } catch (IllegalArgumentException e) { + // should get exception + } + } + + @Test + public void testNullNestedProperty() { + NestedMethodProperty<String> managerNameProperty = new NestedMethodProperty<String>( + vaadin, "manager.name"); + NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>( + vaadin, "manager.address.street"); + + joonas.setAddress(null); + assertNull(streetProperty.getValue()); + + vaadin.setManager(null); + assertNull(managerNameProperty.getValue()); + assertNull(streetProperty.getValue()); + + vaadin.setManager(joonas); + Assert.assertEquals("Joonas", managerNameProperty.getValue()); + Assert.assertNull(streetProperty.getValue()); + + } + + @Test + public void testMultiLevelNestedPropertySetValue() { + NestedMethodProperty<String> managerNameProperty = new NestedMethodProperty<String>( + vaadin, "manager.name"); + NestedMethodProperty<Address> addressProperty = new NestedMethodProperty<Address>( + vaadin, "manager.address"); + NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>( + vaadin, "manager.address.street"); + NestedMethodProperty<Integer> postalCodePrimitiveProperty = new NestedMethodProperty<Integer>( + vaadin, "manager.address.postalCodePrimitive"); + NestedMethodProperty<Integer> postalCodeObjectProperty = new NestedMethodProperty<Integer>( + vaadin, "manager.address.postalCodeObject"); + + managerNameProperty.setValue("Joonas L"); + Assert.assertEquals("Joonas L", joonas.getName()); + streetProperty.setValue("Ruukinkatu"); + Assert.assertEquals("Ruukinkatu", oldMill.getStreet()); + postalCodePrimitiveProperty.setValue(0); + postalCodeObjectProperty.setValue(1); + Assert.assertEquals(0, oldMill.getPostalCodePrimitive()); + Assert.assertEquals(Integer.valueOf(1), oldMill.getPostalCodeObject()); + + postalCodeObjectProperty.setValue(null); + Assert.assertNull(oldMill.getPostalCodeObject()); + + Address address2 = new Address("Other street", 12345); + addressProperty.setValue(address2); + Assert.assertEquals("Other street", streetProperty.getValue()); + } + + @Test + public void testSerialization() throws IOException, ClassNotFoundException { + NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>( + vaadin, "manager.address.street"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + new ObjectOutputStream(baos).writeObject(streetProperty); + @SuppressWarnings("unchecked") + NestedMethodProperty<String> property2 = (NestedMethodProperty<String>) new ObjectInputStream( + new ByteArrayInputStream(baos.toByteArray())).readObject(); + + Assert.assertEquals("Ruukinkatu 2-4", property2.getValue()); + } + + @Test + public void testSerializationWithIntermediateNull() + throws IOException, ClassNotFoundException { + vaadin.setManager(null); + NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>( + vaadin, "manager.address.street"); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + new ObjectOutputStream(baos).writeObject(streetProperty); + @SuppressWarnings("unchecked") + NestedMethodProperty<String> property2 = (NestedMethodProperty<String>) new ObjectInputStream( + new ByteArrayInputStream(baos.toByteArray())).readObject(); + + Assert.assertNull(property2.getValue()); + } + + @Test + public void testIsReadOnly() { + NestedMethodProperty<String> streetProperty = new NestedMethodProperty<String>( + vaadin, "manager.address.street"); + NestedMethodProperty<Boolean> booleanProperty = new NestedMethodProperty<Boolean>( + vaadin, "manager.address.boolean"); + + Assert.assertFalse(streetProperty.isReadOnly()); + Assert.assertTrue(booleanProperty.isReadOnly()); + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/ObjectPropertyTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/ObjectPropertyTest.java new file mode 100644 index 0000000000..e0307034cf --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/ObjectPropertyTest.java @@ -0,0 +1,102 @@ +package com.vaadin.data.util; + +import org.junit.Assert; +import org.junit.Test; + +public class ObjectPropertyTest { + + public static class TestSuperClass { + private String name; + + public TestSuperClass(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + @Override + public String toString() { + return getName(); + } + } + + public static class TestSubClass extends TestSuperClass { + public TestSubClass(String name) { + super("Subclass: " + name); + } + } + + private TestSuperClass super1 = new TestSuperClass("super1"); + private TestSubClass sub1 = new TestSubClass("sub1"); + + @Test + public void testSimple() { + ObjectProperty<TestSuperClass> prop1 = new ObjectProperty<TestSuperClass>( + super1, TestSuperClass.class); + Assert.assertEquals("super1", prop1.getValue().getName()); + prop1 = new ObjectProperty<TestSuperClass>(super1); + Assert.assertEquals("super1", prop1.getValue().getName()); + + ObjectProperty<TestSubClass> prop2 = new ObjectProperty<TestSubClass>( + sub1, TestSubClass.class); + Assert.assertEquals("Subclass: sub1", prop2.getValue().getName()); + prop2 = new ObjectProperty<TestSubClass>(sub1); + Assert.assertEquals("Subclass: sub1", prop2.getValue().getName()); + } + + @Test + public void testSetValueObjectSuper() { + ObjectProperty<TestSuperClass> prop = new ObjectProperty<TestSuperClass>( + super1, TestSuperClass.class); + Assert.assertEquals("super1", prop.getValue().getName()); + prop.setValue(new TestSuperClass("super2")); + Assert.assertEquals("super1", super1.getName()); + Assert.assertEquals("super2", prop.getValue().getName()); + } + + @Test + public void testSetValueObjectSub() { + ObjectProperty<TestSubClass> prop = new ObjectProperty<TestSubClass>( + sub1, TestSubClass.class); + Assert.assertEquals("Subclass: sub1", prop.getValue().getName()); + prop.setValue(new TestSubClass("sub2")); + Assert.assertEquals("Subclass: sub1", sub1.getName()); + Assert.assertEquals("Subclass: sub2", prop.getValue().getName()); + } + + @Test + public void testSetValueStringSuper() { + ObjectProperty<TestSuperClass> prop = new ObjectProperty<TestSuperClass>( + super1, TestSuperClass.class); + Assert.assertEquals("super1", prop.getValue().getName()); + prop.setValue(new TestSuperClass("super2")); + Assert.assertEquals("super1", super1.getName()); + Assert.assertEquals("super2", prop.getValue().getName()); + } + + @Test + public void testSetValueStringSub() { + ObjectProperty<TestSubClass> prop = new ObjectProperty<TestSubClass>( + sub1, TestSubClass.class); + Assert.assertEquals("Subclass: sub1", prop.getValue().getName()); + prop.setValue(new TestSubClass("sub2")); + Assert.assertEquals("Subclass: sub1", sub1.getName()); + Assert.assertEquals("Subclass: sub2", prop.getValue().getName()); + } + + @Test + public void testMixedGenerics() { + ObjectProperty<TestSuperClass> prop = new ObjectProperty<TestSuperClass>( + sub1); + Assert.assertEquals("Subclass: sub1", prop.getValue().getName()); + Assert.assertEquals(prop.getType(), TestSubClass.class); + // create correct subclass based on the runtime type of the instance + // given to ObjectProperty constructor, which is a subclass of the type + // parameter + prop.setValue(new TestSubClass("sub2")); + Assert.assertEquals("Subclass: sub2", prop.getValue().getName()); + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/PerformanceTestIndexedContainerTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/PerformanceTestIndexedContainerTest.java new file mode 100644 index 0000000000..5f64c0e8d8 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/PerformanceTestIndexedContainerTest.java @@ -0,0 +1,120 @@ +package com.vaadin.data.util; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.SortedSet; +import java.util.TreeSet; + +import org.junit.Assert; +import org.junit.Test; + +public class PerformanceTestIndexedContainerTest { + + private static final int REPEATS = 10; + private final static int ITEMS = 50000; + private static final long ADD_ITEM_FAIL_THRESHOLD = 200; + // TODO should improve performance of these methods + private static final long ADD_ITEM_AT_FAIL_THRESHOLD = 5000; + private static final long ADD_ITEM_AFTER_FAIL_THRESHOLD = 5000; + private static final long ADD_ITEM_AFTER_LAST_FAIL_THRESHOLD = 5000; + private static final long ADD_ITEMS_CONSTRUCTOR_FAIL_THRESHOLD = 200; + + @Test + public void testAddItemPerformance() { + Collection<Long> times = new ArrayList<Long>(); + for (int j = 0; j < REPEATS; ++j) { + IndexedContainer c = new IndexedContainer(); + long start = System.currentTimeMillis(); + for (int i = 0; i < ITEMS; i++) { + c.addItem(); + } + times.add(System.currentTimeMillis() - start); + } + checkMedian(ITEMS, times, "IndexedContainer.addItem()", + ADD_ITEM_FAIL_THRESHOLD); + } + + @Test + public void testAddItemAtPerformance() { + Collection<Long> times = new ArrayList<Long>(); + for (int j = 0; j < REPEATS; ++j) { + IndexedContainer c = new IndexedContainer(); + long start = System.currentTimeMillis(); + for (int i = 0; i < ITEMS; i++) { + c.addItemAt(0); + } + times.add(System.currentTimeMillis() - start); + } + checkMedian(ITEMS, times, "IndexedContainer.addItemAt()", + ADD_ITEM_AT_FAIL_THRESHOLD); + } + + @Test + public void testAddItemAfterPerformance() { + Object initialId = "Item0"; + Collection<Long> times = new ArrayList<Long>(); + for (int j = 0; j < REPEATS; ++j) { + IndexedContainer c = new IndexedContainer(); + c.addItem(initialId); + long start = System.currentTimeMillis(); + for (int i = 0; i < ITEMS; i++) { + c.addItemAfter(initialId); + } + times.add(System.currentTimeMillis() - start); + } + checkMedian(ITEMS, times, "IndexedContainer.addItemAfter()", + ADD_ITEM_AFTER_FAIL_THRESHOLD); + } + + @Test + public void testAddItemAfterLastPerformance() { + // TODO running with less items because slow otherwise + Collection<Long> times = new ArrayList<Long>(); + for (int j = 0; j < REPEATS; ++j) { + IndexedContainer c = new IndexedContainer(); + c.addItem(); + long start = System.currentTimeMillis(); + for (int i = 0; i < ITEMS / 3; i++) { + c.addItemAfter(c.lastItemId()); + } + times.add(System.currentTimeMillis() - start); + } + checkMedian(ITEMS / 3, times, "IndexedContainer.addItemAfter(lastId)", + ADD_ITEM_AFTER_LAST_FAIL_THRESHOLD); + } + + @Test + public void testAddItemsConstructorPerformance() { + Collection<Object> items = new ArrayList<Object>(50000); + for (int i = 0; i < ITEMS; ++i) { + items.add(new Object()); + } + + SortedSet<Long> times = new TreeSet<Long>(); + for (int j = 0; j < REPEATS; ++j) { + long start = System.currentTimeMillis(); + new IndexedContainer(items); + times.add(System.currentTimeMillis() - start); + } + checkMedian(ITEMS, times, "IndexedContainer(Collection)", + ADD_ITEMS_CONSTRUCTOR_FAIL_THRESHOLD); + } + + private void checkMedian(int items, Collection<Long> times, + String methodName, long threshold) { + long median = median(times); + System.out.println( + methodName + " timings (ms) for " + items + " items: " + times); + Assert.assertTrue(methodName + " too slow, median time " + median + + "ms for " + items + " items", median <= threshold); + } + + private Long median(Collection<Long> times) { + ArrayList<Long> list = new ArrayList<Long>(times); + Collections.sort(list); + // not exact median in some cases, but good enough + return list.get(list.size() / 2); + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/PropertyDescriptorTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/PropertyDescriptorTest.java new file mode 100644 index 0000000000..af9db229c5 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/PropertyDescriptorTest.java @@ -0,0 +1,84 @@ +package com.vaadin.data.util; + +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.data.Property; +import com.vaadin.data.util.NestedMethodPropertyTest.Person; + +public class PropertyDescriptorTest { + + @Test + public void testMethodPropertyDescriptorSerialization() throws Exception { + PropertyDescriptor[] pds = Introspector.getBeanInfo(Person.class) + .getPropertyDescriptors(); + + MethodPropertyDescriptor<Person> descriptor = null; + + for (PropertyDescriptor pd : pds) { + if ("name".equals(pd.getName())) { + descriptor = new MethodPropertyDescriptor<Person>(pd.getName(), + String.class, pd.getReadMethod(), pd.getWriteMethod()); + break; + } + } + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + new ObjectOutputStream(baos).writeObject(descriptor); + @SuppressWarnings("unchecked") + VaadinPropertyDescriptor<Person> descriptor2 = (VaadinPropertyDescriptor<Person>) new ObjectInputStream( + new ByteArrayInputStream(baos.toByteArray())).readObject(); + + Property<?> property = descriptor2 + .createProperty(new Person("John", null)); + Assert.assertEquals("John", property.getValue()); + } + + @Test + public void testSimpleNestedPropertyDescriptorSerialization() + throws Exception { + NestedPropertyDescriptor<Person> pd = new NestedPropertyDescriptor<Person>( + "name", Person.class); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + new ObjectOutputStream(baos).writeObject(pd); + @SuppressWarnings("unchecked") + VaadinPropertyDescriptor<Person> pd2 = (VaadinPropertyDescriptor<Person>) new ObjectInputStream( + new ByteArrayInputStream(baos.toByteArray())).readObject(); + + Property<?> property = pd2.createProperty(new Person("John", null)); + Assert.assertEquals("John", property.getValue()); + } + + @Test + public void testNestedPropertyDescriptorSerialization() throws Exception { + NestedPropertyDescriptor<Person> pd = new NestedPropertyDescriptor<Person>( + "address.street", Person.class); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + new ObjectOutputStream(baos).writeObject(pd); + @SuppressWarnings("unchecked") + VaadinPropertyDescriptor<Person> pd2 = (VaadinPropertyDescriptor<Person>) new ObjectInputStream( + new ByteArrayInputStream(baos.toByteArray())).readObject(); + + Property<?> property = pd2.createProperty(new Person("John", null)); + Assert.assertNull(property.getValue()); + } + + @Test + public void testMethodPropertyDescriptorWithPrimitivePropertyType() + throws Exception { + MethodPropertyDescriptor<Person> pd = new MethodPropertyDescriptor<Person>( + "age", int.class, Person.class.getMethod("getAge"), + Person.class.getMethod("setAge", int.class)); + + Assert.assertEquals(Integer.class, pd.getPropertyType()); + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/PropertySetItemTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/PropertySetItemTest.java new file mode 100644 index 0000000000..fc91a20dd0 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/PropertySetItemTest.java @@ -0,0 +1,432 @@ +package com.vaadin.data.util; + +import java.util.Iterator; + +import org.easymock.EasyMock; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.Item.PropertySetChangeEvent; +import com.vaadin.data.Item.PropertySetChangeListener; + +public class PropertySetItemTest { + + private static final String ID1 = "id1"; + private static final String ID2 = "id2"; + private static final String ID3 = "id3"; + + private static final String VALUE1 = "value1"; + private static final String VALUE2 = "value2"; + private static final String VALUE3 = "value3"; + + private ObjectProperty<String> prop1; + private ObjectProperty<String> prop2; + private ObjectProperty<String> prop3; + + private PropertySetChangeListener propertySetListenerMock; + private PropertySetChangeListener propertySetListenerMock2; + + @Before + public void setUp() { + prop1 = new ObjectProperty<String>(VALUE1, String.class); + prop2 = new ObjectProperty<String>(VALUE2, String.class); + prop3 = new ObjectProperty<String>(VALUE3, String.class); + + propertySetListenerMock = EasyMock + .createStrictMock(PropertySetChangeListener.class); + propertySetListenerMock2 = EasyMock + .createMock(PropertySetChangeListener.class); + } + + @After + public void tearDown() { + prop1 = null; + prop2 = null; + prop3 = null; + + propertySetListenerMock = null; + propertySetListenerMock2 = null; + } + + private PropertysetItem createPropertySetItem() { + return new PropertysetItem(); + } + + @Test + public void testEmptyItem() { + PropertysetItem item = createPropertySetItem(); + Assert.assertNotNull(item.getItemPropertyIds()); + Assert.assertEquals(0, item.getItemPropertyIds().size()); + } + + @Test + public void testGetProperty() { + PropertysetItem item = createPropertySetItem(); + + Assert.assertNull(item.getItemProperty(ID1)); + + item.addItemProperty(ID1, prop1); + + Assert.assertEquals(prop1, item.getItemProperty(ID1)); + Assert.assertNull(item.getItemProperty(ID2)); + } + + @Test + public void testAddSingleProperty() { + PropertysetItem item = createPropertySetItem(); + + item.addItemProperty(ID1, prop1); + Assert.assertEquals(1, item.getItemPropertyIds().size()); + Object firstValue = item.getItemPropertyIds().iterator().next(); + Assert.assertEquals(ID1, firstValue); + Assert.assertEquals(prop1, item.getItemProperty(ID1)); + } + + @Test + public void testAddMultipleProperties() { + PropertysetItem item = createPropertySetItem(); + + item.addItemProperty(ID1, prop1); + Assert.assertEquals(1, item.getItemPropertyIds().size()); + Assert.assertEquals(prop1, item.getItemProperty(ID1)); + + item.addItemProperty(ID2, prop2); + Assert.assertEquals(2, item.getItemPropertyIds().size()); + Assert.assertEquals(prop1, item.getItemProperty(ID1)); + Assert.assertEquals(prop2, item.getItemProperty(ID2)); + + item.addItemProperty(ID3, prop3); + Assert.assertEquals(3, item.getItemPropertyIds().size()); + } + + @Test + public void testAddedPropertyOrder() { + PropertysetItem item = createPropertySetItem(); + item.addItemProperty(ID1, prop1); + item.addItemProperty(ID2, prop2); + item.addItemProperty(ID3, prop3); + + Iterator<?> it = item.getItemPropertyIds().iterator(); + Assert.assertEquals(ID1, it.next()); + Assert.assertEquals(ID2, it.next()); + Assert.assertEquals(ID3, it.next()); + } + + @Test + public void testAddPropertyTwice() { + PropertysetItem item = createPropertySetItem(); + Assert.assertTrue(item.addItemProperty(ID1, prop1)); + Assert.assertFalse(item.addItemProperty(ID1, prop1)); + + Assert.assertEquals(1, item.getItemPropertyIds().size()); + Assert.assertEquals(prop1, item.getItemProperty(ID1)); + } + + @Test + public void testCannotChangeProperty() { + PropertysetItem item = createPropertySetItem(); + Assert.assertTrue(item.addItemProperty(ID1, prop1)); + + Assert.assertEquals(prop1, item.getItemProperty(ID1)); + + Assert.assertFalse(item.addItemProperty(ID1, prop2)); + + Assert.assertEquals(1, item.getItemPropertyIds().size()); + Assert.assertEquals(prop1, item.getItemProperty(ID1)); + } + + @Test + public void testRemoveProperty() { + PropertysetItem item = createPropertySetItem(); + item.addItemProperty(ID1, prop1); + item.removeItemProperty(ID1); + + Assert.assertEquals(0, item.getItemPropertyIds().size()); + Assert.assertNull(item.getItemProperty(ID1)); + } + + @Test + public void testRemovePropertyOrder() { + PropertysetItem item = createPropertySetItem(); + item.addItemProperty(ID1, prop1); + item.addItemProperty(ID2, prop2); + item.addItemProperty(ID3, prop3); + + item.removeItemProperty(ID2); + + Iterator<?> it = item.getItemPropertyIds().iterator(); + Assert.assertEquals(ID1, it.next()); + Assert.assertEquals(ID3, it.next()); + } + + @Test + public void testRemoveNonExistentListener() { + PropertysetItem item = createPropertySetItem(); + item.removeListener(propertySetListenerMock); + } + + @Test + public void testRemoveListenerTwice() { + PropertysetItem item = createPropertySetItem(); + item.addListener(propertySetListenerMock); + item.removeListener(propertySetListenerMock); + item.removeListener(propertySetListenerMock); + } + + @Test + public void testAddPropertyNotification() { + // exactly one notification each time + PropertysetItem item = createPropertySetItem(); + + // Expectations and start test + propertySetListenerMock.itemPropertySetChange( + EasyMock.isA(PropertySetChangeEvent.class)); + EasyMock.replay(propertySetListenerMock); + + // Add listener and add a property -> should end up in listener once + item.addListener(propertySetListenerMock); + item.addItemProperty(ID1, prop1); + + // Ensure listener was called once + EasyMock.verify(propertySetListenerMock); + + // Remove the listener -> should not end up in listener when adding a + // property + item.removeListener(propertySetListenerMock); + item.addItemProperty(ID2, prop2); + + // Ensure listener still has been called only once + EasyMock.verify(propertySetListenerMock); + } + + @Test + public void testRemovePropertyNotification() { + // exactly one notification each time + PropertysetItem item = createPropertySetItem(); + item.addItemProperty(ID1, prop1); + item.addItemProperty(ID2, prop2); + + // Expectations and start test + propertySetListenerMock.itemPropertySetChange( + EasyMock.isA(PropertySetChangeEvent.class)); + EasyMock.replay(propertySetListenerMock); + + // Add listener and add a property -> should end up in listener once + item.addListener(propertySetListenerMock); + item.removeItemProperty(ID1); + + // Ensure listener was called once + EasyMock.verify(propertySetListenerMock); + + // Remove the listener -> should not end up in listener + item.removeListener(propertySetListenerMock); + item.removeItemProperty(ID2); + + // Ensure listener still has been called only once + EasyMock.verify(propertySetListenerMock); + } + + @Test + public void testItemEqualsNull() { + PropertysetItem item = createPropertySetItem(); + + Assert.assertFalse(item.equals(null)); + } + + @Test + public void testEmptyItemEquals() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + Assert.assertTrue(item1.equals(item2)); + } + + @Test + public void testItemEqualsSingleProperty() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + item2.addItemProperty(ID1, prop1); + PropertysetItem item3 = createPropertySetItem(); + item3.addItemProperty(ID1, prop1); + PropertysetItem item4 = createPropertySetItem(); + item4.addItemProperty(ID1, prop2); + PropertysetItem item5 = createPropertySetItem(); + item5.addItemProperty(ID2, prop2); + + Assert.assertFalse(item1.equals(item2)); + Assert.assertFalse(item1.equals(item3)); + Assert.assertFalse(item1.equals(item4)); + Assert.assertFalse(item1.equals(item5)); + + Assert.assertTrue(item2.equals(item3)); + Assert.assertFalse(item2.equals(item4)); + Assert.assertFalse(item2.equals(item5)); + + Assert.assertFalse(item3.equals(item4)); + Assert.assertFalse(item3.equals(item5)); + + Assert.assertFalse(item4.equals(item5)); + + Assert.assertFalse(item2.equals(item1)); + } + + @Test + public void testItemEqualsMultipleProperties() { + PropertysetItem item1 = createPropertySetItem(); + item1.addItemProperty(ID1, prop1); + + PropertysetItem item2 = createPropertySetItem(); + item2.addItemProperty(ID1, prop1); + item2.addItemProperty(ID2, prop2); + + PropertysetItem item3 = createPropertySetItem(); + item3.addItemProperty(ID1, prop1); + item3.addItemProperty(ID2, prop2); + + Assert.assertFalse(item1.equals(item2)); + + Assert.assertTrue(item2.equals(item3)); + } + + @Test + public void testItemEqualsPropertyOrder() { + PropertysetItem item1 = createPropertySetItem(); + item1.addItemProperty(ID1, prop1); + item1.addItemProperty(ID2, prop2); + + PropertysetItem item2 = createPropertySetItem(); + item2.addItemProperty(ID2, prop2); + item2.addItemProperty(ID1, prop1); + + Assert.assertFalse(item1.equals(item2)); + } + + @Test + public void testEqualsSingleListener() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + item1.addListener(propertySetListenerMock); + + Assert.assertFalse(item1.equals(item2)); + Assert.assertFalse(item2.equals(item1)); + + item2.addListener(propertySetListenerMock); + + Assert.assertTrue(item1.equals(item2)); + Assert.assertTrue(item2.equals(item1)); + } + + @Test + public void testEqualsMultipleListeners() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + item1.addListener(propertySetListenerMock); + item1.addListener(propertySetListenerMock2); + + item2.addListener(propertySetListenerMock); + + Assert.assertFalse(item1.equals(item2)); + Assert.assertFalse(item2.equals(item1)); + + item2.addListener(propertySetListenerMock2); + + Assert.assertTrue(item1.equals(item2)); + Assert.assertTrue(item2.equals(item1)); + } + + @Test + public void testEqualsAddRemoveListener() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + item1.addListener(propertySetListenerMock); + item1.removeListener(propertySetListenerMock); + + Assert.assertTrue(item1.equals(item2)); + Assert.assertTrue(item2.equals(item1)); + } + + @Test + public void testItemHashCodeEmpty() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + Assert.assertEquals(item1.hashCode(), item2.hashCode()); + } + + @Test + public void testItemHashCodeAddProperties() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + Assert.assertEquals(item1.hashCode(), item2.hashCode()); + + item1.addItemProperty(ID1, prop1); + item1.addItemProperty(ID2, prop2); + // hashCodes can be equal even if items are different + + item2.addItemProperty(ID1, prop1); + item2.addItemProperty(ID2, prop2); + // but here hashCodes must be equal + Assert.assertEquals(item1.hashCode(), item2.hashCode()); + } + + @Test + public void testItemHashCodeAddListeners() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + Assert.assertEquals(item1.hashCode(), item2.hashCode()); + + item1.addListener(propertySetListenerMock); + // hashCodes can be equal even if items are different + + item2.addListener(propertySetListenerMock); + // but here hashCodes must be equal + Assert.assertEquals(item1.hashCode(), item2.hashCode()); + } + + @Test + public void testItemHashCodeAddRemoveProperty() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + item1.addItemProperty(ID1, prop1); + item1.removeItemProperty(ID1); + + Assert.assertEquals(item1.hashCode(), item2.hashCode()); + } + + @Test + public void testItemHashCodeAddRemoveListener() { + PropertysetItem item1 = createPropertySetItem(); + PropertysetItem item2 = createPropertySetItem(); + + item1.addListener(propertySetListenerMock); + item1.removeListener(propertySetListenerMock); + + Assert.assertEquals(item1.hashCode(), item2.hashCode()); + } + + @Test + public void testToString() { + // toString() behavior is specified in the class javadoc + PropertysetItem item = createPropertySetItem(); + + Assert.assertEquals("", item.toString()); + + item.addItemProperty(ID1, prop1); + + Assert.assertEquals(String.valueOf(prop1.getValue()), item.toString()); + + item.addItemProperty(ID2, prop2); + + Assert.assertEquals(String.valueOf(prop1.getValue()) + " " + + String.valueOf(prop2.getValue()), item.toString()); + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/ReflectToolsGetSuperFieldTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/ReflectToolsGetSuperFieldTest.java new file mode 100644 index 0000000000..df4258f316 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/ReflectToolsGetSuperFieldTest.java @@ -0,0 +1,35 @@ +package com.vaadin.data.util; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.vaadin.data.fieldgroup.FieldGroup; +import com.vaadin.data.fieldgroup.PropertyId; +import com.vaadin.v7.ui.LegacyTextField; + +public class ReflectToolsGetSuperFieldTest { + + @Test + public void getFieldFromSuperClass() { + class MyClass { + @PropertyId("testProperty") + LegacyTextField test = new LegacyTextField("This is a test"); + } + class MySubClass extends MyClass { + // no fields here + } + + PropertysetItem item = new PropertysetItem(); + item.addItemProperty("testProperty", + new ObjectProperty<String>("Value of testProperty")); + + MySubClass form = new MySubClass(); + + FieldGroup binder = new FieldGroup(item); + binder.bindMemberFields(form); + + assertTrue("Value of testProperty".equals(form.test.getValue())); + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/data/util/TransactionalPropertyWrapperTest.java b/compatibility-server/src/test/java/com/vaadin/data/util/TransactionalPropertyWrapperTest.java new file mode 100644 index 0000000000..ef3e416f96 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/data/util/TransactionalPropertyWrapperTest.java @@ -0,0 +1,117 @@ +/* + * Copyright 2000-2016 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.data.util; + +import static org.junit.Assert.assertTrue; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; + +import com.vaadin.data.fieldgroup.FieldGroup; +import com.vaadin.v7.ui.LegacyTextField; + +/** + * Test verifying that TransactionalPropertyWrapper removes it's listener from + * wrapped Property + * + * @since 7.1.15 + * @author Vaadin Ltd + */ +public class TransactionalPropertyWrapperTest { + + @SuppressWarnings("serial") + public class TestingProperty<T extends Object> + extends ObjectProperty<Object> { + + private List<ValueChangeListener> listeners = new ArrayList<ValueChangeListener>(); + + public TestingProperty(Object value) { + super(value); + } + + @Override + public void addValueChangeListener(ValueChangeListener listener) { + super.addValueChangeListener(listener); + listeners.add(listener); + } + + @Override + public void removeValueChangeListener(ValueChangeListener listener) { + super.removeValueChangeListener(listener); + if (listeners.contains(listener)) { + listeners.remove(listener); + } + } + + public boolean hasListeners() { + return !listeners.isEmpty(); + } + } + + private final LegacyTextField nameField = new LegacyTextField("Name"); + private final LegacyTextField ageField = new LegacyTextField("Age"); + private final LegacyTextField unboundField = new LegacyTextField( + "No FieldGroup"); + private final TestingProperty<String> unboundProp = new TestingProperty<String>( + "Hello World"); + private final PropertysetItem item = new PropertysetItem(); + + @Test + public void fieldGroupBindAndUnbind() { + item.addItemProperty("name", + new TestingProperty<String>("Just some text")); + item.addItemProperty("age", new TestingProperty<String>("42")); + + final FieldGroup binder = new FieldGroup(item); + binder.setBuffered(false); + + for (int i = 0; i < 2; ++i) { + binder.bind(nameField, "name"); + binder.bind(ageField, "age"); + unboundField.setPropertyDataSource(unboundProp); + + assertTrue("No listeners in Properties", fieldsHaveListeners(true)); + + binder.unbind(nameField); + binder.unbind(ageField); + unboundField.setPropertyDataSource(null); + + assertTrue("Listeners in Properties after unbinding", + fieldsHaveListeners(false)); + } + } + + /** + * Check that all listeners have same hasListeners() response + * + * @param expected + * expected response + * @return true if all are the same as expected. false if not + */ + private boolean fieldsHaveListeners(boolean expected) { + for (Object id : item.getItemPropertyIds()) { + TestingProperty<?> itemProperty = (TestingProperty<?>) item + .getItemProperty(id); + + if (itemProperty.hasListeners() != expected) { + return false; + } + } + return unboundProp.hasListeners() == expected; + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/ContextClickListenerTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/ContextClickListenerTest.java new file mode 100644 index 0000000000..1b93a3063d --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/ContextClickListenerTest.java @@ -0,0 +1,163 @@ +/* + * Copyright 2000-2016 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.tests.server; + +import java.util.EventObject; + +import org.easymock.EasyMock; +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.event.ContextClickEvent; +import com.vaadin.event.ContextClickEvent.ContextClickListener; +import com.vaadin.ui.AbstractComponent; +import com.vaadin.ui.LegacyGrid.GridContextClickEvent; +import com.vaadin.ui.Table.TableContextClickEvent; + +/** + * Server-side unit tests to see that context click events are sent to listeners + * correctly. + * + * If a listener is listening to a super type of an event, it should get the + * event. i.e. Listening to ContextClickEvent, it should get the specialized + * GridContextClickEvent as well. + * + * If a listener is listening to a sub-type of an event, it should not get the + * super version. i.e. Listening to GridContextClickEvent, it should not get a + * plain ContextClickEvent. + */ +public class ContextClickListenerTest extends AbstractComponent { + + private final static ContextClickEvent contextClickEvent = EasyMock + .createMock(ContextClickEvent.class); + private final static GridContextClickEvent gridContextClickEvent = EasyMock + .createMock(GridContextClickEvent.class); + private final static TableContextClickEvent tableContextClickEvent = EasyMock + .createMock(TableContextClickEvent.class); + + private final AssertListener contextListener = new AssertListener(); + private final AssertListener ctxtListener2 = new AssertListener(); + + public static class AssertListener implements ContextClickListener { + + private Class<?> expected = null; + private String error = null; + + @Override + public void contextClick(ContextClickEvent event) { + if (expected == null) { + error = "Unexpected context click event."; + return; + } + + if (!expected.isAssignableFrom(event.getClass())) { + error = "Expected event type did not match the actual event."; + } + + expected = null; + } + + public <T extends ContextClickEvent> void expect(Class<T> clazz) { + validate(); + expected = clazz; + } + + public void validate() { + if (expected != null) { + Assert.fail("Expected context click never happened."); + } else if (error != null) { + Assert.fail(error); + } + } + } + + @Test + public void testListenerGetsASubClass() { + addContextClickListener(contextListener); + contextListener.expect(GridContextClickEvent.class); + fireEvent(gridContextClickEvent); + } + + @Test + public void testListenerGetsExactClass() { + addContextClickListener(contextListener); + contextListener.expect(ContextClickEvent.class); + fireEvent(contextClickEvent); + } + + /** + * Multiple listeners should get fitting events. + */ + @Test + public void testMultipleListenerGetEvents() { + addContextClickListener(ctxtListener2); + addContextClickListener(contextListener); + + ctxtListener2.expect(GridContextClickEvent.class); + contextListener.expect(GridContextClickEvent.class); + + fireEvent(gridContextClickEvent); + } + + @Test + public void testAddAndRemoveListener() { + addContextClickListener(contextListener); + contextListener.expect(ContextClickEvent.class); + + fireEvent(contextClickEvent); + + removeContextClickListener(contextListener); + + fireEvent(contextClickEvent); + } + + @Test + public void testAddAndRemoveMultipleListeners() { + addContextClickListener(ctxtListener2); + addContextClickListener(contextListener); + + ctxtListener2.expect(GridContextClickEvent.class); + contextListener.expect(GridContextClickEvent.class); + fireEvent(gridContextClickEvent); + + removeContextClickListener(ctxtListener2); + + contextListener.expect(GridContextClickEvent.class); + fireEvent(gridContextClickEvent); + } + + @Test(expected = AssertionError.class) + public void testExpectedEventNotReceived() { + addContextClickListener(contextListener); + contextListener.expect(GridContextClickEvent.class); + fireEvent(contextClickEvent); + } + + @Test(expected = AssertionError.class) + public void testUnexpectedEventReceived() { + addContextClickListener(contextListener); + fireEvent(gridContextClickEvent); + } + + @Override + protected void fireEvent(EventObject event) { + super.fireEvent(event); + + // Validate listeners automatically. + ctxtListener2.validate(); + contextListener.validate(); + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/BeanFieldGroupTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/BeanFieldGroupTest.java new file mode 100644 index 0000000000..f5c315b440 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/BeanFieldGroupTest.java @@ -0,0 +1,172 @@ +package com.vaadin.tests.server.component.fieldgroup; + +import static org.junit.Assert.assertEquals; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.data.Item; +import com.vaadin.data.fieldgroup.BeanFieldGroup; +import com.vaadin.data.fieldgroup.FieldGroup.CommitException; +import com.vaadin.data.fieldgroup.PropertyId; +import com.vaadin.data.util.BeanItem; +import com.vaadin.ui.RichTextArea; +import com.vaadin.v7.ui.LegacyField; +import com.vaadin.v7.ui.LegacyTextField; + +public class BeanFieldGroupTest { + + private static final String DEFAULT_FOR_BASIC_FIELD = "default"; + + public static class MyBean { + + private String basicField = DEFAULT_FOR_BASIC_FIELD; + + private String anotherField; + + private MyNestedBean nestedBean = new MyNestedBean(); + + public MyNestedBean getNestedBean() { + return nestedBean; + } + + /** + * @return the basicField + */ + public String getBasicField() { + return basicField; + } + + /** + * @param basicField + * the basicField to set + */ + public void setBasicField(String basicField) { + this.basicField = basicField; + } + + /** + * @return the anotherField + */ + public String getAnotherField() { + return anotherField; + } + + /** + * @param anotherField + * the anotherField to set + */ + public void setAnotherField(String anotherField) { + this.anotherField = anotherField; + } + } + + public static class MyNestedBean { + + private String hello = "Hello world"; + + public String getHello() { + return hello; + } + } + + public static class ViewStub { + + LegacyTextField basicField = new LegacyTextField(); + + @PropertyId("anotherField") + LegacyTextField boundWithAnnotation = new LegacyTextField(); + } + + @SuppressWarnings("unchecked") + @Test + public void testStaticBindingHelper() { + MyBean myBean = new MyBean(); + + ViewStub viewStub = new ViewStub(); + BeanFieldGroup<MyBean> bindFields = BeanFieldGroup + .bindFieldsUnbuffered(myBean, viewStub); + + LegacyField<String> field = (LegacyField<String>) bindFields + .getField("basicField"); + Assert.assertEquals(DEFAULT_FOR_BASIC_FIELD, myBean.basicField); + field.setValue("Foo"); + Assert.assertEquals("Foo", myBean.basicField); + + field = (LegacyField<String>) bindFields.getField("anotherField"); + field.setValue("Foo"); + Assert.assertEquals("Foo", myBean.anotherField); + } + + @SuppressWarnings("unchecked") + @Test + public void testStaticBufferedBindingHelper() throws CommitException { + MyBean myBean = new MyBean(); + + ViewStub viewStub = new ViewStub(); + BeanFieldGroup<MyBean> bindFields = BeanFieldGroup + .bindFieldsBuffered(myBean, viewStub); + + LegacyField<String> basicField = (LegacyField<String>) bindFields + .getField("basicField"); + basicField.setValue("Foo"); + Assert.assertEquals(DEFAULT_FOR_BASIC_FIELD, myBean.basicField); + + LegacyField<String> anotherField = (LegacyField<String>) bindFields + .getField("anotherField"); + anotherField.setValue("Foo"); + Assert.assertNull(myBean.anotherField); + + bindFields.commit(); + + Assert.assertEquals("Foo", myBean.basicField); + Assert.assertEquals("Foo", myBean.anotherField); + + } + + @Test + public void buildAndBindNestedProperty() { + + MyBean bean = new MyBean(); + + BeanFieldGroup<MyBean> bfg = new BeanFieldGroup<MyBean>(MyBean.class); + bfg.setItemDataSource(bean); + + com.vaadin.v7.ui.LegacyField<?> helloField = bfg + .buildAndBind("Hello string", "nestedBean.hello"); + assertEquals(bean.nestedBean.hello, helloField.getValue().toString()); + } + + @Test + public void buildAndBindNestedRichTextAreaProperty() { + + MyBean bean = new MyBean(); + + BeanFieldGroup<MyBean> bfg = new BeanFieldGroup<MyBean>(MyBean.class); + bfg.setItemDataSource(bean); + + RichTextArea helloField = bfg.buildAndBind("Hello string", + "nestedBean.hello", RichTextArea.class); + assertEquals(bean.nestedBean.hello, helloField.getValue().toString()); + } + + @Test + public void setDataSource_nullBean_nullBeanIsSetInDataSource() { + BeanFieldGroup<MyBean> group = new BeanFieldGroup<MyBean>(MyBean.class); + + group.setItemDataSource((MyBean) null); + + BeanItem<MyBean> dataSource = group.getItemDataSource(); + Assert.assertNull("Data source is null for null bean", dataSource); + } + + @Test + public void setDataSource_nullItem_nullDataSourceIsSet() { + BeanFieldGroup<MyBean> group = new BeanFieldGroup<MyBean>(MyBean.class); + + group.setItemDataSource((Item) null); + BeanItem<MyBean> dataSource = group.getItemDataSource(); + Assert.assertNull("Group returns not null data source", dataSource); + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/CaseInsensitiveBindingTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/CaseInsensitiveBindingTest.java new file mode 100644 index 0000000000..a324c02cfc --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/CaseInsensitiveBindingTest.java @@ -0,0 +1,85 @@ +package com.vaadin.tests.server.component.fieldgroup; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.vaadin.data.fieldgroup.FieldGroup; +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.data.util.PropertysetItem; +import com.vaadin.ui.FormLayout; +import com.vaadin.v7.ui.LegacyTextField; + +public class CaseInsensitiveBindingTest { + + @Test + public void caseInsensitivityAndUnderscoreRemoval() { + PropertysetItem item = new PropertysetItem(); + item.addItemProperty("LastName", new ObjectProperty<String>("Sparrow")); + + class MyForm extends FormLayout { + LegacyTextField lastName = new LegacyTextField("Last name"); + + public MyForm() { + + // Should bind to the LastName property + addComponent(lastName); + } + } + + MyForm form = new MyForm(); + + FieldGroup binder = new FieldGroup(item); + binder.bindMemberFields(form); + + assertTrue("Sparrow".equals(form.lastName.getValue())); + } + + @Test + public void UnderscoreRemoval() { + PropertysetItem item = new PropertysetItem(); + item.addItemProperty("first_name", new ObjectProperty<String>("Jack")); + + class MyForm extends FormLayout { + LegacyTextField firstName = new LegacyTextField("First name"); + + public MyForm() { + // Should bind to the first_name property + addComponent(firstName); + } + } + + MyForm form = new MyForm(); + + FieldGroup binder = new FieldGroup(item); + binder.bindMemberFields(form); + + assertTrue("Jack".equals(form.firstName.getValue())); + } + + @Test + public void perfectMatchPriority() { + PropertysetItem item = new PropertysetItem(); + item.addItemProperty("first_name", + new ObjectProperty<String>("Not this")); + item.addItemProperty("firstName", new ObjectProperty<String>("This")); + + class MyForm extends FormLayout { + LegacyTextField firstName = new LegacyTextField("First name"); + + public MyForm() { + // should bind to the firstName property, not first_name + // property + addComponent(firstName); + } + } + + MyForm form = new MyForm(); + + FieldGroup binder = new FieldGroup(item); + binder.bindMemberFields(form); + + assertTrue("This".equals(form.firstName.getValue())); + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/FieldGroupTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/FieldGroupTest.java new file mode 100644 index 0000000000..43d2bf8a6a --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/FieldGroupTest.java @@ -0,0 +1,149 @@ +/* + * Copyright 2000-2016 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.tests.server.component.fieldgroup; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.data.Item; +import com.vaadin.data.Property; +import com.vaadin.data.fieldgroup.FieldGroup; +import com.vaadin.data.fieldgroup.FieldGroup.CommitException; +import com.vaadin.data.util.AbstractProperty; +import com.vaadin.v7.data.Validator.InvalidValueException; +import com.vaadin.v7.ui.LegacyField; +import com.vaadin.v7.ui.LegacyTextField; + +/** + * + * Tests for {@link FieldGroup}. + * + * @author Vaadin Ltd + */ +public class FieldGroupTest { + + @Test + public void setReadOnly_readOnlyAndNoDataSource_fieldIsReadOnly() { + FieldGroup fieldGroup = new FieldGroup(); + + LegacyTextField field = new LegacyTextField(); + fieldGroup.bind(field, "property"); + + fieldGroup.setReadOnly(true); + + Assert.assertTrue("Field is not read only", field.isReadOnly()); + } + + @Test + public void setReadOnly_writableAndNoDataSource_fieldIsWritable() { + FieldGroup fieldGroup = new FieldGroup(); + + LegacyTextField field = new LegacyTextField(); + fieldGroup.bind(field, "property"); + + fieldGroup.setReadOnly(false); + + Assert.assertFalse("Field is not writable", field.isReadOnly()); + } + + @Test + public void commit_validationFailed_allValidationFailuresAvailable() + throws CommitException { + FieldGroup fieldGroup = new FieldGroup(); + + fieldGroup.setItemDataSource(new TestItem()); + + LegacyTextField field1 = new LegacyTextField(); + field1.setRequired(true); + fieldGroup.bind(field1, "prop1"); + + LegacyTextField field2 = new LegacyTextField(); + field2.setRequired(true); + fieldGroup.bind(field2, "prop2"); + + Set<LegacyTextField> set = new HashSet<>(Arrays.asList(field1, field2)); + + try { + fieldGroup.commit(); + Assert.fail("No commit exception is thrown"); + } catch (CommitException exception) { + Map<LegacyField<?>, ? extends InvalidValueException> invalidFields = exception + .getInvalidFields(); + for (Entry<LegacyField<?>, ? extends InvalidValueException> entry : invalidFields + .entrySet()) { + set.remove(entry.getKey()); + } + Assert.assertEquals( + "Some fields are not found in the invalid fields map", 0, + set.size()); + Assert.assertEquals( + "Invalid value exception should be thrown for each field", + 2, invalidFields.size()); + } + } + + private static class TestItem implements Item { + + @Override + public Property<String> getItemProperty(Object id) { + return new StringProperty(); + } + + @Override + public Collection<?> getItemPropertyIds() { + return Arrays.asList("prop1", "prop2"); + } + + @Override + public boolean addItemProperty(Object id, Property property) + throws UnsupportedOperationException { + return false; + } + + @Override + public boolean removeItemProperty(Object id) + throws UnsupportedOperationException { + return false; + } + + } + + private static class StringProperty extends AbstractProperty<String> { + + @Override + public String getValue() { + return null; + } + + @Override + public void setValue(String newValue) + throws Property.ReadOnlyException { + } + + @Override + public Class<? extends String> getType() { + return String.class; + } + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/FieldGroupWithReadOnlyPropertiesTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/FieldGroupWithReadOnlyPropertiesTest.java new file mode 100644 index 0000000000..f14b966a2d --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/FieldGroupWithReadOnlyPropertiesTest.java @@ -0,0 +1,51 @@ +package com.vaadin.tests.server.component.fieldgroup; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.vaadin.data.fieldgroup.FieldGroup; +import com.vaadin.data.util.BeanItem; +import com.vaadin.tests.data.bean.BeanWithReadOnlyField; +import com.vaadin.v7.ui.LegacyTextField; + +public class FieldGroupWithReadOnlyPropertiesTest { + + private LegacyTextField readOnlyField = new LegacyTextField(); + private LegacyTextField writableField = new LegacyTextField(); + + @Test + public void bindReadOnlyPropertyToFieldGroup() { + BeanWithReadOnlyField bean = new BeanWithReadOnlyField(); + BeanItem<BeanWithReadOnlyField> beanItem = new BeanItem<BeanWithReadOnlyField>( + bean); + beanItem.getItemProperty("readOnlyField").setReadOnly(true); + + FieldGroup fieldGroup = new FieldGroup(beanItem); + fieldGroup.bindMemberFields(this); + + assertTrue(readOnlyField.isReadOnly()); + assertFalse(writableField.isReadOnly()); + } + + @Test + public void fieldGroupSetReadOnlyTest() { + BeanWithReadOnlyField bean = new BeanWithReadOnlyField(); + BeanItem<BeanWithReadOnlyField> beanItem = new BeanItem<BeanWithReadOnlyField>( + bean); + beanItem.getItemProperty("readOnlyField").setReadOnly(true); + + FieldGroup fieldGroup = new FieldGroup(beanItem); + fieldGroup.bindMemberFields(this); + + fieldGroup.setReadOnly(true); + assertTrue(readOnlyField.isReadOnly()); + assertTrue(writableField.isReadOnly()); + + fieldGroup.setReadOnly(false); + assertTrue(readOnlyField.isReadOnly()); + assertFalse(writableField.isReadOnly()); + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/FieldNamedDescriptionTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/FieldNamedDescriptionTest.java new file mode 100644 index 0000000000..0ef30316ac --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/fieldgroup/FieldNamedDescriptionTest.java @@ -0,0 +1,53 @@ +package com.vaadin.tests.server.component.fieldgroup; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; + +import com.vaadin.data.fieldgroup.FieldGroup; +import com.vaadin.data.fieldgroup.PropertyId; +import com.vaadin.data.util.ObjectProperty; +import com.vaadin.data.util.PropertysetItem; +import com.vaadin.ui.FormLayout; +import com.vaadin.v7.ui.LegacyTextField; + +public class FieldNamedDescriptionTest { + + @Test + public void bindReadOnlyPropertyToFieldGroup() { + // Create an item + PropertysetItem item = new PropertysetItem(); + item.addItemProperty("name", new ObjectProperty<String>("Zaphod")); + item.addItemProperty("description", + new ObjectProperty<String>("This is a description")); + + // Define a form as a class that extends some layout + class MyForm extends FormLayout { + // Member that will bind to the "name" property + LegacyTextField name = new LegacyTextField("Name"); + + // This member will not bind to the desctiptionProperty as the name + // description conflicts with something in the binding process + @PropertyId("description") + LegacyTextField description = new LegacyTextField("Description"); + + public MyForm() { + + // Add the fields + addComponent(name); + addComponent(description); + } + } + + // Create one + MyForm form = new MyForm(); + + // Now create a binder that can also creates the fields + // using the default field factory + FieldGroup binder = new FieldGroup(item); + binder.bindMemberFields(form); + + assertTrue(form.description.getValue().equals("This is a description")); + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridAddRowBuiltinContainerTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridAddRowBuiltinContainerTest.java new file mode 100644 index 0000000000..3bff93c042 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridAddRowBuiltinContainerTest.java @@ -0,0 +1,219 @@ +/* + * Copyright 2000-2016 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.tests.server.component.grid; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.Container; +import com.vaadin.data.Item; +import com.vaadin.data.util.BeanItem; +import com.vaadin.data.util.BeanItemContainer; +import com.vaadin.data.util.MethodProperty.MethodException; +import com.vaadin.tests.data.bean.Person; +import com.vaadin.ui.LegacyGrid; + +public class GridAddRowBuiltinContainerTest { + LegacyGrid grid = new LegacyGrid(); + Container.Indexed container; + + @Before + public void setUp() { + container = grid.getContainerDataSource(); + + grid.addColumn("myColumn"); + } + + @Test + public void testSimpleCase() { + Object itemId = grid.addRow("Hello"); + + Assert.assertEquals(Integer.valueOf(1), itemId); + + Assert.assertEquals("There should be one item in the container", 1, + container.size()); + + Assert.assertEquals("Hello", container.getItem(itemId) + .getItemProperty("myColumn").getValue()); + } + + @Test(expected = IllegalArgumentException.class) + public void testNullParameter() { + // cast to Object[] to distinguish from one null varargs value + grid.addRow((Object[]) null); + } + + @Test + public void testNullValue() { + // cast to Object to distinguish from a null varargs array + Object itemId = grid.addRow((Object) null); + + Assert.assertEquals(null, container.getItem(itemId) + .getItemProperty("myColumn").getValue()); + } + + @Test(expected = IllegalArgumentException.class) + public void testAddInvalidType() { + grid.addRow(Integer.valueOf(5)); + } + + @Test + public void testMultipleProperties() { + grid.addColumn("myOther", Integer.class); + + Object itemId = grid.addRow("Hello", Integer.valueOf(3)); + + Item item = container.getItem(itemId); + Assert.assertEquals("Hello", + item.getItemProperty("myColumn").getValue()); + Assert.assertEquals(Integer.valueOf(3), + item.getItemProperty("myOther").getValue()); + } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidPropertyAmount() { + grid.addRow("Hello", Integer.valueOf(3)); + } + + @Test + public void testRemovedColumn() { + grid.addColumn("myOther", Integer.class); + grid.removeColumn("myColumn"); + + grid.addRow(Integer.valueOf(3)); + + Item item = container.getItem(Integer.valueOf(1)); + Assert.assertEquals("Default value should be used for removed column", + "", item.getItemProperty("myColumn").getValue()); + Assert.assertEquals(Integer.valueOf(3), + item.getItemProperty("myOther").getValue()); + } + + @Test + public void testMultiplePropertiesAfterReorder() { + grid.addColumn("myOther", Integer.class); + + grid.setColumnOrder("myOther", "myColumn"); + + grid.addRow(Integer.valueOf(3), "Hello"); + + Item item = container.getItem(Integer.valueOf(1)); + Assert.assertEquals("Hello", + item.getItemProperty("myColumn").getValue()); + Assert.assertEquals(Integer.valueOf(3), + item.getItemProperty("myOther").getValue()); + } + + @Test + public void testInvalidType_NothingAdded() { + try { + grid.addRow(Integer.valueOf(5)); + + // Can't use @Test(expect = Foo.class) since we also want to verify + // state after exception was thrown + Assert.fail("Adding wrong type should throw ClassCastException"); + } catch (IllegalArgumentException e) { + Assert.assertEquals("No row should have been added", 0, + container.size()); + } + } + + @Test + public void testUnsupportingContainer() { + setContainerRemoveColumns(new BeanItemContainer<Person>(Person.class)); + try { + + grid.addRow("name"); + + // Can't use @Test(expect = Foo.class) since we also want to verify + // state after exception was thrown + Assert.fail( + "Adding to BeanItemContainer container should throw UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + Assert.assertEquals("No row should have been added", 0, + container.size()); + } + } + + @Test + public void testCustomContainer() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class) { + @Override + public Object addItem() { + BeanItem<Person> item = addBean(new Person()); + return getBeanIdResolver().getIdForBean(item.getBean()); + } + }; + + setContainerRemoveColumns(container); + + grid.addRow("name"); + + Assert.assertEquals(1, container.size()); + + Assert.assertEquals("name", container.getIdByIndex(0).getFirstName()); + } + + @Test + public void testSetterThrowing() { + BeanItemContainer<Person> container = new BeanItemContainer<Person>( + Person.class) { + @Override + public Object addItem() { + BeanItem<Person> item = addBean(new Person() { + @Override + public void setFirstName(String firstName) { + if ("name".equals(firstName)) { + throw new RuntimeException(firstName); + } else { + super.setFirstName(firstName); + } + } + }); + return getBeanIdResolver().getIdForBean(item.getBean()); + } + }; + + setContainerRemoveColumns(container); + + try { + + grid.addRow("name"); + + // Can't use @Test(expect = Foo.class) since we also want to verify + // state after exception was thrown + Assert.fail("Adding row should throw MethodException"); + } catch (MethodException e) { + Assert.assertEquals("Got the wrong exception", "name", + e.getCause().getMessage()); + + Assert.assertEquals("There should be no rows in the container", 0, + container.size()); + } + } + + private void setContainerRemoveColumns( + BeanItemContainer<Person> container) { + // Remove predefined column so we can change container + grid.removeAllColumns(); + grid.setContainerDataSource(container); + grid.removeAllColumns(); + grid.addColumn("firstName"); + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridChildrenTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridChildrenTest.java new file mode 100644 index 0000000000..f126e636ba --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridChildrenTest.java @@ -0,0 +1,59 @@ +/* + * Copyright 2000-2016 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.tests.server.component.grid; + +import java.util.Iterator; + +import com.vaadin.ui.LegacyGrid; +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.ui.Component; +import com.vaadin.ui.LegacyGrid.FooterCell; +import com.vaadin.ui.LegacyGrid.HeaderCell; +import com.vaadin.ui.Label; + +public class GridChildrenTest { + + @Test + public void componentsInMergedHeader() { + LegacyGrid grid = new LegacyGrid(); + grid.addColumn("foo"); + grid.addColumn("bar"); + grid.addColumn("baz"); + HeaderCell merged = grid.getDefaultHeaderRow().join("foo", "bar", + "baz"); + Label label = new Label(); + merged.setComponent(label); + Iterator<Component> i = grid.iterator(); + Assert.assertEquals(label, i.next()); + Assert.assertFalse(i.hasNext()); + } + + @Test + public void componentsInMergedFooter() { + LegacyGrid grid = new LegacyGrid(); + grid.addColumn("foo"); + grid.addColumn("bar"); + grid.addColumn("baz"); + FooterCell merged = grid.addFooterRowAt(0).join("foo", "bar", "baz"); + Label label = new Label(); + merged.setComponent(label); + Iterator<Component> i = grid.iterator(); + Assert.assertEquals(label, i.next()); + Assert.assertFalse(i.hasNext()); + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridColumnAddingAndRemovingTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridColumnAddingAndRemovingTest.java new file mode 100644 index 0000000000..1af2577fa3 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridColumnAddingAndRemovingTest.java @@ -0,0 +1,134 @@ +/* + * Copyright 2000-2016 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.tests.server.component.grid; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import com.vaadin.ui.LegacyGrid; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.Container; +import com.vaadin.data.Property; +import com.vaadin.data.util.IndexedContainer; + +public class GridColumnAddingAndRemovingTest { + + LegacyGrid grid = new LegacyGrid(); + Container.Indexed container; + + @Before + public void setUp() { + container = grid.getContainerDataSource(); + container.addItem(); + } + + @Test + public void testAddColumn() { + grid.addColumn("foo"); + + Property<?> property = container + .getContainerProperty(container.firstItemId(), "foo"); + assertEquals(property.getType(), String.class); + } + + @Test(expected = IllegalStateException.class) + public void testAddColumnTwice() { + grid.addColumn("foo"); + grid.addColumn("foo"); + } + + @Test + public void testAddRemoveAndAddAgainColumn() { + grid.addColumn("foo"); + grid.removeColumn("foo"); + + // Removing a column, doesn't remove the property + Property<?> property = container + .getContainerProperty(container.firstItemId(), "foo"); + assertEquals(property.getType(), String.class); + grid.addColumn("foo"); + } + + @Test + public void testAddNumberColumns() { + grid.addColumn("bar", Integer.class); + grid.addColumn("baz", Double.class); + + Property<?> property = container + .getContainerProperty(container.firstItemId(), "bar"); + assertEquals(property.getType(), Integer.class); + assertEquals(null, property.getValue()); + property = container.getContainerProperty(container.firstItemId(), + "baz"); + assertEquals(property.getType(), Double.class); + assertEquals(null, property.getValue()); + } + + @Test(expected = IllegalStateException.class) + public void testAddDifferentTypeColumn() { + grid.addColumn("foo"); + grid.removeColumn("foo"); + grid.addColumn("foo", Integer.class); + } + + @Test(expected = IllegalStateException.class) + public void testAddColumnToNonDefaultContainer() { + grid.setContainerDataSource(new IndexedContainer()); + grid.addColumn("foo"); + } + + @Test + public void testAddColumnForExistingProperty() { + grid.addColumn("bar"); + IndexedContainer container2 = new IndexedContainer(); + container2.addContainerProperty("foo", Integer.class, 0); + container2.addContainerProperty("bar", String.class, ""); + grid.setContainerDataSource(container2); + assertNull("Grid should not have a column for property foo", + grid.getColumn("foo")); + assertNotNull("Grid did should have a column for property bar", + grid.getColumn("bar")); + for (LegacyGrid.Column column : grid.getColumns()) { + assertNotNull("Grid getColumns returned a null value", column); + } + + grid.removeAllColumns(); + grid.addColumn("foo"); + assertNotNull("Grid should now have a column for property foo", + grid.getColumn("foo")); + assertNull("Grid should not have a column for property bar anymore", + grid.getColumn("bar")); + } + + @Test(expected = IllegalStateException.class) + public void testAddIncompatibleColumnProperty() { + grid.addColumn("bar"); + grid.removeAllColumns(); + grid.addColumn("bar", Integer.class); + } + + @Test + public void testAddBooleanColumnProperty() { + grid.addColumn("foo", Boolean.class); + Property<?> property = container + .getContainerProperty(container.firstItemId(), "foo"); + assertEquals(property.getType(), Boolean.class); + assertEquals(property.getValue(), null); + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridColumnsTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridColumnsTest.java new file mode 100644 index 0000000000..570e9b92fc --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridColumnsTest.java @@ -0,0 +1,413 @@ +/* + * Copyright 2000-2016 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.tests.server.component.grid; + +import static org.easymock.EasyMock.and; +import static org.easymock.EasyMock.capture; +import static org.easymock.EasyMock.isA; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.Set; + +import com.vaadin.ui.LegacyGrid; +import org.easymock.Capture; +import org.easymock.EasyMock; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.server.KeyMapper; +import com.vaadin.shared.ui.grid.GridColumnState; +import com.vaadin.shared.ui.grid.GridState; +import com.vaadin.shared.util.SharedUtil; +import com.vaadin.ui.LegacyGrid.Column; +import com.vaadin.ui.LegacyGrid.ColumnResizeEvent; +import com.vaadin.ui.LegacyGrid.ColumnResizeListener; +import com.vaadin.v7.ui.LegacyTextField; + +public class GridColumnsTest { + + private LegacyGrid grid; + + private GridState state; + + private Method getStateMethod; + + private Field columnIdGeneratorField; + + private KeyMapper<Object> columnIdMapper; + + @Before + @SuppressWarnings("unchecked") + public void setup() throws Exception { + IndexedContainer ds = new IndexedContainer(); + for (int c = 0; c < 10; c++) { + ds.addContainerProperty("column" + c, String.class, ""); + } + ds.addContainerProperty("noSort", Object.class, null); + grid = new LegacyGrid(ds); + + getStateMethod = LegacyGrid.class.getDeclaredMethod("getState"); + getStateMethod.setAccessible(true); + + state = (GridState) getStateMethod.invoke(grid); + + columnIdGeneratorField = LegacyGrid.class.getDeclaredField("columnKeys"); + columnIdGeneratorField.setAccessible(true); + + columnIdMapper = (KeyMapper<Object>) columnIdGeneratorField.get(grid); + } + + @Test + public void testColumnGeneration() throws Exception { + + for (Object propertyId : grid.getContainerDataSource() + .getContainerPropertyIds()) { + + // All property ids should get a column + Column column = grid.getColumn(propertyId); + assertNotNull(column); + + // Humanized property id should be the column header by default + assertEquals( + SharedUtil.camelCaseToHumanFriendly(propertyId.toString()), + grid.getDefaultHeaderRow().getCell(propertyId).getText()); + } + } + + @Test + public void testModifyingColumnProperties() throws Exception { + + // Modify first column + Column column = grid.getColumn("column1"); + assertNotNull(column); + + column.setHeaderCaption("CustomHeader"); + assertEquals("CustomHeader", column.getHeaderCaption()); + assertEquals(column.getHeaderCaption(), + grid.getDefaultHeaderRow().getCell("column1").getText()); + + column.setWidth(100); + assertEquals(100, column.getWidth(), 0.49d); + assertEquals(column.getWidth(), getColumnState("column1").width, 0.49d); + + try { + column.setWidth(-1); + fail("Setting width to -1 should throw exception"); + } catch (IllegalArgumentException iae) { + // expected + } + + assertEquals(100, column.getWidth(), 0.49d); + assertEquals(100, getColumnState("column1").width, 0.49d); + } + + @Test + public void testRemovingColumnByRemovingPropertyFromContainer() + throws Exception { + + Column column = grid.getColumn("column1"); + assertNotNull(column); + + // Remove column + grid.getContainerDataSource().removeContainerProperty("column1"); + + try { + column.setHeaderCaption("asd"); + + fail("Succeeded in modifying a detached column"); + } catch (IllegalStateException ise) { + // Detached state should throw exception + } + + try { + column.setWidth(123); + fail("Succeeded in modifying a detached column"); + } catch (IllegalStateException ise) { + // Detached state should throw exception + } + + assertNull(grid.getColumn("column1")); + assertNull(getColumnState("column1")); + } + + @Test + public void testAddingColumnByAddingPropertyToContainer() throws Exception { + grid.getContainerDataSource().addContainerProperty("columnX", + String.class, ""); + Column column = grid.getColumn("columnX"); + assertNotNull(column); + } + + @Test + public void testHeaderVisiblility() throws Exception { + + assertTrue(grid.isHeaderVisible()); + assertTrue(state.header.visible); + + grid.setHeaderVisible(false); + assertFalse(grid.isHeaderVisible()); + assertFalse(state.header.visible); + + grid.setHeaderVisible(true); + assertTrue(grid.isHeaderVisible()); + assertTrue(state.header.visible); + } + + @Test + public void testFooterVisibility() throws Exception { + + assertTrue(grid.isFooterVisible()); + assertTrue(state.footer.visible); + + grid.setFooterVisible(false); + assertFalse(grid.isFooterVisible()); + assertFalse(state.footer.visible); + + grid.setFooterVisible(true); + assertTrue(grid.isFooterVisible()); + assertTrue(state.footer.visible); + } + + @Test + public void testSetFrozenColumnCount() { + assertEquals("Grid should not start with a frozen column", 0, + grid.getFrozenColumnCount()); + grid.setFrozenColumnCount(2); + assertEquals("Freezing two columns should freeze two columns", 2, + grid.getFrozenColumnCount()); + } + + @Test + public void testSetFrozenColumnCountThroughColumn() { + assertEquals("Grid should not start with a frozen column", 0, + grid.getFrozenColumnCount()); + grid.getColumns().get(2).setLastFrozenColumn(); + assertEquals( + "Setting the third column as last frozen should freeze three columns", + 3, grid.getFrozenColumnCount()); + } + + @Test + public void testFrozenColumnRemoveColumn() { + assertEquals("Grid should not start with a frozen column", 0, + grid.getFrozenColumnCount()); + + int containerSize = grid.getContainerDataSource() + .getContainerPropertyIds().size(); + grid.setFrozenColumnCount(containerSize); + + Object propertyId = grid.getContainerDataSource() + .getContainerPropertyIds().iterator().next(); + + grid.getContainerDataSource().removeContainerProperty(propertyId); + assertEquals("Frozen column count should update when removing last row", + containerSize - 1, grid.getFrozenColumnCount()); + } + + @Test + public void testReorderColumns() { + Set<?> containerProperties = new LinkedHashSet<Object>( + grid.getContainerDataSource().getContainerPropertyIds()); + Object[] properties = new Object[] { "column3", "column2", "column6" }; + grid.setColumnOrder(properties); + + int i = 0; + // Test sorted columns are first in order + for (Object property : properties) { + containerProperties.remove(property); + assertEquals(columnIdMapper.key(property), + state.columnOrder.get(i++)); + } + + // Test remaining columns are in original order + for (Object property : containerProperties) { + assertEquals(columnIdMapper.key(property), + state.columnOrder.get(i++)); + } + + try { + grid.setColumnOrder("foo", "bar", "baz"); + fail("Grid allowed sorting with non-existent properties"); + } catch (IllegalArgumentException e) { + // All ok + } + } + + @Test(expected = IllegalArgumentException.class) + public void testRemoveColumnThatDoesNotExist() { + grid.removeColumn("banana phone"); + } + + @Test(expected = IllegalStateException.class) + public void testSetNonSortableColumnSortable() { + Column noSortColumn = grid.getColumn("noSort"); + assertFalse("Object property column should not be sortable.", + noSortColumn.isSortable()); + noSortColumn.setSortable(true); + } + + @Test + public void testColumnsEditableByDefault() { + for (Column c : grid.getColumns()) { + assertTrue(c + " should be editable", c.isEditable()); + } + } + + @Test + public void testPropertyAndColumnEditorFieldsMatch() { + Column column1 = grid.getColumn("column1"); + column1.setEditorField(new LegacyTextField()); + assertSame(column1.getEditorField(), + grid.getColumn("column1").getEditorField()); + + Column column2 = grid.getColumn("column2"); + column2.setEditorField(new LegacyTextField()); + assertSame(column2.getEditorField(), column2.getEditorField()); + } + + @Test + public void testUneditableColumnHasNoField() { + Column col = grid.getColumn("column1"); + + col.setEditable(false); + + assertFalse("Column should be uneditable", col.isEditable()); + assertNull("Uneditable column should not be auto-assigned a Field", + col.getEditorField()); + } + + private GridColumnState getColumnState(Object propertyId) { + String columnId = columnIdMapper.key(propertyId); + for (GridColumnState columnState : state.columns) { + if (columnState.id.equals(columnId)) { + return columnState; + } + } + return null; + } + + @Test + public void testAddAndRemoveSortableColumn() { + boolean sortable = grid.getColumn("column1").isSortable(); + grid.removeColumn("column1"); + grid.addColumn("column1"); + assertEquals("Column sortability changed when re-adding", sortable, + grid.getColumn("column1").isSortable()); + } + + @Test + public void testSetColumns() { + grid.setColumns("column7", "column0", "column9"); + Iterator<Column> it = grid.getColumns().iterator(); + assertEquals(it.next().getPropertyId(), "column7"); + assertEquals(it.next().getPropertyId(), "column0"); + assertEquals(it.next().getPropertyId(), "column9"); + assertFalse(it.hasNext()); + } + + @Test + public void testAddingColumnsWithSetColumns() { + LegacyGrid g = new LegacyGrid(); + g.setColumns("c1", "c2", "c3"); + Iterator<Column> it = g.getColumns().iterator(); + assertEquals(it.next().getPropertyId(), "c1"); + assertEquals(it.next().getPropertyId(), "c2"); + assertEquals(it.next().getPropertyId(), "c3"); + assertFalse(it.hasNext()); + } + + @Test(expected = IllegalStateException.class) + public void testAddingColumnsWithSetColumnsNonDefaultContainer() { + grid.setColumns("column1", "column2", "column50"); + } + + @Test + public void testDefaultColumnHidingToggleCaption() { + Column firstColumn = grid.getColumns().get(0); + firstColumn.setHeaderCaption("headerCaption"); + assertEquals(null, firstColumn.getHidingToggleCaption()); + } + + @Test + public void testOverriddenColumnHidingToggleCaption() { + Column firstColumn = grid.getColumns().get(0); + firstColumn.setHidingToggleCaption("hidingToggleCaption"); + firstColumn.setHeaderCaption("headerCaption"); + assertEquals("hidingToggleCaption", + firstColumn.getHidingToggleCaption()); + } + + @Test + public void testColumnSetWidthFiresResizeEvent() { + final Column firstColumn = grid.getColumns().get(0); + + // prepare a listener mock that captures the argument + ColumnResizeListener mock = EasyMock + .createMock(ColumnResizeListener.class); + Capture<ColumnResizeEvent> capturedEvent = new Capture<ColumnResizeEvent>(); + mock.columnResize( + and(capture(capturedEvent), isA(ColumnResizeEvent.class))); + EasyMock.expectLastCall().once(); + + // Tell it to wait for the call + EasyMock.replay(mock); + + // Cause a resize event + grid.addColumnResizeListener(mock); + firstColumn.setWidth(firstColumn.getWidth() + 10); + + // Verify the method was called + EasyMock.verify(mock); + + // Asserts on the captured event + ColumnResizeEvent event = capturedEvent.getValue(); + assertEquals("Event column was not first column.", firstColumn, + event.getColumn()); + assertFalse("Event should not be userOriginated", + event.isUserOriginated()); + } + + @Test + public void textHeaderCaptionIsReturned() { + Column firstColumn = grid.getColumns().get(0); + + firstColumn.setHeaderCaption("text"); + + assertThat(firstColumn.getHeaderCaption(), is("text")); + } + + @Test + public void defaultCaptionIsReturnedForHtml() { + Column firstColumn = grid.getColumns().get(0); + + grid.getDefaultHeaderRow().getCell("column0").setHtml("<b>html</b>"); + + assertThat(firstColumn.getHeaderCaption(), is("Column0")); + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridContainerNotSortableTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridContainerNotSortableTest.java new file mode 100644 index 0000000000..fa6c57df93 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridContainerNotSortableTest.java @@ -0,0 +1,103 @@ +/* + * Copyright 2000-2016 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.tests.server.component.grid; + +import static org.junit.Assert.assertFalse; + +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.Map; + +import com.vaadin.ui.LegacyGrid; +import org.junit.Test; + +import com.vaadin.data.Item; +import com.vaadin.data.Property; +import com.vaadin.data.util.AbstractInMemoryContainer; +import com.vaadin.ui.LegacyGrid.Column; + +public class GridContainerNotSortableTest { + + final AbstractInMemoryContainer<Object, Object, Item> notSortableDataSource = new AbstractInMemoryContainer<Object, Object, Item>() { + + private Map<Object, Property<?>> properties = new LinkedHashMap<Object, Property<?>>(); + + { + properties.put("Foo", new Property<String>() { + + @Override + public String getValue() { + return "foo"; + } + + @Override + public void setValue(String newValue) throws ReadOnlyException { + throw new ReadOnlyException(); + } + + @Override + public Class<? extends String> getType() { + return String.class; + } + + @Override + public boolean isReadOnly() { + return true; + } + + @Override + public void setReadOnly(boolean newStatus) { + throw new UnsupportedOperationException(); + } + }); + } + + @Override + public Collection<?> getContainerPropertyIds() { + return properties.keySet(); + } + + @Override + public Property getContainerProperty(Object itemId, Object propertyId) { + return properties.get(propertyId); + } + + @Override + public Class<?> getType(Object propertyId) { + return properties.get(propertyId).getType(); + } + + @Override + protected Item getUnfilteredItem(Object itemId) { + return null; + } + }; + + @Test + public void testGridWithNotSortableContainer() { + new LegacyGrid(notSortableDataSource); + } + + @Test(expected = IllegalStateException.class) + public void testNotSortableGridSetColumnSortable() { + LegacyGrid grid = new LegacyGrid(); + grid.setContainerDataSource(notSortableDataSource); + Column column = grid.getColumn("Foo"); + assertFalse("Column should not be sortable initially.", + column.isSortable()); + column.setSortable(true); + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridContainerTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridContainerTest.java new file mode 100644 index 0000000000..7b07aefcb2 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridContainerTest.java @@ -0,0 +1,159 @@ +/* + * Copyright 2000-2016 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.tests.server.component.grid; + +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.io.OutputStream; + +import com.vaadin.ui.LegacyGrid; +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.ui.Component; +import com.vaadin.ui.LegacyGrid.DetailsGenerator; +import com.vaadin.ui.LegacyGrid.RowReference; +import com.vaadin.ui.Label; + +public class GridContainerTest { + + /** + * Null Stream used with serialization tests + */ + protected static OutputStream NULLSTREAM = new OutputStream() { + @Override + public void write(int b) { + } + }; + + @Test + public void testDetailsGeneratorDoesNotResetOnContainerChange() { + LegacyGrid grid = new LegacyGrid(); + DetailsGenerator detGen = new DetailsGenerator() { + + @Override + public Component getDetails(RowReference rowReference) { + return new Label("Empty details"); + } + }; + grid.setDetailsGenerator(detGen); + + grid.setContainerDataSource(createContainer()); + + Assert.assertEquals("DetailsGenerator changed", detGen, + grid.getDetailsGenerator()); + } + + @Test + public void testSetContainerTwice() throws Exception { + + TestGrid grid = new TestGrid(); + + grid.setContainerDataSource(createContainer()); + + // Simulate initial response to ensure "lazy" state changes are done + // before resetting the datasource + grid.beforeClientResponse(true); + grid.getDataProvider().beforeClientResponse(true); + + grid.setContainerDataSource(createContainer()); + } + + @SuppressWarnings("unchecked") + private IndexedContainer createContainer() { + IndexedContainer container = new IndexedContainer(); + container.addContainerProperty("x", String.class, null); + container.addItem(0).getItemProperty("x").setValue("y"); + return container; + } + + @Test + public void setColumnsOrder() { + LegacyGrid grid = new LegacyGrid(); + IndexedContainer ic = new IndexedContainer(); + ic.addContainerProperty("foo", String.class, ""); + ic.addContainerProperty("baz", String.class, ""); + ic.addContainerProperty("bar", String.class, ""); + grid.setContainerDataSource(ic); + grid.setColumns("foo", "baz", "bar"); + + Assert.assertEquals("foo", grid.getColumns().get(0).getPropertyId()); + Assert.assertEquals("baz", grid.getColumns().get(1).getPropertyId()); + Assert.assertEquals("bar", grid.getColumns().get(2).getPropertyId()); + } + + @Test + public void addColumnNotInContainer() { + LegacyGrid grid = new LegacyGrid(); + grid.setContainerDataSource(new IndexedContainer()); + try { + grid.addColumn("notInContainer"); + Assert.fail( + "Adding a property id not in the container should throw an exception"); + } catch (IllegalStateException e) { + Assert.assertTrue(e.getMessage().contains("notInContainer")); + Assert.assertTrue( + e.getMessage().contains("does not exist in the container")); + } + } + + @Test + public void setColumnsForPropertyIdNotInContainer() { + LegacyGrid grid = new LegacyGrid(); + grid.setContainerDataSource(new IndexedContainer()); + try { + grid.setColumns("notInContainer", "notThereEither"); + Assert.fail( + "Setting columns for property ids not in the container should throw an exception"); + } catch (IllegalStateException e) { + // addColumn is run in random order.. + Assert.assertTrue(e.getMessage().contains("notInContainer") + || e.getMessage().contains("notThereEither")); + Assert.assertTrue( + e.getMessage().contains("does not exist in the container")); + } + } + + @Test(expected = IllegalStateException.class) + public void multipleAddColumnsForDefaultContainer() { + LegacyGrid grid = new LegacyGrid(); + grid.addColumn("foo"); + grid.addColumn("foo"); + } + + @Test + public void testSerializeRpcDataProviderWithRowChanges() + throws IOException { + LegacyGrid grid = new LegacyGrid(); + IndexedContainer container = new IndexedContainer(); + grid.setContainerDataSource(container); + container.addItem(); + serializeComponent(grid); + } + + protected void serializeComponent(Component component) throws IOException { + ObjectOutputStream stream = null; + try { + stream = new ObjectOutputStream(NULLSTREAM); + stream.writeObject(component); + } finally { + if (stream != null) { + stream.close(); + } + } + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridEditorTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridEditorTest.java new file mode 100644 index 0000000000..15daa264d9 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridEditorTest.java @@ -0,0 +1,296 @@ +/* + * Copyright 2000-2016 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.tests.server.component.grid; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +import java.lang.reflect.Method; + +import com.vaadin.ui.LegacyGrid; +import com.vaadin.v7.ui.LegacyField; +import com.vaadin.v7.ui.LegacyTextField; + +import org.easymock.EasyMock; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.Item; +import com.vaadin.data.Property; +import com.vaadin.data.fieldgroup.FieldGroup; +import com.vaadin.data.fieldgroup.FieldGroup.CommitException; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.server.MockVaadinSession; +import com.vaadin.server.VaadinService; +import com.vaadin.server.VaadinSession; + +public class GridEditorTest { + + private static final Object PROPERTY_NAME = "name"; + private static final Object PROPERTY_AGE = "age"; + private static final String DEFAULT_NAME = "Some Valid Name"; + private static final Integer DEFAULT_AGE = 25; + private static final Object ITEM_ID = new Object(); + + // Explicit field for the test session to save it from GC + private VaadinSession session; + + private final LegacyGrid grid = new LegacyGrid(); + private Method doEditMethod; + + @Before + @SuppressWarnings("unchecked") + public void setup() throws SecurityException, NoSuchMethodException { + IndexedContainer container = new IndexedContainer(); + container.addContainerProperty(PROPERTY_NAME, String.class, "[name]"); + container.addContainerProperty(PROPERTY_AGE, Integer.class, + Integer.valueOf(-1)); + + Item item = container.addItem(ITEM_ID); + item.getItemProperty(PROPERTY_NAME).setValue(DEFAULT_NAME); + item.getItemProperty(PROPERTY_AGE).setValue(DEFAULT_AGE); + grid.setContainerDataSource(container); + + // VaadinSession needed for ConverterFactory + VaadinService mockService = EasyMock + .createNiceMock(VaadinService.class); + session = new MockVaadinSession(mockService); + VaadinSession.setCurrent(session); + session.lock(); + + // Access to method for actual editing. + doEditMethod = LegacyGrid.class.getDeclaredMethod("doEditItem"); + doEditMethod.setAccessible(true); + } + + @After + public void tearDown() { + session.unlock(); + session = null; + VaadinSession.setCurrent(null); + } + + @Test + public void testInitAssumptions() throws Exception { + assertFalse(grid.isEditorEnabled()); + assertNull(grid.getEditedItemId()); + assertNotNull(grid.getEditorFieldGroup()); + } + + @Test + public void testSetEnabled() throws Exception { + assertFalse(grid.isEditorEnabled()); + grid.setEditorEnabled(true); + assertTrue(grid.isEditorEnabled()); + } + + @Test + public void testSetDisabled() throws Exception { + assertFalse(grid.isEditorEnabled()); + grid.setEditorEnabled(true); + grid.setEditorEnabled(false); + assertFalse(grid.isEditorEnabled()); + } + + @Test + public void testSetReEnabled() throws Exception { + assertFalse(grid.isEditorEnabled()); + grid.setEditorEnabled(true); + grid.setEditorEnabled(false); + grid.setEditorEnabled(true); + assertTrue(grid.isEditorEnabled()); + } + + @Test + public void testDetached() throws Exception { + FieldGroup oldFieldGroup = grid.getEditorFieldGroup(); + grid.removeAllColumns(); + grid.setContainerDataSource(new IndexedContainer()); + assertFalse(oldFieldGroup == grid.getEditorFieldGroup()); + } + + @Test(expected = IllegalStateException.class) + public void testDisabledEditItem() throws Exception { + grid.editItem(ITEM_ID); + } + + @Test + public void testEditItem() throws Exception { + startEdit(); + assertEquals(ITEM_ID, grid.getEditedItemId()); + assertEquals(getEditedItem(), + grid.getEditorFieldGroup().getItemDataSource()); + + assertEquals(DEFAULT_NAME, + grid.getColumn(PROPERTY_NAME).getEditorField().getValue()); + assertEquals(String.valueOf(DEFAULT_AGE), + grid.getColumn(PROPERTY_AGE).getEditorField().getValue()); + } + + @Test + public void testSaveEditor() throws Exception { + startEdit(); + LegacyTextField field = (LegacyTextField) grid.getColumn(PROPERTY_NAME) + .getEditorField(); + + field.setValue("New Name"); + assertEquals(DEFAULT_NAME, field.getPropertyDataSource().getValue()); + + grid.saveEditor(); + assertTrue(grid.isEditorActive()); + assertFalse(field.isModified()); + assertEquals("New Name", field.getValue()); + assertEquals("New Name", getEditedProperty(PROPERTY_NAME).getValue()); + } + + @Test + public void testSaveEditorCommitFail() throws Exception { + startEdit(); + + ((LegacyTextField) grid.getColumn(PROPERTY_AGE).getEditorField()) + .setValue("Invalid"); + try { + // Manual fail instead of @Test(expected=...) to check it is + // saveEditor that fails and not setValue + grid.saveEditor(); + Assert.fail( + "CommitException expected when saving an invalid field value"); + } catch (CommitException e) { + // expected + } + } + + @Test + public void testCancelEditor() throws Exception { + startEdit(); + LegacyTextField field = (LegacyTextField) grid.getColumn(PROPERTY_NAME) + .getEditorField(); + field.setValue("New Name"); + + Property<?> datasource = field.getPropertyDataSource(); + + grid.cancelEditor(); + assertFalse(grid.isEditorActive()); + assertNull(grid.getEditedItemId()); + assertFalse(field.isModified()); + assertEquals("", field.getValue()); + assertEquals(DEFAULT_NAME, datasource.getValue()); + assertNull(field.getPropertyDataSource()); + assertNull(grid.getEditorFieldGroup().getItemDataSource()); + } + + @Test(expected = IllegalArgumentException.class) + public void testNonexistentEditItem() throws Exception { + grid.setEditorEnabled(true); + grid.editItem(new Object()); + } + + @Test + public void testGetField() throws Exception { + startEdit(); + + assertNotNull(grid.getColumn(PROPERTY_NAME).getEditorField()); + } + + @Test + public void testGetFieldWithoutItem() throws Exception { + grid.setEditorEnabled(true); + assertNotNull(grid.getColumn(PROPERTY_NAME).getEditorField()); + } + + @Test + public void testCustomBinding() { + LegacyTextField textField = new LegacyTextField(); + grid.getColumn(PROPERTY_NAME).setEditorField(textField); + + startEdit(); + + assertSame(textField, grid.getColumn(PROPERTY_NAME).getEditorField()); + } + + @Test(expected = IllegalStateException.class) + public void testDisableWhileEditing() { + startEdit(); + grid.setEditorEnabled(false); + } + + @Test + public void testFieldIsNotReadonly() { + startEdit(); + + LegacyField<?> field = grid.getColumn(PROPERTY_NAME).getEditorField(); + assertFalse(field.isReadOnly()); + } + + @Test + public void testFieldIsReadonlyWhenFieldGroupIsReadonly() { + startEdit(); + + grid.getEditorFieldGroup().setReadOnly(true); + LegacyField<?> field = grid.getColumn(PROPERTY_NAME).getEditorField(); + assertTrue(field.isReadOnly()); + } + + @Test + public void testColumnRemoved() { + LegacyField<?> field = grid.getColumn(PROPERTY_NAME).getEditorField(); + + assertSame("field should be attached to ", grid, field.getParent()); + + grid.removeColumn(PROPERTY_NAME); + + assertNull("field should be detached from ", field.getParent()); + } + + @Test + public void testSetFieldAgain() { + LegacyTextField field = new LegacyTextField(); + grid.getColumn(PROPERTY_NAME).setEditorField(field); + + field = new LegacyTextField(); + grid.getColumn(PROPERTY_NAME).setEditorField(field); + + assertSame("new field should be used.", field, + grid.getColumn(PROPERTY_NAME).getEditorField()); + } + + private void startEdit() { + grid.setEditorEnabled(true); + grid.editItem(ITEM_ID); + // Simulate succesful client response to actually start the editing. + try { + doEditMethod.invoke(grid); + } catch (Exception e) { + Assert.fail("Editing item " + ITEM_ID + " failed. Cause: " + + e.getCause().toString()); + } + } + + private Item getEditedItem() { + assertNotNull(grid.getEditedItemId()); + return grid.getContainerDataSource().getItem(grid.getEditedItemId()); + } + + private Property<?> getEditedProperty(Object propertyId) { + return getEditedItem().getItemProperty(PROPERTY_NAME); + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridExtensionTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridExtensionTest.java new file mode 100644 index 0000000000..452d2713a4 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridExtensionTest.java @@ -0,0 +1,41 @@ +/* + * Copyright 2000-2016 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.tests.server.component.grid; + +import static org.junit.Assert.assertTrue; + +import com.vaadin.ui.LegacyGrid; +import org.junit.Test; + +import com.vaadin.ui.LegacyGrid.AbstractGridExtension; + +public class GridExtensionTest { + + public static class DummyGridExtension extends AbstractGridExtension { + + public DummyGridExtension(LegacyGrid grid) { + super(grid); + } + } + + @Test + public void testCreateExtension() { + LegacyGrid grid = new LegacyGrid(); + DummyGridExtension dummy = new DummyGridExtension(grid); + assertTrue("DummyGridExtension never made it to Grid", + grid.getExtensions().contains(dummy)); + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridSelectionTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridSelectionTest.java new file mode 100644 index 0000000000..7e910d2428 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridSelectionTest.java @@ -0,0 +1,377 @@ +/* + * Copyright 2000-2013 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.tests.server.component.grid; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.Collection; + +import com.vaadin.ui.LegacyGrid; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.event.SelectionEvent; +import com.vaadin.event.SelectionEvent.SelectionListener; +import com.vaadin.ui.LegacyGrid.SelectionMode; +import com.vaadin.ui.LegacyGrid.SelectionModel; + +public class GridSelectionTest { + + private static class MockSelectionChangeListener + implements SelectionListener { + private SelectionEvent event; + + @Override + public void select(final SelectionEvent event) { + this.event = event; + } + + public Collection<?> getAdded() { + return event.getAdded(); + } + + public Collection<?> getRemoved() { + return event.getRemoved(); + } + + public void clearEvent() { + /* + * This method is not strictly needed as the event will simply be + * overridden, but it's good practice, and makes the code more + * obvious. + */ + event = null; + } + + public boolean eventHasHappened() { + return event != null; + } + } + + private LegacyGrid grid; + private MockSelectionChangeListener mockListener; + + private final Object itemId1Present = "itemId1Present"; + private final Object itemId2Present = "itemId2Present"; + + private final Object itemId1NotPresent = "itemId1NotPresent"; + private final Object itemId2NotPresent = "itemId2NotPresent"; + + @Before + public void setup() { + final IndexedContainer container = new IndexedContainer(); + container.addItem(itemId1Present); + container.addItem(itemId2Present); + for (int i = 2; i < 10; i++) { + container.addItem(new Object()); + } + + assertEquals("init size", 10, container.size()); + assertTrue("itemId1Present", container.containsId(itemId1Present)); + assertTrue("itemId2Present", container.containsId(itemId2Present)); + assertFalse("itemId1NotPresent", + container.containsId(itemId1NotPresent)); + assertFalse("itemId2NotPresent", + container.containsId(itemId2NotPresent)); + + grid = new LegacyGrid(container); + + mockListener = new MockSelectionChangeListener(); + grid.addSelectionListener(mockListener); + + assertFalse("eventHasHappened", mockListener.eventHasHappened()); + } + + @Test + public void defaultSelectionModeIsSingle() { + assertTrue(grid.getSelectionModel() instanceof SelectionModel.Single); + } + + @Test(expected = IllegalStateException.class) + public void getSelectedRowThrowsExceptionMulti() { + grid.setSelectionMode(SelectionMode.MULTI); + grid.getSelectedRow(); + } + + @Test(expected = IllegalStateException.class) + public void getSelectedRowThrowsExceptionNone() { + grid.setSelectionMode(SelectionMode.NONE); + grid.getSelectedRow(); + } + + @Test(expected = IllegalStateException.class) + public void selectThrowsExceptionNone() { + grid.setSelectionMode(SelectionMode.NONE); + grid.select(itemId1Present); + } + + @Test(expected = IllegalStateException.class) + public void deselectRowThrowsExceptionNone() { + grid.setSelectionMode(SelectionMode.NONE); + grid.deselect(itemId1Present); + } + + @Test + public void selectionModeMapsToMulti() { + assertTrue(grid.setSelectionMode( + SelectionMode.MULTI) instanceof SelectionModel.Multi); + } + + @Test + public void selectionModeMapsToSingle() { + assertTrue(grid.setSelectionMode( + SelectionMode.SINGLE) instanceof SelectionModel.Single); + } + + @Test + public void selectionModeMapsToNone() { + assertTrue(grid.setSelectionMode( + SelectionMode.NONE) instanceof SelectionModel.None); + } + + @Test(expected = IllegalArgumentException.class) + public void selectionModeNullThrowsException() { + grid.setSelectionMode(null); + } + + @Test + public void noSelectModel_isSelected() { + grid.setSelectionMode(SelectionMode.NONE); + assertFalse("itemId1Present", grid.isSelected(itemId1Present)); + assertFalse("itemId1NotPresent", grid.isSelected(itemId1NotPresent)); + } + + @Test(expected = IllegalStateException.class) + public void noSelectModel_getSelectedRow() { + grid.setSelectionMode(SelectionMode.NONE); + grid.getSelectedRow(); + } + + @Test + public void noSelectModel_getSelectedRows() { + grid.setSelectionMode(SelectionMode.NONE); + assertTrue(grid.getSelectedRows().isEmpty()); + } + + @Test + public void selectionCallsListenerMulti() { + grid.setSelectionMode(SelectionMode.MULTI); + selectionCallsListener(); + } + + @Test + public void selectionCallsListenerSingle() { + grid.setSelectionMode(SelectionMode.SINGLE); + selectionCallsListener(); + } + + private void selectionCallsListener() { + grid.select(itemId1Present); + assertEquals("added size", 1, mockListener.getAdded().size()); + assertEquals("added item", itemId1Present, + mockListener.getAdded().iterator().next()); + assertEquals("removed size", 0, mockListener.getRemoved().size()); + } + + @Test + public void deselectionCallsListenerMulti() { + grid.setSelectionMode(SelectionMode.MULTI); + deselectionCallsListener(); + } + + @Test + public void deselectionCallsListenerSingle() { + grid.setSelectionMode(SelectionMode.SINGLE); + deselectionCallsListener(); + } + + private void deselectionCallsListener() { + grid.select(itemId1Present); + mockListener.clearEvent(); + + grid.deselect(itemId1Present); + assertEquals("removed size", 1, mockListener.getRemoved().size()); + assertEquals("removed item", itemId1Present, + mockListener.getRemoved().iterator().next()); + assertEquals("removed size", 0, mockListener.getAdded().size()); + } + + @Test + public void deselectPresentButNotSelectedItemIdShouldntFireListenerMulti() { + grid.setSelectionMode(SelectionMode.MULTI); + deselectPresentButNotSelectedItemIdShouldntFireListener(); + } + + @Test + public void deselectPresentButNotSelectedItemIdShouldntFireListenerSingle() { + grid.setSelectionMode(SelectionMode.SINGLE); + deselectPresentButNotSelectedItemIdShouldntFireListener(); + } + + private void deselectPresentButNotSelectedItemIdShouldntFireListener() { + grid.deselect(itemId1Present); + assertFalse(mockListener.eventHasHappened()); + } + + @Test + public void deselectNotPresentItemIdShouldNotThrowExceptionMulti() { + grid.setSelectionMode(SelectionMode.MULTI); + grid.deselect(itemId1NotPresent); + } + + @Test + public void deselectNotPresentItemIdShouldNotThrowExceptionSingle() { + grid.setSelectionMode(SelectionMode.SINGLE); + grid.deselect(itemId1NotPresent); + } + + @Test(expected = IllegalArgumentException.class) + public void selectNotPresentItemIdShouldThrowExceptionMulti() { + grid.setSelectionMode(SelectionMode.MULTI); + grid.select(itemId1NotPresent); + } + + @Test(expected = IllegalArgumentException.class) + public void selectNotPresentItemIdShouldThrowExceptionSingle() { + grid.setSelectionMode(SelectionMode.SINGLE); + grid.select(itemId1NotPresent); + } + + @Test + public void selectAllMulti() { + grid.setSelectionMode(SelectionMode.MULTI); + final SelectionModel.Multi select = (SelectionModel.Multi) grid + .getSelectionModel(); + select.selectAll(); + assertEquals("added size", 10, mockListener.getAdded().size()); + assertEquals("removed size", 0, mockListener.getRemoved().size()); + assertTrue("itemId1Present", + mockListener.getAdded().contains(itemId1Present)); + assertTrue("itemId2Present", + mockListener.getAdded().contains(itemId2Present)); + } + + @Test + public void deselectAllMulti() { + grid.setSelectionMode(SelectionMode.MULTI); + final SelectionModel.Multi select = (SelectionModel.Multi) grid + .getSelectionModel(); + select.selectAll(); + mockListener.clearEvent(); + + select.deselectAll(); + assertEquals("removed size", 10, mockListener.getRemoved().size()); + assertEquals("added size", 0, mockListener.getAdded().size()); + assertTrue("itemId1Present", + mockListener.getRemoved().contains(itemId1Present)); + assertTrue("itemId2Present", + mockListener.getRemoved().contains(itemId2Present)); + assertTrue("selectedRows is empty", grid.getSelectedRows().isEmpty()); + } + + @Test + public void gridDeselectAllMultiAllSelected() { + grid.setSelectionMode(SelectionMode.MULTI); + final SelectionModel.Multi select = (SelectionModel.Multi) grid + .getSelectionModel(); + select.selectAll(); + mockListener.clearEvent(); + + assertTrue(grid.deselectAll()); + assertEquals("removed size", 10, mockListener.getRemoved().size()); + assertEquals("added size", 0, mockListener.getAdded().size()); + assertTrue("itemId1Present", + mockListener.getRemoved().contains(itemId1Present)); + assertTrue("itemId2Present", + mockListener.getRemoved().contains(itemId2Present)); + assertTrue("selectedRows is empty", grid.getSelectedRows().isEmpty()); + + } + + @Test + public void gridDeselectAllMultiOneSelected() { + grid.setSelectionMode(SelectionMode.MULTI); + final SelectionModel.Multi select = (SelectionModel.Multi) grid + .getSelectionModel(); + select.select(itemId2Present); + mockListener.clearEvent(); + + assertTrue(grid.deselectAll()); + assertEquals("removed size", 1, mockListener.getRemoved().size()); + assertEquals("added size", 0, mockListener.getAdded().size()); + assertFalse("itemId1Present", + mockListener.getRemoved().contains(itemId1Present)); + assertTrue("itemId2Present", + mockListener.getRemoved().contains(itemId2Present)); + assertTrue("selectedRows is empty", grid.getSelectedRows().isEmpty()); + + } + + @Test + public void gridDeselectAllSingleNoneSelected() { + grid.setSelectionMode(SelectionMode.SINGLE); + assertFalse(grid.deselectAll()); + assertTrue("selectedRows is empty", grid.getSelectedRows().isEmpty()); + } + + @Test + public void gridDeselectAllSingleOneSelected() { + grid.setSelectionMode(SelectionMode.SINGLE); + final SelectionModel.Single select = (SelectionModel.Single) grid + .getSelectionModel(); + select.select(itemId2Present); + mockListener.clearEvent(); + + assertTrue(grid.deselectAll()); + assertEquals("removed size", 1, mockListener.getRemoved().size()); + assertEquals("added size", 0, mockListener.getAdded().size()); + assertFalse("itemId1Present", + mockListener.getRemoved().contains(itemId1Present)); + assertTrue("itemId2Present", + mockListener.getRemoved().contains(itemId2Present)); + assertTrue("selectedRows is empty", grid.getSelectedRows().isEmpty()); + + } + + @Test + public void gridDeselectAllMultiNoneSelected() { + grid.setSelectionMode(SelectionMode.MULTI); + + assertFalse(grid.deselectAll()); + assertTrue("selectedRows is empty", grid.getSelectedRows().isEmpty()); + + } + + @Test + public void reselectionDeselectsPreviousSingle() { + grid.setSelectionMode(SelectionMode.SINGLE); + grid.select(itemId1Present); + mockListener.clearEvent(); + + grid.select(itemId2Present); + assertEquals("added size", 1, mockListener.getAdded().size()); + assertEquals("removed size", 1, mockListener.getRemoved().size()); + assertEquals("added item", itemId2Present, + mockListener.getAdded().iterator().next()); + assertEquals("removed item", itemId1Present, + mockListener.getRemoved().iterator().next()); + assertEquals("selectedRows is correct", itemId2Present, + grid.getSelectedRow()); + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridStateTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridStateTest.java new file mode 100644 index 0000000000..9f5f67d8be --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridStateTest.java @@ -0,0 +1,44 @@ +/* + * Copyright 2000-2016 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.tests.server.component.grid; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.shared.ui.grid.GridState; +import com.vaadin.ui.LegacyGrid; + +/** + * Tests for Grid State. + * + */ +public class GridStateTest { + + @Test + public void getPrimaryStyleName_gridHasCustomPrimaryStyleName() { + LegacyGrid grid = new LegacyGrid(); + GridState state = new GridState(); + Assert.assertEquals("Unexpected primary style name", + state.primaryStyleName, grid.getPrimaryStyleName()); + } + + @Test + public void gridStateHasCustomPrimaryStyleName() { + GridState state = new GridState(); + Assert.assertEquals("Unexpected primary style name", "v-grid", + state.primaryStyleName); + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridStaticSectionTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridStaticSectionTest.java new file mode 100644 index 0000000000..7a8209d50b --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/GridStaticSectionTest.java @@ -0,0 +1,132 @@ +/* + * Copyright 2000-2016 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.tests.server.component.grid; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.lang.reflect.Method; + +import com.vaadin.ui.LegacyGrid; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.Container.Indexed; +import com.vaadin.data.util.IndexedContainer; + +public class GridStaticSectionTest extends LegacyGrid { + + private Indexed dataSource = new IndexedContainer(); + + @Before + public void setUp() { + dataSource.addContainerProperty("firstName", String.class, ""); + dataSource.addContainerProperty("lastName", String.class, ""); + dataSource.addContainerProperty("streetAddress", String.class, ""); + dataSource.addContainerProperty("zipCode", Integer.class, null); + setContainerDataSource(dataSource); + } + + @Test + public void testAddAndRemoveHeaders() { + assertEquals(1, getHeaderRowCount()); + prependHeaderRow(); + assertEquals(2, getHeaderRowCount()); + removeHeaderRow(0); + assertEquals(1, getHeaderRowCount()); + removeHeaderRow(0); + assertEquals(0, getHeaderRowCount()); + assertEquals(null, getDefaultHeaderRow()); + HeaderRow row = appendHeaderRow(); + assertEquals(1, getHeaderRowCount()); + assertEquals(null, getDefaultHeaderRow()); + setDefaultHeaderRow(row); + assertEquals(row, getDefaultHeaderRow()); + } + + @Test + public void testAddAndRemoveFooters() { + // By default there are no footer rows + assertEquals(0, getFooterRowCount()); + FooterRow row = appendFooterRow(); + + assertEquals(1, getFooterRowCount()); + prependFooterRow(); + assertEquals(2, getFooterRowCount()); + assertEquals(row, getFooterRow(1)); + removeFooterRow(0); + assertEquals(1, getFooterRowCount()); + removeFooterRow(0); + assertEquals(0, getFooterRowCount()); + } + + @Test + public void testUnusedPropertyNotInCells() { + removeColumn("firstName"); + assertNull("firstName cell was not removed from existing row", + getDefaultHeaderRow().getCell("firstName")); + HeaderRow newRow = appendHeaderRow(); + assertNull("firstName cell was created when it should not.", + newRow.getCell("firstName")); + addColumn("firstName"); + assertNotNull( + "firstName cell was not created for default row when added again", + getDefaultHeaderRow().getCell("firstName")); + assertNotNull( + "firstName cell was not created for new row when added again", + newRow.getCell("firstName")); + + } + + @Test + public void testJoinHeaderCells() { + HeaderRow mergeRow = prependHeaderRow(); + mergeRow.join("firstName", "lastName").setText("Name"); + mergeRow.join(mergeRow.getCell("streetAddress"), + mergeRow.getCell("zipCode")); + } + + @Test(expected = IllegalStateException.class) + public void testJoinHeaderCellsIncorrectly() throws Throwable { + HeaderRow mergeRow = prependHeaderRow(); + mergeRow.join("firstName", "zipCode").setText("Name"); + sanityCheck(); + } + + @Test + public void testJoinAllFooterCells() { + FooterRow mergeRow = prependFooterRow(); + mergeRow.join(dataSource.getContainerPropertyIds().toArray()) + .setText("All the stuff."); + } + + private void sanityCheck() throws Throwable { + Method sanityCheckHeader; + try { + sanityCheckHeader = LegacyGrid.Header.class + .getDeclaredMethod("sanityCheck"); + sanityCheckHeader.setAccessible(true); + Method sanityCheckFooter = LegacyGrid.Footer.class + .getDeclaredMethod("sanityCheck"); + sanityCheckFooter.setAccessible(true); + sanityCheckHeader.invoke(getHeader()); + sanityCheckFooter.invoke(getFooter()); + } catch (Exception e) { + throw e.getCause(); + } + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/MultiSelectionModelTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/MultiSelectionModelTest.java new file mode 100644 index 0000000000..1199486742 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/MultiSelectionModelTest.java @@ -0,0 +1,171 @@ +/* + * Copyright 2000-2016 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.tests.server.component.grid; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import com.vaadin.ui.LegacyGrid; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.Container; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.event.SelectionEvent; +import com.vaadin.event.SelectionEvent.SelectionListener; +import com.vaadin.ui.LegacyGrid.MultiSelectionModel; +import com.vaadin.ui.LegacyGrid.SelectionMode; + +public class MultiSelectionModelTest { + + private Object itemId1Present = "itemId1Present"; + private Object itemId2Present = "itemId2Present"; + private Object itemId3Present = "itemId3Present"; + + private Object itemIdNotPresent = "itemIdNotPresent"; + private Container.Indexed dataSource; + private MultiSelectionModel model; + private LegacyGrid grid; + + private boolean expectingEvent = false; + private boolean expectingDeselectEvent; + private List<Object> select = new ArrayList<Object>(); + private List<Object> deselect = new ArrayList<Object>(); + + @Before + public void setUp() { + dataSource = createDataSource(); + grid = new LegacyGrid(dataSource); + grid.setSelectionMode(SelectionMode.MULTI); + model = (MultiSelectionModel) grid.getSelectionModel(); + } + + @After + public void tearDown() { + Assert.assertFalse("Some expected select event did not happen.", + expectingEvent); + Assert.assertFalse("Some expected deselect event did not happen.", + expectingDeselectEvent); + } + + private IndexedContainer createDataSource() { + final IndexedContainer container = new IndexedContainer(); + container.addItem(itemId1Present); + container.addItem(itemId2Present); + container.addItem(itemId3Present); + for (int i = 3; i < 10; i++) { + container.addItem(new Object()); + } + + return container; + } + + @Test + public void testSelectAndDeselectRow() throws Throwable { + try { + expectSelectEvent(itemId1Present); + model.select(itemId1Present); + expectDeselectEvent(itemId1Present); + model.deselect(itemId1Present); + } catch (Exception e) { + throw e.getCause(); + } + + verifyCurrentSelection(); + } + + @Test + public void testAddSelection() throws Throwable { + try { + expectSelectEvent(itemId1Present); + model.select(itemId1Present); + expectSelectEvent(itemId2Present); + model.select(itemId2Present); + } catch (Exception e) { + throw e.getCause(); + } + + verifyCurrentSelection(itemId1Present, itemId2Present); + } + + @Test + public void testSettingSelection() throws Throwable { + try { + expectSelectEvent(itemId2Present, itemId1Present); + model.setSelected(Arrays + .asList(new Object[] { itemId1Present, itemId2Present })); + verifyCurrentSelection(itemId1Present, itemId2Present); + + expectDeselectEvent(itemId1Present); + expectSelectEvent(itemId3Present); + model.setSelected(Arrays + .asList(new Object[] { itemId3Present, itemId2Present })); + verifyCurrentSelection(itemId3Present, itemId2Present); + } catch (Exception e) { + throw e.getCause(); + } + } + + private void expectSelectEvent(Object... selectArray) { + select = Arrays.asList(selectArray); + addListener(); + } + + private void expectDeselectEvent(Object... deselectArray) { + deselect = Arrays.asList(deselectArray); + addListener(); + } + + private void addListener() { + if (expectingEvent) { + return; + } + + expectingEvent = true; + grid.addSelectionListener(new SelectionListener() { + + @Override + public void select(SelectionEvent event) { + Assert.assertTrue("Selection did not contain expected items", + event.getAdded().containsAll(select)); + Assert.assertTrue("Selection contained unexpected items", + select.containsAll(event.getAdded())); + select = new ArrayList<Object>(); + + Assert.assertTrue("Deselection did not contain expected items", + event.getRemoved().containsAll(deselect)); + Assert.assertTrue("Deselection contained unexpected items", + deselect.containsAll(event.getRemoved())); + deselect = new ArrayList<Object>(); + + grid.removeSelectionListener(this); + expectingEvent = false; + } + }); + } + + private void verifyCurrentSelection(Object... selection) { + final List<Object> selected = Arrays.asList(selection); + if (model.getSelectedRows().containsAll(selected) + && selected.containsAll(model.getSelectedRows())) { + return; + } + Assert.fail("Not all items were correctly selected"); + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/SingleSelectionModelTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/SingleSelectionModelTest.java new file mode 100644 index 0000000000..3183ad9021 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/SingleSelectionModelTest.java @@ -0,0 +1,153 @@ +/* + * Copyright 2000-2016 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.tests.server.component.grid; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.Container; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.event.SelectionEvent; +import com.vaadin.event.SelectionEvent.SelectionListener; +import com.vaadin.ui.LegacyGrid; +import com.vaadin.ui.LegacyGrid.SelectionMode; +import com.vaadin.ui.LegacyGrid.SingleSelectionModel; + +public class SingleSelectionModelTest { + + private Object itemId1Present = "itemId1Present"; + private Object itemId2Present = "itemId2Present"; + + private Object itemIdNotPresent = "itemIdNotPresent"; + private Container.Indexed dataSource; + private SingleSelectionModel model; + private LegacyGrid grid; + + private boolean expectingEvent = false; + + @Before + public void setUp() { + dataSource = createDataSource(); + grid = new LegacyGrid(dataSource); + grid.setSelectionMode(SelectionMode.SINGLE); + model = (SingleSelectionModel) grid.getSelectionModel(); + } + + @After + public void tearDown() { + Assert.assertFalse("Some expected event did not happen.", + expectingEvent); + } + + private IndexedContainer createDataSource() { + final IndexedContainer container = new IndexedContainer(); + container.addItem(itemId1Present); + container.addItem(itemId2Present); + for (int i = 2; i < 10; i++) { + container.addItem(new Object()); + } + + return container; + } + + @Test + public void testSelectAndDeselctRow() throws Throwable { + try { + expectEvent(itemId1Present, null); + model.select(itemId1Present); + expectEvent(null, itemId1Present); + model.select(null); + } catch (Exception e) { + throw e.getCause(); + } + } + + @Test + public void testSelectAndChangeSelectedRow() throws Throwable { + try { + expectEvent(itemId1Present, null); + model.select(itemId1Present); + expectEvent(itemId2Present, itemId1Present); + model.select(itemId2Present); + } catch (Exception e) { + throw e.getCause(); + } + } + + @Test + public void testRemovingSelectedRowAndThenDeselecting() throws Throwable { + try { + expectEvent(itemId2Present, null); + model.select(itemId2Present); + dataSource.removeItem(itemId2Present); + expectEvent(null, itemId2Present); + model.select(null); + } catch (Exception e) { + throw e.getCause(); + } + } + + @Test + public void testSelectAndReSelectRow() throws Throwable { + try { + expectEvent(itemId1Present, null); + model.select(itemId1Present); + expectEvent(null, null); + // This is no-op. Nothing should happen. + model.select(itemId1Present); + } catch (Exception e) { + throw e.getCause(); + } + Assert.assertTrue("Should still wait for event", expectingEvent); + expectingEvent = false; + } + + @Test(expected = IllegalArgumentException.class) + public void testSelectNonExistentRow() { + model.select(itemIdNotPresent); + } + + private void expectEvent(final Object selected, final Object deselected) { + expectingEvent = true; + grid.addSelectionListener(new SelectionListener() { + + @Override + public void select(SelectionEvent event) { + if (selected != null) { + Assert.assertTrue("Selection did not contain expected item", + event.getAdded().contains(selected)); + } else { + Assert.assertTrue("Unexpected selection", + event.getAdded().isEmpty()); + } + + if (deselected != null) { + Assert.assertTrue( + "DeSelection did not contain expected item", + event.getRemoved().contains(deselected)); + } else { + Assert.assertTrue("Unexpected selection", + event.getRemoved().isEmpty()); + } + + grid.removeSelectionListener(this); + expectingEvent = false; + } + }); + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/TestGrid.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/TestGrid.java new file mode 100644 index 0000000000..9b2dde4d24 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/TestGrid.java @@ -0,0 +1,62 @@ +/* + * Copyright 2000-2016 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.tests.server.component.grid; + +import java.lang.reflect.Field; + +import org.easymock.EasyMock; + +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.server.communication.data.RpcDataProviderExtension; +import com.vaadin.ui.ConnectorTracker; +import com.vaadin.ui.LegacyGrid; +import com.vaadin.ui.UI; + +/** + * A Grid attached to a mock UI with a mock ConnectorTracker. + * + * @since 7.4 + * @author Vaadin Ltd + */ +public class TestGrid extends LegacyGrid { + + public TestGrid() { + super(); + init(); + } + + public TestGrid(IndexedContainer c) { + super(c); + init(); + } + + public RpcDataProviderExtension getDataProvider() throws Exception { + Field dseField = LegacyGrid.class.getDeclaredField("datasourceExtension"); + dseField.setAccessible(true); + return (RpcDataProviderExtension) dseField.get(this); + } + + private void init() { + UI mockUI = EasyMock.createNiceMock(UI.class); + ConnectorTracker mockCT = EasyMock + .createNiceMock(ConnectorTracker.class); + EasyMock.expect(mockUI.getConnectorTracker()).andReturn(mockCT) + .anyTimes(); + EasyMock.replay(mockUI, mockCT); + + setParent(mockUI); + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridColumnDeclarativeTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridColumnDeclarativeTest.java new file mode 100644 index 0000000000..71d24a2d8e --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridColumnDeclarativeTest.java @@ -0,0 +1,101 @@ +/* + * Copyright 2000-2016 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.tests.server.component.grid.declarative; + +import com.vaadin.ui.LegacyGrid; +import org.junit.Test; + +public class GridColumnDeclarativeTest extends GridDeclarativeTestBase { + + @Test + public void testSimpleGridColumns() { + String design = "<vaadin-legacy-grid><table>"// + + "<colgroup>" + + " <col sortable width='100' property-id='Column1'>" + + " <col sortable=false max-width='200' expand='2' property-id='Column2'>" + + " <col sortable editable=false resizable=false min-width='15' expand='1' property-id='Column3'>" + + " <col sortable hidable hiding-toggle-caption='col 4' property-id='Column4'>" + + " <col sortable hidden property-id='Column5'>" + + "</colgroup>" // + + "<thead />" // + + "</table></vaadin-legacy-grid>"; + LegacyGrid grid = new LegacyGrid(); + grid.addColumn("Column1", String.class).setWidth(100); + grid.addColumn("Column2", String.class).setMaximumWidth(200) + .setExpandRatio(2).setSortable(false); + grid.addColumn("Column3", String.class).setMinimumWidth(15) + .setExpandRatio(1).setEditable(false).setResizable(false); + grid.addColumn("Column4", String.class).setHidable(true) + .setHidingToggleCaption("col 4").setResizable(true); + grid.addColumn("Column5", String.class).setHidden(true); + + // Remove the default header + grid.removeHeaderRow(grid.getDefaultHeaderRow()); + + // Use the read grid component to do another pass on write. + testRead(design, grid, true); + testWrite(design, grid); + } + + @Test + public void testReadColumnsWithoutPropertyId() { + String design = "<vaadin-legacy-grid><table>"// + + "<colgroup>" + + " <col sortable=true width='100' property-id='Column1'>" + + " <col sortable=true max-width='200' expand='2'>" // property-id="property-1" + + " <col sortable=true min-width='15' expand='1' property-id='Column3'>" + + " <col sortable=true hidden=true hidable=true hiding-toggle-caption='col 4'>" // property-id="property-3" + + "</colgroup>" // + + "</table></vaadin-legacy-grid>"; + LegacyGrid grid = new LegacyGrid(); + grid.addColumn("Column1", String.class).setWidth(100); + grid.addColumn("property-1", String.class).setMaximumWidth(200) + .setExpandRatio(2); + grid.addColumn("Column3", String.class).setMinimumWidth(15) + .setExpandRatio(1); + grid.addColumn("property-3", String.class).setHidable(true) + .setHidden(true).setHidingToggleCaption("col 4"); + + testRead(design, grid); + } + + @Test + public void testReadEmptyExpand() { + String design = "<vaadin-legacy-grid><table>"// + + "<colgroup>" + " <col sortable=true expand />" + + "</colgroup>" // + + "</table></vaadin-legacy-grid>"; + + LegacyGrid grid = new LegacyGrid(); + grid.addColumn("property-0", String.class).setExpandRatio(1); + + testRead(design, grid); + } + + @Test + public void testReadColumnWithNoAttributes() { + String design = "<vaadin-legacy-grid><table>"// + + "<colgroup>" // + + " <col />" // + + "</colgroup>" // + + "</table></vaadin-legacy-grid>"; + + LegacyGrid grid = new LegacyGrid(); + grid.addColumn("property-0", String.class); + + testRead(design, grid); + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridDeclarativeAttributeTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridDeclarativeAttributeTest.java new file mode 100644 index 0000000000..8ca99327dc --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridDeclarativeAttributeTest.java @@ -0,0 +1,84 @@ +/* + * Copyright 2000-2016 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.tests.server.component.grid.declarative; + +import static org.junit.Assert.assertSame; + +import com.vaadin.ui.LegacyGrid; +import org.junit.Test; + +import com.vaadin.shared.ui.grid.HeightMode; +import com.vaadin.tests.design.DeclarativeTestBase; +import com.vaadin.ui.LegacyGrid.MultiSelectionModel; +import com.vaadin.ui.LegacyGrid.NoSelectionModel; +import com.vaadin.ui.LegacyGrid.SingleSelectionModel; + +/** + * Tests declarative support for {@link Grid} properties. + * + * @since + * @author Vaadin Ltd + */ +public class GridDeclarativeAttributeTest extends DeclarativeTestBase<LegacyGrid> { + + @Test + public void testBasicAttributes() { + + String design = "<vaadin-legacy-grid editable rows=20 frozen-columns=-1 " + + "editor-save-caption='Tallenna' editor-cancel-caption='Peruuta' column-reordering-allowed>"; + + LegacyGrid grid = new LegacyGrid(); + grid.setEditorEnabled(true); + grid.setHeightMode(HeightMode.ROW); + grid.setHeightByRows(20); + grid.setFrozenColumnCount(-1); + grid.setEditorSaveCaption("Tallenna"); + grid.setEditorCancelCaption("Peruuta"); + grid.setColumnReorderingAllowed(true); + + testRead(design, grid); + testWrite(design, grid); + } + + @Test + public void testFrozenColumnsAttributes() { + String design = "<vaadin-legacy-grid frozen-columns='2'><table>" // + + "<colgroup><col><col><col></colgroup></table></vaadin-legacy-grid>"; + + LegacyGrid grid = new LegacyGrid(); + grid.addColumn("property-0", String.class); + grid.addColumn("property-1", String.class); + grid.addColumn("property-2", String.class); + grid.setFrozenColumnCount(2); + + testRead(design, grid); + } + + @Test + public void testSelectionMode() { + String design = "<vaadin-legacy-grid selection-mode='none'>"; + assertSame(NoSelectionModel.class, + read(design).getSelectionModel().getClass()); + + design = "<vaadin-legacy-grid selection-mode='single'>"; + assertSame(SingleSelectionModel.class, + read(design).getSelectionModel().getClass()); + + design = "<vaadin-legacy-grid selection-mode='multi'>"; + assertSame(MultiSelectionModel.class, + read(design).getSelectionModel().getClass()); + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridDeclarativeTestBase.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridDeclarativeTestBase.java new file mode 100644 index 0000000000..3e97910be7 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridDeclarativeTestBase.java @@ -0,0 +1,159 @@ +/* + * Copyright 2000-2016 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.tests.server.component.grid.declarative; + +import java.util.List; + +import com.vaadin.ui.LegacyGrid; +import org.junit.Assert; + +import com.vaadin.tests.design.DeclarativeTestBase; +import com.vaadin.ui.LegacyGrid.Column; +import com.vaadin.ui.LegacyGrid.FooterCell; +import com.vaadin.ui.LegacyGrid.FooterRow; +import com.vaadin.ui.LegacyGrid.HeaderCell; +import com.vaadin.ui.LegacyGrid.HeaderRow; + +public class GridDeclarativeTestBase extends DeclarativeTestBase<LegacyGrid> { + + @Override + public LegacyGrid testRead(String design, LegacyGrid expected) { + return testRead(design, expected, false); + } + + public LegacyGrid testRead(String design, LegacyGrid expected, boolean retestWrite) { + return testRead(design, expected, retestWrite, false); + } + + public LegacyGrid testRead(String design, LegacyGrid expected, boolean retestWrite, + boolean writeData) { + LegacyGrid actual = super.testRead(design, expected); + + compareGridColumns(expected, actual); + compareHeaders(expected, actual); + compareFooters(expected, actual); + + if (retestWrite) { + testWrite(design, actual, writeData); + } + + return actual; + } + + private void compareHeaders(LegacyGrid expected, LegacyGrid actual) { + Assert.assertEquals("Different header row count", + expected.getHeaderRowCount(), actual.getHeaderRowCount()); + for (int i = 0; i < expected.getHeaderRowCount(); ++i) { + HeaderRow expectedRow = expected.getHeaderRow(i); + HeaderRow actualRow = actual.getHeaderRow(i); + + if (expectedRow.equals(expected.getDefaultHeaderRow())) { + Assert.assertEquals("Different index for default header row", + actual.getDefaultHeaderRow(), actualRow); + } + + for (Column c : expected.getColumns()) { + String baseError = "Difference when comparing cell for " + + c.toString() + " on header row " + i + ": "; + Object propertyId = c.getPropertyId(); + HeaderCell expectedCell = expectedRow.getCell(propertyId); + HeaderCell actualCell = actualRow.getCell(propertyId); + + switch (expectedCell.getCellType()) { + case TEXT: + Assert.assertEquals(baseError + "Text content", + expectedCell.getText(), actualCell.getText()); + break; + case HTML: + Assert.assertEquals(baseError + "HTML content", + expectedCell.getHtml(), actualCell.getHtml()); + break; + case WIDGET: + assertEquals(baseError + "Component content", + expectedCell.getComponent(), + actualCell.getComponent()); + break; + } + } + } + } + + private void compareFooters(LegacyGrid expected, LegacyGrid actual) { + Assert.assertEquals("Different footer row count", + expected.getFooterRowCount(), actual.getFooterRowCount()); + for (int i = 0; i < expected.getFooterRowCount(); ++i) { + FooterRow expectedRow = expected.getFooterRow(i); + FooterRow actualRow = actual.getFooterRow(i); + + for (Column c : expected.getColumns()) { + String baseError = "Difference when comparing cell for " + + c.toString() + " on footer row " + i + ": "; + Object propertyId = c.getPropertyId(); + FooterCell expectedCell = expectedRow.getCell(propertyId); + FooterCell actualCell = actualRow.getCell(propertyId); + + switch (expectedCell.getCellType()) { + case TEXT: + Assert.assertEquals(baseError + "Text content", + expectedCell.getText(), actualCell.getText()); + break; + case HTML: + Assert.assertEquals(baseError + "HTML content", + expectedCell.getHtml(), actualCell.getHtml()); + break; + case WIDGET: + assertEquals(baseError + "Component content", + expectedCell.getComponent(), + actualCell.getComponent()); + break; + } + } + } + } + + private void compareGridColumns(LegacyGrid expected, LegacyGrid actual) { + List<Column> columns = expected.getColumns(); + List<Column> actualColumns = actual.getColumns(); + Assert.assertEquals("Different amount of columns", columns.size(), + actualColumns.size()); + for (int i = 0; i < columns.size(); ++i) { + Column col1 = columns.get(i); + Column col2 = actualColumns.get(i); + String baseError = "Error when comparing columns for property " + + col1.getPropertyId() + ": "; + assertEquals(baseError + "Property id", col1.getPropertyId(), + col2.getPropertyId()); + assertEquals(baseError + "Width", col1.getWidth(), col2.getWidth()); + assertEquals(baseError + "Maximum width", col1.getMaximumWidth(), + col2.getMaximumWidth()); + assertEquals(baseError + "Minimum width", col1.getMinimumWidth(), + col2.getMinimumWidth()); + assertEquals(baseError + "Expand ratio", col1.getExpandRatio(), + col2.getExpandRatio()); + assertEquals(baseError + "Sortable", col1.isSortable(), + col2.isSortable()); + assertEquals(baseError + "Editable", col1.isEditable(), + col2.isEditable()); + assertEquals(baseError + "Hidable", col1.isHidable(), + col2.isHidable()); + assertEquals(baseError + "Hidden", col1.isHidden(), + col2.isHidden()); + assertEquals(baseError + "HidingToggleCaption", + col1.getHidingToggleCaption(), + col2.getHidingToggleCaption()); + } + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridHeaderFooterDeclarativeTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridHeaderFooterDeclarativeTest.java new file mode 100644 index 0000000000..1207063c16 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridHeaderFooterDeclarativeTest.java @@ -0,0 +1,356 @@ +/* + * Copyright 2000-2016 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.tests.server.component.grid.declarative; + +import com.vaadin.ui.LegacyGrid; +import org.jsoup.nodes.Element; +import org.jsoup.parser.Tag; +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.shared.ui.label.ContentMode; +import com.vaadin.ui.LegacyGrid.Column; +import com.vaadin.ui.LegacyGrid.FooterRow; +import com.vaadin.ui.LegacyGrid.HeaderRow; +import com.vaadin.ui.Label; +import com.vaadin.ui.declarative.DesignContext; + +public class GridHeaderFooterDeclarativeTest extends GridDeclarativeTestBase { + + @Test + public void testSingleDefaultHeader() { + //@formatter:off + String design = "<vaadin-legacy-grid><table>" + + "<colgroup>" + + " <col sortable property-id='Column1'>" + + " <col sortable property-id='Column2'>" + + " <col sortable property-id='Column3'>" + + "</colgroup>" + + "<thead>" + + " <tr default><th plain-text>Column1<th plain-text>Column2<th plain-text>Column3</tr>" + + "</thead>" + + "</table></vaadin-legacy-grid>"; + //@formatter:on + LegacyGrid grid = new LegacyGrid(); + grid.addColumn("Column1", String.class); + grid.addColumn("Column2", String.class); + grid.addColumn("Column3", String.class); + + testWrite(design, grid); + testRead(design, grid, true); + } + + @Test + public void testSingleDefaultHTMLHeader() { + //@formatter:off + String design = "<vaadin-legacy-grid><table>" + + "<colgroup>" + + " <col sortable property-id='Column1'>" + + " <col sortable property-id='Column2'>" + + " <col sortable property-id='Column3'>" + "</colgroup>" + + "<thead>" + + " <tr default><th>Column1<th>Column2<th>Column3</tr>" + + "</thead>" + + "</table></vaadin-legacy-grid>"; + //@formatter:on + LegacyGrid grid = new LegacyGrid(); + grid.addColumn("Column1", String.class); + grid.addColumn("Column2", String.class); + grid.addColumn("Column3", String.class); + + HeaderRow row = grid.getDefaultHeaderRow(); + for (Column c : grid.getColumns()) { + row.getCell(c.getPropertyId()).setHtml(c.getHeaderCaption()); + } + + testWrite(design, grid); + testRead(design, grid, true); + } + + @Test + public void testNoHeaderRows() { + //@formatter:off + String design = "<vaadin-legacy-grid><table>" + + "<colgroup>" + + " <col sortable property-id='Column1'>" + + "</colgroup>" + + "<thead />" + + "</table></vaadin-legacy-grid>"; + //@formatter:on + LegacyGrid grid = new LegacyGrid(); + grid.addColumn("Column1", String.class); + grid.removeHeaderRow(grid.getDefaultHeaderRow()); + + testWrite(design, grid); + testRead(design, grid, true); + } + + @Test + public void testMultipleHeadersWithColSpans() { + //@formatter:off + String design = "<vaadin-legacy-grid><table>" + + "<colgroup>" + + " <col sortable property-id='Column1'>" + + " <col sortable property-id='Column2'>" + + " <col sortable property-id='Column3'>" + + "</colgroup>" + + "<thead>" + + " <tr><th colspan=3>Baz</tr>" + + " <tr default><th>Column1<th>Column2<th>Column3</tr>" + + " <tr><th>Foo<th colspan=2>Bar</tr>" + + "</thead>" + + "</table></vaadin-legacy-grid>"; + //@formatter:on + LegacyGrid grid = new LegacyGrid(); + grid.addColumn("Column1", String.class); + grid.addColumn("Column2", String.class); + grid.addColumn("Column3", String.class); + + HeaderRow row = grid.getDefaultHeaderRow(); + for (Column c : grid.getColumns()) { + row.getCell(c.getPropertyId()).setHtml(c.getHeaderCaption()); + } + + grid.prependHeaderRow().join("Column1", "Column2", "Column3") + .setHtml("Baz"); + row = grid.appendHeaderRow(); + row.getCell("Column1").setHtml("Foo"); + row.join("Column2", "Column3").setHtml("Bar"); + + testWrite(design, grid); + testRead(design, grid, true); + } + + @Test + public void testSingleDefaultFooter() { + //@formatter:off + String design = "<vaadin-legacy-grid><table>" + + "<colgroup>" + + " <col sortable property-id='Column1'>" + + " <col sortable property-id='Column2'>" + + " <col sortable property-id='Column3'>" + + "</colgroup>" + + "<thead />" // No headers read or written + + "<tfoot>" + + " <tr><td plain-text>Column1<td plain-text>Column2<td plain-text>Column3</tr>" + + "</tfoot>" + + "</table></vaadin-legacy-grid>"; + //@formatter:on + LegacyGrid grid = new LegacyGrid(); + grid.addColumn("Column1", String.class); + grid.addColumn("Column2", String.class); + grid.addColumn("Column3", String.class); + + FooterRow row = grid.appendFooterRow(); + for (Column c : grid.getColumns()) { + row.getCell(c.getPropertyId()).setText(c.getHeaderCaption()); + } + + grid.removeHeaderRow(grid.getDefaultHeaderRow()); + + testWrite(design, grid); + testRead(design, grid, true); + } + + @Test + public void testSingleDefaultHTMLFooter() { + //@formatter:off + String design = "<vaadin-legacy-grid><table>" + + "<colgroup>" + + " <col sortable property-id='Column1'>" + + " <col sortable property-id='Column2'>" + + " <col sortable property-id='Column3'>" + "</colgroup>" + + "<thead />" // No headers read or written + + "<tfoot>" + + " <tr><td>Column1<td>Column2<td>Column3</tr>" + + "</tfoot>" + + "</table></vaadin-legacy-grid>"; + //@formatter:on + + LegacyGrid grid = new LegacyGrid(); + grid.addColumn("Column1", String.class); + grid.addColumn("Column2", String.class); + grid.addColumn("Column3", String.class); + + FooterRow row = grid.appendFooterRow(); + for (Column c : grid.getColumns()) { + row.getCell(c.getPropertyId()).setHtml(c.getHeaderCaption()); + } + + grid.removeHeaderRow(grid.getDefaultHeaderRow()); + + testWrite(design, grid); + testRead(design, grid, true); + } + + @Test + public void testMultipleFootersWithColSpans() { + //@formatter:off + String design = "<vaadin-legacy-grid><table>" + + "<colgroup>" + + " <col sortable property-id='Column1'>" + + " <col sortable property-id='Column2'>" + + " <col sortable property-id='Column3'>" + + "</colgroup>" + + "<thead />" // No headers read or written. + + "<tfoot>" + + " <tr><td colspan=3>Baz</tr>" + + " <tr><td>Column1<td>Column2<td>Column3</tr>" + + " <tr><td>Foo<td colspan=2>Bar</tr>" + + "</tfoot>" + + "</table></vaadin-legacy-grid>"; + //@formatter:on + + LegacyGrid grid = new LegacyGrid(); + grid.addColumn("Column1", String.class); + grid.addColumn("Column2", String.class); + grid.addColumn("Column3", String.class); + + FooterRow row = grid.appendFooterRow(); + for (Column c : grid.getColumns()) { + row.getCell(c.getPropertyId()).setHtml(c.getHeaderCaption()); + } + + grid.prependFooterRow().join("Column1", "Column2", "Column3") + .setHtml("Baz"); + row = grid.appendFooterRow(); + row.getCell("Column1").setHtml("Foo"); + row.join("Column2", "Column3").setHtml("Bar"); + + grid.removeHeaderRow(grid.getDefaultHeaderRow()); + + testWrite(design, grid); + testRead(design, grid, true); + } + + @Test + public void testComponentInGridHeader() { + //@formatter:off + String design = "<vaadin-legacy-grid><table>" + + "<colgroup>" + + " <col sortable property-id='Column1'>" + + "</colgroup>" + + "<thead>" + + "<tr default><th><vaadin-label><b>Foo</b></vaadin-label></tr>" + + "</thead>" + + "</table></vaadin-legacy-grid>"; + //@formatter:on + Label component = new Label("<b>Foo</b>"); + component.setContentMode(ContentMode.HTML); + + LegacyGrid grid = new LegacyGrid(); + grid.addColumn("Column1", String.class); + grid.getDefaultHeaderRow().getCell("Column1").setComponent(component); + + testRead(design, grid, true); + testWrite(design, grid); + } + + @Test + public void testComponentInGridFooter() { + //@formatter:off + String design = "<vaadin-legacy-grid><table>" + + "<colgroup>" + + " <col sortable property-id='Column1'>" + + "</colgroup>" + + "<thead />" // No headers read or written + + "<tfoot>" + + "<tr><td><vaadin-label><b>Foo</b></vaadin-label></tr>" + + "</tfoot>" + + "</table></vaadin-legacy-grid>"; + //@formatter:on + + Label component = new Label("<b>Foo</b>"); + component.setContentMode(ContentMode.HTML); + + LegacyGrid grid = new LegacyGrid(); + grid.addColumn("Column1", String.class); + grid.prependFooterRow().getCell("Column1").setComponent(component); + grid.removeHeaderRow(grid.getDefaultHeaderRow()); + + testRead(design, grid, true); + testWrite(design, grid); + } + + @Test + public void testHtmlEntitiesinGridHeaderFooter() { + //@formatter:off + String design = "<vaadin-legacy-grid><table>" + + "<colgroup>" + + " <col sortable=\"true\" property-id=\"> test\">" + + "</colgroup>" + + "<thead>" + + " <tr><th plain-text=\"true\">> Test</th></tr>" + + "</thead>" + + "<tfoot>" + + " <tr><td plain-text=\"true\">> Test</td></tr>" + + "</tfoot>" + + "<tbody />" + + "</table></vaadin-legacy-grid>"; + //@formatter:on + + LegacyGrid grid = read(design); + String actualHeader = grid.getHeaderRow(0).getCell("> test").getText(); + String actualFooter = grid.getFooterRow(0).getCell("> test").getText(); + String expected = "> Test"; + + Assert.assertEquals(expected, actualHeader); + Assert.assertEquals(expected, actualFooter); + + design = design.replace("plain-text=\"true\"", ""); + grid = read(design); + actualHeader = grid.getHeaderRow(0).getCell("> test").getHtml(); + actualFooter = grid.getFooterRow(0).getCell("> test").getHtml(); + expected = "> Test"; + + Assert.assertEquals(expected, actualHeader); + Assert.assertEquals(expected, actualFooter); + + grid = new LegacyGrid(); + grid.setColumns("test"); + HeaderRow header = grid.addHeaderRowAt(0); + FooterRow footer = grid.addFooterRowAt(0); + grid.removeHeaderRow(grid.getDefaultHeaderRow()); + + // entities should be encoded when writing back, not interpreted as HTML + header.getCell("test").setText("& Test"); + footer.getCell("test").setText("& Test"); + + Element root = new Element(Tag.valueOf("vaadin-legacy-grid"), ""); + grid.writeDesign(root, new DesignContext()); + + Assert.assertEquals("&amp; Test", + root.getElementsByTag("th").get(0).html()); + Assert.assertEquals("&amp; Test", + root.getElementsByTag("td").get(0).html()); + + header = grid.addHeaderRowAt(0); + footer = grid.addFooterRowAt(0); + + // entities should not be encoded, this is already given as HTML + header.getCell("test").setHtml("& Test"); + footer.getCell("test").setHtml("& Test"); + + root = new Element(Tag.valueOf("vaadin-legacy-grid"), ""); + grid.writeDesign(root, new DesignContext()); + + Assert.assertEquals("& Test", + root.getElementsByTag("th").get(0).html()); + Assert.assertEquals("& Test", + root.getElementsByTag("td").get(0).html()); + + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridInlineDataDeclarativeTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridInlineDataDeclarativeTest.java new file mode 100644 index 0000000000..f5b98824cd --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridInlineDataDeclarativeTest.java @@ -0,0 +1,124 @@ +/* + * Copyright 2000-2016 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.tests.server.component.grid.declarative; + +import com.vaadin.ui.LegacyGrid; +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.data.Container; + +public class GridInlineDataDeclarativeTest extends GridDeclarativeTestBase { + + @Test + public void testSimpleInlineData() { + String design = "<vaadin-legacy-grid><table>"// + + "<colgroup>" + " <col sortable property-id='Col1' />" + + "</colgroup>" // + + "<thead />" // No headers read or written + + "<tbody>" // + + "<tr><td>Foo</tr>" // + + "<tr><td>Bar</tr>" // + + "<tr><td>Baz</tr>" // + + "</tbody>" // + + "</table></vaadin-legacy-grid>"; + + LegacyGrid grid = new LegacyGrid(); + grid.addColumn("Col1", String.class); + grid.addRow("Foo"); + grid.addRow("Bar"); + grid.addRow("Baz"); + + // Remove default header + grid.removeHeaderRow(grid.getDefaultHeaderRow()); + + testWrite(design, grid, true); + testRead(design, grid, true, true); + } + + @Test + public void testMultipleColumnsInlineData() { + String design = "<vaadin-legacy-grid><table>"// + + "<colgroup>" + " <col sortable property-id='Col1' />" + + " <col sortable property-id='Col2' />" + + " <col sortable property-id='Col3' />" // + + "</colgroup>" // + + "<thead />" // No headers read or written + + "<tbody>" // + + "<tr><td>Foo<td>Bar<td>Baz</tr>" // + + "<tr><td>My<td>Summer<td>Car</tr>" // + + "</tbody>" // + + "</table></vaadin-legacy-grid>"; + + LegacyGrid grid = new LegacyGrid(); + grid.addColumn("Col1", String.class); + grid.addColumn("Col2", String.class); + grid.addColumn("Col3", String.class); + grid.addRow("Foo", "Bar", "Baz"); + grid.addRow("My", "Summer", "Car"); + + // Remove default header + grid.removeHeaderRow(grid.getDefaultHeaderRow()); + + testWrite(design, grid, true); + testRead(design, grid, true, true); + } + + @Test + public void testMultipleColumnsInlineDataReordered() { + String design = "<vaadin-legacy-grid><table>"// + + "<colgroup>" + " <col sortable property-id='Col2' />" + + " <col sortable property-id='Col3' />" + + " <col sortable property-id='Col1' />" // + + "</colgroup>" // + + "<thead />" // No headers read or written + + "<tbody>" // + + "<tr><td>Bar<td>Baz<td>Foo</tr>" // + + "<tr><td>Summer<td>Car<td>My</tr>" // + + "</tbody>" // + + "</table></vaadin-legacy-grid>"; + + LegacyGrid grid = new LegacyGrid(); + grid.addColumn("Col1", String.class); + grid.addColumn("Col2", String.class); + grid.addColumn("Col3", String.class); + grid.addRow("Foo", "Bar", "Baz"); + grid.addRow("My", "Summer", "Car"); + grid.setColumnOrder("Col2", "Col3", "Col1"); + + // Remove default header + grid.removeHeaderRow(grid.getDefaultHeaderRow()); + + testWrite(design, grid, true); + testRead(design, grid, true, true); + } + + @Test + public void testHtmlEntities() { + String design = "<vaadin-legacy-grid><table>"// + + "<colgroup>" + " <col property-id='test' />" + "</colgroup>" // + + "<thead />" // No headers read or written + + "<tbody>" // + + " <tr><td>&Test</tr></td>" + "</tbody>" + + "</table></vaadin-legacy-grid>"; + + LegacyGrid read = read(design); + Container cds = read.getContainerDataSource(); + Assert.assertEquals("&Test", + cds.getItem(cds.getItemIds().iterator().next()) + .getItemProperty("test").getValue()); + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridStructureDeclarativeTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridStructureDeclarativeTest.java new file mode 100644 index 0000000000..b55b0815f8 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/declarative/GridStructureDeclarativeTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2000-2016 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.tests.server.component.grid.declarative; + +import com.vaadin.ui.LegacyGrid; +import org.junit.Test; + +import com.vaadin.ui.declarative.DesignException; + +public class GridStructureDeclarativeTest extends GridDeclarativeTestBase { + + @Test + public void testReadEmptyGrid() { + String design = "<vaadin-legacy-grid />"; + testRead(design, new LegacyGrid(), false); + } + + @Test + public void testEmptyGrid() { + String design = "<vaadin-legacy-grid></vaadin-legacy-grid>"; + LegacyGrid expected = new LegacyGrid(); + testWrite(design, expected); + testRead(design, expected, true); + } + + @Test(expected = DesignException.class) + public void testMalformedGrid() { + String design = "<vaadin-legacy-grid><vaadin-label /></vaadin-legacy-grid>"; + testRead(design, new LegacyGrid()); + } + + @Test(expected = DesignException.class) + public void testGridWithNoColGroup() { + String design = "<vaadin-legacy-grid><table><thead><tr><th>Foo</tr></thead></table></vaadin-legacy-grid>"; + testRead(design, new LegacyGrid()); + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/sort/SortTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/sort/SortTest.java new file mode 100644 index 0000000000..beb774528f --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/component/grid/sort/SortTest.java @@ -0,0 +1,205 @@ +/* + * Copyright 2000-2016 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.tests.server.component.grid.sort; + +import java.util.Arrays; +import java.util.List; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.sort.Sort; +import com.vaadin.data.sort.SortOrder; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.event.SortEvent; +import com.vaadin.event.SortEvent.SortListener; +import com.vaadin.shared.data.sort.SortDirection; +import com.vaadin.ui.LegacyGrid; + +public class SortTest { + + class DummySortingIndexedContainer extends IndexedContainer { + + private Object[] expectedProperties; + private boolean[] expectedAscending; + private boolean sorted = true; + + @Override + public void sort(Object[] propertyId, boolean[] ascending) { + Assert.assertEquals( + "Different amount of expected and actual properties,", + expectedProperties.length, propertyId.length); + Assert.assertEquals( + "Different amount of expected and actual directions", + expectedAscending.length, ascending.length); + for (int i = 0; i < propertyId.length; ++i) { + Assert.assertEquals("Sorting properties differ", + expectedProperties[i], propertyId[i]); + Assert.assertEquals("Sorting directions differ", + expectedAscending[i], ascending[i]); + } + sorted = true; + } + + public void expectedSort(Object[] properties, + SortDirection[] directions) { + assert directions.length == properties.length : "Array dimensions differ"; + expectedProperties = properties; + expectedAscending = new boolean[directions.length]; + for (int i = 0; i < directions.length; ++i) { + expectedAscending[i] = (directions[i] == SortDirection.ASCENDING); + } + sorted = false; + } + + public boolean isSorted() { + return sorted; + } + } + + class RegisteringSortChangeListener implements SortListener { + private List<SortOrder> order; + + @Override + public void sort(SortEvent event) { + assert order == null : "The same listener was notified multipe times without checking"; + + order = event.getSortOrder(); + } + + public void assertEventFired(SortOrder... expectedOrder) { + Assert.assertEquals(Arrays.asList(expectedOrder), order); + + // Reset for nest test + order = null; + } + + } + + private DummySortingIndexedContainer container; + private RegisteringSortChangeListener listener; + private LegacyGrid grid; + + @Before + public void setUp() { + container = createContainer(); + container.expectedSort(new Object[] {}, new SortDirection[] {}); + + listener = new RegisteringSortChangeListener(); + + grid = new LegacyGrid(container); + grid.addSortListener(listener); + } + + @After + public void tearDown() { + Assert.assertTrue("Container was not sorted after the test.", + container.isSorted()); + } + + @Test(expected = IllegalArgumentException.class) + public void testInvalidSortDirection() { + Sort.by("foo", null); + } + + @Test(expected = IllegalStateException.class) + public void testSortOneColumnMultipleTimes() { + Sort.by("foo").then("bar").then("foo"); + } + + @Test(expected = IllegalArgumentException.class) + public void testSortingByUnexistingProperty() { + grid.sort("foobar"); + } + + @Test(expected = IllegalArgumentException.class) + public void testSortingByUnsortableProperty() { + container.addContainerProperty("foobar", Object.class, null); + grid.sort("foobar"); + } + + @Test + public void testGridDirectSortAscending() { + container.expectedSort(new Object[] { "foo" }, + new SortDirection[] { SortDirection.ASCENDING }); + grid.sort("foo"); + + listener.assertEventFired( + new SortOrder("foo", SortDirection.ASCENDING)); + } + + @Test + public void testGridDirectSortDescending() { + container.expectedSort(new Object[] { "foo" }, + new SortDirection[] { SortDirection.DESCENDING }); + grid.sort("foo", SortDirection.DESCENDING); + + listener.assertEventFired( + new SortOrder("foo", SortDirection.DESCENDING)); + } + + @Test + public void testGridSortBy() { + container.expectedSort(new Object[] { "foo", "bar", "baz" }, + new SortDirection[] { SortDirection.ASCENDING, + SortDirection.ASCENDING, SortDirection.DESCENDING }); + grid.sort(Sort.by("foo").then("bar").then("baz", + SortDirection.DESCENDING)); + + listener.assertEventFired(new SortOrder("foo", SortDirection.ASCENDING), + new SortOrder("bar", SortDirection.ASCENDING), + new SortOrder("baz", SortDirection.DESCENDING)); + + } + + @Test + public void testChangeContainerAfterSorting() { + class Person { + } + + container.expectedSort(new Object[] { "foo", "bar", "baz" }, + new SortDirection[] { SortDirection.ASCENDING, + SortDirection.ASCENDING, SortDirection.DESCENDING }); + grid.sort(Sort.by("foo").then("bar").then("baz", + SortDirection.DESCENDING)); + + listener.assertEventFired(new SortOrder("foo", SortDirection.ASCENDING), + new SortOrder("bar", SortDirection.ASCENDING), + new SortOrder("baz", SortDirection.DESCENDING)); + + container = new DummySortingIndexedContainer(); + container.addContainerProperty("foo", Person.class, null); + container.addContainerProperty("baz", String.class, ""); + container.addContainerProperty("bar", Person.class, null); + container.expectedSort(new Object[] { "baz" }, + new SortDirection[] { SortDirection.DESCENDING }); + grid.setContainerDataSource(container); + + listener.assertEventFired( + new SortOrder("baz", SortDirection.DESCENDING)); + + } + + private DummySortingIndexedContainer createContainer() { + DummySortingIndexedContainer container = new DummySortingIndexedContainer(); + container.addContainerProperty("foo", Integer.class, 0); + container.addContainerProperty("bar", Integer.class, 0); + container.addContainerProperty("baz", Integer.class, 0); + return container; + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/renderer/ImageRendererTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/renderer/ImageRendererTest.java new file mode 100644 index 0000000000..822a2353ac --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/renderer/ImageRendererTest.java @@ -0,0 +1,85 @@ +/* + * Copyright 2000-2016 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.tests.server.renderer; + +import static org.junit.Assert.assertEquals; + +import java.io.File; + +import org.easymock.EasyMock; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.server.ClassResource; +import com.vaadin.server.ExternalResource; +import com.vaadin.server.FileResource; +import com.vaadin.server.FontAwesome; +import com.vaadin.server.ThemeResource; +import com.vaadin.ui.LegacyGrid; +import com.vaadin.ui.UI; +import com.vaadin.ui.renderers.ImageRenderer; + +import elemental.json.JsonObject; +import elemental.json.JsonValue; + +public class ImageRendererTest { + + private ImageRenderer renderer; + + @Before + public void setUp() { + UI mockUI = EasyMock.createNiceMock(UI.class); + EasyMock.replay(mockUI); + + LegacyGrid grid = new LegacyGrid(); + grid.setParent(mockUI); + + renderer = new ImageRenderer(); + renderer.setParent(grid); + } + + @Test + public void testThemeResource() { + JsonValue v = renderer.encode(new ThemeResource("foo.png")); + assertEquals("theme://foo.png", getUrl(v)); + } + + @Test + public void testExternalResource() { + JsonValue v = renderer + .encode(new ExternalResource("http://example.com/foo.png")); + assertEquals("http://example.com/foo.png", getUrl(v)); + } + + @Test(expected = IllegalArgumentException.class) + public void testFileResource() { + renderer.encode(new FileResource(new File("/tmp/foo.png"))); + } + + @Test(expected = IllegalArgumentException.class) + public void testClassResource() { + renderer.encode(new ClassResource("img/foo.png")); + } + + @Test(expected = IllegalArgumentException.class) + public void testFontIcon() { + renderer.encode(FontAwesome.AMBULANCE); + } + + private String getUrl(JsonValue v) { + return ((JsonObject) v).get("uRL").asString(); + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/renderer/RendererTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/renderer/RendererTest.java new file mode 100644 index 0000000000..5eec5b6ea8 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/renderer/RendererTest.java @@ -0,0 +1,268 @@ +/* + * Copyright 2000-2016 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.tests.server.renderer; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; + +import java.util.Date; +import java.util.Locale; + +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.Item; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.server.VaadinSession; +import com.vaadin.tests.server.component.grid.TestGrid; +import com.vaadin.tests.util.AlwaysLockedVaadinSession; +import com.vaadin.ui.LegacyGrid; +import com.vaadin.ui.LegacyGrid.AbstractRenderer; +import com.vaadin.ui.LegacyGrid.Column; +import com.vaadin.ui.renderers.ButtonRenderer; +import com.vaadin.ui.renderers.DateRenderer; +import com.vaadin.ui.renderers.HtmlRenderer; +import com.vaadin.ui.renderers.NumberRenderer; +import com.vaadin.ui.renderers.TextRenderer; +import com.vaadin.v7.data.util.converter.LegacyConverter; +import com.vaadin.v7.data.util.converter.LegacyStringToIntegerConverter; + +import elemental.json.JsonValue; + +public class RendererTest { + + private static class TestBean { + int i = 42; + + @Override + public String toString() { + return "TestBean [" + i + "]"; + } + } + + private static class ExtendedBean extends TestBean { + float f = 3.14f; + } + + private static class TestRenderer extends TextRenderer { + @Override + public JsonValue encode(String value) { + return super.encode("renderer(" + value + ")"); + } + } + + private static class TestConverter + implements LegacyConverter<String, TestBean> { + + @Override + public TestBean convertToModel(String value, + Class<? extends TestBean> targetType, Locale locale) + throws ConversionException { + return null; + } + + @Override + public String convertToPresentation(TestBean value, + Class<? extends String> targetType, Locale locale) + throws ConversionException { + if (value instanceof ExtendedBean) { + return "ExtendedBean(" + value.i + ", " + + ((ExtendedBean) value).f + ")"; + } else { + return "TestBean(" + value.i + ")"; + } + } + + @Override + public Class<TestBean> getModelType() { + return TestBean.class; + } + + @Override + public Class<String> getPresentationType() { + return String.class; + } + } + + private LegacyGrid grid; + + private Column intColumn; + private Column textColumn; + private Column beanColumn; + private Column htmlColumn; + private Column numberColumn; + private Column dateColumn; + private Column extendedBeanColumn; + private Column buttonColumn; + + @Before + @SuppressWarnings("unchecked") + public void setUp() { + VaadinSession.setCurrent(new AlwaysLockedVaadinSession(null)); + + IndexedContainer c = new IndexedContainer(); + + c.addContainerProperty("int", Integer.class, 0); + c.addContainerProperty("text", String.class, ""); + c.addContainerProperty("html", String.class, ""); + c.addContainerProperty("number", Number.class, null); + c.addContainerProperty("date", Date.class, null); + c.addContainerProperty("bean", TestBean.class, null); + c.addContainerProperty("button", String.class, null); + c.addContainerProperty("extendedBean", ExtendedBean.class, null); + + Object id = c.addItem(); + Item item = c.getItem(id); + item.getItemProperty("int").setValue(123); + item.getItemProperty("text").setValue("321"); + item.getItemProperty("html").setValue("<b>html</b>"); + item.getItemProperty("number").setValue(3.14); + item.getItemProperty("date").setValue(new Date(123456789)); + item.getItemProperty("bean").setValue(new TestBean()); + item.getItemProperty("extendedBean").setValue(new ExtendedBean()); + + grid = new TestGrid(c); + + intColumn = grid.getColumn("int"); + textColumn = grid.getColumn("text"); + htmlColumn = grid.getColumn("html"); + numberColumn = grid.getColumn("number"); + dateColumn = grid.getColumn("date"); + beanColumn = grid.getColumn("bean"); + extendedBeanColumn = grid.getColumn("extendedBean"); + buttonColumn = grid.getColumn("button"); + + } + + @Test + public void testDefaultRendererAndConverter() throws Exception { + assertSame(TextRenderer.class, intColumn.getRenderer().getClass()); + assertSame(LegacyStringToIntegerConverter.class, + intColumn.getConverter().getClass()); + + assertSame(TextRenderer.class, textColumn.getRenderer().getClass()); + // String->String; converter not needed + assertNull(textColumn.getConverter()); + + assertSame(TextRenderer.class, beanColumn.getRenderer().getClass()); + // MyBean->String; converter not found + assertNull(beanColumn.getConverter()); + } + + @Test + public void testFindCompatibleConverter() throws Exception { + intColumn.setRenderer(renderer()); + assertSame(LegacyStringToIntegerConverter.class, + intColumn.getConverter().getClass()); + + textColumn.setRenderer(renderer()); + assertNull(textColumn.getConverter()); + } + + @Test(expected = IllegalArgumentException.class) + public void testCannotFindConverter() { + beanColumn.setRenderer(renderer()); + } + + @Test + public void testExplicitConverter() throws Exception { + beanColumn.setRenderer(renderer(), converter()); + extendedBeanColumn.setRenderer(renderer(), converter()); + } + + @Test + public void testEncoding() throws Exception { + assertEquals("42", render(intColumn, 42).asString()); + intColumn.setRenderer(renderer()); + assertEquals("renderer(42)", render(intColumn, 42).asString()); + + assertEquals("2.72", render(textColumn, "2.72").asString()); + textColumn.setRenderer(new TestRenderer()); + assertEquals("renderer(2.72)", render(textColumn, "2.72").asString()); + } + + @Test + public void testEncodingWithoutConverter() throws Exception { + assertEquals("TestBean [42]", + render(beanColumn, new TestBean()).asString()); + } + + @Test + public void testBeanEncoding() throws Exception { + beanColumn.setRenderer(renderer(), converter()); + extendedBeanColumn.setRenderer(renderer(), converter()); + + assertEquals("renderer(TestBean(42))", + render(beanColumn, new TestBean()).asString()); + assertEquals("renderer(ExtendedBean(42, 3.14))", + render(beanColumn, new ExtendedBean()).asString()); + + assertEquals("renderer(ExtendedBean(42, 3.14))", + render(extendedBeanColumn, new ExtendedBean()).asString()); + } + + @Test + public void testNullEncoding() { + + textColumn.setRenderer(new TextRenderer()); + htmlColumn.setRenderer(new HtmlRenderer()); + numberColumn.setRenderer(new NumberRenderer()); + dateColumn.setRenderer(new DateRenderer()); + buttonColumn.setRenderer(new ButtonRenderer()); + + assertEquals("", textColumn.getRenderer().encode(null).asString()); + assertEquals("", htmlColumn.getRenderer().encode(null).asString()); + assertEquals("", numberColumn.getRenderer().encode(null).asString()); + assertEquals("", dateColumn.getRenderer().encode(null).asString()); + assertEquals("", buttonColumn.getRenderer().encode(null).asString()); + } + + @Test + public void testNullEncodingWithDefault() { + + textColumn.setRenderer(new TextRenderer("default value")); + htmlColumn.setRenderer(new HtmlRenderer("default value")); + numberColumn.setRenderer( + new NumberRenderer("%s", Locale.getDefault(), "default value")); + dateColumn.setRenderer(new DateRenderer("%s", "default value")); + buttonColumn.setRenderer(new ButtonRenderer("default value")); + + assertEquals("default value", + textColumn.getRenderer().encode(null).asString()); + assertEquals("default value", + htmlColumn.getRenderer().encode(null).asString()); + assertEquals("default value", + numberColumn.getRenderer().encode(null).asString()); + assertEquals("default value", + dateColumn.getRenderer().encode(null).asString()); + assertEquals("default value", + buttonColumn.getRenderer().encode(null).asString()); + } + + private TestConverter converter() { + return new TestConverter(); + } + + private TestRenderer renderer() { + return new TestRenderer(); + } + + private JsonValue render(Column column, Object value) { + return AbstractRenderer.encodeValue(value, column.getRenderer(), + column.getConverter(), grid.getLocale()); + } +} diff --git a/compatibility-server/src/test/java/com/vaadin/tests/server/validation/BeanValidationTest.java b/compatibility-server/src/test/java/com/vaadin/tests/server/validation/BeanValidationTest.java new file mode 100644 index 0000000000..a8e6238d4b --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/tests/server/validation/BeanValidationTest.java @@ -0,0 +1,129 @@ +package com.vaadin.tests.server.validation; + +import org.junit.Assert; +import org.junit.Test; + +import com.vaadin.data.fieldgroup.BeanFieldGroup; +import com.vaadin.tests.data.bean.BeanToValidate; +import com.vaadin.v7.data.Validator.InvalidValueException; +import com.vaadin.v7.data.validator.LegacyBeanValidator; +import com.vaadin.v7.ui.LegacyField; + +public class BeanValidationTest { + @Test(expected = InvalidValueException.class) + public void testBeanValidationNull() { + LegacyBeanValidator validator = new LegacyBeanValidator( + BeanToValidate.class, "firstname"); + validator.validate(null); + } + + @Test(expected = InvalidValueException.class) + public void testBeanValidationStringTooShort() { + LegacyBeanValidator validator = new LegacyBeanValidator( + BeanToValidate.class, "firstname"); + validator.validate("aa"); + } + + @Test + public void testBeanValidationStringOk() { + LegacyBeanValidator validator = new LegacyBeanValidator( + BeanToValidate.class, "firstname"); + validator.validate("aaa"); + } + + @Test(expected = InvalidValueException.class) + public void testBeanValidationIntegerTooSmall() { + LegacyBeanValidator validator = new LegacyBeanValidator( + BeanToValidate.class, "age"); + validator.validate(17); + } + + @Test + public void testBeanValidationIntegerOk() { + LegacyBeanValidator validator = new LegacyBeanValidator( + BeanToValidate.class, "age"); + validator.validate(18); + } + + @Test(expected = InvalidValueException.class) + public void testBeanValidationTooManyDigits() { + LegacyBeanValidator validator = new LegacyBeanValidator( + BeanToValidate.class, "decimals"); + validator.validate("1234.567"); + } + + @Test + public void testBeanValidationDigitsOk() { + LegacyBeanValidator validator = new LegacyBeanValidator( + BeanToValidate.class, "decimals"); + validator.validate("123.45"); + } + + @Test + public void testBeanValidationException_OneValidationError() { + InvalidValueException[] causes = null; + LegacyBeanValidator validator = new LegacyBeanValidator( + BeanToValidate.class, "lastname"); + try { + validator.validate(null); + } catch (InvalidValueException e) { + causes = e.getCauses(); + } + + Assert.assertEquals(1, causes.length); + } + + @Test + public void testBeanValidationsException_TwoValidationErrors() { + InvalidValueException[] causes = null; + LegacyBeanValidator validator = new LegacyBeanValidator( + BeanToValidate.class, "nickname"); + try { + validator.validate("A"); + } catch (InvalidValueException e) { + causes = e.getCauses(); + } + + Assert.assertEquals(2, causes.length); + } + + @Test + public void testBeanValidationNotAddedTwice() { + // See ticket #11045 + BeanFieldGroup<BeanToValidate> fieldGroup = new BeanFieldGroup<BeanToValidate>( + BeanToValidate.class); + + BeanToValidate beanToValidate = new BeanToValidate(); + beanToValidate.setFirstname("a"); + fieldGroup.setItemDataSource(beanToValidate); + + LegacyField<?> nameField = fieldGroup.buildAndBind("firstname"); + Assert.assertEquals(1, nameField.getValidators().size()); + + try { + nameField.validate(); + } catch (InvalidValueException e) { + // The 1 cause is from BeanValidator, where it tells what failed + // 1 validation exception never gets wrapped. + Assert.assertEquals(1, e.getCauses().length); + } + + // Create new, identical bean to cause duplicate validator unless #11045 + // is fixed + beanToValidate = new BeanToValidate(); + beanToValidate.setFirstname("a"); + fieldGroup.setItemDataSource(beanToValidate); + + Assert.assertEquals(1, nameField.getValidators().size()); + + try { + nameField.validate(); + } catch (InvalidValueException e) { + // The 1 cause is from BeanValidator, where it tells what failed + // 1 validation exception never gets wrapped. + Assert.assertEquals(1, e.getCauses().length); + } + + } + +} diff --git a/compatibility-server/src/test/java/com/vaadin/ui/TableTest.java b/compatibility-server/src/test/java/com/vaadin/ui/TableTest.java new file mode 100644 index 0000000000..f09313f685 --- /dev/null +++ b/compatibility-server/src/test/java/com/vaadin/ui/TableTest.java @@ -0,0 +1,78 @@ +/* + * Copyright 2000-2016 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 java.util.Collection; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import com.vaadin.data.util.BeanItemContainerGenerator; + +public class TableTest { + + Table table; + + @Before + public void init() { + table = new Table(); + } + + @Test + public void initiallyEmpty() { + Assert.assertTrue(table.isEmpty()); + } + + @Test + public void emptyAfterClearSingleSelect() { + table.setContainerDataSource( + BeanItemContainerGenerator.createContainer(100)); + Assert.assertTrue(table.isEmpty()); + Object first = table.getContainerDataSource().getItemIds().iterator() + .next(); + table.setValue(first); + Assert.assertEquals(first, table.getValue()); + Assert.assertFalse(table.isEmpty()); + table.clear(); + Assert.assertEquals(null, table.getValue()); + Assert.assertTrue(table.isEmpty()); + } + + @Test + public void emptyAfterClearMultiSelect() { + table.setMultiSelect(true); + table.setContainerDataSource( + BeanItemContainerGenerator.createContainer(100)); + + Assert.assertTrue(table.isEmpty()); + Assert.assertArrayEquals(new Object[] {}, + ((Collection) table.getValue()).toArray()); + + Object first = table.getContainerDataSource().getItemIds().iterator() + .next(); + table.select(first); + Assert.assertArrayEquals(new Object[] { first }, + ((Collection) table.getValue()).toArray()); + Assert.assertFalse(table.isEmpty()); + + table.clear(); + Assert.assertArrayEquals(new Object[] {}, + ((Collection) table.getValue()).toArray()); + Assert.assertTrue(table.isEmpty()); + } + +} |