From: Mikael Grankvist Date: Wed, 11 Feb 2015 08:38:52 +0000 (+0200) Subject: Table should load widgets after container content refresh (#16611) X-Git-Tag: 7.4.1~34 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=4dcc41fd008700bdf30f4c2a414f31f889eb6ded;p=vaadin-framework.git Table should load widgets after container content refresh (#16611) Change-Id: I887830f31f886743d1bd7167236e2f7b61349dd7 --- diff --git a/client/src/com/vaadin/client/ui/VScrollTable.java b/client/src/com/vaadin/client/ui/VScrollTable.java index 6b4bb8eb9d..a648128f4d 100644 --- a/client/src/com/vaadin/client/ui/VScrollTable.java +++ b/client/src/com/vaadin/client/ui/VScrollTable.java @@ -1225,7 +1225,12 @@ public class VScrollTable extends FlowPanel implements HasWidgets, // Without this call the scroll position is messed up in IE even after // the lazy scroller has set the scroll position to the first visible // item - scrollBodyPanel.getScrollPosition(); + int pos = scrollBodyPanel.getScrollPosition(); + + // Reset first row in view port so client requests correct last row. + if (pos == 0) { + firstRowInViewPort = 0; + } scrollBody = createScrollBody(); @@ -3380,7 +3385,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, /** * Saves natural column width if it hasn't been saved already. - * + * * @param columnIndex * @since 7.3.9 */ @@ -4322,7 +4327,7 @@ public class VScrollTable extends FlowPanel implements HasWidgets, /** * Saves natural column width if it hasn't been saved already. - * + * * @param columnIndex * @since 7.3.9 */ diff --git a/uitest/src/com/vaadin/tests/components/table/ReloadWidgets.java b/uitest/src/com/vaadin/tests/components/table/ReloadWidgets.java new file mode 100644 index 0000000000..ef72f92a4e --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/ReloadWidgets.java @@ -0,0 +1,118 @@ +package com.vaadin.tests.components.table; + +import com.vaadin.data.util.BeanItemContainer; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Table; + +@SuppressWarnings("serial") +public class ReloadWidgets extends AbstractTestUI { + + int pressed = 0; + + @Override + protected void setup(VaadinRequest request) { + + final Table table = new Table(null, new BeanItemContainer( + Bean.class)); + table.setId("table"); + table.setSizeFull(); + + table.setColumnHeader("col1", "Text"); + table.setColumnHeader("col2", "Button"); + + fillTable(table); + + Button button = new Button("Refresh"); + button.setId("refresh"); + button.addClickListener(new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + table.removeAllItems(); + fillTable(table); + } + }); + getLayout().addComponent(button); + getLayout().addComponent(table); + getLayout().setExpandRatio(table, 1f); + } + + @Override + protected String getTestDescription() { + return "Table should always populate button widgets to column 2"; + } + + @Override + protected Integer getTicketNumber() { + return 16611; + } + + private void fillTable(Table table) { + int i = 0; + int size = pressed % 2 == 0 ? 500 : 499; + pressed++; + for (int step = 0; step < i + size; step++) { + String caption = Integer.toString(step); + Button button = new Button(caption); + button.setId(caption); + Bean itemId = new Bean(caption, button); + table.addItem(itemId); + } + } + + public class Bean { + private String col1; + private Button col2; + + public Bean(String col1, Button col2) { + this.col1 = col1; + this.col2 = col2; + } + + public String getCol1() { + return col1; + } + + public void setCol1(String col1) { + this.col1 = col1; + } + + public Button getCol2() { + return col2; + } + + public void setCol2(Button col2) { + this.col2 = col2; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + Bean bean = (Bean) o; + + if (!col1.equals(bean.col1)) { + return false; + } + if (!col2.equals(bean.col2)) { + return false; + } + + return true; + } + + @Override + public int hashCode() { + int result = col1.hashCode(); + result = 31 * result + col2.hashCode(); + return result; + } + } +} diff --git a/uitest/src/com/vaadin/tests/components/table/ReloadWidgetsTest.java b/uitest/src/com/vaadin/tests/components/table/ReloadWidgetsTest.java new file mode 100644 index 0000000000..c92e00ab29 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/table/ReloadWidgetsTest.java @@ -0,0 +1,80 @@ +package com.vaadin.tests.components.table; + +import java.util.List; + +import org.junit.Assert; +import org.junit.Test; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.support.ui.ExpectedCondition; + +import com.vaadin.testbench.By; +import com.vaadin.testbench.elements.TableElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +public class ReloadWidgetsTest extends MultiBrowserTest { + + private int rowHeight = -1; + + private WebElement wrapper; + + @Override + public void setup() throws Exception { + super.setup(); + openTestURL(); + + TableElement table = $(TableElement.class).id("table"); + rowHeight = table.getCell(1, 0).getLocation().getY() + - table.getCell(0, 0).getLocation().getY(); + + wrapper = findElement(By.className("v-table-body-wrapper")); + } + + @Test + public void testScrollingThenUpdatingContents() throws Exception { + // Scroll down to row 44 so that we get the cut-off point where the + // problem becomes apparent + testBenchElement(wrapper).scroll(44 * rowHeight); + waitForScrollToFinish(); + + // Assert that we have the button widget. + Assert.assertTrue( + "Button widget was not found after scrolling for the first time", + !findElements(By.id("46")).isEmpty()); + + // Now refresh the container contents + WebElement refreshButton = findElement(By.id("refresh")); + refreshButton.click(); + + // Again scroll down to row 44 so we get the cut-off point visible + testBenchElement(wrapper).scroll(44 * rowHeight); + waitForScrollToFinish(); + + // Assert that we still get the button + Assert.assertTrue( + "Button widget was not found after refreshing container items.", + !findElements(By.id("46")).isEmpty()); + } + + /** + * Waits until the scroll position indicator goes away, signifying that all + * the required rows have been fetched. + */ + private void waitForScrollToFinish() { + waitUntil(new ExpectedCondition() { + @Override + public Boolean apply(WebDriver input) { + List elements = findElements(By + .className("v-table-scrollposition")); + return elements.isEmpty() || !elements.get(0).isDisplayed(); + } + + @Override + public String toString() { + // Timed out after 10 seconds waiting for ... + return "scroll position indicator to vanish"; + } + }); + } + +}