diff options
author | Aleksi Hietanen <aleksi@vaadin.com> | 2017-05-11 08:56:28 +0300 |
---|---|---|
committer | Henri Sara <henri.sara@gmail.com> | 2017-05-11 08:56:28 +0300 |
commit | dc6e754f8c84c76ca086e6e862977062e5235734 (patch) | |
tree | 205147b55d3776fcca298387b8729cfc660a6232 /uitest | |
parent | d25697a1230d24886b8d2219039fcb2dd38bd17c (diff) | |
download | vaadin-framework-dc6e754f8c84c76ca086e6e862977062e5235734.tar.gz vaadin-framework-dc6e754f8c84c76ca086e6e862977062e5235734.zip |
Reset HierarchicalDataCommunicator on changes (#9275)
Reset HDC when encountering unexpected changes in the data.
Additionally this patch fixes an issue with client and server caches
getting out of sync during resets.
Diffstat (limited to 'uitest')
2 files changed, 210 insertions, 0 deletions
diff --git a/uitest/src/main/java/com/vaadin/tests/components/treegrid/TreeGridChangingHierarchy.java b/uitest/src/main/java/com/vaadin/tests/components/treegrid/TreeGridChangingHierarchy.java new file mode 100644 index 0000000000..c7943524e4 --- /dev/null +++ b/uitest/src/main/java/com/vaadin/tests/components/treegrid/TreeGridChangingHierarchy.java @@ -0,0 +1,89 @@ +package com.vaadin.tests.components.treegrid; + +import java.util.stream.Stream; + +import com.vaadin.data.HierarchyData; +import com.vaadin.data.ValueProvider; +import com.vaadin.data.provider.HierarchicalQuery; +import com.vaadin.data.provider.InMemoryHierarchicalDataProvider; +import com.vaadin.server.SerializablePredicate; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.TreeGrid; + +public class TreeGridChangingHierarchy extends AbstractTestUI { + + private static class TestDataProvider + extends InMemoryHierarchicalDataProvider<String> { + + private HierarchyData<String> hierarchyData; + + public TestDataProvider(HierarchyData<String> hierarchyData) { + super(hierarchyData); + this.hierarchyData = hierarchyData; + } + + @Override + public boolean hasChildren(String item) { + if (!hierarchyData.contains(item)) { + return false; + } + return super.hasChildren(item); + } + + @Override + public Stream<String> fetchChildren( + HierarchicalQuery<String, SerializablePredicate<String>> query) { + if (!hierarchyData.contains(query.getParent())) { + return Stream.empty(); + } + return super.fetchChildren(query); + } + } + + @Override + protected void setup(VaadinRequest request) { + HierarchyData<String> data = new HierarchyData<>(); + data.addItems(null, "a", "b", "c").addItem("b", "b/a"); + + TreeGrid<String> grid = new TreeGrid<>(); + grid.setDataProvider(new TestDataProvider(data)); + grid.addColumn(ValueProvider.identity()); + + Button btn = new Button("add items to a and refresh"); + btn.addClickListener(event -> { + data.addItems("a", "a/a", "a/b"); + grid.getDataProvider().refreshItem("a"); + }); + Button btn2 = new Button("add items to a/a and refresh"); + btn2.addClickListener(event -> { + data.addItems("a/a", "a/a/a", "a/a/c").addItem("a/a/a", "a/a/a/a"); + grid.getDataProvider().refreshItem("a/a"); + }); + Button btn3 = new Button("remove a/a"); + btn3.addClickListener(event -> { + data.removeItem("a/a"); + }); + Button btn4 = new Button("remove children of a/a"); + btn4.addClickListener(event -> { + data.removeItem("a/a/a"); + data.removeItem("a/a/c"); + }); + Button btn5 = new Button("remove a"); + btn5.addClickListener(event -> { + data.removeItem("a"); + }); + Button btn6 = new Button("remove children of a"); + btn6.addClickListener(event -> { + data.removeItem("a/a"); + data.removeItem("a/b"); + }); + Button btn7 = new Button("remove children of a/a/a"); + btn7.addClickListener(event -> { + data.removeItem("a/a/a/a"); + }); + + addComponents(grid, btn, btn2, btn3, btn4, btn5, btn6, btn7); + } +} diff --git a/uitest/src/test/java/com/vaadin/tests/components/treegrid/TreeGridChangingHierarchyTest.java b/uitest/src/test/java/com/vaadin/tests/components/treegrid/TreeGridChangingHierarchyTest.java new file mode 100644 index 0000000000..89273af661 --- /dev/null +++ b/uitest/src/test/java/com/vaadin/tests/components/treegrid/TreeGridChangingHierarchyTest.java @@ -0,0 +1,121 @@ +package com.vaadin.tests.components.treegrid; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.openqa.selenium.By; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.testbench.elements.TreeGridElement; +import com.vaadin.tests.tb3.SingleBrowserTest; + +public class TreeGridChangingHierarchyTest extends SingleBrowserTest { + + private TreeGridElement grid; + private ButtonElement addItemsToABtn; + private ButtonElement addItemsToAABtn; + private ButtonElement removeAABtn; + private ButtonElement removeChildrenOfAABtn; + private ButtonElement removeABtn; + private ButtonElement removeChildrenOfABtn; + private ButtonElement removeChildrenOfAAABtn; + + @Before + public void before() { + setDebug(true); + openTestURL(); + grid = $(TreeGridElement.class).first(); + addItemsToABtn = $(ButtonElement.class).get(0); + addItemsToAABtn = $(ButtonElement.class).get(1); + removeAABtn = $(ButtonElement.class).get(2); + removeChildrenOfAABtn = $(ButtonElement.class).get(3); + removeABtn = $(ButtonElement.class).get(4); + removeChildrenOfABtn = $(ButtonElement.class).get(5); + removeChildrenOfAAABtn = $(ButtonElement.class).get(6); + } + + @After + public void after() { + assertNoErrorNotifications(); + assertFalse(isElementPresent(By.className("v-errorindicator"))); + } + + @Test + public void removing_items_from_hierarchy() { + addItemsToABtn.click(); + addItemsToAABtn.click(); + grid.expandWithClick(0); + grid.expandWithClick(1); + grid.collapseWithClick(0); + removeAABtn.click(); + // Item removed from hierarchy. when encountering less children than + // expected, should reset: + grid.expandWithClick(0); + // expand "a" after the reset: + grid.expandWithClick(0); + // "a/a" should be removed from a's children: + assertEquals("a/b", grid.getCell(1, 0).getText()); + } + + @Test + public void removing_all_children_from_item() { + addItemsToABtn.click(); + assertTrue(grid.isRowCollapsed(0, 0)); + // drop added children from backing data source + removeChildrenOfABtn.click(); + // changes are not refreshed, thus the row should still appear as + // collapsed + assertTrue(grid.isRowCollapsed(0, 0)); + // when encountering 0 children, will reset + grid.expandWithClick(0); + assertEquals(3, grid.getRowCount()); + assertFalse(grid.hasExpandToggle(0, 0)); + // verify other items still expand/collapse correctly: + grid.expandWithClick(1); + assertEquals("b/a", grid.getCell(2, 0).getText()); + assertEquals(4, grid.getRowCount()); + grid.collapseWithClick(1); + assertEquals("c", grid.getCell(2, 0).getText()); + assertEquals(3, grid.getRowCount()); + } + + @Test + public void removal_of_deeply_nested_items() { + addItemsToABtn.click(); + addItemsToAABtn.click(); + grid.expandWithClick(0); + grid.expandWithClick(1); + grid.expandWithClick(2); + removeChildrenOfAAABtn.click(); + grid.collapseWithClick(1); + // reset should get triggered here + grid.expandWithClick(1); + grid.expandWithClick(0); + grid.expandWithClick(1); + assertEquals("a/a/a", grid.getCell(2, 0).getText()); + assertFalse(grid.hasExpandToggle(2, 0)); + } + + @Test + public void changing_selection_from_selected_removed_item() { + addItemsToABtn.click(); + grid.expandWithClick(0); + grid.getCell(1, 0).click(); + removeChildrenOfABtn.click(); + grid.collapseWithClick(0); + grid.getCell(1, 0).click(); + assertTrue(grid.getRow(1).isSelected()); + } + + @Test + public void remove_item_from_root() { + addItemsToABtn.click(); + removeABtn.click(); + grid.expandWithClick(0); + assertEquals("b", grid.getCell(0, 0).getText()); + } +} |