summaryrefslogtreecommitdiffstats
path: root/uitest
diff options
context:
space:
mode:
authorPekka Hyvönen <pekka@vaadin.com>2015-04-30 13:40:45 +0300
committerPekka Hyvönen <pekka@vaadin.com>2015-04-30 13:40:52 +0300
commitef9fb276a93d1a7967ef0e6405dee56c8aa2a148 (patch)
tree622280f6e6e2904fef61c3483fe36e14ab6b924d /uitest
parenta9bc160aee00b93340ac3f047505e032d4a696b0 (diff)
parentbbf30fff168fd4a9552d23c8341e27aa1821884b (diff)
downloadvaadin-framework-ef9fb276a93d1a7967ef0e6405dee56c8aa2a148.tar.gz
vaadin-framework-ef9fb276a93d1a7967ef0e6405dee56c8aa2a148.zip
Merge branch 'grid-7.5'
Change-Id: Ifa976fa4be1258fd35999de17775da70afedb2a8
Diffstat (limited to 'uitest')
-rw-r--r--uitest/src/com/vaadin/testbench/elements/GridElement.java367
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridDetailsLocation.java121
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/GridDetailsLocationTest.java361
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorBasicClientFeaturesTest.java75
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java22
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java287
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java139
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridColumnHidingTest.java994
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridColumnReorderTest.java649
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSidebarFeatures.java24
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridDetailsClientTest.java241
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridSidebarContentTest.java156
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/element/CustomGridElement.java46
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorBasicsTest.java6
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorSpacerTest.java583
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridColumnReorderTest.java347
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridColumnVisibilityTest.java280
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridDetailsServerTest.java306
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSidebarThemeTest.java84
-rw-r--r--uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/LoadingIndicatorTest.java7
-rw-r--r--uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java20
-rw-r--r--uitest/src/com/vaadin/tests/util/PersonContainer.java6
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorBasicClientFeaturesWidget.java114
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorProxy.java35
-rw-r--r--uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java344
25 files changed, 5212 insertions, 402 deletions
diff --git a/uitest/src/com/vaadin/testbench/elements/GridElement.java b/uitest/src/com/vaadin/testbench/elements/GridElement.java
deleted file mode 100644
index 68ddfc878e..0000000000
--- a/uitest/src/com/vaadin/testbench/elements/GridElement.java
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * Copyright 2000-2014 Vaadin Ltd.
- *
- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License. You may obtain a copy of
- * the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package com.vaadin.testbench.elements;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.openqa.selenium.NoSuchElementException;
-import org.openqa.selenium.WebElement;
-
-import com.vaadin.testbench.By;
-import com.vaadin.testbench.TestBenchElement;
-import com.vaadin.testbench.elementsbase.AbstractElement;
-import com.vaadin.testbench.elementsbase.ServerClass;
-
-/**
- * TestBench Element API for Grid
- *
- * @since
- * @author Vaadin Ltd
- */
-@ServerClass("com.vaadin.ui.Grid")
-public class GridElement extends AbstractComponentElement {
-
- public static class GridCellElement extends AbstractElement {
-
- private static final String FOCUSED_CELL_CLASS_NAME = "-cell-focused";
- private static final String FROZEN_CLASS_NAME = "frozen";
-
- public boolean isFocused() {
- return getAttribute("class").contains(FOCUSED_CELL_CLASS_NAME);
- }
-
- public boolean isFrozen() {
- return getAttribute("class").contains(FROZEN_CLASS_NAME);
- }
- }
-
- public static class GridRowElement extends AbstractElement {
-
- private static final String FOCUSED_CLASS_NAME = "-row-focused";
- private static final String SELECTED_CLASS_NAME = "-row-selected";
-
- public boolean isFocused() {
- return getAttribute("class").contains(FOCUSED_CLASS_NAME);
- }
-
- @Override
- public boolean isSelected() {
- return getAttribute("class").contains(SELECTED_CLASS_NAME);
- }
- }
-
- public static class GridEditorElement extends AbstractElement {
-
- private GridElement grid;
-
- private GridEditorElement setGrid(GridElement grid) {
- this.grid = grid;
- return this;
- }
-
- /**
- * Gets the editor field for column in given index.
- *
- * @param colIndex
- * the column index
- * @return the editor field for given location
- *
- * @throws NoSuchElementException
- * if {@code isEditable(colIndex) == false}
- */
- public TestBenchElement getField(int colIndex) {
- return grid.getSubPart("#editor[" + colIndex + "]");
- }
-
- /**
- * Gets whether the column with the given index is editable, that is,
- * has an associated editor field.
- *
- * @param colIndex
- * the column index
- * @return {@code true} if the column has an editor field, {@code false}
- *  otherwise
- */
- public boolean isEditable(int colIndex) {
- return grid
- .isElementPresent(By.vaadin("#editor[" + colIndex + "]"));
- }
-
- /**
- * Checks whether a field is marked with an error.
- *
- * @param colIndex
- * column index
- * @return <code>true</code> iff the field is marked with an error
- */
- public boolean isFieldErrorMarked(int colIndex) {
- return getField(colIndex).getAttribute("class").contains("error");
- }
-
- /**
- * Saves the fields of this editor.
- * <p>
- * <em>Note:</em> that this closes the editor making this element
- * useless.
- */
- public void save() {
- findElement(By.className("v-grid-editor-save")).click();
- }
-
- /**
- * Cancels this editor.
- * <p>
- * <em>Note:</em> that this closes the editor making this element
- * useless.
- */
- public void cancel() {
- findElement(By.className("v-grid-editor-cancel")).click();
- }
-
- /**
- * Gets the error message text, or <code>null</code> if no message is
- * present.
- */
- public String getErrorMessage() {
- WebElement messageWrapper = findElement(By
- .className("v-grid-editor-message"));
- List<WebElement> divs = messageWrapper.findElements(By
- .tagName("div"));
- if (divs.isEmpty()) {
- return null;
- } else {
- return divs.get(0).getText();
- }
- }
- }
-
- /**
- * Scrolls Grid element so that wanted row is displayed
- *
- * @param index
- * Target row
- */
- public void scrollToRow(int index) {
- try {
- getSubPart("#cell[" + index + "]");
- } catch (NoSuchElementException e) {
- // Expected, ignore it.
- }
- }
-
- /**
- * Gets cell element with given row and column index.
- *
- * @param rowIndex
- * Row index
- * @param colIndex
- * Column index
- * @return Cell element with given indices.
- */
- public GridCellElement getCell(int rowIndex, int colIndex) {
- scrollToRow(rowIndex);
- return getSubPart("#cell[" + rowIndex + "][" + colIndex + "]").wrap(
- GridCellElement.class);
- }
-
- /**
- * Gets row element with given row index.
- *
- * @param index
- * Row index
- * @return Row element with given index.
- */
- public GridRowElement getRow(int index) {
- scrollToRow(index);
- return getSubPart("#cell[" + index + "]").wrap(GridRowElement.class);
- }
-
- /**
- * Gets header cell element with given row and column index.
- *
- * @param rowIndex
- * Row index
- * @param colIndex
- * Column index
- * @return Header cell element with given indices.
- */
- public GridCellElement getHeaderCell(int rowIndex, int colIndex) {
- return getSubPart("#header[" + rowIndex + "][" + colIndex + "]").wrap(
- GridCellElement.class);
- }
-
- /**
- * Gets footer cell element with given row and column index.
- *
- * @param rowIndex
- * Row index
- * @param colIndex
- * Column index
- * @return Footer cell element with given indices.
- */
- public GridCellElement getFooterCell(int rowIndex, int colIndex) {
- return getSubPart("#footer[" + rowIndex + "][" + colIndex + "]").wrap(
- GridCellElement.class);
- }
-
- /**
- * Gets list of header cell elements on given row.
- *
- * @param rowIndex
- * Row index
- * @return Header cell elements on given row.
- */
- public List<GridCellElement> getHeaderCells(int rowIndex) {
- List<GridCellElement> headers = new ArrayList<GridCellElement>();
- for (TestBenchElement e : TestBenchElement.wrapElements(
- getSubPart("#header[" + rowIndex + "]").findElements(
- By.xpath("./th")), getCommandExecutor())) {
- headers.add(e.wrap(GridCellElement.class));
- }
- return headers;
- }
-
- /**
- * Gets list of header cell elements on given row.
- *
- * @param rowIndex
- * Row index
- * @return Header cell elements on given row.
- */
- public List<GridCellElement> getFooterCells(int rowIndex) {
- List<GridCellElement> footers = new ArrayList<GridCellElement>();
- for (TestBenchElement e : TestBenchElement.wrapElements(
- getSubPart("#footer[" + rowIndex + "]").findElements(
- By.xpath("./td")), getCommandExecutor())) {
- footers.add(e.wrap(GridCellElement.class));
- }
- return footers;
- }
-
- /**
- * Get header row count
- *
- * @return Header row count
- */
- public int getHeaderCount() {
- return getSubPart("#header").findElements(By.xpath("./tr")).size();
- }
-
- /**
- * Get footer row count
- *
- * @return Footer row count
- */
- public int getFooterCount() {
- return getSubPart("#footer").findElements(By.xpath("./tr")).size();
- }
-
- /**
- * Get a header row by index
- *
- * @param rowIndex
- * Row index
- * @return The th element of the row
- */
- public TestBenchElement getHeaderRow(int rowIndex) {
- return getSubPart("#header[" + rowIndex + "]");
- }
-
- /**
- * Get a footer row by index
- *
- * @param rowIndex
- * Row index
- * @return The tr element of the row
- */
- public TestBenchElement getFooterRow(int rowIndex) {
- return getSubPart("#footer[" + rowIndex + "]");
- }
-
- /**
- * Get the vertical scroll element
- *
- * @return The element representing the vertical scrollbar
- */
- public TestBenchElement getVerticalScroller() {
- List<WebElement> rootElements = findElements(By.xpath("./div"));
- return (TestBenchElement) rootElements.get(0);
- }
-
- /**
- * Get the horizontal scroll element
- *
- * @return The element representing the horizontal scrollbar
- */
- public TestBenchElement getHorizontalScroller() {
- List<WebElement> rootElements = findElements(By.xpath("./div"));
- return (TestBenchElement) rootElements.get(1);
- }
-
- /**
- * Get the header element
- *
- * @return The thead element
- */
- public TestBenchElement getHeader() {
- return getSubPart("#header");
- }
-
- /**
- * Get the body element
- *
- * @return the tbody element
- */
- public TestBenchElement getBody() {
- return getSubPart("#cell");
- }
-
- /**
- * Get the footer element
- *
- * @return the tfoot element
- */
- public TestBenchElement getFooter() {
- return getSubPart("#footer");
- }
-
- /**
- * Get the element wrapping the table element
- *
- * @return The element that wraps the table element
- */
- public TestBenchElement getTableWrapper() {
- List<WebElement> rootElements = findElements(By.xpath("./div"));
- return (TestBenchElement) rootElements.get(2);
- }
-
- public GridEditorElement getEditor() {
- return getSubPart("#editor").wrap(GridEditorElement.class)
- .setGrid(this);
- }
-
- /**
- * Helper function to get Grid subparts wrapped correctly
- *
- * @param subPartSelector
- * SubPart to be used in ComponentLocator
- * @return SubPart element wrapped in TestBenchElement class
- */
- private TestBenchElement getSubPart(String subPartSelector) {
- return (TestBenchElement) findElement(By.vaadin(subPartSelector));
- }
-}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridDetailsLocation.java b/uitest/src/com/vaadin/tests/components/grid/GridDetailsLocation.java
new file mode 100644
index 0000000000..2880df44b0
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridDetailsLocation.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import com.vaadin.annotations.Theme;
+import com.vaadin.data.Property.ValueChangeEvent;
+import com.vaadin.data.Property.ValueChangeListener;
+import com.vaadin.server.VaadinRequest;
+import com.vaadin.tests.util.Person;
+import com.vaadin.tests.util.PersonContainer;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.CheckBox;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.Grid.DetailsGenerator;
+import com.vaadin.ui.Grid.RowReference;
+import com.vaadin.ui.Grid.SelectionMode;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Layout;
+import com.vaadin.ui.TextField;
+import com.vaadin.ui.UI;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.themes.ValoTheme;
+
+@Theme(ValoTheme.THEME_NAME)
+public class GridDetailsLocation extends UI {
+
+ private final DetailsGenerator detailsGenerator = new DetailsGenerator() {
+ @Override
+ public Component getDetails(RowReference rowReference) {
+ Person person = (Person) rowReference.getItemId();
+ Label label = new Label(person.getFirstName() + " "
+ + person.getLastName());
+ // currently the decorator row doesn't change its height when the
+ // content height is different.
+ label.setHeight("30px");
+ return label;
+ }
+ };
+
+ private TextField numberTextField;
+ private Grid grid;
+
+ @Override
+ protected void init(VaadinRequest request) {
+
+ Layout layout = new VerticalLayout();
+
+ grid = new Grid(PersonContainer.createWithTestData(1000));
+ grid.setSelectionMode(SelectionMode.NONE);
+ layout.addComponent(grid);
+
+ final CheckBox checkbox = new CheckBox("Details generator");
+ checkbox.addValueChangeListener(new ValueChangeListener() {
+ @Override
+ @SuppressWarnings("boxing")
+ public void valueChange(ValueChangeEvent event) {
+ if (checkbox.getValue()) {
+ grid.setDetailsGenerator(detailsGenerator);
+ } else {
+ grid.setDetailsGenerator(DetailsGenerator.NULL);
+ }
+ }
+ });
+ layout.addComponent(checkbox);
+
+ numberTextField = new TextField("Row");
+ numberTextField.setImmediate(true);
+ layout.addComponent(numberTextField);
+
+ layout.addComponent(new Button("Toggle and scroll",
+ new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ toggle();
+ scrollTo();
+ }
+ }));
+ layout.addComponent(new Button("Scroll and toggle",
+ new Button.ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ scrollTo();
+ toggle();
+ }
+ }));
+
+ setContent(layout);
+ }
+
+ private void toggle() {
+ Object itemId = getItemId();
+ boolean isVisible = grid.isDetailsVisible(itemId);
+ grid.setDetailsVisible(itemId, !isVisible);
+ }
+
+ private void scrollTo() {
+ grid.scrollTo(getItemId());
+ }
+
+ private Object getItemId() {
+ int row = Integer.parseInt(numberTextField.getValue());
+ Object itemId = grid.getContainerDataSource().getIdByIndex(row);
+ return itemId;
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/GridDetailsLocationTest.java b/uitest/src/com/vaadin/tests/components/grid/GridDetailsLocationTest.java
new file mode 100644
index 0000000000..c14503fb8d
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/GridDetailsLocationTest.java
@@ -0,0 +1,361 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.JavascriptExecutor;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.StaleElementReferenceException;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.remote.DesiredCapabilities;
+import org.openqa.selenium.support.ui.ExpectedCondition;
+
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.elements.ButtonElement;
+import com.vaadin.testbench.elements.CheckBoxElement;
+import com.vaadin.testbench.elements.GridElement.GridRowElement;
+import com.vaadin.testbench.elements.TextFieldElement;
+import com.vaadin.testbench.parallel.Browser;
+import com.vaadin.testbench.parallel.TestCategory;
+import com.vaadin.tests.components.grid.basicfeatures.element.CustomGridElement;
+import com.vaadin.tests.tb3.MultiBrowserTest;
+
+@TestCategory("grid")
+public class GridDetailsLocationTest extends MultiBrowserTest {
+
+ private static final int detailsDefaultHeight = 51;
+ private static final int detailsDefinedHeight = 33;
+ private static final int detailsDefinedHeightIE8 = 31;
+
+ private static class Param {
+ private final int rowIndex;
+ private final boolean useGenerator;
+ private final boolean scrollFirstToBottom;
+
+ public Param(int rowIndex, boolean useGenerator,
+ boolean scrollFirstToBottom) {
+ this.rowIndex = rowIndex;
+ this.useGenerator = useGenerator;
+ this.scrollFirstToBottom = scrollFirstToBottom;
+ }
+
+ public int getRowIndex() {
+ return rowIndex;
+ }
+
+ public boolean useGenerator() {
+ return useGenerator;
+ }
+
+ public boolean scrollFirstToBottom() {
+ return scrollFirstToBottom;
+ }
+
+ @Override
+ public String toString() {
+ return "Param [rowIndex=" + getRowIndex() + ", useGenerator="
+ + useGenerator() + ", scrollFirstToBottom="
+ + scrollFirstToBottom() + "]";
+ }
+
+ }
+
+ public static Collection<Param> parameters() {
+ List<Param> data = new ArrayList<Param>();
+
+ int[] params = new int[] { 0, 500, 999 };
+
+ for (int rowIndex : params) {
+
+ data.add(new Param(rowIndex, false, false));
+ data.add(new Param(rowIndex, true, false));
+ data.add(new Param(rowIndex, false, true));
+ data.add(new Param(rowIndex, true, true));
+ }
+
+ return data;
+ }
+
+ @Before
+ public void setUp() {
+ setDebug(true);
+ }
+
+ @Test
+ public void toggleAndScroll() throws Throwable {
+ for (Param param : parameters()) {
+ try {
+ openTestURL();
+ useGenerator(param.useGenerator());
+ scrollToBottom(param.scrollFirstToBottom());
+
+ // the tested method
+ toggleAndScroll(param.getRowIndex());
+
+ verifyLocation(param);
+ } catch (Throwable t) {
+ throw new Throwable("" + param, t);
+ }
+ }
+ }
+
+ @Test
+ public void scrollAndToggle() throws Throwable {
+ for (Param param : parameters()) {
+ try {
+ openTestURL();
+ useGenerator(param.useGenerator());
+ scrollToBottom(param.scrollFirstToBottom());
+
+ // the tested method
+ scrollAndToggle(param.getRowIndex());
+
+ verifyLocation(param);
+
+ } catch (Throwable t) {
+ throw new Throwable("" + param, t);
+ }
+ }
+ }
+
+ @Test
+ public void testDetailsHeightWithNoGenerator() {
+ openTestURL();
+ toggleAndScroll(5);
+
+ verifyDetailsRowHeight(5, detailsDefaultHeight, 0);
+ verifyDetailsDecoratorLocation(5, 0, 0);
+
+ toggleAndScroll(0);
+
+ verifyDetailsRowHeight(0, detailsDefaultHeight, 0);
+ verifyDetailsDecoratorLocation(0, 0, 1);
+
+ verifyDetailsRowHeight(5, detailsDefaultHeight, 1);
+ verifyDetailsDecoratorLocation(5, 1, 0);
+ }
+
+ @Test
+ public void testDetailsHeightWithGenerator() {
+ openTestURL();
+ useGenerator(true);
+ toggleAndScroll(5);
+
+ verifyDetailsRowHeight(5, getDefinedHeight(), 0);
+ verifyDetailsDecoratorLocation(5, 0, 0);
+
+ toggleAndScroll(0);
+
+ verifyDetailsRowHeight(0, getDefinedHeight(), 0);
+ // decorator elements are in DOM in the order they have been added
+ verifyDetailsDecoratorLocation(0, 0, 1);
+
+ verifyDetailsRowHeight(5, getDefinedHeight(), 1);
+ verifyDetailsDecoratorLocation(5, 1, 0);
+ }
+
+ private int getDefinedHeight() {
+ boolean ie8 = isIE8();
+ return ie8 ? detailsDefinedHeightIE8 : detailsDefinedHeight;
+ }
+
+ private void verifyDetailsRowHeight(int rowIndex, int expectedHeight,
+ int visibleIndexOfSpacer) {
+ waitForDetailsVisible();
+ WebElement details = getDetailsElement(visibleIndexOfSpacer);
+ Assert.assertEquals("Wrong details row height", expectedHeight, details
+ .getSize().getHeight());
+ }
+
+ private void verifyDetailsDecoratorLocation(int row,
+ int visibleIndexOfSpacer, int visibleIndexOfDeco) {
+ WebElement detailsElement = getDetailsElement(visibleIndexOfSpacer);
+ WebElement detailsDecoElement = getDetailsDecoElement(visibleIndexOfDeco);
+ GridRowElement rowElement = getGrid().getRow(row);
+
+ Assert.assertEquals(
+ "Details deco top position does not match row top pos",
+ rowElement.getLocation().getY(), detailsDecoElement
+ .getLocation().getY());
+ Assert.assertEquals(
+ "Details deco bottom position does not match details bottom pos",
+ detailsElement.getLocation().getY()
+ + detailsElement.getSize().getHeight(),
+ detailsDecoElement.getLocation().getY()
+ + detailsDecoElement.getSize().getHeight());
+ }
+
+ private void verifyLocation(Param param) {
+ Assert.assertFalse("Notification was present",
+ isElementPresent(By.className("v-Notification")));
+
+ TestBenchElement headerRow = getGrid().getHeaderRow(0);
+ final int topBoundary = headerRow.getLocation().getX()
+ + headerRow.getSize().height;
+ final int bottomBoundary = getGrid().getLocation().getX()
+ + getGrid().getSize().getHeight()
+ - getHorizontalScrollbar().getSize().height;
+
+ GridRowElement row = getGrid().getRow(param.getRowIndex());
+ final int rowTop = row.getLocation().getX();
+
+ waitForDetailsVisible();
+ WebElement details = getDetailsElement();
+ final int detailsBottom = details.getLocation().getX()
+ + details.getSize().getHeight();
+
+ assertGreaterOrEqual("Row top should be inside grid, gridTop:"
+ + topBoundary + " rowTop" + rowTop, topBoundary, rowTop);
+ assertLessThanOrEqual(
+ "Decorator bottom should be inside grid, gridBottom:"
+ + bottomBoundary + " decoratorBotton:" + detailsBottom,
+ detailsBottom, bottomBoundary);
+
+ verifyDetailsRowHeight(param.getRowIndex(),
+ param.useGenerator() ? getDefinedHeight()
+ : detailsDefaultHeight, 0);
+ verifyDetailsDecoratorLocation(param.getRowIndex(), 0, 0);
+
+ Assert.assertFalse("Notification was present",
+ isElementPresent(By.className("v-Notification")));
+ }
+
+ private final By locator = By.className("v-grid-spacer");
+
+ private WebElement getDetailsElement() {
+ return getDetailsElement(0);
+ }
+
+ private WebElement getDetailsElement(int index) {
+ return findElements(locator).get(index);
+ }
+
+ private WebElement getDetailsDecoElement(int index) {
+ return findElements(By.className("v-grid-spacer-deco")).get(index);
+ }
+
+ private void waitForDetailsVisible() {
+ waitUntil(new ExpectedCondition<WebElement>() {
+
+ @Override
+ public WebElement apply(WebDriver driver) {
+ try {
+ WebElement detailsElement = getDetailsElement();
+ return detailsElement.isDisplayed()
+ && detailsElement.getSize().getHeight() > 3 ? detailsElement
+ : null;
+ } catch (StaleElementReferenceException e) {
+ return null;
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "visibility of element located by " + locator;
+ }
+
+ }, 5);
+ waitForElementVisible(By.className("v-grid-spacer"));
+ }
+
+ private void scrollToBottom(boolean scrollFirstToBottom) {
+ if (scrollFirstToBottom) {
+ executeScript("arguments[0].scrollTop = 9999999",
+ getVerticalScrollbar());
+ }
+ }
+
+ private void useGenerator(boolean use) {
+ CheckBoxElement checkBox = $(CheckBoxElement.class).first();
+ boolean isChecked = isCheckedValo(checkBox);
+ if (use != isChecked) {
+ clickValo(checkBox);
+ }
+ }
+
+ private boolean isIE8() {
+ DesiredCapabilities desiredCapabilities = getDesiredCapabilities();
+ DesiredCapabilities ie8Capabilities = Browser.IE8
+ .getDesiredCapabilities();
+ return desiredCapabilities.getBrowserName().equals(
+ ie8Capabilities.getBrowserName())
+ && desiredCapabilities.getVersion().equals(
+ ie8Capabilities.getVersion());
+ }
+
+ @SuppressWarnings("boxing")
+ private boolean isCheckedValo(CheckBoxElement checkBoxElement) {
+ WebElement checkbox = checkBoxElement.findElement(By.tagName("input"));
+ Object value = executeScript("return arguments[0].checked;", checkbox);
+ return (Boolean) value;
+ }
+
+ private void clickValo(CheckBoxElement checkBoxElement) {
+ checkBoxElement.findElement(By.tagName("label")).click();
+ }
+
+ private Object executeScript(String string, Object... param) {
+ return ((JavascriptExecutor) getDriver()).executeScript(string, param);
+ }
+
+ private void scrollAndToggle(int row) {
+ setRow(row);
+ getScrollAndToggle().click();
+ }
+
+ private void toggleAndScroll(int row) {
+ setRow(row);
+ getToggleAndScroll().click();
+ }
+
+ private ButtonElement getScrollAndToggle() {
+ return $(ButtonElement.class).caption("Scroll and toggle").first();
+ }
+
+ private ButtonElement getToggleAndScroll() {
+ return $(ButtonElement.class).caption("Toggle and scroll").first();
+ }
+
+ private void setRow(int row) {
+ $(TextFieldElement.class).first().clear();
+ $(TextFieldElement.class).first().sendKeys(String.valueOf(row),
+ Keys.ENTER, Keys.TAB);
+ }
+
+ private CustomGridElement getGrid() {
+ return $(CustomGridElement.class).first();
+ }
+
+ private WebElement getVerticalScrollbar() {
+ WebElement scrollBar = getGrid().findElement(
+ By.className("v-grid-scroller-vertical"));
+ return scrollBar;
+ }
+
+ private WebElement getHorizontalScrollbar() {
+ WebElement scrollBar = getGrid().findElement(
+ By.className("v-grid-scroller-horizontal"));
+ return scrollBar;
+ }
+} \ No newline at end of file
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorBasicClientFeaturesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorBasicClientFeaturesTest.java
index e03d50415c..c1b8028cbf 100644
--- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorBasicClientFeaturesTest.java
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorBasicClientFeaturesTest.java
@@ -19,6 +19,8 @@ import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import java.util.List;
+
import org.openqa.selenium.By;
import org.openqa.selenium.Dimension;
import org.openqa.selenium.JavascriptExecutor;
@@ -29,15 +31,21 @@ import com.vaadin.testbench.TestBenchElement;
import com.vaadin.testbench.parallel.TestCategory;
import com.vaadin.tests.tb3.MultiBrowserTest;
-@TestCategory("escalator")
+@TestCategory("grid")
public abstract class EscalatorBasicClientFeaturesTest extends MultiBrowserTest {
+
+ private static final String LOGICAL_ROW_ATTRIBUTE_NAME = "vLogicalRow";
+ private static final String SPACER_CSS_CLASS = "v-escalator-spacer";
+
protected static final String COLUMNS_AND_ROWS = "Columns and Rows";
protected static final String COLUMNS = "Columns";
protected static final String ADD_ONE_COLUMN_TO_BEGINNING = "Add one column to beginning";
protected static final String ADD_ONE_ROW_TO_BEGINNING = "Add one row to beginning";
+ protected static final String ADD_ONE_ROW_TO_END = "Add one row to end";
protected static final String REMOVE_ONE_COLUMN_FROM_BEGINNING = "Remove one column from beginning";
protected static final String REMOVE_ONE_ROW_FROM_BEGINNING = "Remove one row from beginning";
+ protected static final String REMOVE_ALL_ROWS = "Remove all rows";
protected static final String REMOVE_50_ROWS_FROM_BOTTOM = "Remove 50 rows from bottom";
protected static final String REMOVE_50_ROWS_FROM_ALMOST_BOTTOM = "Remove 50 rows from almost bottom";
protected static final String ADD_ONE_OF_EACH_ROW = "Add one of each row";
@@ -48,6 +56,8 @@ public abstract class EscalatorBasicClientFeaturesTest extends MultiBrowserTest
protected static final String BODY_ROWS = "Body Rows";
protected static final String FOOTER_ROWS = "Footer Rows";
+ protected static final String SCROLL_TO = "Scroll to...";
+
protected static final String REMOVE_ALL_INSERT_SCROLL = "Remove all, insert 30 and scroll 40px";
protected static final String GENERAL = "General";
@@ -65,6 +75,20 @@ public abstract class EscalatorBasicClientFeaturesTest extends MultiBrowserTest
protected static final String COLUMN_SPANNING = "Column spanning";
protected static final String COLSPAN_NORMAL = "Apply normal colspan";
protected static final String COLSPAN_NONE = "Apply no colspan";
+ protected static final String SET_100PX = "Set 100px";
+ protected static final String SPACERS = "Spacers";
+ protected static final String FOCUSABLE_UPDATER = "Focusable Updater";
+ protected static final String SCROLL_HERE_ANY_0PADDING = "Scroll here (ANY, 0)";
+ protected static final String SCROLL_HERE_SPACERBELOW_ANY_0PADDING = "Scroll here row+spacer below (ANY, 0)";
+ protected static final String REMOVE = "Remove";
+
+ protected static final String ROW_MINUS1 = "Row -1";
+ protected static final String ROW_0 = "Row 0";
+ protected static final String ROW_1 = "Row 1";
+ protected static final String ROW_25 = "Row 25";
+ protected static final String ROW_50 = "Row 50";
+ protected static final String ROW_75 = "Row 75";
+ protected static final String ROW_99 = "Row 99";
@Override
protected Class<?> getUIClass() {
@@ -163,15 +187,16 @@ public abstract class EscalatorBasicClientFeaturesTest extends MultiBrowserTest
private TestBenchElement getRow(String sectionTag, int row) {
TestBenchElement escalator = getEscalator();
WebElement tableSection = escalator.findElement(By.tagName(sectionTag));
- By xpath;
+ String xpathExpression = "tr[not(@class='" + SPACER_CSS_CLASS + "')]";
if (row >= 0) {
int fromFirst = row + 1;
- xpath = By.xpath("tr[" + fromFirst + "]");
+ xpathExpression += "[" + fromFirst + "]";
} else {
int fromLast = Math.abs(row + 1);
- xpath = By.xpath("tr[last() - " + fromLast + "]");
+ xpathExpression += "[last() - " + fromLast + "]";
}
+ By xpath = By.xpath(xpathExpression);
if (tableSection != null
&& ((TestBenchElement) tableSection).isElementPresent(xpath)) {
return (TestBenchElement) tableSection.findElement(xpath);
@@ -235,17 +260,26 @@ public abstract class EscalatorBasicClientFeaturesTest extends MultiBrowserTest
}
protected void scrollVerticallyTo(int px) {
- executeScript("arguments[0].scrollTop = " + px, getVerticalScrollbar());
+ getVerticalScrollbar().scroll(px);
}
- protected TestBenchElement getVerticalScrollbar() {
+ protected long getScrollTop() {
+ return ((Long) executeScript("return arguments[0].scrollTop;",
+ getVerticalScrollbar())).longValue();
+ }
+
+ private TestBenchElement getVerticalScrollbar() {
return (TestBenchElement) getEscalator().findElement(
By.className("v-escalator-scroller-vertical"));
}
protected void scrollHorizontallyTo(int px) {
- executeScript("arguments[0].scrollLeft = " + px,
- getHorizontalScrollbar());
+ getHorizontalScrollbar().scrollLeft(px);
+ }
+
+ protected long getScrollLeft() {
+ return ((Long) executeScript("return arguments[0].scrollLeft;",
+ getHorizontalScrollbar())).longValue();
}
protected TestBenchElement getHorizontalScrollbar() {
@@ -260,4 +294,29 @@ public abstract class EscalatorBasicClientFeaturesTest extends MultiBrowserTest
protected void populate() {
selectMenuPath(GENERAL, POPULATE_COLUMN_ROW);
}
+
+ private List<WebElement> getSpacers() {
+ return getEscalator().findElements(By.className(SPACER_CSS_CLASS));
+ }
+
+ protected boolean spacersAreFoundInDom() {
+ List<WebElement> spacers = getSpacers();
+ return spacers != null && !spacers.isEmpty();
+ }
+
+ @SuppressWarnings("boxing")
+ protected WebElement getSpacer(int logicalRowIndex) {
+ List<WebElement> spacers = getSpacers();
+ System.out.println("size: " + spacers.size());
+ for (WebElement spacer : spacers) {
+ System.out.println(spacer + ", " + logicalRowIndex);
+ Boolean isInDom = (Boolean) executeScript("return arguments[0]['"
+ + LOGICAL_ROW_ATTRIBUTE_NAME + "'] === arguments[1]",
+ spacer, logicalRowIndex);
+ if (isInDom) {
+ return spacer;
+ }
+ }
+ return null;
+ }
}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java
index ad3e1fe5eb..754529d10d 100644
--- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java
@@ -15,13 +15,15 @@
*/
package com.vaadin.tests.components.grid.basicfeatures;
+import java.util.List;
+
import org.openqa.selenium.Dimension;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import com.vaadin.testbench.By;
import com.vaadin.testbench.TestBenchElement;
-import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.tests.components.grid.basicfeatures.element.CustomGridElement;
/**
* GridBasicClientFeatures.
@@ -79,13 +81,27 @@ public abstract class GridBasicClientFeaturesTest extends GridBasicFeaturesTest
}
@Override
- protected GridElement getGridElement() {
+ protected CustomGridElement getGridElement() {
if (composite) {
// Composite requires the basic client features widget for subparts
return ((TestBenchElement) findElement(By
- .vaadin("//TestWidgetComponent"))).wrap(GridElement.class);
+ .vaadin("//TestWidgetComponent")))
+ .wrap(CustomGridElement.class);
} else {
return super.getGridElement();
}
}
+
+ @Override
+ protected void assertColumnHeaderOrder(int... indices) {
+ List<TestBenchElement> headers = getGridHeaderRowCells();
+ for (int i = 0; i < indices.length; i++) {
+ assertColumnHeader("HEADER (0," + indices[i] + ")", headers.get(i));
+ }
+ }
+
+ protected void toggleColumnReorder() {
+ selectMenuPath("Component", "State", "Column Reordering");
+ }
+
}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java
index e5a46894b8..8c60deaf3c 100644
--- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java
@@ -46,10 +46,17 @@ import com.vaadin.tests.components.AbstractComponentTest;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.CssLayout;
import com.vaadin.ui.Grid;
import com.vaadin.ui.Grid.CellReference;
import com.vaadin.ui.Grid.CellStyleGenerator;
import com.vaadin.ui.Grid.Column;
+import com.vaadin.ui.Grid.ColumnReorderEvent;
+import com.vaadin.ui.Grid.ColumnReorderListener;
+import com.vaadin.ui.Grid.ColumnVisibilityChangeEvent;
+import com.vaadin.ui.Grid.ColumnVisibilityChangeListener;
+import com.vaadin.ui.Grid.DetailsGenerator;
import com.vaadin.ui.Grid.FooterCell;
import com.vaadin.ui.Grid.HeaderCell;
import com.vaadin.ui.Grid.HeaderRow;
@@ -58,6 +65,9 @@ import com.vaadin.ui.Grid.RowReference;
import com.vaadin.ui.Grid.RowStyleGenerator;
import com.vaadin.ui.Grid.SelectionMode;
import com.vaadin.ui.Grid.SelectionModel;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.Notification;
+import com.vaadin.ui.Panel;
import com.vaadin.ui.renderers.DateRenderer;
import com.vaadin.ui.renderers.HtmlRenderer;
import com.vaadin.ui.renderers.NumberRenderer;
@@ -109,6 +119,74 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
}
};
+ private ColumnReorderListener columnReorderListener = new ColumnReorderListener() {
+
+ @Override
+ public void columnReorder(ColumnReorderEvent event) {
+ log("Columns reordered, userOriginated: "
+ + event.isUserOriginated());
+ }
+ };
+
+ private ColumnVisibilityChangeListener columnVisibilityListener = new ColumnVisibilityChangeListener() {
+ @Override
+ public void columnVisibilityChanged(ColumnVisibilityChangeEvent event) {
+ log("Visibility changed: "//
+ + "propertyId: " + event.getColumn().getPropertyId() //
+ + ", isHidden: " + event.getColumn().isHidden() //
+ + ", userOriginated: " + event.isUserOriginated());
+ }
+ };
+
+ private Panel detailsPanel;
+
+ private final DetailsGenerator detailedDetailsGenerator = new DetailsGenerator() {
+ @Override
+ public Component getDetails(final RowReference rowReference) {
+ CssLayout cssLayout = new CssLayout();
+ cssLayout.setHeight("200px");
+ cssLayout.setWidth("100%");
+
+ Item item = rowReference.getItem();
+ for (Object propertyId : item.getItemPropertyIds()) {
+ Property<?> prop = item.getItemProperty(propertyId);
+ String string = prop.getValue().toString();
+ cssLayout.addComponent(new Label(string));
+ }
+
+ final int rowIndex = grid.getContainerDataSource().indexOfId(
+ rowReference.getItemId());
+ ClickListener clickListener = new ClickListener() {
+ @Override
+ public void buttonClick(ClickEvent event) {
+ Notification.show("You clicked on the "
+ + "button in the details for " + "row " + rowIndex);
+ }
+ };
+ cssLayout.addComponent(new Button("Press me", clickListener));
+ return cssLayout;
+ }
+ };
+
+ private final DetailsGenerator watchingDetailsGenerator = new DetailsGenerator() {
+ private int id = 0;
+
+ @Override
+ public Component getDetails(RowReference rowReference) {
+ return new Label("You are watching item id "
+ + rowReference.getItemId() + " (" + (id++) + ")");
+ }
+ };
+
+ private final DetailsGenerator hierarchicalDetailsGenerator = new DetailsGenerator() {
+ @Override
+ public Component getDetails(RowReference rowReference) {
+ detailsPanel = new Panel();
+ detailsPanel.setContent(new Label("One"));
+ return detailsPanel;
+ }
+ };
+
@Override
@SuppressWarnings("unchecked")
protected Grid constructComponent() {
@@ -213,7 +291,9 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
// Set varying column widths
for (int col = 0; col < COLUMNS; col++) {
- grid.getColumn(getColumnProperty(col)).setWidth(100 + col * 50);
+ Column column = grid.getColumn(getColumnProperty(col));
+ column.setWidth(100 + col * 50);
+ column.setHidable(isColumnHidableByDefault(col));
}
grid.addSortListener(new SortListener() {
@@ -248,10 +328,35 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
addFilterActions();
+ addInternalActions();
+
+ createDetailsActions();
+
this.grid = grid;
return grid;
}
+ protected boolean isColumnHidableByDefault(int col) {
+ return false;
+ }
+
+ protected boolean isColumnHiddenByDefault(int col) {
+ return false;
+ }
+
+ private void addInternalActions() {
+ createClickAction("Update column order without updating client",
+ "Internals", new Command<Grid, Void>() {
+ @Override
+ public void execute(Grid grid, Void value, Object data) {
+ List<Column> columns = grid.getColumns();
+ grid.setColumnOrder(columns.get(1).getPropertyId(),
+ columns.get(0).getPropertyId());
+ grid.getUI().getConnectorTracker().markClean(grid);
+ }
+ }, null);
+ }
+
private void addFilterActions() {
createClickAction("Column 1 starts with \"(23\"", "Filter",
new Command<Grid, Void>() {
@@ -494,6 +599,29 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
}
});
+ createBooleanAction("ColumnReorderListener", "State", false,
+ new Command<Grid, Boolean>() {
+
+ @Override
+ public void execute(Grid grid, Boolean value, Object data) {
+ if (value) {
+ grid.addColumnReorderListener(columnReorderListener);
+ } else {
+ grid.removeColumnReorderListener(columnReorderListener);
+ }
+ }
+ });
+ createBooleanAction("ColumnVisibilityChangeListener", "State", false,
+ new Command<Grid, Boolean>() {
+ @Override
+ public void execute(Grid grid, Boolean value, Object data) {
+ if (value) {
+ grid.addColumnVisibilityChangeListener(columnVisibilityListener);
+ } else {
+ grid.removeColumnVisibilityChangeListener(columnVisibilityListener);
+ }
+ }
+ });
createBooleanAction("Single select allow deselect", "State",
singleSelectAllowDeselect, new Command<Grid, Boolean>() {
@@ -508,6 +636,14 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
}
}
});
+ createBooleanAction("Column Reordering Allowed", "State", false,
+ new Command<Grid, Boolean>() {
+
+ @Override
+ public void execute(Grid c, Boolean value, Object data) {
+ c.setColumnReorderingAllowed(value);
+ }
+ });
}
protected void createHeaderActions() {
@@ -630,9 +766,9 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
}, null);
}
+ @SuppressWarnings("boxing")
protected void createColumnActions() {
createCategory("Columns", null);
-
for (int c = 0; c < COLUMNS; c++) {
final int index = c;
createCategory(getColumnProperty(c), "Columns");
@@ -640,16 +776,55 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
createClickAction("Add / Remove", getColumnProperty(c),
new Command<Grid, String>() {
+ boolean wasHidable;
+ boolean wasHidden;
+ String wasColumnHidingToggleCaption;
+
@Override
public void execute(Grid grid, String value, Object data) {
String columnProperty = getColumnProperty((Integer) data);
- if (grid.getColumn(columnProperty) == null) {
- grid.addColumn(columnProperty);
+ Column column = grid.getColumn(columnProperty);
+ if (column == null) {
+ column = grid.addColumn(columnProperty);
+ column.setHidable(wasHidable);
+ column.setHidden(wasHidden);
+ column.setHidingToggleCaption(wasColumnHidingToggleCaption);
} else {
+ wasHidable = column.isHidable();
+ wasHidden = column.isHidden();
+ wasColumnHidingToggleCaption = column
+ .getHidingToggleCaption();
grid.removeColumn(columnProperty);
}
}
}, null, c);
+ createClickAction("Move left", getColumnProperty(c),
+ new Command<Grid, String>() {
+
+ @Override
+ public void execute(Grid grid, String value, Object data) {
+ final String columnProperty = getColumnProperty((Integer) data);
+ List<Column> cols = grid.getColumns();
+ List<Object> reordered = new ArrayList<Object>();
+ boolean addAsLast = false;
+ for (int i = 0; i < cols.size(); i++) {
+ Column col = cols.get(i);
+ if (col.getPropertyId().equals(columnProperty)) {
+ if (i == 0) {
+ addAsLast = true;
+ } else {
+ reordered.add(i - 1, columnProperty);
+ }
+ } else {
+ reordered.add(col.getPropertyId());
+ }
+ }
+ if (addAsLast) {
+ reordered.add(columnProperty);
+ }
+ grid.setColumnOrder(reordered.toArray());
+ }
+ }, null, c);
createBooleanAction("Sortable", getColumnProperty(c), true,
new Command<Grid, Boolean>() {
@@ -663,6 +838,37 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
}
}, c);
+ createBooleanAction("Hidable", getColumnProperty(c),
+ isColumnHidableByDefault(c), new Command<Grid, Boolean>() {
+ @Override
+ public void execute(Grid c, Boolean hidable,
+ Object propertyId) {
+ grid.getColumn(propertyId).setHidable(hidable);
+ }
+ }, getColumnProperty(c));
+
+ createBooleanAction("Hidden", getColumnProperty(c),
+ isColumnHiddenByDefault(c), new Command<Grid, Boolean>() {
+ @Override
+ public void execute(Grid c, Boolean hidden,
+ Object propertyId) {
+ grid.getColumn(propertyId).setHidden(hidden);
+ }
+ }, getColumnProperty(c));
+ createClickAction("Change hiding toggle caption",
+ getColumnProperty(c), new Command<Grid, String>() {
+ int count = 0;
+
+ @Override
+ public void execute(Grid grid, String value, Object data) {
+ final String columnProperty = getColumnProperty((Integer) data);
+ grid.getColumn(columnProperty)
+ .setHidingToggleCaption(
+ columnProperty + " caption "
+ + count++);
+ }
+ }, null, c);
+
createCategory("Column " + c + " Width", getColumnProperty(c));
createClickAction("Auto", "Column " + c + " Width",
@@ -680,7 +886,6 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
createClickAction("25.5px", "Column " + c + " Width",
new Command<Grid, Void>() {
@Override
- @SuppressWarnings("boxing")
public void execute(Grid grid, Void value,
Object columnIndex) {
grid.getColumns().get((Integer) columnIndex)
@@ -778,6 +983,17 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
}, c);
}
+ createBooleanAction("All columns hidable", "Columns", false,
+ new Command<Grid, Boolean>() {
+
+ @Override
+ public void execute(Grid c, Boolean value, Object data) {
+ for (Column col : grid.getColumns()) {
+ col.setHidable(value);
+ }
+
+ }
+ });
}
private static String getColumnProperty(int c) {
@@ -1051,6 +1267,67 @@ public class GridBasicFeatures extends AbstractComponentTest<Grid> {
}, null);
}
+ private void createDetailsActions() {
+ Command<Grid, DetailsGenerator> swapDetailsGenerator = new Command<Grid, DetailsGenerator>() {
+ @Override
+ public void execute(Grid c, DetailsGenerator generator, Object data) {
+ grid.setDetailsGenerator(generator);
+ }
+ };
+
+ Command<Grid, Boolean> openOrCloseItemId = new Command<Grid, Boolean>() {
+ @Override
+ @SuppressWarnings("boxing")
+ public void execute(Grid g, Boolean visible, Object itemId) {
+ g.setDetailsVisible(itemId, visible);
+ }
+ };
+
+ createCategory("Generators", "Details");
+ createClickAction("NULL", "Generators", swapDetailsGenerator,
+ DetailsGenerator.NULL);
+ createClickAction("\"Watching\"", "Generators", swapDetailsGenerator,
+ watchingDetailsGenerator);
+ createClickAction("Detailed", "Generators", swapDetailsGenerator,
+ detailedDetailsGenerator);
+ createClickAction("Hierarchical", "Generators", swapDetailsGenerator,
+ hierarchicalDetailsGenerator);
+
+ createClickAction("- Change Component", "Generators",
+ new Command<Grid, Void>() {
+ @Override
+ public void execute(Grid c, Void value, Object data) {
+ Label label = (Label) detailsPanel.getContent();
+ if (label.getValue().equals("One")) {
+ detailsPanel.setContent(new Label("Two"));
+ } else {
+ detailsPanel.setContent(new Label("One"));
+ }
+ }
+ }, null);
+
+ createClickAction("Toggle firstItemId", "Details",
+ new Command<Grid, Void>() {
+ @Override
+ public void execute(Grid g, Void value, Object data) {
+ Object firstItemId = g.getContainerDataSource()
+ .firstItemId();
+ boolean toggle = g.isDetailsVisible(firstItemId);
+ g.setDetailsVisible(firstItemId, !toggle);
+ g.setDetailsVisible(firstItemId, toggle);
+ }
+ }, null);
+
+ createBooleanAction("Open firstItemId", "Details", false,
+ openOrCloseItemId, ds.firstItemId());
+
+ createBooleanAction("Open 1", "Details", false, openOrCloseItemId,
+ ds.getIdByIndex(1));
+
+ createBooleanAction("Open 995", "Details", false, openOrCloseItemId,
+ ds.getIdByIndex(995));
+ }
+
@Override
protected Integer getTicketNumber() {
return 12829;
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java
index e22fcc422b..469bf37c2f 100644
--- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java
@@ -15,6 +15,9 @@
*/
package com.vaadin.tests.components.grid.basicfeatures;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
import java.util.ArrayList;
import java.util.List;
@@ -25,13 +28,18 @@ import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import com.vaadin.testbench.TestBenchElement;
-import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
import com.vaadin.testbench.parallel.TestCategory;
+import com.vaadin.tests.components.grid.basicfeatures.element.CustomGridElement;
import com.vaadin.tests.tb3.MultiBrowserTest;
@TestCategory("grid")
public abstract class GridBasicFeaturesTest extends MultiBrowserTest {
+ public enum CellSide {
+ LEFT, RIGHT;
+ }
+
@Override
protected boolean requireWindowFocusForIE() {
return true;
@@ -59,9 +67,9 @@ public abstract class GridBasicFeaturesTest extends MultiBrowserTest {
}
}
- protected GridElement getGridElement() {
+ protected CustomGridElement getGridElement() {
return ((TestBenchElement) findElement(By.id("testComponent")))
- .wrap(GridElement.class);
+ .wrap(CustomGridElement.class);
}
protected void scrollGridVerticallyTo(double px) {
@@ -69,6 +77,11 @@ public abstract class GridBasicFeaturesTest extends MultiBrowserTest {
getGridVerticalScrollbar());
}
+ protected void scrollGridHorizontallyTo(double px) {
+ executeScript("arguments[0].scrollLeft = " + px,
+ getGridHorizontalScrollbar());
+ }
+
protected int getGridVerticalScrollPos() {
return ((Number) executeScript("return arguments[0].scrollTop",
getGridVerticalScrollbar())).intValue();
@@ -117,6 +130,12 @@ public abstract class GridBasicFeaturesTest extends MultiBrowserTest {
By.xpath("//div[contains(@class, \"v-grid-scroller-vertical\")]"));
}
+ protected WebElement getGridHorizontalScrollbar() {
+ return getDriver()
+ .findElement(
+ By.xpath("//div[contains(@class, \"v-grid-scroller-horizontal\")]"));
+ }
+
/**
* Reloads the page without restartApplication. This occasionally breaks
* stuff.
@@ -127,4 +146,118 @@ public abstract class GridBasicFeaturesTest extends MultiBrowserTest {
testUrl = testUrl.replace("?&", "?");
driver.get(testUrl);
}
+
+ protected void focusCell(int row, int column) {
+ getGridElement().getCell(row, column).click();
+ }
+
+ protected void setFrozenColumns(int numberOfFrozenColumns) {
+ selectMenuPath("Component", "State", "Frozen column count",
+ Integer.toString(numberOfFrozenColumns));
+ }
+
+ protected void assertColumnHeaderOrder(int... indices) {
+ List<TestBenchElement> headers = getGridHeaderRowCells();
+ for (int i = 0; i < indices.length; i++) {
+ assertColumnHeader("Column " + indices[i], headers.get(i));
+ }
+ }
+
+ protected void assertColumnHeader(String expectedHeaderCaption,
+ TestBenchElement testBenchElement) {
+ assertEquals(expectedHeaderCaption.toLowerCase(), testBenchElement
+ .getText().toLowerCase());
+ }
+
+ protected GridCellElement getDefaultColumnHeader(int index) {
+ List<GridCellElement> headerRowCells = getGridElement().getHeaderCells(
+ 0);
+ return headerRowCells.get(index);
+ }
+
+ protected void dragAndDropDefaultColumnHeader(int draggedColumnHeaderIndex,
+ int onTopOfColumnHeaderIndex, CellSide cellSide) {
+ GridCellElement columnHeader = getDefaultColumnHeader(onTopOfColumnHeaderIndex);
+ new Actions(getDriver())
+ .clickAndHold(getDefaultColumnHeader(draggedColumnHeaderIndex))
+ .moveToElement(
+ columnHeader,
+ getHorizontalOffsetForDragAndDrop(columnHeader,
+ cellSide), 0).release().perform();
+ }
+
+ private int getHorizontalOffsetForDragAndDrop(GridCellElement columnHeader,
+ CellSide cellSide) {
+ if (cellSide == CellSide.LEFT) {
+ return 5;
+ } else {
+ int half = columnHeader.getSize().getWidth() / 2;
+ return half + (half / 2);
+ }
+ }
+
+ protected void dragAndDropColumnHeader(int headerRow,
+ int draggedColumnHeaderIndex, int onTopOfColumnHeaderIndex,
+ CellSide cellSide) {
+ GridCellElement headerCell = getGridElement().getHeaderCell(headerRow,
+ onTopOfColumnHeaderIndex);
+ new Actions(getDriver())
+ .clickAndHold(
+ getGridElement().getHeaderCell(headerRow,
+ draggedColumnHeaderIndex))
+ .moveToElement(
+ headerCell,
+ getHorizontalOffsetForDragAndDrop(headerCell, cellSide),
+ 0).release().perform();
+ }
+
+ protected void dragAndDropColumnHeader(int headerRow,
+ int draggedColumnHeaderIndex, int onTopOfColumnHeaderIndex,
+ int horizontalOffset) {
+ GridCellElement headerCell = getGridElement().getHeaderCell(headerRow,
+ onTopOfColumnHeaderIndex);
+ new Actions(getDriver())
+ .clickAndHold(
+ getGridElement().getHeaderCell(headerRow,
+ draggedColumnHeaderIndex))
+ .moveToElement(headerCell, horizontalOffset, 0).release()
+ .perform();
+ }
+
+ protected void assertColumnIsSorted(int index) {
+ WebElement columnHeader = getDefaultColumnHeader(index);
+ assertTrue(columnHeader.getAttribute("class").contains("sort"));
+ }
+
+ protected void assertFocusedCell(int row, int column) {
+ assertTrue(getGridElement().getCell(row, column).getAttribute("class")
+ .contains("focused"));
+ }
+
+ protected WebElement getSidebar() {
+ List<WebElement> elements = findElements(By.className("v-grid-sidebar"));
+ return elements.isEmpty() ? null : elements.get(0);
+ }
+
+ protected WebElement getSidebarOpenButton() {
+ List<WebElement> elements = findElements(By
+ .className("v-grid-sidebar-button"));
+ return elements.isEmpty() ? null : elements.get(0);
+ }
+
+ /**
+ * Returns the toggle inside the sidebar for hiding the column at the given
+ * index, or null if not found.
+ */
+ protected WebElement getColumnHidingToggle(int columnIndex) {
+ WebElement sidebar = getSidebar();
+ List<WebElement> elements = sidebar.findElements(By
+ .className("column-hiding-toggle"));
+ for (WebElement e : elements) {
+ if ((e.getText().toLowerCase()).startsWith("column " + columnIndex)) {
+ return e;
+ }
+ }
+ return null;
+ }
}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridColumnHidingTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridColumnHidingTest.java
new file mode 100644
index 0000000000..b446bdef48
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridColumnHidingTest.java
@@ -0,0 +1,994 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures;
+
+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.List;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.testbench.parallel.TestCategory;
+
+@TestCategory("grid")
+public class GridColumnHidingTest extends GridBasicClientFeaturesTest {
+
+ private static final String CAPTION_0_1 = "Join column cells 0, 1";
+ private static final String CAPTION_1_2 = "Join columns 1, 2";
+ private static final String CAPTION_3_4_5 = "Join columns 3, 4, 5";
+ private static final String CAPTION_ALL = "Join all columns";
+
+ @Before
+ public void before() {
+ openTestURL();
+ }
+
+ @Test
+ public void testColumnHiding_hidingColumnsFromAPI_works() {
+ selectMenuPath("Component", "State", "Width", "1000px");
+ assertColumnHeaderOrder(0, 1, 2, 3, 4, 5, 6);
+
+ toggleHideColumnAPI(0);
+ assertColumnHeaderOrder(1, 2, 3, 4, 5, 6);
+
+ toggleHideColumnAPI(1);
+ toggleHideColumnAPI(2);
+ toggleHideColumnAPI(3);
+ assertColumnHeaderOrder(4, 5, 6, 7, 8);
+ }
+
+ @Test
+ public void testColumnHiding_unhidingColumnsFromAPI_works() {
+ selectMenuPath("Component", "State", "Width", "1000px");
+ assertColumnHeaderOrder(0, 1, 2, 3, 4, 5, 6);
+
+ toggleHideColumnAPI(0);
+ assertColumnHeaderOrder(1, 2, 3, 4, 5, 6);
+
+ toggleHideColumnAPI(0);
+ assertColumnHeaderOrder(0, 1, 2, 3, 4, 5, 6);
+
+ toggleHideColumnAPI(1);
+ toggleHideColumnAPI(2);
+ toggleHideColumnAPI(3);
+ assertColumnHeaderOrder(0, 4, 5, 6, 7, 8);
+
+ toggleHideColumnAPI(1);
+ toggleHideColumnAPI(2);
+ assertColumnHeaderOrder(0, 1, 2, 4, 5, 6);
+ }
+
+ @Test
+ public void testColumnHiding_hidingUnhidingFromAPI_works() {
+ selectMenuPath("Component", "State", "Width", "1000px");
+ assertColumnHeaderOrder(0, 1, 2, 3, 4, 5, 6);
+
+ toggleHideColumnAPI(2);
+ assertColumnHeaderOrder(0, 1, 3, 4, 5, 6);
+
+ toggleHideColumnAPI(2);
+ assertColumnHeaderOrder(0, 1, 2, 3, 4, 5, 6);
+
+ toggleHideColumnAPI(2);
+ assertColumnHeaderOrder(0, 1, 3, 4, 5, 6);
+
+ toggleHideColumnAPI(2);
+ assertColumnHeaderOrder(0, 1, 2, 3, 4, 5, 6);
+ }
+
+ @Test
+ public void testColumnHiding_changeVisibilityAPI_triggersClientSideEvent() {
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+ selectMenuPath("Component", "Internals", "Listeners",
+ "Add Column Visibility Change listener");
+
+ toggleHideColumnAPI(2);
+ assertColumnHeaderOrder(0, 1, 3, 4);
+
+ WebElement webElement = findElement(By.id("columnvisibility"));
+ int counter = Integer.parseInt(webElement.getAttribute("counter"));
+ int columnIndex = Integer.parseInt(webElement
+ .getAttribute("columnindex"));
+ boolean userOriginated = Boolean.parseBoolean(webElement
+ .getAttribute("useroriginated"));
+ boolean hidden = Boolean.parseBoolean(webElement
+ .getAttribute("ishidden"));
+
+ assertNotNull("no event fired", webElement);
+ assertEquals(1, counter);
+ assertEquals(2, columnIndex);
+ assertEquals(false, userOriginated);
+ assertEquals(true, hidden);
+
+ toggleHideColumnAPI(2);
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+
+ webElement = findElement(By.id("columnvisibility"));
+ counter = Integer.parseInt(webElement.getAttribute("counter"));
+ columnIndex = Integer.parseInt(webElement.getAttribute("columnIndex"));
+ userOriginated = Boolean.parseBoolean(webElement
+ .getAttribute("userOriginated"));
+ hidden = Boolean.parseBoolean(webElement.getAttribute("ishidden"));
+
+ assertNotNull("no event fired", webElement);
+ assertEquals(2, counter);
+ assertEquals(2, columnIndex);
+ assertEquals(false, userOriginated);
+ assertEquals(false, hidden);
+ }
+
+ @Test
+ public void testColumnHiding_changeVisibilityToggle_triggersClientSideEvent() {
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+ selectMenuPath("Component", "Internals", "Listeners",
+ "Add Column Visibility Change listener");
+
+ toggleHidableColumnAPI(2);
+ clickSidebarOpenButton();
+ getColumnHidingToggle(2).click();
+ assertColumnHeaderOrder(0, 1, 3, 4);
+
+ WebElement webElement = findElement(By.id("columnvisibility"));
+ int counter = Integer.parseInt(webElement.getAttribute("counter"));
+ int columnIndex = Integer.parseInt(webElement
+ .getAttribute("columnindex"));
+ boolean userOriginated = Boolean.parseBoolean(webElement
+ .getAttribute("useroriginated"));
+ boolean hidden = Boolean.parseBoolean(webElement
+ .getAttribute("ishidden"));
+
+ assertNotNull("no event fired", webElement);
+ assertEquals(1, counter);
+ assertEquals(2, columnIndex);
+ assertEquals(true, userOriginated);
+ assertEquals(true, hidden);
+
+ getColumnHidingToggle(2).click();
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+
+ webElement = findElement(By.id("columnvisibility"));
+ counter = Integer.parseInt(webElement.getAttribute("counter"));
+ columnIndex = Integer.parseInt(webElement.getAttribute("columnIndex"));
+ userOriginated = Boolean.parseBoolean(webElement
+ .getAttribute("userOriginated"));
+ hidden = Boolean.parseBoolean(webElement.getAttribute("ishidden"));
+
+ assertNotNull("no event fired", webElement);
+ assertEquals(2, counter);
+ assertEquals(2, columnIndex);
+ assertEquals(true, userOriginated);
+ assertEquals(false, hidden);
+ }
+
+ @Test
+ public void testColumnHidability_onTriggerColumnHidability_showsSidebarButton() {
+ WebElement sidebar = getSidebar();
+ assertNull(sidebar);
+
+ toggleHidableColumnAPI(0);
+
+ sidebar = getSidebar();
+ assertNotNull(sidebar);
+ }
+
+ @Test
+ public void testColumnHidability_triggeringColumnHidabilityWithSeveralColumns_showsAndHidesSiderbarButton() {
+ verifySidebarNotVisible();
+
+ toggleHidableColumnAPI(3);
+ toggleHidableColumnAPI(4);
+
+ verifySidebarVisible();
+
+ toggleHidableColumnAPI(3);
+
+ verifySidebarVisible();
+
+ toggleHidableColumnAPI(4);
+
+ verifySidebarNotVisible();
+ }
+
+ @Test
+ public void testColumnHidability_clickingSidebarButton_opensClosesSidebar() {
+ toggleHidableColumnAPI(0);
+ verifySidebarClosed();
+
+ clickSidebarOpenButton();
+
+ verifySidebarOpened();
+
+ clickSidebarOpenButton();
+
+ verifySidebarClosed();
+ }
+
+ @Test
+ public void testColumnHidability_settingColumnHidable_showsToggleInSidebar() {
+ toggleHidableColumnAPI(0);
+ verifySidebarClosed();
+ clickSidebarOpenButton();
+ verifySidebarOpened();
+
+ verifyColumnHidingOption(0, false);
+ }
+
+ @Test
+ public void testColumnHiding_hidingColumnWithToggle_works() {
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+ toggleHidableColumnAPI(0);
+ verifySidebarClosed();
+ clickSidebarOpenButton();
+ verifySidebarOpened();
+ verifyColumnHidingOption(0, false);
+
+ getColumnHidingToggle(0).click();
+ verifyColumnHidingOption(0, true);
+ assertColumnHeaderOrder(1, 2, 3, 4);
+
+ getColumnHidingToggle(0).click();
+ verifyColumnHidingOption(0, false);
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+ }
+
+ @Test
+ public void testColumnHiding_updatingHiddenWhileSidebarClosed_updatesToggleValue() {
+ toggleHidableColumnAPI(0);
+ toggleHidableColumnAPI(3);
+ toggleHideColumnAPI(3);
+ assertColumnHeaderOrder(0, 1, 2, 4);
+ verifySidebarClosed();
+
+ clickSidebarOpenButton();
+ verifySidebarOpened();
+ verifyColumnHidingOption(0, false);
+ verifyColumnHidingOption(3, true);
+
+ clickSidebarOpenButton();
+ verifySidebarClosed();
+
+ toggleHideColumnAPI(0);
+ toggleHideColumnAPI(3);
+
+ clickSidebarOpenButton();
+ verifySidebarOpened();
+ verifyColumnHidingOption(0, true);
+ verifyColumnHidingOption(3, false);
+
+ }
+
+ @Test
+ public void testColumnHiding_hidingMultipleColumnsWithToggle_hidesColumns() {
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+
+ toggleHideColumnAPI(1);
+ toggleHidableColumnAPI(0);
+ toggleHidableColumnAPI(1);
+ toggleHidableColumnAPI(2);
+ toggleHidableColumnAPI(3);
+ toggleHidableColumnAPI(4);
+ verifySidebarClosed();
+ assertColumnHeaderOrder(0, 2, 3, 4);
+
+ clickSidebarOpenButton();
+ verifySidebarOpened();
+ verifyColumnHidingOption(0, false);
+ verifyColumnHidingOption(1, true);
+ verifyColumnHidingOption(2, false);
+ verifyColumnHidingOption(3, false);
+ verifyColumnHidingOption(4, false);
+
+ // must be done in a funny order so that the header indexes won't break
+ // (because of data source uses counter)
+ getColumnHidingToggle(1).click();
+ getColumnHidingToggle(2).click();
+ getColumnHidingToggle(3).click();
+ getColumnHidingToggle(4).click();
+ getColumnHidingToggle(0).click();
+ verifyColumnHidingOption(0, true);
+ verifyColumnHidingOption(1, false);
+ verifyColumnHidingOption(2, true);
+ verifyColumnHidingOption(3, true);
+ verifyColumnHidingOption(4, true);
+
+ assertColumnHeaderOrder(1, 5, 6, 7);
+
+ getColumnHidingToggle(0).click();
+ getColumnHidingToggle(2).click();
+ getColumnHidingToggle(1).click();
+ verifyColumnHidingOption(0, false);
+ verifyColumnHidingOption(1, true);
+ verifyColumnHidingOption(2, false);
+ assertColumnHeaderOrder(0, 2, 5, 6);
+ }
+
+ @Test
+ public void testColumnHidability_changingHidabilityWhenSidebarClosed_addsRemovesToggles() {
+ toggleHideColumnAPI(0);
+ toggleHideColumnAPI(4);
+ assertColumnHeaderOrder(1, 2, 3, 5);
+ toggleHidableColumnAPI(0);
+ toggleHidableColumnAPI(3);
+ toggleHidableColumnAPI(4);
+ verifySidebarClosed();
+
+ clickSidebarOpenButton();
+ verifySidebarOpened();
+ verifyColumnHidingOption(0, true);
+ verifyColumnHidingOption(3, false);
+ verifyColumnHidingOption(4, true);
+
+ clickSidebarOpenButton();
+ verifySidebarClosed();
+
+ toggleHidableColumnAPI(0);
+ toggleHidableColumnAPI(3);
+
+ verifySidebarClosed();
+ clickSidebarOpenButton();
+ verifySidebarOpened();
+ verifyColumnHidingOption(4, true);
+
+ assertNull(getColumnHidingToggle(0));
+ assertNull(getColumnHidingToggle(3));
+ }
+
+ @Test
+ public void testColumnHidability_togglingHidability_placesTogglesInRightOrder() {
+ toggleHidableColumnAPI(3);
+ toggleHidableColumnAPI(2);
+ clickSidebarOpenButton();
+
+ verifyColumnHidingTogglesOrder(2, 3);
+
+ toggleHidableColumnAPI(1);
+ toggleHidableColumnAPI(2);
+ toggleHidableColumnAPI(6);
+ toggleHidableColumnAPI(0);
+
+ verifyColumnHidingTogglesOrder(0, 1, 3, 6);
+
+ clickSidebarOpenButton();
+
+ toggleHidableColumnAPI(2);
+ toggleHidableColumnAPI(4);
+ toggleHidableColumnAPI(7);
+
+ clickSidebarOpenButton();
+
+ verifyColumnHidingTogglesOrder(0, 1, 2, 3, 4, 6, 7);
+ }
+
+ @Test
+ public void testColumnHidability_reorderingColumns_updatesColumnToggleOrder() {
+ selectMenuPath("Component", "State", "Width", "1000px");
+ toggleHidableColumnAPI(0);
+ toggleHidableColumnAPI(1);
+ toggleHidableColumnAPI(3);
+ toggleHidableColumnAPI(4);
+ clickSidebarOpenButton();
+ verifyColumnHidingTogglesOrder(0, 1, 3, 4);
+ clickSidebarOpenButton();
+
+ toggleColumnReorder();
+ dragAndDropColumnHeader(0, 3, 0, CellSide.LEFT);
+
+ assertColumnHeaderOrder(3, 0, 1, 2, 4);
+ clickSidebarOpenButton();
+ verifyColumnHidingTogglesOrder(3, 0, 1, 4);
+
+ clickSidebarOpenButton();
+ dragAndDropColumnHeader(0, 1, 3, CellSide.RIGHT);
+ dragAndDropColumnHeader(0, 4, 0, CellSide.LEFT);
+ dragAndDropColumnHeader(0, 3, 0, CellSide.LEFT);
+
+ assertColumnHeaderOrder(2, 4, 3, 1, 0);
+ clickSidebarOpenButton();
+ verifyColumnHidingTogglesOrder(4, 3, 1, 0);
+ }
+
+ @Test
+ public void testColumnHidingAndReorder_reorderingOverHiddenColumn_orderIsKept() {
+ selectMenuPath("Component", "State", "Width", "1000px");
+ toggleColumnReorder();
+ toggleHideColumnAPI(0);
+ assertColumnHeaderOrder(1, 2, 3, 4, 5);
+
+ dragAndDropColumnHeader(0, 1, 0, CellSide.LEFT);
+ assertColumnHeaderOrder(2, 1, 3, 4, 5);
+
+ toggleHideColumnAPI(0);
+ assertColumnHeaderOrder(0, 2, 1, 3, 4, 5);
+
+ toggleHideColumnAPI(1);
+ assertColumnHeaderOrder(0, 2, 3, 4, 5);
+
+ // right side of hidden column
+ dragAndDropColumnHeader(0, 0, 2, CellSide.LEFT);
+ assertColumnHeaderOrder(2, 0, 3, 4, 5);
+
+ toggleHideColumnAPI(1);
+ assertColumnHeaderOrder(2, 1, 0, 3, 4, 5);
+
+ toggleHideColumnAPI(0);
+ assertColumnHeaderOrder(2, 1, 3, 4, 5);
+
+ // left side of hidden column
+ dragAndDropColumnHeader(0, 0, 1, CellSide.RIGHT);
+ assertColumnHeaderOrder(1, 2, 3, 4, 5);
+
+ toggleHideColumnAPI(0);
+ assertColumnHeaderOrder(1, 0, 2, 3, 4, 5);
+ }
+
+ @Test
+ public void testColumnHidingAndReorder_reorderingWithMultipleHiddenColumns_works() {
+ selectMenuPath("Component", "State", "Width", "1000px");
+ toggleColumnReorder();
+ toggleHideColumnAPI(2);
+ toggleHideColumnAPI(3);
+ assertColumnHeaderOrder(0, 1, 4, 5, 6);
+
+ dragAndDropDefaultColumnHeader(0, 2, CellSide.LEFT);
+ assertColumnHeaderOrder(1, 0, 4, 5, 6);
+
+ toggleHideColumnAPI(3);
+ assertColumnHeaderOrder(1, 3, 0, 4, 5, 6);
+
+ toggleHideColumnAPI(2);
+ assertColumnHeaderOrder(1, 2, 3, 0, 4, 5, 6);
+
+ toggleHideColumnAPI(0);
+ toggleHideColumnAPI(4);
+ assertColumnHeaderOrder(1, 2, 3, 5, 6);
+
+ dragAndDropDefaultColumnHeader(4, 3, CellSide.LEFT);
+ assertColumnHeaderOrder(1, 2, 3, 6, 5);
+
+ dragAndDropDefaultColumnHeader(4, 2, CellSide.RIGHT);
+ assertColumnHeaderOrder(1, 2, 3, 5, 6);
+
+ toggleHideColumnAPI(0);
+ assertColumnHeaderOrder(1, 2, 3, 0, 5, 6);
+
+ toggleHideColumnAPI(4);
+ assertColumnHeaderOrder(1, 2, 3, 0, 4, 5, 6);
+ }
+
+ @Test
+ public void testReorderingHiddenColumns_movingHiddenColumn_indexIsUpdated() {
+ selectMenuPath("Component", "State", "Width", "1000px");
+ toggleHideColumnAPI(2);
+ toggleHideColumnAPI(3);
+ assertColumnHeaderOrder(0, 1, 4, 5, 6);
+
+ moveColumnLeft(3);
+ assertColumnHeaderOrder(0, 1, 4, 5, 6);
+
+ toggleHideColumnAPI(3);
+ assertColumnHeaderOrder(0, 1, 3, 4, 5, 6);
+ toggleHideColumnAPI(2);
+ assertColumnHeaderOrder(0, 1, 3, 2, 4, 5, 6);
+
+ toggleHideColumnAPI(2);
+ toggleHideColumnAPI(3);
+ assertColumnHeaderOrder(0, 1, 4, 5, 6);
+
+ moveColumnLeft(2);
+ moveColumnLeft(2);
+ moveColumnLeft(2);
+ assertColumnHeaderOrder(0, 1, 4, 5, 6);
+
+ toggleHideColumnAPI(2);
+ assertColumnHeaderOrder(2, 0, 1, 4, 5, 6);
+ toggleHideColumnAPI(3);
+ assertColumnHeaderOrder(2, 0, 1, 3, 4, 5, 6);
+ }
+
+ // keyboard actions not working in client side test case?
+ @Test
+ @Ignore
+ public void testNavigationWithHiddenColumns_navigatingOverHiddenColumn_goesToNextVisibleColumn() {
+ selectMenuPath("Component", "State", "Width", "1000px");
+ toggleHideColumnAPI(2);
+ toggleHideColumnAPI(3);
+ assertColumnHeaderOrder(0, 1, 4, 5, 6);
+
+ getGridElement().getCell(2, 4).click();
+ GridCellElement cell = getGridElement().getCell(2, 4);
+ assertTrue(cell.isFocused());
+
+ new Actions(getDriver()).sendKeys(Keys.ARROW_LEFT);
+ cell = getGridElement().getCell(2, 1);
+ assertTrue(cell.isFocused());
+
+ new Actions(getDriver()).sendKeys(Keys.ARROW_RIGHT);
+ cell = getGridElement().getCell(2, 4);
+ assertTrue(cell.isFocused());
+ }
+
+ @Test
+ public void testNavigationWithHiddenColumns_hiddenFirstAndLastColumn_keepsNavigation() {
+ selectMenuPath("Component", "State", "Width", "1000px");
+ toggleHideColumnAPI(0);
+ assertColumnHeaderOrder(1, 2, 3, 4, 5, 6);
+
+ getGridElement().getCell(2, 1).click();
+ assertTrue(getGridElement().getCell(2, 1).isFocused());
+
+ new Actions(getDriver()).sendKeys(Keys.ARROW_LEFT);
+ GridCellElement cell = getGridElement().getCell(2, 1);
+ assertTrue(cell.isFocused());
+
+ scrollGridHorizontallyTo(10000);
+
+ //
+ getGridElement().getHeaderCell(0, 9).click();
+ cell = getGridElement().getHeaderCell(0, 9);
+ assertTrue(cell.isFocused());
+ toggleHideColumnAPI(10);
+ toggleHideColumnAPI(11);
+
+ new Actions(getDriver()).sendKeys(Keys.ARROW_RIGHT);
+ new Actions(getDriver()).sendKeys(Keys.ARROW_RIGHT);
+ toggleHideColumnAPI(10);
+ toggleHideColumnAPI(11);
+ cell = getGridElement().getHeaderCell(0, 9);
+ assertTrue(cell.isFocused());
+ }
+
+ @Test
+ public void testFrozenColumnHiding_lastFrozenColumnHidden_isFrozenWhenMadeVisible() {
+ toggleFrozenColumns(2);
+ toggleHidableColumnAPI(0);
+ toggleHidableColumnAPI(1);
+ getSidebarOpenButton().click();
+ verifyColumnIsFrozen(0);
+ verifyColumnIsFrozen(1);
+ verifyColumnIsNotFrozen(2);
+ assertColumnHeaderOrder(0, 1, 2, 3);
+
+ getColumnHidingToggle(1).click();
+ verifyColumnIsFrozen(0);
+ // the grid element indexing doesn't take hidden columns into account!
+ verifyColumnIsNotFrozen(1);
+ assertColumnHeaderOrder(0, 2, 3);
+
+ getColumnHidingToggle(0).click();
+ verifyColumnIsNotFrozen(0);
+ assertColumnHeaderOrder(2, 3, 4);
+
+ getColumnHidingToggle(0).click();
+ assertColumnHeaderOrder(0, 2, 3);
+ verifyColumnIsFrozen(0);
+ verifyColumnIsNotFrozen(1);
+
+ getColumnHidingToggle(1).click();
+ assertColumnHeaderOrder(0, 1, 2, 3);
+ verifyColumnIsFrozen(0);
+ verifyColumnIsFrozen(1);
+ verifyColumnIsNotFrozen(2);
+ }
+
+ @Test
+ public void testFrozenColumnHiding_columnHiddenFrozenCountChanged_columnIsFrozenWhenVisible() {
+ toggleHidableColumnAPI(1);
+ toggleHidableColumnAPI(2);
+ getSidebarOpenButton().click();
+ getColumnHidingToggle(1).click();
+ getColumnHidingToggle(2).click();
+ assertColumnHeaderOrder(0, 3, 4);
+
+ toggleFrozenColumns(3);
+ verifyColumnIsFrozen(0);
+ // the grid element indexing doesn't take hidden columns into account!
+ verifyColumnIsNotFrozen(1);
+ verifyColumnIsNotFrozen(2);
+
+ getColumnHidingToggle(2).click();
+ verifyColumnIsFrozen(0);
+ verifyColumnIsFrozen(1);
+ verifyColumnIsNotFrozen(2);
+ verifyColumnIsNotFrozen(3);
+
+ getColumnHidingToggle(1).click();
+ verifyColumnIsFrozen(0);
+ verifyColumnIsFrozen(1);
+ verifyColumnIsFrozen(2);
+ verifyColumnIsNotFrozen(3);
+ verifyColumnIsNotFrozen(4);
+ }
+
+ @Test
+ public void testSpannedCells_hidingColumnInBeginning_rendersSpannedCellCorrectly() {
+ loadSpannedCellsFixture();
+ verifySpannedCellsFixtureStart();
+
+ toggleHideColumnAPI(0);
+
+ verifyNumberOfCellsInHeader(0, 7);
+ verifyNumberOfCellsInHeader(1, 5);
+ verifyNumberOfCellsInHeader(2, 6);
+ verifyNumberOfCellsInHeader(3, 1);
+ verifyHeaderCellContent(1, 0, CAPTION_0_1);
+ verifyHeaderCellContent(1, 2, CAPTION_3_4_5);
+ verifyHeaderCellContent(2, 0, CAPTION_1_2);
+ verifyHeaderCellContent(3, 0, CAPTION_ALL);
+ verifyHeaderCellColspan(1, 0, 1);
+ verifyHeaderCellColspan(1, 2, 3);
+ verifyHeaderCellColspan(2, 1, 2);
+
+ toggleHideColumnAPI(0);
+
+ verifySpannedCellsFixtureStart();
+
+ toggleHideColumnAPI(1);
+
+ verifyNumberOfCellsInHeader(0, 7);
+ verifyNumberOfCellsInHeader(1, 5);
+ verifyNumberOfCellsInHeader(2, 7);
+ verifyNumberOfCellsInHeader(3, 1);
+ verifyHeaderCellContent(1, 0, CAPTION_0_1);
+ verifyHeaderCellContent(1, 2, CAPTION_3_4_5);
+ verifyHeaderCellContent(2, 1, CAPTION_1_2);
+ verifyHeaderCellContent(3, 0, CAPTION_ALL);
+ verifyHeaderCellColspan(1, 0, 1);
+ verifyHeaderCellColspan(1, 2, 3);
+ verifyHeaderCellColspan(2, 1, 1);
+
+ toggleHideColumnAPI(3);
+
+ verifyNumberOfCellsInHeader(0, 6);
+ verifyNumberOfCellsInHeader(1, 5);
+ verifyNumberOfCellsInHeader(2, 6);
+ verifyNumberOfCellsInHeader(3, 1);
+ verifyHeaderCellContent(1, 0, CAPTION_0_1);
+ verifyHeaderCellContent(1, 2, CAPTION_3_4_5);
+ verifyHeaderCellContent(2, 1, CAPTION_1_2);
+ verifyHeaderCellContent(3, 0, CAPTION_ALL);
+ verifyHeaderCellColspan(1, 0, 1);
+ verifyHeaderCellColspan(1, 2, 2);
+ verifyHeaderCellColspan(2, 1, 1);
+
+ toggleHideColumnAPI(1);
+
+ verifyNumberOfCellsInHeader(0, 7);
+ verifyNumberOfCellsInHeader(1, 5);
+ verifyNumberOfCellsInHeader(2, 6);
+ verifyNumberOfCellsInHeader(3, 1);
+ verifyHeaderCellContent(1, 0, CAPTION_0_1);
+ verifyHeaderCellContent(1, 3, CAPTION_3_4_5);
+ verifyHeaderCellContent(2, 1, CAPTION_1_2);
+ verifyHeaderCellContent(3, 0, CAPTION_ALL);
+ verifyHeaderCellColspan(1, 0, 2);
+ verifyHeaderCellColspan(1, 3, 2);
+ verifyHeaderCellColspan(2, 1, 2);
+
+ toggleHideColumnAPI(3);
+
+ verifySpannedCellsFixtureStart();
+ }
+
+ @Test
+ public void testSpannedCells_hidingColumnInMiddle_rendersSpannedCellCorrectly() {
+ loadSpannedCellsFixture();
+ verifySpannedCellsFixtureStart();
+
+ toggleHideColumnAPI(4);
+
+ verifyNumberOfCellsInHeader(0, 7);
+ verifyNumberOfCellsInHeader(1, 5);
+ verifyNumberOfCellsInHeader(2, 6);
+ verifyNumberOfCellsInHeader(3, 1);
+ verifyHeaderCellContent(1, 0, CAPTION_0_1);
+ verifyHeaderCellContent(1, 3, CAPTION_3_4_5);
+ verifyHeaderCellContent(2, 1, CAPTION_1_2);
+ verifyHeaderCellContent(3, 0, CAPTION_ALL);
+ verifyHeaderCellColspan(1, 0, 2);
+ verifyHeaderCellColspan(1, 3, 2);
+ verifyHeaderCellColspan(2, 1, 2);
+
+ toggleHideColumnAPI(4);
+
+ verifySpannedCellsFixtureStart();
+ }
+
+ @Test
+ public void testSpannedCells_hidingColumnInEnd_rendersSpannedCellCorrectly() {
+ loadSpannedCellsFixture();
+ verifySpannedCellsFixtureStart();
+
+ toggleHideColumnAPI(1);
+
+ verifyNumberOfCellsInHeader(0, 7);
+ verifyNumberOfCellsInHeader(1, 5);
+ verifyNumberOfCellsInHeader(2, 7);
+ verifyNumberOfCellsInHeader(3, 1);
+ verifyHeaderCellContent(1, 0, CAPTION_0_1);
+ verifyHeaderCellContent(1, 2, CAPTION_3_4_5);
+ verifyHeaderCellContent(2, 1, CAPTION_1_2);
+ verifyHeaderCellContent(3, 1, CAPTION_ALL);
+ verifyHeaderCellColspan(1, 0, 1);
+ verifyHeaderCellColspan(1, 2, 3);
+ verifyHeaderCellColspan(2, 1, 1);
+
+ toggleHideColumnAPI(1);
+
+ verifySpannedCellsFixtureStart();
+
+ toggleHideColumnAPI(2);
+
+ verifyNumberOfCellsInHeader(0, 7);
+ verifyNumberOfCellsInHeader(1, 4);
+ verifyNumberOfCellsInHeader(2, 7);
+ verifyNumberOfCellsInHeader(3, 1);
+ verifyHeaderCellContent(1, 0, CAPTION_0_1);
+ verifyHeaderCellContent(1, 3, CAPTION_3_4_5);
+ verifyHeaderCellContent(2, 1, CAPTION_1_2);
+ verifyHeaderCellContent(3, 0, CAPTION_ALL);
+ verifyHeaderCellColspan(1, 0, 2);
+ verifyHeaderCellColspan(1, 3, 3);
+ verifyHeaderCellColspan(2, 1, 1);
+
+ toggleHideColumnAPI(5);
+
+ verifyNumberOfCellsInHeader(0, 6);
+ verifyNumberOfCellsInHeader(1, 4);
+ verifyNumberOfCellsInHeader(2, 6);
+ verifyNumberOfCellsInHeader(3, 1);
+ verifyHeaderCellContent(1, 0, CAPTION_0_1);
+ verifyHeaderCellContent(1, 3, CAPTION_3_4_5);
+ verifyHeaderCellContent(2, 1, CAPTION_1_2);
+ verifyHeaderCellContent(3, 0, CAPTION_ALL);
+ verifyHeaderCellColspan(1, 0, 2);
+ verifyHeaderCellColspan(1, 3, 2);
+ verifyHeaderCellColspan(2, 1, 1);
+
+ toggleHideColumnAPI(5);
+ toggleHideColumnAPI(2);
+
+ verifySpannedCellsFixtureStart();
+ }
+
+ @Test
+ public void testSpannedCells_spanningCellOverHiddenColumn_rendersSpannedCellCorrectly() {
+ selectMenuPath("Component", "State", "Width", "1000px");
+ appendHeaderRow();
+ toggleHideColumnAPI(4);
+ toggleHideColumnAPI(8);
+ toggleHideColumnAPI(9);
+ toggleHideColumnAPI(10);
+ toggleHideColumnAPI(11);
+ assertColumnHeaderOrder(0, 1, 2, 3, 5, 6, 7);
+ verifyNumberOfCellsInHeader(1, 7);
+
+ mergeHeaderCellsTwoThreeFour(2);
+
+ verifyNumberOfCellsInHeader(1, 6);
+ verifyHeaderCellContent(1, 3, CAPTION_3_4_5);
+ verifyHeaderCellColspan(1, 3, 2);
+ }
+
+ @Test
+ public void testSpannedCells_spanningCellAllHiddenColumns_rendersSpannedCellCorrectly() {
+ selectMenuPath("Component", "State", "Width", "1000px");
+ appendHeaderRow();
+ toggleHideColumnAPI(3);
+ toggleHideColumnAPI(4);
+ toggleHideColumnAPI(5);
+ toggleHideColumnAPI(8);
+ toggleHideColumnAPI(9);
+ toggleHideColumnAPI(10);
+ toggleHideColumnAPI(11);
+ assertColumnHeaderOrder(0, 1, 2, 6, 7);
+ verifyNumberOfCellsInHeader(1, 5);
+
+ mergeHeaderCellsTwoThreeFour(2);
+
+ verifyNumberOfCellsInHeader(1, 5);
+ verifyHeaderCellColspan(1, 0, 1);
+ verifyHeaderCellColspan(1, 1, 1);
+ verifyHeaderCellColspan(1, 2, 1);
+ verifyHeaderCellColspan(1, 3, 1);
+ verifyHeaderCellColspan(1, 4, 1);
+ }
+
+ private void loadSpannedCellsFixture() {
+ selectMenuPath("Component", "State", "Width", "1000px");
+ appendHeaderRow();
+ appendHeaderRow();
+ appendHeaderRow();
+ mergeHeaderCellsTwoThreeFour(2);
+ mergeHeaderCellsZeroOne(2);
+ mergeHeaderCellsOneTwo(3);
+ mergeHeaderCellsAll(4);
+ toggleHideColumnAPI(8);
+ toggleHideColumnAPI(9);
+ toggleHideColumnAPI(10);
+ toggleHideColumnAPI(11);
+ }
+
+ private void verifySpannedCellsFixtureStart() {
+ assertColumnHeaderOrder(0, 1, 2, 3, 4, 5, 6, 7);
+ verifyNumberOfCellsInHeader(0, 8);
+ verifyNumberOfCellsInHeader(1, 5);
+ verifyNumberOfCellsInHeader(2, 7);
+ verifyNumberOfCellsInHeader(3, 1);
+ verifyHeaderCellContent(1, 0, CAPTION_0_1);
+ verifyHeaderCellContent(1, 3, CAPTION_3_4_5);
+ verifyHeaderCellContent(2, 1, CAPTION_1_2);
+ verifyHeaderCellContent(3, 0, CAPTION_ALL);
+ verifyHeaderCellColspan(1, 0, 2);
+ verifyHeaderCellColspan(1, 3, 3);
+ verifyHeaderCellColspan(2, 1, 2);
+ }
+
+ private void toggleFrozenColumns(int count) {
+ selectMenuPath("Component", "State", "Frozen column count", count
+ + " columns");
+ }
+
+ private void verifyHeaderCellColspan(int row, int column, int colspan) {
+ assertEquals(Integer.valueOf(colspan), Integer.valueOf(Integer
+ .parseInt(getGridElement().getHeaderCell(row, column)
+ .getAttribute("colspan"))));
+ }
+
+ private void verifyNumberOfCellsInHeader(int row, int numberOfCells) {
+ int size = 0;
+ for (TestBenchElement cell : getGridElement().getHeaderCells(row)) {
+ if (cell.isDisplayed()) {
+ size++;
+ }
+ }
+ assertEquals(numberOfCells, size);
+ }
+
+ private void verifyHeaderCellContent(int row, int column, String content) {
+ GridCellElement headerCell = getGridElement()
+ .getHeaderCell(row, column);
+ assertEquals(content.toLowerCase(), headerCell.getText().toLowerCase());
+ assertTrue(headerCell.isDisplayed());
+ }
+
+ private void verifyColumnIsFrozen(int index) {
+ assertTrue(getGridElement().getHeaderCell(0, index).isFrozen());
+ }
+
+ private void verifyColumnIsNotFrozen(int index) {
+ assertFalse(getGridElement().getHeaderCell(0, index).isFrozen());
+ }
+
+ private void verifyColumnHidingTogglesOrder(int... indices) {
+ WebElement sidebar = getSidebar();
+ List<WebElement> elements = sidebar.findElements(By
+ .className("column-hiding-toggle"));
+ for (int i = 0; i < indices.length; i++) {
+ WebElement e = elements.get(i);
+ assertTrue(("Header (0," + indices[i] + ")").equalsIgnoreCase(e
+ .getText()));
+ }
+ }
+
+ private void verifyColumnHidingOption(int columnIndex, boolean hidden) {
+ WebElement columnHidingToggle = getColumnHidingToggle(columnIndex);
+ assertEquals(hidden,
+ columnHidingToggle.getAttribute("class").contains("hidden"));
+ }
+
+ private void verifySidebarOpened() {
+ WebElement sidebar = getSidebar();
+ assertTrue(sidebar.getAttribute("class").contains("opened"));
+ }
+
+ private void verifySidebarClosed() {
+ WebElement sidebar = getSidebar();
+ assertFalse(sidebar.getAttribute("class").contains("opened"));
+ }
+
+ private void verifySidebarNotVisible() {
+ WebElement sidebar = getSidebar();
+ assertNull(sidebar);
+ }
+
+ private void verifySidebarVisible() {
+ WebElement sidebar = getSidebar();
+ assertNotNull(sidebar);
+ }
+
+ @Override
+ protected WebElement getSidebar() {
+ List<WebElement> elements = findElements(By.className("v-grid-sidebar"));
+ return elements.isEmpty() ? null : elements.get(0);
+ }
+
+ @Override
+ protected WebElement getSidebarOpenButton() {
+ List<WebElement> elements = findElements(By
+ .className("v-grid-sidebar-button"));
+ return elements.isEmpty() ? null : elements.get(0);
+ }
+
+ /**
+ * Returns the toggle inside the sidebar for hiding the column at the given
+ * index, or null if not found.
+ */
+ @Override
+ protected WebElement getColumnHidingToggle(int columnIndex) {
+ WebElement sidebar = getSidebar();
+ List<WebElement> elements = sidebar.findElements(By
+ .className("column-hiding-toggle"));
+ for (WebElement e : elements) {
+ if (("Header (0," + columnIndex + ")")
+ .equalsIgnoreCase(e.getText())) {
+ return e;
+ }
+ }
+ return null;
+ }
+
+ private void clickSidebarOpenButton() {
+ getSidebarOpenButton().click();
+ }
+
+ private void moveColumnLeft(int index) {
+ selectMenuPath("Component", "Columns", "Column " + index,
+ "Move column left");
+ }
+
+ private void toggleHidableColumnAPI(int columnIndex) {
+ selectMenuPath("Component", "Columns", "Column " + columnIndex,
+ "Hidable");
+ }
+
+ private void toggleHideColumnAPI(int columnIndex) {
+ selectMenuPath("Component", "Columns", "Column " + columnIndex,
+ "Hidden");
+ }
+
+ private void appendHeaderRow() {
+ selectMenuPath("Component", "Header", "Append row");
+ }
+
+ private void mergeHeaderCellsZeroOne(int row) {
+ selectMenuPath("Component", "Header", "Row " + row, CAPTION_0_1);
+ }
+
+ private void mergeHeaderCellsOneTwo(int row) {
+ selectMenuPath("Component", "Header", "Row " + row, CAPTION_1_2);
+ }
+
+ private void mergeHeaderCellsTwoThreeFour(int row) {
+ selectMenuPath("Component", "Header", "Row " + row, CAPTION_3_4_5);
+ }
+
+ private void mergeHeaderCellsAll(int row) {
+ selectMenuPath("Component", "Header", "Row " + row, CAPTION_ALL);
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridColumnReorderTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridColumnReorderTest.java
new file mode 100644
index 0000000000..d779a5c81a
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridColumnReorderTest.java
@@ -0,0 +1,649 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.interactions.Actions;
+
+import com.vaadin.testbench.elements.GridElement.GridCellElement;
+import com.vaadin.testbench.parallel.TestCategory;
+
+/**
+ *
+ * @author Vaadin Ltd
+ */
+@TestCategory("grid")
+public class GridColumnReorderTest extends GridBasicClientFeaturesTest {
+
+ @Before
+ public void before() {
+ openTestURL();
+ }
+
+ @Test
+ public void columnReorderEventTriggered() {
+ final int firstIndex = 3;
+ final int secondIndex = 4;
+ final String firstHeaderText = getGridElement().getHeaderCell(0,
+ firstIndex).getText();
+ final String secondHeaderText = getGridElement().getHeaderCell(0,
+ secondIndex).getText();
+ selectMenuPath("Component", "Internals", "Listeners",
+ "Add ColumnReorder listener");
+ selectMenuPath("Component", "Columns", "Column " + secondIndex,
+ "Move column left");
+ // columns 3 and 4 should have swapped to 4 and 3
+ GridCellElement headerCell = getGridElement().getHeaderCell(0,
+ firstIndex);
+ assertEquals(secondHeaderText, headerCell.getText());
+ headerCell = getGridElement().getHeaderCell(0, secondIndex);
+ assertEquals(firstHeaderText, headerCell.getText());
+
+ // the reorder event should have typed the order to this label
+ WebElement columnReorderElement = findElement(By.id("columnreorder"));
+ int eventIndex = Integer.parseInt(columnReorderElement
+ .getAttribute("columns"));
+ assertEquals(1, eventIndex);
+
+ // trigger another event
+ selectMenuPath("Component", "Columns", "Column " + secondIndex,
+ "Move column left");
+ columnReorderElement = findElement(By.id("columnreorder"));
+ eventIndex = Integer.parseInt(columnReorderElement
+ .getAttribute("columns"));
+ assertEquals(2, eventIndex);
+ }
+
+ @Test
+ public void testColumnReorder_onReorder_columnReorderEventTriggered() {
+ final int firstIndex = 3;
+ final int secondIndex = 4;
+ final String firstHeaderText = getGridElement().getHeaderCell(0,
+ firstIndex).getText();
+ final String secondHeaderText = getGridElement().getHeaderCell(0,
+ secondIndex).getText();
+ selectMenuPath("Component", "Internals", "Listeners",
+ "Add ColumnReorder listener");
+ selectMenuPath("Component", "Columns", "Column " + secondIndex,
+ "Move column left");
+ // columns 3 and 4 should have swapped to 4 and 3
+ GridCellElement headerCell = getGridElement().getHeaderCell(0,
+ firstIndex);
+ assertEquals(secondHeaderText, headerCell.getText());
+ headerCell = getGridElement().getHeaderCell(0, secondIndex);
+ assertEquals(firstHeaderText, headerCell.getText());
+
+ // the reorder event should have typed the order to this label
+ WebElement columnReorderElement = findElement(By.id("columnreorder"));
+ int eventIndex = Integer.parseInt(columnReorderElement
+ .getAttribute("columns"));
+ assertEquals(1, eventIndex);
+
+ // trigger another event
+ selectMenuPath("Component", "Columns", "Column " + secondIndex,
+ "Move column left");
+ columnReorderElement = findElement(By.id("columnreorder"));
+ eventIndex = Integer.parseInt(columnReorderElement
+ .getAttribute("columns"));
+ assertEquals(2, eventIndex);
+ }
+
+ @Test
+ public void testColumnReorder_draggingSortedColumn_sortIndicatorShownOnDraggedElement() {
+ // given
+ toggleColumnReorder();
+ toggleSortableColumn(0);
+ sortColumn(0);
+
+ // when
+ startDragButDontDropOnDefaultColumnHeader(0);
+
+ // then
+ WebElement draggedElement = getDraggedHeaderElement();
+ assertTrue(draggedElement.getAttribute("class").contains("sort"));
+ }
+
+ @Test
+ public void testColumnReorder_draggingSortedColumn_sortStays() {
+ // given
+ toggleColumnReorder();
+ toggleSortableColumn(0);
+ sortColumn(0);
+
+ // when
+ dragAndDropDefaultColumnHeader(0, 2, CellSide.LEFT);
+
+ // then
+ assertColumnIsSorted(1);
+ }
+
+ @Test
+ public void testColumnReorder_draggingFocusedHeader_focusShownOnDraggedElement() {
+ // given
+ toggleColumnReorder();
+ focusDefaultHeader(0);
+
+ // when
+ startDragButDontDropOnDefaultColumnHeader(0);
+
+ // then
+ WebElement draggedElement = getDraggedHeaderElement();
+ assertTrue(draggedElement.getAttribute("class").contains("focused"));
+ }
+
+ @Test
+ public void testColumnReorder_draggingFocusedHeader_focusIsKeptOnHeader() {
+ // given
+ toggleColumnReorder();
+ focusDefaultHeader(0);
+
+ // when
+ dragAndDropDefaultColumnHeader(0, 3, CellSide.LEFT);
+
+ // then
+ WebElement defaultColumnHeader = getDefaultColumnHeader(2);
+ String attribute = defaultColumnHeader.getAttribute("class");
+ assertTrue(attribute.contains("focused"));
+ }
+
+ @Test
+ public void testColumnReorder_draggingFocusedCellColumn_focusIsKeptOnCell() {
+ // given
+ toggleColumnReorder();
+ focusCell(2, 2);
+
+ // when
+ dragAndDropDefaultColumnHeader(2, 0, CellSide.LEFT);
+
+ // then
+ assertFocusedCell(2, 0);
+ }
+
+ @Test
+ public void testColumnReorderWithHiddenColumn_draggingFocusedCellColumnOverHiddenColumn_focusIsKeptOnCell() {
+ // given
+ toggleColumnReorder();
+ selectMenuPath("Component", "Columns", "Column 1", "Hidden");
+ focusCell(2, 2);
+ assertFocusedCell(2, 2);
+
+ // when
+ dragAndDropDefaultColumnHeader(1, 0, CellSide.LEFT);
+
+ // then
+ assertFocusedCell(2, 2);
+
+ // when
+ dragAndDropDefaultColumnHeader(0, 2, CellSide.LEFT);
+
+ // then
+ assertFocusedCell(2, 2);
+ }
+
+ @Test
+ public void testColumnReorder_dragColumnFromRightToLeftOfFocusedCellColumn_focusIsKept() {
+ // given
+ toggleColumnReorder();
+ focusCell(1, 3);
+
+ // when
+ dragAndDropDefaultColumnHeader(4, 1, CellSide.LEFT);
+
+ // then
+ assertFocusedCell(1, 4);
+ }
+
+ @Test
+ public void testColumnReorder_dragColumnFromLeftToRightOfFocusedCellColumn_focusIsKept() {
+ // given
+ toggleColumnReorder();
+ focusCell(4, 2);
+
+ // when
+ dragAndDropDefaultColumnHeader(0, 4, CellSide.LEFT);
+
+ // then
+ assertFocusedCell(4, 1);
+ }
+
+ @Test
+ public void testColumnReorder_draggingHeaderRowThatHasColumnHeadersSpanned_cantDropInsideSpannedHeaderFromOutside() {
+ // given
+ toggleColumnReorder();
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 2", "Join columns 1, 2");
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+
+ // when
+ int horizontalOffset = (getGridElement().getHeaderCell(1, 1).getSize()
+ .getWidth() / 2) - 10;
+ dragAndDropColumnHeader(1, 3, 1, horizontalOffset);
+
+ // then
+ assertColumnHeaderOrder(0, 3, 1, 2, 4);
+ }
+
+ @Test
+ public void testColumnReorder_anotherRowHasColumnHeadersSpanned_cantDropInsideSpannedHeaderFromOutside() {
+ // given
+ toggleColumnReorder();
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 2", "Join columns 1, 2");
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+
+ // when
+ int horizontalOffset = (getGridElement().getHeaderCell(1, 1).getSize()
+ .getWidth() / 2) + 10;
+ dragAndDropColumnHeader(0, 0, 2, horizontalOffset);
+
+ // then
+ assertColumnHeaderOrder(1, 2, 0, 3, 4);
+ }
+
+ @Test
+ public void testColumnReorder_cellInsideSpannedHeader_cantBeDroppedOutsideSpannedArea() {
+ // given
+ toggleColumnReorder();
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 2", "Join columns 1, 2");
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+
+ // when
+ dragAndDropColumnHeader(0, 2, 0, CellSide.LEFT);
+
+ // then
+ assertColumnHeaderOrder(0, 2, 1, 3, 4);
+ }
+
+ @Test
+ public void testColumnReorder_cellInsideTwoCrossingSpanningHeaders_cantTouchThis() {
+ // given
+ toggleColumnReorder();
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 2", "Join column cells 0, 1");
+ selectMenuPath("Component", "Header", "Row 3", "Join columns 1, 2");
+ dragAndDropColumnHeader(0, 3, 0, CellSide.LEFT);
+ assertColumnHeaderOrder(3, 0, 1, 2, 4);
+
+ // when
+ dragAndDropColumnHeader(0, 2, 0, CellSide.LEFT);
+
+ // then
+ assertColumnHeaderOrder(3, 0, 1, 2, 4);
+ }
+
+ @Test
+ public void testColumnReorder_cellsInsideSpannedHeaderAndBlockedByOtherSpannedCells_cantTouchThose() {
+ // given
+ toggleColumnReorder();
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 2", "Join column cells 0, 1");
+ selectMenuPath("Component", "Header", "Row 3", "Join columns 1, 2");
+ dragAndDropColumnHeader(0, 3, 0, CellSide.LEFT);
+ assertColumnHeaderOrder(3, 0, 1, 2, 4);
+
+ // when then
+ dragAndDropColumnHeader(0, 1, 3, CellSide.LEFT);
+ assertColumnHeaderOrder(3, 0, 1, 2, 4);
+
+ dragAndDropColumnHeader(1, 2, 1, CellSide.LEFT);
+ assertColumnHeaderOrder(3, 0, 1, 2, 4);
+
+ dragAndDropColumnHeader(2, 1, 2, CellSide.RIGHT);
+ assertColumnHeaderOrder(3, 0, 1, 2, 4);
+ }
+
+ @Test
+ public void testColumnReorder_cellsInsideSpannedHeaderAndBlockedByOtherSpannedCells_reorderingLimited() {
+ // given
+ toggleColumnReorder();
+ selectMenuPath("Component", "State", "Width", "750px");
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 2", "Join columns 3, 4, 5");
+ dragAndDropColumnHeader(0, 0, 4, CellSide.RIGHT);
+ selectMenuPath("Component", "Header", "Row 3", "Join columns 1, 2");
+ scrollGridHorizontallyTo(0);
+ assertColumnHeaderOrder(1, 2, 3, 4, 5);
+
+ // when then
+ dragAndDropColumnHeader(0, 1, 4, CellSide.LEFT);
+ scrollGridHorizontallyTo(0);
+ assertColumnHeaderOrder(1, 2, 3, 4, 5);
+
+ dragAndDropColumnHeader(0, 2, 4, CellSide.LEFT);
+ scrollGridHorizontallyTo(0);
+ assertColumnHeaderOrder(1, 2, 3, 4, 5);
+
+ dragAndDropColumnHeader(0, 3, 4, CellSide.RIGHT);
+ scrollGridHorizontallyTo(0);
+ assertColumnHeaderOrder(1, 2, 3, 5, 4);
+
+ dragAndDropColumnHeader(0, 4, 2, CellSide.RIGHT);
+ scrollGridHorizontallyTo(0);
+ assertColumnHeaderOrder(1, 2, 3, 4, 5);
+
+ dragAndDropColumnHeader(2, 3, 4, CellSide.RIGHT);
+ scrollGridHorizontallyTo(0);
+ assertColumnHeaderOrder(1, 2, 3, 5, 4);
+
+ dragAndDropColumnHeader(2, 4, 2, CellSide.RIGHT);
+ scrollGridHorizontallyTo(0);
+ assertColumnHeaderOrder(1, 2, 3, 4, 5);
+ }
+
+ @Test
+ public void testColumnReorder_cellsInsideTwoAdjacentSpannedHeaders_reorderingLimited() {
+ // given
+ toggleColumnReorder();
+ selectMenuPath("Component", "State", "Width", "750px");
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 2", "Join columns 3, 4, 5");
+ dragAndDropColumnHeader(0, 0, 4, CellSide.RIGHT);
+ scrollGridHorizontallyTo(0);
+ dragAndDropColumnHeader(0, 1, 4, CellSide.RIGHT);
+ scrollGridHorizontallyTo(0);
+ selectMenuPath("Component", "Header", "Row 3", "Join columns 1, 2");
+ assertColumnHeaderOrder(1, 3, 4, 5, 2);
+
+ // when then
+ dragAndDropColumnHeader(0, 1, 4, CellSide.LEFT);
+ assertColumnHeaderOrder(1, 4, 3, 5, 2);
+
+ dragAndDropColumnHeader(0, 2, 4, CellSide.LEFT);
+ assertColumnHeaderOrder(1, 4, 3, 5, 2);
+
+ dragAndDropColumnHeader(0, 2, 0, CellSide.LEFT);
+ assertColumnHeaderOrder(1, 3, 4, 5, 2);
+ }
+
+ @Test
+ public void testColumnReorder_footerHasSpannedCells_cantDropInside() {
+ // given
+ toggleColumnReorder();
+ selectMenuPath("Component", "Footer", "Append row");
+ selectMenuPath("Component", "Footer", "Row 1", "Join columns 1, 2");
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+
+ // when
+ dragAndDropColumnHeader(0, 3, 1, CellSide.RIGHT);
+
+ // then
+ assertColumnHeaderOrder(0, 3, 1, 2, 4);
+ }
+
+ @Test
+ public void testColumnReorder_cellInsideASpannedFooter_cantBeDroppedOutsideSpannedArea() {
+ // given
+ toggleColumnReorder();
+ selectMenuPath("Component", "Footer", "Append row");
+ selectMenuPath("Component", "Footer", "Row 1", "Join columns 1, 2");
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+
+ // when
+ dragAndDropColumnHeader(0, 2, 0, CellSide.LEFT);
+
+ // then
+ assertColumnHeaderOrder(0, 2, 1, 3, 4);
+ }
+
+ @Test
+ public void testColumnReorder_cellInsideTwoCrossingSpanningFooters_cantTouchThis() {
+ // given
+ toggleColumnReorder();
+ selectMenuPath("Component", "Footer", "Append row");
+ selectMenuPath("Component", "Footer", "Append row");
+ selectMenuPath("Component", "Footer", "Row 1", "Join column cells 0, 1");
+ selectMenuPath("Component", "Footer", "Row 2", "Join columns 1, 2");
+ dragAndDropColumnHeader(0, 3, 0, CellSide.LEFT);
+ assertColumnHeaderOrder(3, 0, 1, 2, 4);
+
+ // when
+ dragAndDropColumnHeader(0, 2, 0, CellSide.LEFT);
+
+ // then
+ assertColumnHeaderOrder(3, 0, 1, 2, 4);
+ }
+
+ @Test
+ public void testColumnReorder_cellsInsideTwoAdjacentSpannedHeaderAndFooter_reorderingLimited() {
+ // given
+ toggleColumnReorder();
+ selectMenuPath("Component", "State", "Width", "750px");
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Footer", "Append row");
+ selectMenuPath("Component", "Header", "Row 2", "Join columns 3, 4, 5");
+ dragAndDropColumnHeader(0, 0, 5, CellSide.LEFT);
+ scrollGridHorizontallyTo(0);
+ dragAndDropColumnHeader(0, 1, 5, CellSide.LEFT);
+ scrollGridHorizontallyTo(0);
+ selectMenuPath("Component", "Footer", "Row 1", "Join columns 1, 2");
+ assertColumnHeaderOrder(1, 3, 4, 5, 2);
+
+ // when then
+ dragAndDropColumnHeader(0, 1, 3, CellSide.RIGHT);
+ assertColumnHeaderOrder(1, 4, 3, 5, 2);
+
+ dragAndDropColumnHeader(0, 2, 4, CellSide.RIGHT);
+ assertColumnHeaderOrder(1, 4, 3, 5, 2);
+
+ dragAndDropColumnHeader(0, 2, 0, CellSide.RIGHT);
+ assertColumnHeaderOrder(1, 3, 4, 5, 2);
+ }
+
+ @Test
+ public void testColumnReorder_draggingASpannedCell_dragWorksNormally() {
+ // given
+ toggleColumnReorder();
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 2", "Join columns 1, 2");
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+
+ // when
+ dragAndDropColumnHeader(1, 1, 4, CellSide.LEFT);
+ scrollGridHorizontallyTo(0);
+
+ // then
+ assertColumnHeaderOrder(0, 3, 1, 2, 4);
+ }
+
+ @Test
+ public void testColumnReorder_twoEqualSpannedCells_bothCanBeDragged() {
+ // given
+ toggleColumnReorder();
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 2", "Join columns 1, 2");
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 3", "Join columns 1, 2");
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+
+ // when
+ dragAndDropColumnHeader(1, 1, 4, CellSide.LEFT);
+ scrollGridHorizontallyTo(0);
+
+ // then
+ assertColumnHeaderOrder(0, 3, 1, 2, 4);
+
+ // when
+ dragAndDropColumnHeader(2, 3, 0, CellSide.LEFT);
+
+ // then
+ assertColumnHeaderOrder(1, 2, 0, 3, 4);
+ }
+
+ @Test
+ public void testColumReorder_twoCrossingSpanningHeaders_neitherCanBeDragged() {
+ // given
+ toggleColumnReorder();
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 2", "Join columns 1, 2");
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 3", "Join column cells 0, 1");
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+
+ // when
+ dragAndDropColumnHeader(1, 1, 4, CellSide.LEFT);
+
+ // then
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+
+ // when
+ dragAndDropColumnHeader(2, 0, 3, CellSide.RIGHT);
+
+ // then
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+ }
+
+ @Test
+ public void testColumnReorder_spannedCellHasAnotherSpannedCellInside_canBeDraggedNormally() {
+ // given
+ toggleColumnReorder();
+ selectMenuPath("Component", "State", "Width", "750px");
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 2", "Join columns 3, 4, 5");
+ dragAndDropColumnHeader(1, 3, 1, CellSide.LEFT);
+ scrollGridHorizontallyTo(0);
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 3", "Join columns 1, 2");
+ assertColumnHeaderOrder(0, 3, 4, 5, 1);
+
+ // when
+ dragAndDropColumnHeader(1, 1, 0, CellSide.LEFT);
+
+ // then
+ assertColumnHeaderOrder(3, 4, 5, 0, 1);
+ }
+
+ @Test
+ public void testColumnReorder_spannedCellInsideAnotherSpanned_canBeDraggedWithBoundaries() {
+ // given
+ toggleColumnReorder();
+ selectMenuPath("Component", "State", "Width", "750px");
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 2", "Join columns 3, 4, 5");
+ dragAndDropColumnHeader(1, 3, 1, CellSide.LEFT);
+ scrollGridHorizontallyTo(0);
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 3", "Join columns 1, 2");
+ assertColumnHeaderOrder(0, 3, 4, 5, 1);
+
+ // when
+ dragAndDropColumnHeader(2, 1, 3, CellSide.RIGHT);
+ scrollGridHorizontallyTo(0);
+
+ // then
+ assertColumnHeaderOrder(0, 5, 3, 4, 1);
+
+ // when
+ dragAndDropColumnHeader(2, 2, 0, CellSide.LEFT);
+ scrollGridHorizontallyTo(0);
+
+ // then
+ assertColumnHeaderOrder(0, 3, 4, 5, 1);
+ }
+
+ @Test
+ public void testColumnReorder_cellInsideAndNextToSpannedCells_canBeDraggedWithBoundaries() {
+ // given
+ toggleColumnReorder();
+ selectMenuPath("Component", "State", "Width", "750px");
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 2", "Join columns 3, 4, 5");
+ dragAndDropColumnHeader(1, 3, 1, CellSide.LEFT);
+ scrollGridHorizontallyTo(0);
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 3", "Join columns 1, 2");
+ assertColumnHeaderOrder(0, 3, 4, 5, 1);
+
+ // when
+ dragAndDropColumnHeader(2, 3, 0, CellSide.LEFT);
+ scrollGridHorizontallyTo(0);
+
+ // then
+ assertColumnHeaderOrder(0, 5, 3, 4, 1);
+
+ // when
+ dragAndDropColumnHeader(2, 1, 4, CellSide.LEFT);
+ scrollGridHorizontallyTo(0);
+
+ // then
+ assertColumnHeaderOrder(0, 3, 4, 5, 1);
+ }
+
+ @Test
+ public void testColumnReorder_multipleSpannedCells_dragWorksNormally() {
+ toggleColumnReorder();
+ selectMenuPath("Component", "State", "Width", "750px");
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 2", "Join columns 3, 4, 5");
+ selectMenuPath("Component", "Header", "Append row");
+ selectMenuPath("Component", "Header", "Row 3", "Join columns 1, 2");
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+
+ // when
+ dragAndDropColumnHeader(1, 3, 1, CellSide.RIGHT);
+ scrollGridHorizontallyTo(0);
+
+ // then
+ assertColumnHeaderOrder(0, 3, 4, 5, 1);
+
+ // when
+ scrollGridHorizontallyTo(100);
+ dragAndDropColumnHeader(2, 4, 2, CellSide.LEFT);
+ scrollGridHorizontallyTo(0);
+
+ // then
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+
+ // when
+ dragAndDropColumnHeader(0, 0, 3, CellSide.LEFT);
+ scrollGridHorizontallyTo(0);
+
+ // then
+ assertColumnHeaderOrder(1, 2, 0, 3, 4);
+ }
+
+ private void toggleSortableColumn(int index) {
+ selectMenuPath("Component", "Columns", "Column " + index, "Sortable");
+ }
+
+ private void startDragButDontDropOnDefaultColumnHeader(int index) {
+ new Actions(getDriver())
+ .clickAndHold(getGridHeaderRowCells().get(index))
+ .moveByOffset(100, 0).perform();
+ }
+
+ private void sortColumn(int index) {
+ getGridHeaderRowCells().get(index).click();
+ }
+
+ private void focusDefaultHeader(int index) {
+ getGridHeaderRowCells().get(index).click();
+ }
+
+ private WebElement getDraggedHeaderElement() {
+ return findElement(By.className("dragged-column-header"));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSidebarFeatures.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSidebarFeatures.java
new file mode 100644
index 0000000000..9494988cf4
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridSidebarFeatures.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures;
+
+public class GridSidebarFeatures extends GridBasicFeatures {
+
+ @Override
+ protected boolean isColumnHidableByDefault(int col) {
+ return true;
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridDetailsClientTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridDetailsClientTest.java
new file mode 100644
index 0000000000..88158c7f6f
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridDetailsClientTest.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.client;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+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.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.openqa.selenium.NoSuchElementException;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.shared.ui.grid.Range;
+import com.vaadin.shared.ui.grid.ScrollDestination;
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.ElementQuery;
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.elements.NotificationElement;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest;
+
+public class GridDetailsClientTest extends GridBasicClientFeaturesTest {
+
+ private static final String[] SET_GENERATOR = new String[] { "Component",
+ "Row details", "Set generator" };
+ private static final String[] SET_FAULTY_GENERATOR = new String[] {
+ "Component", "Row details", "Set faulty generator" };
+ private static final String[] SET_EMPTY_GENERATOR = new String[] {
+ "Component", "Row details", "Set empty generator" };
+
+ @Before
+ public void setUp() {
+ setDebug(true);
+ openTestURL();
+ }
+
+ @Test(expected = NoSuchElementException.class)
+ public void noDetailsByDefault() {
+ assertNull("details for row 1 should not exist at the start",
+ getGridElement().getDetails(1));
+ }
+
+ @Test
+ public void nullRendererShowsDetailsPlaceholder() {
+ toggleDetailsFor(1);
+ TestBenchElement details = getGridElement().getDetails(1);
+ assertNotNull("details for row 1 should not exist at the start",
+ details);
+ assertTrue("details should've been empty for null renderer", details
+ .getText().isEmpty());
+ }
+
+ @Test
+ public void applyRendererThenOpenDetails() {
+ selectMenuPath(SET_GENERATOR);
+ toggleDetailsFor(1);
+
+ TestBenchElement details = getGridElement().getDetails(1);
+ assertTrue("Unexpected details content",
+ details.getText().startsWith("Row: 1."));
+ }
+
+ @Test
+ public void openDetailsThenAppyRenderer() {
+ toggleDetailsFor(1);
+ selectMenuPath(SET_GENERATOR);
+
+ TestBenchElement details = getGridElement().getDetails(1);
+ assertTrue("Unexpected details content",
+ details.getText().startsWith("Row: 1."));
+ }
+
+ @Test
+ public void openHiddenDetailsThenScrollToIt() {
+ try {
+ getGridElement().getDetails(100);
+ fail("details row for 100 was apparently found, while it shouldn't have been.");
+ } catch (NoSuchElementException e) {
+ // expected
+ }
+
+ selectMenuPath(SET_GENERATOR);
+ toggleDetailsFor(100);
+
+ // scroll a bit beyond so we see below.
+ getGridElement().scrollToRow(101);
+
+ TestBenchElement details = getGridElement().getDetails(100);
+ assertTrue("Unexpected details content",
+ details.getText().startsWith("Row: 100."));
+ }
+
+ @Test
+ public void errorUpdaterShowsErrorNotification() {
+ assertFalse("No notifications should've been at the start",
+ $(NotificationElement.class).exists());
+
+ toggleDetailsFor(1);
+ selectMenuPath(SET_FAULTY_GENERATOR);
+
+ ElementQuery<NotificationElement> notification = $(NotificationElement.class);
+ assertTrue("Was expecting an error notification here",
+ notification.exists());
+ notification.first().close();
+
+ assertEquals("The error details element should be empty", "",
+ getGridElement().getDetails(1).getText());
+ }
+
+ @Test
+ public void updaterStillWorksAfterError() {
+ toggleDetailsFor(1);
+
+ selectMenuPath(SET_FAULTY_GENERATOR);
+ $(NotificationElement.class).first().close();
+ selectMenuPath(SET_GENERATOR);
+
+ assertNotEquals(
+ "New details should've been generated even after error", "",
+ getGridElement().getDetails(1).getText());
+ }
+
+ @Test
+ public void updaterRendersExpectedWidgets() {
+ selectMenuPath(SET_GENERATOR);
+ toggleDetailsFor(1);
+
+ TestBenchElement detailsElement = getGridElement().getDetails(1);
+ assertNotNull(detailsElement.findElement(By.className("gwt-Label")));
+ assertNotNull(detailsElement.findElement(By.className("gwt-Button")));
+ }
+
+ @Test
+ public void widgetsInUpdaterWorkAsExpected() {
+ selectMenuPath(SET_GENERATOR);
+ toggleDetailsFor(1);
+
+ TestBenchElement detailsElement = getGridElement().getDetails(1);
+ WebElement button = detailsElement.findElement(By
+ .className("gwt-Button"));
+ button.click();
+
+ WebElement label = detailsElement
+ .findElement(By.className("gwt-Label"));
+ assertEquals("clicked", label.getText());
+ }
+
+ @Test
+ public void emptyGenerator() {
+ selectMenuPath(SET_EMPTY_GENERATOR);
+ toggleDetailsFor(1);
+
+ assertEquals("empty generator did not produce an empty details row",
+ "", getGridElement().getDetails(1).getText());
+ }
+
+ @Test(expected = NoSuchElementException.class)
+ public void removeDetailsRow() {
+ selectMenuPath(SET_GENERATOR);
+ toggleDetailsFor(1);
+ toggleDetailsFor(1);
+
+ getGridElement().getDetails(1);
+ }
+
+ @Test
+ public void rowElementClassNames() {
+ toggleDetailsFor(0);
+ toggleDetailsFor(1);
+
+ List<WebElement> elements = getGridElement().findElements(
+ By.className("v-grid-spacer"));
+ assertEquals("v-grid-spacer", elements.get(0).getAttribute("class"));
+ assertEquals("v-grid-spacer stripe",
+ elements.get(1).getAttribute("class"));
+ }
+
+ @Test
+ public void scrollDownToRowWithDetails() {
+ toggleDetailsFor(100);
+ scrollToRow(100, ScrollDestination.ANY);
+
+ Range validScrollRange = Range.between(1700, 1715);
+ assertTrue(validScrollRange.contains(getGridVerticalScrollPos()));
+ }
+
+ @Test
+ public void scrollUpToRowWithDetails() {
+ toggleDetailsFor(100);
+ scrollGridVerticallyTo(999999);
+ scrollToRow(100, ScrollDestination.ANY);
+
+ Range validScrollRange = Range.between(1990, 2010);
+ assertTrue(validScrollRange.contains(getGridVerticalScrollPos()));
+ }
+
+ @Test
+ public void cannotScrollBeforeTop() {
+ toggleDetailsFor(1);
+ scrollToRow(0, ScrollDestination.END);
+ assertEquals(0, getGridVerticalScrollPos());
+ }
+
+ @Test
+ public void cannotScrollAfterBottom() {
+ toggleDetailsFor(999);
+ scrollToRow(999, ScrollDestination.START);
+
+ Range expectedRange = Range.withLength(19680, 20);
+ assertTrue(expectedRange.contains(getGridVerticalScrollPos()));
+ }
+
+ private void scrollToRow(int rowIndex, ScrollDestination destination) {
+ selectMenuPath(new String[] { "Component", "State", "Scroll to...",
+ "Row " + rowIndex + "...", "Destination " + destination });
+ }
+
+ private void toggleDetailsFor(int rowIndex) {
+ selectMenuPath(new String[] { "Component", "Row details",
+ "Toggle details for...", "Row " + rowIndex });
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridSidebarContentTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridSidebarContentTest.java
new file mode 100644
index 0000000000..c5092a9c22
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridSidebarContentTest.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.client;
+
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest;
+import com.vaadin.tests.components.grid.basicfeatures.element.CustomGridElement;
+
+public class GridSidebarContentTest extends GridBasicClientFeaturesTest {
+
+ @Test
+ public void testSidebarWithHidableColumn() {
+ openTestURL();
+ CustomGridElement gridElement = getGridElement();
+
+ Assert.assertEquals("Sidebar should not be initially present", 0,
+ countBySelector(".v-grid-sidebar"));
+
+ selectMenuPath("Component", "Columns", "Column 0", "Hidable");
+
+ gridElement.findElement(By.className("v-grid-sidebar-button")).click();
+
+ WebElement toggle = gridElement.findElement(By
+ .className("column-hiding-toggle"));
+
+ Assert.assertEquals("Column 0 should be togglable", "Header (0,0)",
+ toggle.getText());
+
+ selectMenuPath("Component", "Columns", "Column 0", "Hidable");
+ Assert.assertEquals("Sidebar should disappear without toggable column",
+ 0, countBySelector(".v-grid-sidebar"));
+
+ }
+
+ @Test
+ public void testAddingCustomSidebarItem() {
+ openTestURL();
+ CustomGridElement gridElement = getGridElement();
+
+ selectMenuPath("Component", "Sidebar", "Add item to end");
+
+ gridElement.findElement(By.className("v-grid-sidebar-button")).click();
+
+ WebElement sidebarItem = gridElement.findElement(By
+ .cssSelector(".v-grid-sidebar-content .gwt-MenuItem"));
+
+ sidebarItem.click();
+
+ Assert.assertEquals("Sidebar should be closed after clicking item 0",
+ 0, countBySelector(".v-grid-sidebar-content"));
+ }
+
+ @Test
+ public void testProgrammaticSidebarToggle() {
+ openTestURL();
+
+ selectMenuPath("Component", "Columns", "Column 0", "Hidable");
+
+ selectMenuPath("Component", "Sidebar", "Toggle sidebar visibility");
+
+ Assert.assertEquals("Sidebar be open", 1,
+ countBySelector(".v-grid-sidebar-content"));
+
+ selectMenuPath("Component", "Sidebar", "Toggle sidebar visibility");
+
+ Assert.assertEquals("Sidebar be closed", 0,
+ countBySelector(".v-grid-sidebar-content"));
+ }
+
+ @Test
+ public void testBasicSidebarOrder() {
+ openTestURL();
+ CustomGridElement gridElement = getGridElement();
+
+ // First add custom content
+ selectMenuPath("Component", "Sidebar", "Add separator to end");
+ selectMenuPath("Component", "Sidebar", "Add item to end");
+
+ // Then make one column togglable
+ selectMenuPath("Component", "Columns", "Column 0", "Hidable");
+
+ selectMenuPath("Component", "Sidebar", "Toggle sidebar visibility");
+
+ assertSidebarMenuItems("Header (0,0)", null, "Custom menu item 0");
+ }
+
+ @Test
+ public void testSidebarOrderAbuse() {
+ openTestURL();
+ CustomGridElement gridElement = getGridElement();
+
+ selectMenuPath("Component", "Columns", "Column 0", "Hidable");
+ selectMenuPath("Component", "Columns", "Column 1", "Hidable");
+
+ // Inserts a menu item between the two visibility toggles
+ selectMenuPath("Component", "Sidebar", "Add item before index 1");
+
+ selectMenuPath("Component", "Sidebar", "Toggle sidebar visibility");
+
+ // Total order enforcement not implemented at this point. Test can be
+ // updated when it is.
+ assertSidebarMenuItems("Header (0,0)", "Custom menu item 0",
+ "Header (0,1)");
+
+ selectMenuPath("Component", "Columns", "Column 2", "Hidable");
+
+ // Adding a new togglable column should have restored the expected order
+ assertSidebarMenuItems("Header (0,0)", "Header (0,1)", "Header (0,2)",
+ "Custom menu item 0");
+ }
+
+ private void assertSidebarMenuItems(String... items) {
+ List<WebElement> menuItems = getGridElement().findElements(
+ By.cssSelector(".v-grid-sidebar-content td"));
+
+ Assert.assertEquals("Expected " + items.length + " menu items",
+ items.length, menuItems.size());
+
+ for (int i = 0; i < items.length; i++) {
+ String expectedItem = items[i];
+ if (expectedItem == null) {
+ Assert.assertEquals("Item " + i + " should be a separator",
+ "gwt-MenuItemSeparator",
+ menuItems.get(i).getAttribute("class"));
+ } else {
+ Assert.assertEquals("Unexpected content for item " + i,
+ expectedItem, menuItems.get(i).getText());
+ }
+ }
+ }
+
+ private int countBySelector(String cssSelector) {
+ return getGridElement().findElements(By.cssSelector(cssSelector))
+ .size();
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/element/CustomGridElement.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/element/CustomGridElement.java
new file mode 100644
index 0000000000..e1934d4f2b
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/element/CustomGridElement.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.element;
+
+import org.openqa.selenium.NoSuchElementException;
+
+import com.vaadin.testbench.By;
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.elements.GridElement;
+import com.vaadin.testbench.elementsbase.ServerClass;
+
+@ServerClass("com.vaadin.ui.Grid")
+public class CustomGridElement extends GridElement {
+ /**
+ * Gets the element that contains the details of a row.
+ *
+ * @since
+ * @param rowIndex
+ * the index of the row for the details
+ * @return the element that contains the details of a row. <code>null</code>
+ * if no widget is defined for the detials row
+ * @throws NoSuchElementException
+ * if the given details row is currently not open
+ */
+ public TestBenchElement getDetails(int rowIndex)
+ throws NoSuchElementException {
+ return getSubPart("#details[" + rowIndex + "]");
+ }
+
+ private TestBenchElement getSubPart(String subPartSelector) {
+ return (TestBenchElement) findElement(By.vaadin(subPartSelector));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorBasicsTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorBasicsTest.java
index 4742236ac6..1d26477d34 100644
--- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorBasicsTest.java
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorBasicsTest.java
@@ -66,10 +66,8 @@ public class EscalatorBasicsTest extends EscalatorBasicClientFeaturesTest {
selectMenuPath(GENERAL, DETACH_ESCALATOR);
selectMenuPath(GENERAL, ATTACH_ESCALATOR);
- assertEquals("Vertical scroll position", "50", getVerticalScrollbar()
- .getAttribute("scrollTop"));
- assertEquals("Horizontal scroll position", "50",
- getHorizontalScrollbar().getAttribute("scrollLeft"));
+ assertEquals("Vertical scroll position", 50, getScrollTop());
+ assertEquals("Horizontal scroll position", 50, getScrollLeft());
assertEquals("First cell of first visible row", "Row 2: 0,2",
getBodyCell(0, 0).getText());
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorSpacerTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorSpacerTest.java
new file mode 100644
index 0000000000..66c131255f
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorSpacerTest.java
@@ -0,0 +1,583 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.escalator;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.junit.Before;
+import org.junit.ComparisonFailure;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.Keys;
+import org.openqa.selenium.WebElement;
+
+import com.vaadin.client.WidgetUtil;
+import com.vaadin.shared.ui.grid.Range;
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.elements.NotificationElement;
+import com.vaadin.testbench.parallel.BrowserUtil;
+import com.vaadin.tests.components.grid.basicfeatures.EscalatorBasicClientFeaturesTest;
+
+@SuppressWarnings("boxing")
+public class EscalatorSpacerTest extends EscalatorBasicClientFeaturesTest {
+
+ //@formatter:off
+ // separate strings made so that eclipse can show the concatenated string by hovering the mouse over the constant
+
+ // translate3d(0px, 40px, 123px);
+ // translate3d(24px, 15.251px, 0);
+ // translate(0, 40px);
+ private final static String TRANSLATE_VALUE_REGEX =
+ "translate(?:3d|)" // "translate" or "translate3d"
+ + "\\(" // literal "("
+ + "(" // start capturing the x argument
+ + "[0-9]+" // the integer part of the value
+ + "(?:" // start of the subpixel part of the value
+ + "\\.[0-9]" // if we have a period, there must be at least one number after it
+ + "[0-9]*" // any amount of accuracy afterwards is fine
+ + ")?" // the subpixel part is optional
+ + ")"
+ + "(?:px)?" // we don't care if the values are suffixed by "px" or not.
+ + ", "
+ + "(" // start capturing the y argument
+ + "[0-9]+" // the integer part of the value
+ + "(?:" // start of the subpixel part of the value
+ + "\\.[0-9]" // if we have a period, there must be at least one number after it
+ + "[0-9]*" // any amount of accuracy afterwards is fine
+ + ")?" // the subpixel part is optional
+ + ")"
+ + "(?:px)?" // we don't care if the values are suffixed by "px" or not.
+ + "(?:, .*?)?" // the possible z argument, uninteresting (translate doesn't have one, translate3d does)
+ + "\\)" // literal ")"
+ + ";?"; // optional ending semicolon
+
+ // 40px;
+ // 12.34px
+ private final static String PIXEL_VALUE_REGEX =
+ "(" // capture the pixel value
+ + "[0-9]+" // the pixel argument
+ + "(?:" // start of the subpixel part of the value
+ + "\\.[0-9]" // if we have a period, there must be at least one number after it
+ + "[0-9]*" // any amount of accuracy afterwards is fine
+ + ")?" // the subpixel part is optional
+ + ")"
+ + "(?:px)?" // optional "px" string
+ + ";?"; // optional semicolon
+ //@formatter:on
+
+ // also matches "-webkit-transform";
+ private final static Pattern TRANSFORM_CSS_PATTERN = Pattern
+ .compile("transform: (.*?);");
+ private final static Pattern TOP_CSS_PATTERN = Pattern.compile(
+ "top: ([0-9]+(?:\\.[0-9]+)?(?:px)?);?", Pattern.CASE_INSENSITIVE);
+ private final static Pattern LEFT_CSS_PATTERN = Pattern.compile(
+ "left: ([0-9]+(?:\\.[0-9]+)?(?:px)?);?", Pattern.CASE_INSENSITIVE);
+
+ private final static Pattern TRANSLATE_VALUE_PATTERN = Pattern
+ .compile(TRANSLATE_VALUE_REGEX);
+ private final static Pattern PIXEL_VALUE_PATTERN = Pattern.compile(
+ PIXEL_VALUE_REGEX, Pattern.CASE_INSENSITIVE);
+
+ @Before
+ public void before() {
+ setDebug(true);
+ openTestURL();
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, "Set 20px default height");
+ populate();
+ }
+
+ @Test
+ public void openVisibleSpacer() {
+ assertFalse("No spacers should be shown at the start",
+ spacersAreFoundInDom());
+ selectMenuPath(FEATURES, SPACERS, ROW_1, SET_100PX);
+ assertNotNull("Spacer should be shown after setting it", getSpacer(1));
+ }
+
+ @Test
+ public void closeVisibleSpacer() {
+ selectMenuPath(FEATURES, SPACERS, ROW_1, SET_100PX);
+ selectMenuPath(FEATURES, SPACERS, ROW_1, REMOVE);
+ assertNull("Spacer should not exist after removing it", getSpacer(1));
+ }
+
+ @Test
+ public void spacerPushesVisibleRowsDown() {
+ double oldTop = getElementTop(getBodyRow(2));
+ selectMenuPath(FEATURES, SPACERS, ROW_1, SET_100PX);
+ double newTop = getElementTop(getBodyRow(2));
+
+ assertGreater("Row below a spacer was not pushed down", newTop, oldTop);
+ }
+
+ @Test
+ public void addingRowAboveSpacerPushesItDown() {
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, REMOVE_ALL_ROWS);
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, ADD_ONE_ROW_TO_BEGINNING);
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, ADD_ONE_ROW_TO_BEGINNING);
+
+ selectMenuPath(FEATURES, SPACERS, ROW_1, SET_100PX);
+ double oldTop = getElementTop(getSpacer(1));
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, ADD_ONE_ROW_TO_BEGINNING);
+ double newTop = getElementTop(getSpacer(2));
+
+ assertGreater("Spacer should've been pushed down (oldTop: " + oldTop
+ + ", newTop: " + newTop + ")", newTop, oldTop);
+ }
+
+ @Test
+ public void addingRowBelowSpacerDoesNotPushItDown() {
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, REMOVE_ALL_ROWS);
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, ADD_ONE_ROW_TO_BEGINNING);
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, ADD_ONE_ROW_TO_BEGINNING);
+
+ selectMenuPath(FEATURES, SPACERS, ROW_1, SET_100PX);
+ double oldTop = getElementTop(getSpacer(1));
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, ADD_ONE_ROW_TO_END);
+ double newTop = getElementTop(getSpacer(1));
+
+ assertEquals("Spacer should've not been pushed down", newTop, oldTop,
+ WidgetUtil.PIXEL_EPSILON);
+ }
+
+ @Test
+ public void addingRowBelowSpacerIsActuallyRenderedBelowWhenEscalatorIsEmpty() {
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, REMOVE_ALL_ROWS);
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, ADD_ONE_ROW_TO_BEGINNING);
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, ADD_ONE_ROW_TO_BEGINNING);
+
+ selectMenuPath(FEATURES, SPACERS, ROW_1, SET_100PX);
+ double spacerTop = getElementTop(getSpacer(1));
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, ADD_ONE_ROW_TO_END);
+ double rowTop = getElementTop(getBodyRow(2));
+
+ assertEquals("Next row should've been rendered below the spacer",
+ spacerTop + 100, rowTop, WidgetUtil.PIXEL_EPSILON);
+ }
+
+ @Test
+ public void addSpacerAtBottomThenScrollThere() {
+ selectMenuPath(FEATURES, SPACERS, ROW_99, SET_100PX);
+ scrollVerticallyTo(999999);
+
+ assertFalse("Did not expect a notification",
+ $(NotificationElement.class).exists());
+ }
+
+ @Test
+ public void scrollToBottomThenAddSpacerThere() {
+ scrollVerticallyTo(999999);
+ long oldBottomScrollTop = getScrollTop();
+ selectMenuPath(FEATURES, SPACERS, ROW_99, SET_100PX);
+
+ assertEquals("Adding a spacer underneath the current viewport should "
+ + "not scroll anywhere", oldBottomScrollTop, getScrollTop());
+ assertFalse("Got an unexpected notification",
+ $(NotificationElement.class).exists());
+
+ scrollVerticallyTo(999999);
+
+ assertFalse("Got an unexpected notification",
+ $(NotificationElement.class).exists());
+ assertGreater("Adding a spacer should've made the scrollbar scroll "
+ + "further", getScrollTop(), oldBottomScrollTop);
+ }
+
+ @Test
+ public void removingRowAboveSpacerMovesSpacerUp() {
+ selectMenuPath(FEATURES, SPACERS, ROW_1, SET_100PX);
+ WebElement spacer = getSpacer(1);
+ double originalElementTop = getElementTop(spacer);
+
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS,
+ REMOVE_ONE_ROW_FROM_BEGINNING);
+ assertLessThan("spacer should've moved up", getElementTop(spacer),
+ originalElementTop);
+ assertNull("No spacer for row 1 should be found after removing the "
+ + "top row", getSpacer(1));
+ }
+
+ @Test
+ public void removingSpacedRowRemovesSpacer() {
+ selectMenuPath(FEATURES, SPACERS, ROW_1, SET_100PX);
+ assertTrue("Spacer should've been found in the DOM",
+ spacersAreFoundInDom());
+
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS,
+ REMOVE_ONE_ROW_FROM_BEGINNING);
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS,
+ REMOVE_ONE_ROW_FROM_BEGINNING);
+
+ assertFalse("No spacers should be in the DOM after removing "
+ + "associated spacer", spacersAreFoundInDom());
+
+ }
+
+ @Test
+ public void spacersAreFixedInViewport_firstFreezeThenScroll() {
+ selectMenuPath(FEATURES, FROZEN_COLUMNS, FREEZE_1_COLUMN);
+ selectMenuPath(FEATURES, SPACERS, ROW_1, SET_100PX);
+ assertEquals("Spacer's left position should've been 0 at the "
+ + "beginning", 0d, getElementLeft(getSpacer(1)),
+ WidgetUtil.PIXEL_EPSILON);
+
+ int scrollTo = 10;
+ scrollHorizontallyTo(scrollTo);
+ assertEquals("Spacer's left position should've been " + scrollTo
+ + " after scrolling " + scrollTo + "px", scrollTo,
+ getElementLeft(getSpacer(1)), WidgetUtil.PIXEL_EPSILON);
+ }
+
+ @Test
+ public void spacersAreFixedInViewport_firstScrollThenFreeze() {
+ selectMenuPath(FEATURES, FROZEN_COLUMNS, FREEZE_1_COLUMN);
+ int scrollTo = 10;
+ scrollHorizontallyTo(scrollTo);
+ selectMenuPath(FEATURES, SPACERS, ROW_1, SET_100PX);
+ assertEquals("Spacer's left position should've been " + scrollTo
+ + " after scrolling " + scrollTo + "px", scrollTo,
+ getElementLeft(getSpacer(1)), WidgetUtil.PIXEL_EPSILON);
+ }
+
+ @Test
+ public void addingMinusOneSpacerDoesNotScrollWhenScrolledAtTop() {
+ scrollVerticallyTo(5);
+ selectMenuPath(FEATURES, SPACERS, ROW_MINUS1, SET_100PX);
+ assertEquals(
+ "No scroll adjustment should've happened when adding the -1 spacer",
+ 5, getScrollTop());
+ }
+
+ @Test
+ public void removingMinusOneSpacerScrolls() {
+ scrollVerticallyTo(5);
+ selectMenuPath(FEATURES, SPACERS, ROW_MINUS1, SET_100PX);
+ selectMenuPath(FEATURES, SPACERS, ROW_MINUS1, REMOVE);
+ assertEquals("Scroll adjustment should've happened when removing the "
+ + "-1 spacer", 0, getScrollTop());
+ }
+
+ @Test
+ public void scrollToRowWorksProperlyWithSpacers() throws Exception {
+ selectMenuPath(FEATURES, SPACERS, ROW_MINUS1, SET_100PX);
+ selectMenuPath(FEATURES, SPACERS, ROW_1, SET_100PX);
+
+ /*
+ * we check for row -2 instead of -1, because escalator has the one row
+ * buffered underneath the footer
+ */
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, SCROLL_TO, ROW_75);
+ Thread.sleep(500);
+ assertEquals("Row 75: 0,75", getBodyCell(-2, 0).getText());
+
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, SCROLL_TO, ROW_25);
+ Thread.sleep(500);
+
+ try {
+ assertEquals("Row 25: 0,25", getBodyCell(0, 0).getText());
+ } catch (ComparisonFailure retryForIE10andIE11) {
+ /*
+ * This seems to be some kind of subpixel/off-by-one-pixel error.
+ * Everything's scrolled correctly, but Escalator still loads one
+ * row above to the DOM, underneath the header. It's there, but it's
+ * not visible. We'll allow for that one pixel error.
+ */
+ assertEquals("Row 24: 0,24", getBodyCell(0, 0).getText());
+ }
+ }
+
+ @Test
+ public void scrollToSpacerFromAbove() throws Exception {
+ selectMenuPath(FEATURES, SPACERS, ROW_50, SET_100PX);
+ selectMenuPath(FEATURES, SPACERS, ROW_50, SCROLL_HERE_ANY_0PADDING);
+
+ // Browsers might vary with a few pixels.
+ Range allowableScrollRange = Range.between(765, 780);
+ int scrollTop = (int) getScrollTop();
+ assertTrue("Scroll position was not " + allowableScrollRange + ", but "
+ + scrollTop, allowableScrollRange.contains(scrollTop));
+ }
+
+ @Test
+ public void scrollToSpacerFromBelow() throws Exception {
+ selectMenuPath(FEATURES, SPACERS, ROW_50, SET_100PX);
+ scrollVerticallyTo(999999);
+ selectMenuPath(FEATURES, SPACERS, ROW_50, SCROLL_HERE_ANY_0PADDING);
+
+ // Browsers might vary with a few pixels.
+ Range allowableScrollRange = Range.between(1015, 1025);
+ int scrollTop = (int) getScrollTop();
+ assertTrue("Scroll position was not " + allowableScrollRange + ", but "
+ + scrollTop, allowableScrollRange.contains(scrollTop));
+ }
+
+ @Test
+ public void scrollToSpacerAlreadyInViewport() throws Exception {
+ selectMenuPath(FEATURES, SPACERS, ROW_50, SET_100PX);
+ scrollVerticallyTo(1000);
+ selectMenuPath(FEATURES, SPACERS, ROW_50, SCROLL_HERE_ANY_0PADDING);
+
+ assertEquals(getScrollTop(), 1000);
+ }
+
+ @Test
+ public void scrollToRowAndSpacerFromAbove() throws Exception {
+ selectMenuPath(FEATURES, SPACERS, ROW_50, SET_100PX);
+ selectMenuPath(FEATURES, SPACERS, ROW_50,
+ SCROLL_HERE_SPACERBELOW_ANY_0PADDING);
+
+ // Browsers might vary with a few pixels.
+ Range allowableScrollRange = Range.between(765, 780);
+ int scrollTop = (int) getScrollTop();
+ assertTrue("Scroll position was not " + allowableScrollRange + ", but "
+ + scrollTop, allowableScrollRange.contains(scrollTop));
+ }
+
+ @Test
+ public void scrollToRowAndSpacerFromBelow() throws Exception {
+ selectMenuPath(FEATURES, SPACERS, ROW_50, SET_100PX);
+ scrollVerticallyTo(999999);
+ selectMenuPath(FEATURES, SPACERS, ROW_50,
+ SCROLL_HERE_SPACERBELOW_ANY_0PADDING);
+
+ // Browsers might vary with a few pixels.
+ Range allowableScrollRange = Range.between(995, 1005);
+ int scrollTop = (int) getScrollTop();
+ assertTrue("Scroll position was not " + allowableScrollRange + ", but "
+ + scrollTop, allowableScrollRange.contains(scrollTop));
+ }
+
+ @Test
+ public void scrollToRowAndSpacerAlreadyInViewport() throws Exception {
+ selectMenuPath(FEATURES, SPACERS, ROW_50, SET_100PX);
+ scrollVerticallyTo(950);
+ selectMenuPath(FEATURES, SPACERS, ROW_50,
+ SCROLL_HERE_SPACERBELOW_ANY_0PADDING);
+
+ assertEquals(getScrollTop(), 950);
+ }
+
+ @Test
+ public void domCanBeSortedWithFocusInSpacer() throws InterruptedException {
+
+ // Firefox behaves badly with focus-related tests - skip it.
+ if (BrowserUtil.isFirefox(super.getDesiredCapabilities())) {
+ return;
+ }
+
+ selectMenuPath(FEATURES, SPACERS, FOCUSABLE_UPDATER);
+ selectMenuPath(FEATURES, SPACERS, ROW_1, SET_100PX);
+
+ WebElement inputElement = getEscalator().findElement(
+ By.tagName("input"));
+ inputElement.click();
+ scrollVerticallyTo(30);
+
+ // Sleep needed because of all the JS we're doing, and to let
+ // the DOM reordering to take place.
+ Thread.sleep(500);
+
+ assertFalse("Error message detected", $(NotificationElement.class)
+ .exists());
+ }
+
+ @Test
+ public void spacersAreInsertedInCorrectDomPosition() {
+ selectMenuPath(FEATURES, SPACERS, ROW_1, SET_100PX);
+
+ WebElement tbody = getEscalator().findElement(By.tagName("tbody"));
+ WebElement spacer = getChild(tbody, 2);
+ String cssClass = spacer.getAttribute("class");
+ assertTrue("element index 2 was not a spacer (class=\"" + cssClass
+ + "\")", cssClass.contains("-spacer"));
+ }
+
+ @Test
+ public void spacersAreInCorrectDomPositionAfterScroll() {
+ selectMenuPath(FEATURES, SPACERS, ROW_1, SET_100PX);
+
+ scrollVerticallyTo(32); // roughly one row's worth
+
+ WebElement tbody = getEscalator().findElement(By.tagName("tbody"));
+ WebElement spacer = getChild(tbody, 1);
+ String cssClass = spacer.getAttribute("class");
+ assertTrue("element index 1 was not a spacer (class=\"" + cssClass
+ + "\")", cssClass.contains("-spacer"));
+ }
+
+ @Test
+ public void spacerScrolledIntoViewGetsFocus() {
+ selectMenuPath(FEATURES, SPACERS, FOCUSABLE_UPDATER);
+ selectMenuPath(FEATURES, SPACERS, ROW_50, SET_100PX);
+ selectMenuPath(FEATURES, SPACERS, ROW_50, SCROLL_HERE_ANY_0PADDING);
+
+ tryToTabIntoFocusUpdaterElement();
+ assertEquals("input", getFocusedElement().getTagName());
+ }
+
+ @Test
+ public void spacerScrolledOutOfViewDoesNotGetFocus() {
+ selectMenuPath(FEATURES, SPACERS, FOCUSABLE_UPDATER);
+ selectMenuPath(FEATURES, SPACERS, ROW_1, SET_100PX);
+ selectMenuPath(FEATURES, SPACERS, ROW_50, SCROLL_HERE_ANY_0PADDING);
+
+ tryToTabIntoFocusUpdaterElement();
+ assertNotEquals("input", getFocusedElement().getTagName());
+ }
+
+ @Test
+ public void spacerOpenedInViewGetsFocus() {
+ selectMenuPath(FEATURES, SPACERS, FOCUSABLE_UPDATER);
+ selectMenuPath(FEATURES, SPACERS, ROW_1, SET_100PX);
+ tryToTabIntoFocusUpdaterElement();
+ WebElement focusedElement = getFocusedElement();
+ assertEquals("input", focusedElement.getTagName());
+ }
+
+ @Test
+ public void spacerOpenedOutOfViewDoesNotGetFocus() {
+ selectMenuPath(FEATURES, SPACERS, FOCUSABLE_UPDATER);
+ selectMenuPath(FEATURES, SPACERS, ROW_50, SET_100PX);
+
+ tryToTabIntoFocusUpdaterElement();
+ assertNotEquals("input", getFocusedElement().getTagName());
+ }
+
+ @Test
+ public void spacerOpenedInViewAndScrolledOutAndBackAgainGetsFocus() {
+ selectMenuPath(FEATURES, SPACERS, FOCUSABLE_UPDATER);
+ selectMenuPath(FEATURES, SPACERS, ROW_1, SET_100PX);
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, SCROLL_TO, ROW_50);
+ selectMenuPath(FEATURES, SPACERS, ROW_1, SCROLL_HERE_ANY_0PADDING);
+
+ tryToTabIntoFocusUpdaterElement();
+ assertEquals("input", getFocusedElement().getTagName());
+ }
+
+ @Test
+ public void spacerOpenedOutOfViewAndScrolledInAndBackAgainDoesNotGetFocus() {
+ selectMenuPath(FEATURES, SPACERS, FOCUSABLE_UPDATER);
+ selectMenuPath(FEATURES, SPACERS, ROW_50, SET_100PX);
+ selectMenuPath(FEATURES, SPACERS, ROW_50, SCROLL_HERE_ANY_0PADDING);
+ selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, SCROLL_TO, ROW_0);
+
+ tryToTabIntoFocusUpdaterElement();
+ assertNotEquals("input", getFocusedElement().getTagName());
+ }
+
+ private void tryToTabIntoFocusUpdaterElement() {
+ ((TestBenchElement) findElement(By.className("gwt-MenuBar"))).focus();
+ WebElement focusedElement = getFocusedElement();
+ focusedElement.sendKeys(Keys.TAB);
+ }
+
+ private WebElement getChild(WebElement parent, int childIndex) {
+ return (WebElement) executeScript("return arguments[0].children["
+ + childIndex + "];", parent);
+ }
+
+ private static double[] getElementDimensions(WebElement element) {
+ /*
+ * we need to parse the style attribute, since using getCssValue gets a
+ * normalized value that is harder to parse.
+ */
+ String style = element.getAttribute("style");
+
+ String transform = getTransformFromStyle(style);
+ if (transform != null) {
+ return getTranslateValues(transform);
+ }
+
+ double[] result = new double[] { -1, -1 };
+ String left = getLeftFromStyle(style);
+ if (left != null) {
+ result[0] = getPixelValue(left);
+ }
+ String top = getTopFromStyle(style);
+ if (top != null) {
+ result[1] = getPixelValue(top);
+ }
+
+ if (result[0] != -1 && result[1] != -1) {
+ return result;
+ } else {
+ throw new IllegalArgumentException("Could not parse the position "
+ + "information from the CSS \"" + style + "\"");
+ }
+ }
+
+ private static double getElementTop(WebElement element) {
+ return getElementDimensions(element)[1];
+ }
+
+ private static double getElementLeft(WebElement element) {
+ return getElementDimensions(element)[0];
+ }
+
+ private static String getTransformFromStyle(String style) {
+ return getFromStyle(TRANSFORM_CSS_PATTERN, style);
+ }
+
+ private static String getTopFromStyle(String style) {
+ return getFromStyle(TOP_CSS_PATTERN, style);
+ }
+
+ private static String getLeftFromStyle(String style) {
+ return getFromStyle(LEFT_CSS_PATTERN, style);
+ }
+
+ private static String getFromStyle(Pattern pattern, String style) {
+ Matcher matcher = pattern.matcher(style);
+ if (matcher.find()) {
+ assertEquals("wrong amount of groups matched in " + style, 1,
+ matcher.groupCount());
+ return matcher.group(1);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * @return {@code [0] == x}, {@code [1] == y}
+ */
+ private static double[] getTranslateValues(String translate) {
+ Matcher matcher = TRANSLATE_VALUE_PATTERN.matcher(translate);
+ assertTrue("no matches for " + translate + " against "
+ + TRANSLATE_VALUE_PATTERN, matcher.find());
+ assertEquals("wrong amout of groups matched in " + translate, 2,
+ matcher.groupCount());
+
+ return new double[] { Double.parseDouble(matcher.group(1)),
+ Double.parseDouble(matcher.group(2)) };
+ }
+
+ private static double getPixelValue(String top) {
+ Matcher matcher = PIXEL_VALUE_PATTERN.matcher(top);
+ assertTrue("no matches for \"" + top + "\" against "
+ + PIXEL_VALUE_PATTERN, matcher.find());
+ assertEquals("wrong amount of groups matched in " + top, 1,
+ matcher.groupCount());
+ return Double.parseDouble(matcher.group(1));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridColumnReorderTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridColumnReorderTest.java
new file mode 100644
index 0000000000..0d62797ea4
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridColumnReorderTest.java
@@ -0,0 +1,347 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.server;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest;
+
+/**
+ * Tests that Grid columns can be reordered by user with drag and drop #16643.
+ *
+ * @author Vaadin Ltd
+ */
+public class GridColumnReorderTest extends GridBasicFeaturesTest {
+
+ private static final String[] COLUMN_REORDERING_PATH = { "Component",
+ "State", "Column Reordering Allowed" };
+ private static final String[] COLUMN_REORDER_LISTENER_PATH = { "Component",
+ "State", "ColumnReorderListener" };
+
+ @Before
+ public void setUp() {
+ setDebug(true);
+ }
+
+ @Test
+ public void testColumnReordering_firstColumnDroppedOnThird_dropOnLeftSide() {
+ // given
+ openTestURL();
+ assertColumnHeaderOrder(0, 1, 2);
+ toggleColumnReordering();
+
+ // when
+ dragAndDropDefaultColumnHeader(0, 2, CellSide.LEFT);
+
+ // then
+ assertColumnHeaderOrder(1, 0, 2);
+ }
+
+ @Test
+ public void testColumnReordering_firstColumnDroppedOnThird_dropOnRightSide() {
+ // given
+ openTestURL();
+ assertColumnHeaderOrder(0, 1, 2);
+ toggleColumnReordering();
+
+ // when
+ dragAndDropDefaultColumnHeader(0, 2, CellSide.RIGHT);
+
+ // then
+ assertColumnHeaderOrder(1, 2, 0);
+ }
+
+ @Test
+ public void testColumnReordering_reorderingTwiceBackForth_reordered() {
+ // given
+ openTestURL();
+ selectMenuPath("Component", "Size", "Width", "800px");
+ assertColumnHeaderOrder(0, 1, 2, 3, 4);
+ toggleColumnReordering();
+
+ // when
+ dragAndDropDefaultColumnHeader(2, 0, CellSide.LEFT);
+
+ // then
+ assertColumnHeaderOrder(2, 0, 1, 3, 4);
+
+ // when
+ dragAndDropDefaultColumnHeader(1, 3, CellSide.RIGHT);
+
+ // then
+ assertColumnHeaderOrder(2, 1, 3, 0);
+ }
+
+ @Test
+ public void testColumnReordering_notEnabled_noReordering() {
+ // given
+ openTestURL();
+ assertColumnHeaderOrder(0, 1, 2);
+
+ // when
+ dragAndDropDefaultColumnHeader(0, 2, CellSide.RIGHT);
+
+ // then
+ assertColumnHeaderOrder(0, 1, 2);
+ }
+
+ @Test
+ public void testColumnReordering_userChangesRevertedByServer_columnsAreUpdated() {
+ // given
+ openTestURL();
+ assertColumnHeaderOrder(0, 1, 2);
+ toggleColumnReordering();
+
+ // when
+ dragAndDropDefaultColumnHeader(0, 2, CellSide.LEFT);
+ assertColumnHeaderOrder(1, 0, 2);
+ moveColumnManuallyLeftByOne(0);
+
+ // then
+ assertColumnHeaderOrder(0, 1, 2);
+ }
+
+ @Test
+ public void testColumnReordering_concurrentUpdatesFromServer_columnOrderFromServerUsed() {
+ // given
+ openTestURL();
+ assertColumnHeaderOrder(0, 1, 2);
+ toggleColumnReordering();
+
+ // when
+ selectMenuPath(new String[] { "Component", "Internals",
+ "Update column order without updating client" });
+ dragAndDropDefaultColumnHeader(2, 0, CellSide.LEFT);
+
+ // then
+ assertColumnHeaderOrder(1, 0, 2);
+ }
+
+ @Test
+ public void testColumnReordering_triggersReorderEvent_isUserInitiated() {
+ // given
+ openTestURL();
+ toggleColumnReordering();
+
+ // when
+ toggleColumnReorderListener();
+ dragAndDropDefaultColumnHeader(0, 2, CellSide.LEFT);
+
+ // then
+ assertColumnReorderEvent(true);
+ }
+
+ @Test
+ public void testColumnReordering_addAndRemoveListener_registerUnRegisterWorks() {
+ // given
+ openTestURL();
+ toggleColumnReordering();
+ dragAndDropDefaultColumnHeader(0, 2, CellSide.LEFT);
+ assertNoColumnReorderEvent();
+
+ // when
+ toggleColumnReorderListener();
+ dragAndDropDefaultColumnHeader(0, 2, CellSide.RIGHT);
+
+ // then
+ assertColumnReorderEvent(true);
+
+ // when
+ toggleColumnReorderListener();
+ dragAndDropDefaultColumnHeader(0, 3, CellSide.LEFT);
+
+ // then
+ assertNoColumnReorderEvent();
+ }
+
+ @Test
+ public void testColumnReorderingEvent_serverSideReorder_triggersReorderEvent() {
+ openTestURL();
+
+ // when
+ toggleColumnReorderListener();
+ moveColumnManuallyLeftByOne(3);
+
+ // then
+ assertColumnReorderEvent(false);
+ }
+
+ @Test
+ public void testColumnReorder_draggingFrozenColumns_impossible() {
+ // given
+ openTestURL();
+ toggleColumnReordering();
+ setFrozenColumns(2);
+ assertColumnHeaderOrder(0, 1, 2, 3);
+
+ // when
+ dragAndDropDefaultColumnHeader(0, 2, CellSide.LEFT);
+
+ // then
+ assertColumnHeaderOrder(0, 1, 2, 3);
+ assertTrue(getGridElement().getHeaderCell(0, 0).isFrozen());
+ assertTrue(getGridElement().getHeaderCell(0, 1).isFrozen());
+ assertFalse(getGridElement().getHeaderCell(0, 2).isFrozen());
+ }
+
+ @Test
+ public void testColumnReorder_draggingColumnOnTopOfFrozenColumn_columnDroppedRightOfFrozenColumns() {
+ // given
+ openTestURL();
+ toggleColumnReordering();
+ setFrozenColumns(1);
+ assertColumnHeaderOrder(0, 1, 2, 3);
+
+ // when
+ dragAndDropDefaultColumnHeader(2, 0, CellSide.LEFT);
+
+ // then
+ assertColumnHeaderOrder(0, 2, 1, 3);
+ }
+
+ @Test
+ public void testColumnReorder_draggingColumnLeftOfMultiSelectionColumn_columnDroppedRight() {
+ // given
+ openTestURL();
+ toggleColumnReordering();
+ selectMenuPath("Component", "State", "Selection mode", "multi");
+ List<TestBenchElement> gridHeaderRowCells = getGridHeaderRowCells();
+ assertTrue(gridHeaderRowCells.get(0).getText().equals(""));
+ assertColumnHeader("Column 0", gridHeaderRowCells.get(1));
+ assertColumnHeader("Column 1", gridHeaderRowCells.get(2));
+ assertColumnHeader("Column 2", gridHeaderRowCells.get(3));
+
+ // when
+ dragAndDropDefaultColumnHeader(2, 0, CellSide.LEFT);
+
+ // then
+ gridHeaderRowCells = getGridHeaderRowCells();
+ assertTrue(gridHeaderRowCells.get(0).getText().equals(""));
+ assertColumnHeader("Column 1", gridHeaderRowCells.get(1));
+ assertColumnHeader("Column 0", gridHeaderRowCells.get(2));
+ assertColumnHeader("Column 2", gridHeaderRowCells.get(3));
+ }
+
+ @Test
+ public void testColumnReorder_multiSelectionAndFrozenColumns_columnDroppedRight() {
+ // given
+ openTestURL();
+ toggleColumnReordering();
+ selectMenuPath("Component", "State", "Selection mode", "multi");
+ setFrozenColumns(1);
+ List<TestBenchElement> gridHeaderRowCells = getGridHeaderRowCells();
+ assertTrue(gridHeaderRowCells.get(0).getText().equals(""));
+ assertColumnHeader("Column 0", gridHeaderRowCells.get(1));
+ assertColumnHeader("Column 1", gridHeaderRowCells.get(2));
+ assertColumnHeader("Column 2", gridHeaderRowCells.get(3));
+
+ // when
+ dragAndDropDefaultColumnHeader(3, 0, CellSide.LEFT);
+
+ // then
+ gridHeaderRowCells = getGridHeaderRowCells();
+ assertTrue(gridHeaderRowCells.get(0).getText().equals(""));
+ assertColumnHeader("Column 0", gridHeaderRowCells.get(1));
+ assertColumnHeader("Column 2", gridHeaderRowCells.get(2));
+ assertColumnHeader("Column 1", gridHeaderRowCells.get(3));
+ }
+
+ @Test
+ public void testColumnReordering_multiSelectionColumnNotFrozen_stillCantDropLeftSide() {
+ // given
+ openTestURL();
+ toggleColumnReordering();
+ selectMenuPath("Component", "State", "Selection mode", "multi");
+ setFrozenColumns(-1);
+ List<TestBenchElement> gridHeaderRowCells = getGridHeaderRowCells();
+ assertTrue(gridHeaderRowCells.get(0).getText().equals(""));
+ assertColumnHeader("Column 0", gridHeaderRowCells.get(1));
+ assertColumnHeader("Column 1", gridHeaderRowCells.get(2));
+ assertColumnHeader("Column 2", gridHeaderRowCells.get(3));
+
+ // when
+ dragAndDropDefaultColumnHeader(2, 0, CellSide.LEFT);
+
+ // then
+ gridHeaderRowCells = getGridHeaderRowCells();
+ assertTrue(gridHeaderRowCells.get(0).getText().equals(""));
+ assertColumnHeader("Column 1", gridHeaderRowCells.get(1));
+ assertColumnHeader("Column 0", gridHeaderRowCells.get(2));
+ assertColumnHeader("Column 2", gridHeaderRowCells.get(3));
+ }
+
+ @Test
+ public void testColumnReordering_twoHeaderRows_dndReorderingPossibleFromFirstRow() {
+ // given
+ openTestURL();
+ toggleColumnReordering();
+ selectMenuPath("Component", "Header", "Append row");
+ assertColumnHeaderOrder(0, 1, 2, 3);
+
+ // when
+ dragAndDropColumnHeader(0, 0, 2, CellSide.RIGHT);
+
+ // then
+ assertColumnHeaderOrder(1, 2, 0, 3);
+ }
+
+ @Test
+ public void testColumnReordering_twoHeaderRows_dndReorderingPossibleFromSecondRow() {
+ // given
+ openTestURL();
+ toggleColumnReordering();
+ selectMenuPath("Component", "Header", "Append row");
+ assertColumnHeaderOrder(0, 1, 2, 3);
+
+ // when
+ dragAndDropColumnHeader(1, 0, 2, CellSide.RIGHT);
+
+ // then
+ assertColumnHeaderOrder(1, 2, 0, 3);
+ }
+
+ private void toggleColumnReordering() {
+ selectMenuPath(COLUMN_REORDERING_PATH);
+ }
+
+ private void toggleColumnReorderListener() {
+ selectMenuPath(COLUMN_REORDER_LISTENER_PATH);
+ }
+
+ private void moveColumnManuallyLeftByOne(int index) {
+ selectMenuPath(new String[] { "Component", "Columns",
+ "Column " + index, "Move left" });
+ }
+
+ private void assertColumnReorderEvent(boolean userOriginated) {
+ final String logRow = getLogRow(0);
+ assertTrue(logRow.contains("Columns reordered, userOriginated: "
+ + userOriginated));
+ }
+
+ private void assertNoColumnReorderEvent() {
+ final String logRow = getLogRow(0);
+ assertFalse(logRow.contains("Columns reordered"));
+ }
+
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridColumnVisibilityTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridColumnVisibilityTest.java
new file mode 100644
index 0000000000..d01e689b72
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridColumnVisibilityTest.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.server;
+
+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 org.junit.Before;
+import org.junit.Test;
+
+import com.vaadin.testbench.parallel.TestCategory;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest;
+
+@TestCategory("grid")
+public class GridColumnVisibilityTest extends GridBasicFeaturesTest {
+
+ private static final String[] TOGGLE_LISTENER = new String[] { "Component",
+ "State", "ColumnVisibilityChangeListener" };
+ private static final String[] TOGGLE_HIDE_COLUMN_0 = new String[] {
+ "Component", "Columns", "Column 0", "Hidden" };
+
+ private static final String COLUMN_0_BECAME_HIDDEN_MSG = "Visibility "
+ + "changed: propertyId: Column 0, isHidden: true";
+ private static final String COLUMN_0_BECAME_UNHIDDEN_MSG = "Visibility "
+ + "changed: propertyId: Column 0, isHidden: false";
+ private static final String USER_ORIGINATED_TRUE = "userOriginated: true";
+ private static final String USER_ORIGINATED_FALSE = "userOriginated: false";
+
+ @Before
+ public void setUp() {
+ openTestURL();
+ }
+
+ @Test
+ public void columnIsNotShownWhenHidden() {
+ assertEquals("column 0", getGridElement().getHeaderCell(0, 0).getText()
+ .toLowerCase());
+
+ selectMenuPath(TOGGLE_HIDE_COLUMN_0);
+ assertEquals("column 1", getGridElement().getHeaderCell(0, 0).getText()
+ .toLowerCase());
+ }
+
+ @Test
+ public void columnIsShownWhenUnhidden() {
+ selectMenuPath(TOGGLE_HIDE_COLUMN_0);
+ selectMenuPath(TOGGLE_HIDE_COLUMN_0);
+ assertEquals("column 0", getGridElement().getHeaderCell(0, 0).getText()
+ .toLowerCase());
+ }
+
+ @Test
+ public void registeringListener() {
+ assertFalse(logContainsText(COLUMN_0_BECAME_HIDDEN_MSG));
+ selectMenuPath(TOGGLE_LISTENER);
+ assertFalse(logContainsText(COLUMN_0_BECAME_HIDDEN_MSG));
+
+ selectMenuPath(TOGGLE_HIDE_COLUMN_0);
+ assertTrue(logContainsText(COLUMN_0_BECAME_HIDDEN_MSG));
+ assertTrue(logContainsText(USER_ORIGINATED_FALSE));
+
+ selectMenuPath(TOGGLE_HIDE_COLUMN_0);
+ assertTrue(logContainsText(COLUMN_0_BECAME_UNHIDDEN_MSG));
+ assertTrue(logContainsText(USER_ORIGINATED_FALSE));
+ }
+
+ @Test
+ public void deregisteringListener() {
+ selectMenuPath(TOGGLE_LISTENER);
+ selectMenuPath(TOGGLE_HIDE_COLUMN_0);
+
+ selectMenuPath(TOGGLE_LISTENER);
+ selectMenuPath(TOGGLE_HIDE_COLUMN_0);
+ assertFalse(logContainsText(COLUMN_0_BECAME_UNHIDDEN_MSG));
+ }
+
+ @Test
+ public void testColumnHiding_userOriginated_correctParams() {
+ selectMenuPath(TOGGLE_LISTENER);
+ toggleColumnHidable(0);
+ assertColumnHeaderOrder(0, 1, 2, 3);
+
+ getSidebarOpenButton().click();
+ getColumnHidingToggle(0).click();
+ getSidebarOpenButton().click();
+
+ assertColumnHeaderOrder(1, 2, 3);
+ assertTrue(logContainsText(COLUMN_0_BECAME_HIDDEN_MSG));
+ assertTrue(logContainsText(USER_ORIGINATED_TRUE));
+
+ getSidebarOpenButton().click();
+ getColumnHidingToggle(0).click();
+ getSidebarOpenButton().click();
+
+ assertColumnHeaderOrder(0, 1, 2, 3);
+ assertTrue(logContainsText(COLUMN_0_BECAME_UNHIDDEN_MSG));
+ assertTrue(logContainsText(USER_ORIGINATED_TRUE));
+
+ getSidebarOpenButton().click();
+ getColumnHidingToggle(0).click();
+ getSidebarOpenButton().click();
+
+ assertColumnHeaderOrder(1, 2, 3);
+ assertTrue(logContainsText(COLUMN_0_BECAME_HIDDEN_MSG));
+ assertTrue(logContainsText(USER_ORIGINATED_TRUE));
+ }
+
+ @Test
+ public void testColumnHiding_whenHidableColumnRemoved_toggleRemoved() {
+ toggleColumnHidable(0);
+ toggleColumnHidable(1);
+ getSidebarOpenButton().click();
+ assertNotNull(getColumnHidingToggle(0));
+
+ addRemoveColumn(0);
+
+ assertNull(getColumnHidingToggle(0));
+ }
+
+ @Test
+ public void testColumnHiding_whenHidableColumnAdded_toggleWithCorrectCaptionAdded() {
+ selectMenuPath("Component", "Size", "Width", "100%");
+ toggleColumnHidable(0);
+ toggleColumnHidable(1);
+ toggleColumnHidingToggleCaptionChange(0);
+ getSidebarOpenButton().click();
+ assertEquals("Column 0 caption 0", getColumnHidingToggle(0).getText());
+ getSidebarOpenButton().click();
+
+ addRemoveColumn(0);
+ addRemoveColumn(4);
+ addRemoveColumn(5);
+ addRemoveColumn(6);
+ addRemoveColumn(7);
+ addRemoveColumn(8);
+ addRemoveColumn(9);
+ addRemoveColumn(10);
+ assertColumnHeaderOrder(1, 2, 3, 11);
+
+ getSidebarOpenButton().click();
+ assertNull(getColumnHidingToggle(0));
+ getSidebarOpenButton().click();
+
+ addRemoveColumn(0);
+ assertColumnHeaderOrder(1, 2, 3, 11, 0);
+
+ getSidebarOpenButton().click();
+ assertEquals("Column 0 caption 0", getColumnHidingToggle(0).getText());
+ }
+
+ @Test
+ public void testColumnHidingToggleCaption_settingToggleCaption_updatesToggle() {
+ toggleColumnHidable(1);
+ getSidebarOpenButton().click();
+ assertEquals("column 1", getGridElement().getHeaderCell(0, 1).getText()
+ .toLowerCase());
+ assertEquals("Column 1", getColumnHidingToggle(1).getText());
+
+ toggleColumnHidingToggleCaptionChange(1);
+ assertEquals("column 1", getGridElement().getHeaderCell(0, 1).getText()
+ .toLowerCase());
+ assertEquals("Column 1 caption 0", getColumnHidingToggle(1).getText());
+
+ toggleColumnHidingToggleCaptionChange(1);
+ assertEquals("Column 1 caption 1", getColumnHidingToggle(1).getText());
+ }
+
+ @Test
+ public void testColumnHidingToggleCaption_settingWidgetToHeader_toggleCaptionStays() {
+ toggleColumnHidable(1);
+ getSidebarOpenButton().click();
+ assertEquals("column 1", getGridElement().getHeaderCell(0, 1).getText()
+ .toLowerCase());
+ assertEquals("Column 1", getColumnHidingToggle(1).getText());
+
+ selectMenuPath("Component", "Columns", "Column 1", "Header Type",
+ "Widget Header");
+
+ assertEquals("Column 1", getColumnHidingToggle(1).getText());
+ }
+
+ private void toggleColumnHidingToggleCaptionChange(int index) {
+ selectMenuPath("Component", "Columns", "Column " + index,
+ "Change hiding toggle caption");
+ }
+
+ @Test
+ public void testFrozenColumnHiding_hiddenColumnMadeFrozen_frozenWhenMadeVisible() {
+ selectMenuPath("Component", "Size", "Width", "100%");
+ toggleColumnHidable(0);
+ toggleColumnHidable(1);
+ getSidebarOpenButton().click();
+ getColumnHidingToggle(0).click();
+ getColumnHidingToggle(1).click();
+
+ assertColumnHeaderOrder(2, 3, 4, 5);
+
+ setFrozenColumns(2);
+ verifyColumnNotFrozen(0);
+ verifyColumnNotFrozen(1);
+
+ getColumnHidingToggle(0).click();
+ assertColumnHeaderOrder(0, 2, 3, 4, 5);
+ verifyColumnFrozen(0);
+ verifyColumnNotFrozen(1);
+
+ getColumnHidingToggle(1).click();
+ assertColumnHeaderOrder(0, 1, 2, 3, 4, 5);
+ verifyColumnFrozen(0);
+ verifyColumnFrozen(1);
+ verifyColumnNotFrozen(2);
+ }
+
+ @Test
+ public void testFrozenColumnHiding_hiddenFrozenColumnUnfrozen_notFrozenWhenMadeVisible() {
+ selectMenuPath("Component", "Size", "Width", "100%");
+ toggleColumnHidable(0);
+ toggleColumnHidable(1);
+ setFrozenColumns(2);
+ verifyColumnFrozen(0);
+ verifyColumnFrozen(1);
+ verifyColumnNotFrozen(2);
+ verifyColumnNotFrozen(3);
+
+ getSidebarOpenButton().click();
+ getColumnHidingToggle(0).click();
+ getColumnHidingToggle(1).click();
+ assertColumnHeaderOrder(2, 3, 4, 5);
+ verifyColumnNotFrozen(0);
+ verifyColumnNotFrozen(1);
+
+ setFrozenColumns(0);
+ verifyColumnNotFrozen(0);
+ verifyColumnNotFrozen(1);
+
+ getColumnHidingToggle(0).click();
+ assertColumnHeaderOrder(0, 2, 3, 4, 5);
+ verifyColumnNotFrozen(0);
+ verifyColumnNotFrozen(1);
+
+ getColumnHidingToggle(1).click();
+ assertColumnHeaderOrder(0, 1, 2, 3, 4, 5);
+ verifyColumnNotFrozen(0);
+ verifyColumnNotFrozen(1);
+ verifyColumnNotFrozen(2);
+ }
+
+ private void verifyColumnFrozen(int index) {
+ assertTrue(getGridElement().getHeaderCell(0, index).isFrozen());
+ }
+
+ private void verifyColumnNotFrozen(int index) {
+ assertFalse(getGridElement().getHeaderCell(0, index).isFrozen());
+ }
+
+ private void toggleColumnHidable(int index) {
+ selectMenuPath("Component", "Columns", "Column " + index, "Hidable");
+ }
+
+ private void addRemoveColumn(int index) {
+ selectMenuPath("Component", "Columns", "Column " + index,
+ "Add / Remove");
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridDetailsServerTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridDetailsServerTest.java
new file mode 100644
index 0000000000..4ea64073f3
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridDetailsServerTest.java
@@ -0,0 +1,306 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.server;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.openqa.selenium.By;
+import org.openqa.selenium.NoSuchElementException;
+
+import com.vaadin.testbench.TestBenchElement;
+import com.vaadin.testbench.elements.NotificationElement;
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest;
+
+public class GridDetailsServerTest extends GridBasicFeaturesTest {
+ /**
+ * The reason to why last item details wasn't selected is that since it will
+ * exist only after the viewport has been scrolled into view, we wouldn't be
+ * able to scroll that particular details row into view, making tests
+ * awkward with two scroll commands back to back.
+ */
+ private static final int ALMOST_LAST_INDEX = 995;
+ private static final String[] OPEN_ALMOST_LAST_ITEM_DETAILS = new String[] {
+ "Component", "Details", "Open " + ALMOST_LAST_INDEX };
+ private static final String[] OPEN_FIRST_ITEM_DETAILS = new String[] {
+ "Component", "Details", "Open firstItemId" };
+ private static final String[] TOGGLE_FIRST_ITEM_DETAILS = new String[] {
+ "Component", "Details", "Toggle firstItemId" };
+ private static final String[] DETAILS_GENERATOR_NULL = new String[] {
+ "Component", "Details", "Generators", "NULL" };
+ private static final String[] DETAILS_GENERATOR_WATCHING = new String[] {
+ "Component", "Details", "Generators", "\"Watching\"" };
+ private static final String[] DETAILS_GENERATOR_HIERARCHICAL = new String[] {
+ "Component", "Details", "Generators", "Hierarchical" };
+ private static final String[] CHANGE_HIERARCHY = new String[] {
+ "Component", "Details", "Generators", "- Change Component" };
+
+ @Before
+ public void setUp() {
+ openTestURL();
+ }
+
+ @Test
+ public void openVisibleDetails() {
+ try {
+ getGridElement().getDetails(0);
+ fail("Expected NoSuchElementException");
+ } catch (NoSuchElementException ignore) {
+ // expected
+ }
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS);
+ assertNotNull("details should've opened", getGridElement()
+ .getDetails(0));
+ }
+
+ @Test(expected = NoSuchElementException.class)
+ public void closeVisibleDetails() {
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS);
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS);
+
+ getGridElement().getDetails(0);
+ }
+
+ @Test
+ public void openVisiblePopulatedDetails() {
+ selectMenuPath(DETAILS_GENERATOR_WATCHING);
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS);
+ assertNotNull("details should've populated", getGridElement()
+ .getDetails(0).findElement(By.className("v-widget")));
+ }
+
+ @Test(expected = NoSuchElementException.class)
+ public void closeVisiblePopulatedDetails() {
+ selectMenuPath(DETAILS_GENERATOR_WATCHING);
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS);
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS);
+ getGridElement().getDetails(0);
+ }
+
+ @Test
+ public void openDetailsOutsideOfActiveRange() throws InterruptedException {
+ getGridElement().scroll(10000);
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS);
+ getGridElement().scroll(0);
+ Thread.sleep(50);
+ assertNotNull("details should've been opened", getGridElement()
+ .getDetails(0));
+ }
+
+ @Test(expected = NoSuchElementException.class)
+ public void closeDetailsOutsideOfActiveRange() {
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS);
+ getGridElement().scroll(10000);
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS);
+ getGridElement().scroll(0);
+ getGridElement().getDetails(0);
+ }
+
+ @Test
+ public void componentIsVisibleClientSide() {
+ selectMenuPath(DETAILS_GENERATOR_WATCHING);
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS);
+
+ TestBenchElement details = getGridElement().getDetails(0);
+ assertNotNull("No widget detected inside details",
+ details.findElement(By.className("v-widget")));
+ }
+
+ @Test
+ public void openingDetailsTwice() {
+ selectMenuPath(DETAILS_GENERATOR_WATCHING);
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS); // open
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS); // close
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS); // open
+
+ TestBenchElement details = getGridElement().getDetails(0);
+ assertNotNull("No widget detected inside details",
+ details.findElement(By.className("v-widget")));
+ }
+
+ @Test(expected = NoSuchElementException.class)
+ public void scrollingDoesNotCreateAFloodOfDetailsRows() {
+ selectMenuPath(DETAILS_GENERATOR_WATCHING);
+
+ // scroll somewhere to hit uncached rows
+ getGridElement().scrollToRow(101);
+
+ // this should throw
+ getGridElement().getDetails(100);
+ }
+
+ @Test
+ public void openingDetailsOutOfView() {
+ getGridElement().scrollToRow(500);
+
+ selectMenuPath(DETAILS_GENERATOR_WATCHING);
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS);
+
+ getGridElement().scrollToRow(0);
+
+ // if this fails, it'll fail before the assertNotNull
+ assertNotNull("unexpected null details row", getGridElement()
+ .getDetails(0));
+ }
+
+ @Test
+ public void togglingAVisibleDetailsRowWithOneRoundtrip() {
+ selectMenuPath(DETAILS_GENERATOR_WATCHING);
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS); // open
+
+ assertTrue("Unexpected generator content",
+ getGridElement().getDetails(0).getText().endsWith("(0)"));
+ selectMenuPath(TOGGLE_FIRST_ITEM_DETAILS);
+ assertTrue("New component was not displayed in the client",
+ getGridElement().getDetails(0).getText().endsWith("(1)"));
+ }
+
+ @Test
+ public void almostLastItemIdIsRendered() {
+ selectMenuPath(DETAILS_GENERATOR_WATCHING);
+ selectMenuPath(OPEN_ALMOST_LAST_ITEM_DETAILS);
+ scrollGridVerticallyTo(100000);
+
+ TestBenchElement details = getGridElement().getDetails(
+ ALMOST_LAST_INDEX);
+ assertNotNull(details);
+ assertTrue("Unexpected details content",
+ details.getText().endsWith(ALMOST_LAST_INDEX + " (0)"));
+ }
+
+ @Test
+ public void hierarchyChangesWorkInDetails() {
+ selectMenuPath(DETAILS_GENERATOR_HIERARCHICAL);
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS);
+ assertEquals("One", getGridElement().getDetails(0).getText());
+ selectMenuPath(CHANGE_HIERARCHY);
+ assertEquals("Two", getGridElement().getDetails(0).getText());
+ }
+
+ @Ignore("This use case is not currently supported by Grid. If the detail "
+ + "is out of view, the component is detached from the UI and a "
+ + "new instance is generated when scrolled back. Support will "
+ + "maybe be incorporated at a later time")
+ @Test
+ public void hierarchyChangesWorkInDetailsWhileOutOfView() {
+ selectMenuPath(DETAILS_GENERATOR_HIERARCHICAL);
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS);
+ scrollGridVerticallyTo(10000);
+ selectMenuPath(CHANGE_HIERARCHY);
+ scrollGridVerticallyTo(0);
+ assertEquals("Two", getGridElement().getDetails(0).getText());
+ }
+
+ @Test
+ public void swappingDetailsGenerators_noDetailsShown() {
+ selectMenuPath(DETAILS_GENERATOR_WATCHING);
+ selectMenuPath(DETAILS_GENERATOR_NULL);
+ assertFalse("Got some errors", $(NotificationElement.class).exists());
+ }
+
+ @Test
+ public void swappingDetailsGenerators_shownDetails() {
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS);
+ assertTrue("Details should be empty at the start", getGridElement()
+ .getDetails(0).getText().isEmpty());
+
+ selectMenuPath(DETAILS_GENERATOR_WATCHING);
+ assertFalse("Details should not be empty after swapping generator",
+ getGridElement().getDetails(0).getText().isEmpty());
+ }
+
+ @Test
+ public void swappingDetailsGenerators_whileDetailsScrolledOut_showNever() {
+ scrollGridVerticallyTo(1000);
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS);
+ selectMenuPath(DETAILS_GENERATOR_WATCHING);
+ assertFalse("Got some errors", $(NotificationElement.class).exists());
+ }
+
+ @Test
+ public void swappingDetailsGenerators_whileDetailsScrolledOut_showAfter() {
+ scrollGridVerticallyTo(1000);
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS);
+ selectMenuPath(DETAILS_GENERATOR_WATCHING);
+ scrollGridVerticallyTo(0);
+
+ assertFalse("Got some errors", $(NotificationElement.class).exists());
+ assertNotNull("Could not find a details", getGridElement()
+ .getDetails(0));
+ }
+
+ @Test
+ public void swappingDetailsGenerators_whileDetailsScrolledOut_showBefore() {
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS);
+ selectMenuPath(DETAILS_GENERATOR_WATCHING);
+ scrollGridVerticallyTo(1000);
+
+ assertFalse("Got some errors", $(NotificationElement.class).exists());
+ assertNotNull("Could not find a details", getGridElement()
+ .getDetails(0));
+ }
+
+ @Test
+ public void swappingDetailsGenerators_whileDetailsScrolledOut_showBeforeAndAfter() {
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS);
+ selectMenuPath(DETAILS_GENERATOR_WATCHING);
+ scrollGridVerticallyTo(1000);
+ scrollGridVerticallyTo(0);
+
+ assertFalse("Got some errors", $(NotificationElement.class).exists());
+ assertNotNull("Could not find a details", getGridElement()
+ .getDetails(0));
+ }
+
+ @Test
+ public void nullDetailComponentToggling() {
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS);
+ selectMenuPath(DETAILS_GENERATOR_WATCHING);
+ selectMenuPath(DETAILS_GENERATOR_NULL);
+
+ try {
+ assertTrue("Details should be empty with null component",
+ getGridElement().getDetails(0).getText().isEmpty());
+ } catch (NoSuchElementException e) {
+ fail("Expected to find a details row with empty content");
+ }
+
+ selectMenuPath(DETAILS_GENERATOR_WATCHING);
+ assertFalse("Details should be not empty with details component",
+ getGridElement().getDetails(0).getText().isEmpty());
+ }
+
+ @Test
+ public void noAssertErrorsOnEmptyDetailsAndScrollDown() {
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS);
+ scrollGridVerticallyTo(500);
+ assertFalse(logContainsText("AssertionError"));
+ }
+
+ @Test
+ public void noAssertErrorsOnPopulatedDetailsAndScrollDown() {
+ selectMenuPath(DETAILS_GENERATOR_WATCHING);
+ selectMenuPath(OPEN_FIRST_ITEM_DETAILS);
+ scrollGridVerticallyTo(500);
+ assertFalse(logContainsText("AssertionError"));
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSidebarThemeTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSidebarThemeTest.java
new file mode 100644
index 0000000000..5262156b41
--- /dev/null
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSidebarThemeTest.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2000-2014 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.tests.components.grid.basicfeatures.server;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.junit.Test;
+import org.openqa.selenium.interactions.Actions;
+import org.openqa.selenium.remote.DesiredCapabilities;
+
+import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest;
+import com.vaadin.tests.components.grid.basicfeatures.GridSidebarFeatures;
+
+public class GridSidebarThemeTest extends GridBasicFeaturesTest {
+
+ @Test
+ public void testValo() throws Exception {
+ runTestSequence("valo");
+ }
+
+ @Test
+ public void testValoDark() throws Exception {
+ runTestSequence("tests-valo-dark");
+ }
+
+ @Override
+ protected Class<?> getUIClass() {
+ return GridSidebarFeatures.class;
+ }
+
+ private void runTestSequence(String theme) throws IOException {
+ openTestURL("theme=" + theme);
+
+ compareScreen(theme + "|SidebarClosed");
+ getSidebarOpenButton().click();
+
+ compareScreen(theme + "|SidebarOpen");
+
+ new Actions(getDriver()).moveToElement(getColumnHidingToggle(2), 5, 5)
+ .perform();
+
+ compareScreen(theme + "|OnMouseOverNotHiddenToggle");
+
+ getColumnHidingToggle(2).click();
+ getColumnHidingToggle(3).click();
+ getColumnHidingToggle(6).click();
+
+ new Actions(getDriver()).moveToElement(getSidebarOpenButton())
+ .perform();
+ ;
+
+ compareScreen(theme + "|TogglesTriggered");
+
+ new Actions(getDriver()).moveToElement(getColumnHidingToggle(2))
+ .perform();
+ ;
+
+ compareScreen(theme + "|OnMouseOverHiddenToggle");
+
+ getSidebarOpenButton().click();
+
+ compareScreen(theme + "|SidebarClosed2");
+ }
+
+ @Override
+ public List<DesiredCapabilities> getBrowsersToTest() {
+ // phantom JS looks wrong from the beginning, so not tested
+ return getBrowsersExcludingPhantomJS();
+ }
+}
diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/LoadingIndicatorTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/LoadingIndicatorTest.java
index f251313100..f4771b9067 100644
--- a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/LoadingIndicatorTest.java
+++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/LoadingIndicatorTest.java
@@ -19,7 +19,6 @@ import org.junit.Assert;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
-import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.ExpectedConditions;
@@ -83,10 +82,4 @@ public class LoadingIndicatorTest extends GridBasicFeaturesTest {
});
}
- private boolean isLoadingIndicatorVisible() {
- WebElement loadingIndicator = findElement(By
- .className("v-loading-indicator"));
-
- return loadingIndicator.isDisplayed();
- }
}
diff --git a/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java b/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java
index 2d032ecd9e..48f99e5057 100644
--- a/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java
+++ b/uitest/src/com/vaadin/tests/tb3/AbstractTB3Test.java
@@ -938,4 +938,24 @@ public abstract class AbstractTB3Test extends ParallelTest {
protected void click(CheckBoxElement checkbox) {
checkbox.findElement(By.xpath("input")).click();
}
+
+ protected boolean isLoadingIndicatorVisible() {
+ WebElement loadingIndicator = findElement(By
+ .className("v-loading-indicator"));
+
+ return loadingIndicator.isDisplayed();
+ }
+
+ protected void waitUntilLoadingIndicatorNotVisible() {
+ waitUntil(new ExpectedCondition<Boolean>() {
+
+ @Override
+ public Boolean apply(WebDriver input) {
+ WebElement loadingIndicator = input.findElement(By
+ .className("v-loading-indicator"));
+
+ return !loadingIndicator.isDisplayed();
+ }
+ });
+ }
}
diff --git a/uitest/src/com/vaadin/tests/util/PersonContainer.java b/uitest/src/com/vaadin/tests/util/PersonContainer.java
index 611e5d3adb..709086be29 100644
--- a/uitest/src/com/vaadin/tests/util/PersonContainer.java
+++ b/uitest/src/com/vaadin/tests/util/PersonContainer.java
@@ -32,10 +32,14 @@ public class PersonContainer extends BeanItemContainer<Person> implements
}
public static PersonContainer createWithTestData() {
+ return createWithTestData(100);
+ }
+
+ public static PersonContainer createWithTestData(int size) {
PersonContainer c = null;
Random r = new Random(0);
c = new PersonContainer();
- for (int i = 0; i < 100; i++) {
+ for (int i = 0; i < size; i++) {
Person p = new Person();
p.setFirstName(TestDataGenerator.getFirstName(r));
p.setLastName(TestDataGenerator.getLastName(r));
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorBasicClientFeaturesWidget.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorBasicClientFeaturesWidget.java
index 761f32bc9a..c735797731 100644
--- a/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorBasicClientFeaturesWidget.java
+++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorBasicClientFeaturesWidget.java
@@ -6,13 +6,18 @@ import java.util.List;
import com.google.gwt.core.client.Duration;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.TableCellElement;
+import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.vaadin.client.widget.escalator.EscalatorUpdater;
import com.vaadin.client.widget.escalator.FlyweightCell;
import com.vaadin.client.widget.escalator.Row;
import com.vaadin.client.widget.escalator.RowContainer;
+import com.vaadin.client.widget.escalator.RowContainer.BodyRowContainer;
+import com.vaadin.client.widget.escalator.Spacer;
+import com.vaadin.client.widget.escalator.SpacerUpdater;
import com.vaadin.client.widgets.Escalator;
+import com.vaadin.shared.ui.grid.ScrollDestination;
public class EscalatorBasicClientFeaturesWidget extends
PureGWTTestApplication<Escalator> {
@@ -303,6 +308,7 @@ public class EscalatorBasicClientFeaturesWidget extends
createColumnsAndRowsMenu();
createFrozenMenu();
createColspanMenu();
+ createSpacerMenu();
}
private void createFrozenMenu() {
@@ -567,6 +573,26 @@ public class EscalatorBasicClientFeaturesWidget extends
escalator.setScrollTop(40);
}
}, menupath);
+
+ String[] scrollToRowMenuPath = new String[menupath.length + 1];
+ System.arraycopy(menupath, 0, scrollToRowMenuPath, 0, menupath.length);
+ scrollToRowMenuPath[scrollToRowMenuPath.length - 1] = "Scroll to...";
+ for (int i = 0; i < 100; i += 25) {
+ final int rowIndex = i;
+ addMenuCommand("Row " + i, new ScheduledCommand() {
+ @Override
+ public void execute() {
+ escalator.scrollToRow(rowIndex, ScrollDestination.ANY, 0);
+ }
+ }, scrollToRowMenuPath);
+ }
+
+ addMenuCommand("Set 20px default height", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ escalator.getBody().setDefaultRowHeight(20);
+ }
+ }, menupath);
}
private void createRowsMenu(final RowContainer container, String[] menupath) {
@@ -612,6 +638,94 @@ public class EscalatorBasicClientFeaturesWidget extends
}, menupath);
}
+ private void createSpacerMenu() {
+ String[] menupath = { "Features", "Spacers" };
+
+ addMenuCommand("Swap Spacer Updater", new ScheduledCommand() {
+ private final SpacerUpdater CUSTOM = new SpacerUpdater() {
+ @Override
+ public void destroy(Spacer spacer) {
+ spacer.getElement().setInnerText("");
+ }
+
+ @Override
+ public void init(Spacer spacer) {
+ spacer.getElement().setInnerText(
+ "Spacer for row " + spacer.getRow());
+ }
+ };
+
+ @Override
+ public void execute() {
+ BodyRowContainer body = escalator.getBody();
+
+ if (SpacerUpdater.NULL.equals(body.getSpacerUpdater())) {
+ body.setSpacerUpdater(CUSTOM);
+ } else {
+ body.setSpacerUpdater(SpacerUpdater.NULL);
+ }
+ }
+ }, menupath);
+
+ addMenuCommand("Focusable Updater", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ escalator.getBody().setSpacerUpdater(new SpacerUpdater() {
+ @Override
+ public void init(Spacer spacer) {
+ spacer.getElement().appendChild(DOM.createInputText());
+ }
+
+ @Override
+ public void destroy(Spacer spacer) {
+ spacer.getElement().removeAllChildren();
+ }
+ });
+ }
+ }, menupath);
+
+ createSpacersMenuForRow(-1, menupath);
+ createSpacersMenuForRow(1, menupath);
+ createSpacersMenuForRow(50, menupath);
+ createSpacersMenuForRow(99, menupath);
+ }
+
+ private void createSpacersMenuForRow(final int rowIndex, String[] menupath) {
+ menupath = new String[] { menupath[0], menupath[1], "Row " + rowIndex };
+ addMenuCommand("Set 100px", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ escalator.getBody().setSpacer(rowIndex, 100);
+ }
+ }, menupath);
+ addMenuCommand("Set 50px", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ escalator.getBody().setSpacer(rowIndex, 50);
+ }
+ }, menupath);
+ addMenuCommand("Remove", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ escalator.getBody().setSpacer(rowIndex, -1);
+ }
+ }, menupath);
+ addMenuCommand("Scroll here (ANY, 0)", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ escalator.scrollToSpacer(rowIndex, ScrollDestination.ANY, 0);
+ }
+ }, menupath);
+ addMenuCommand("Scroll here row+spacer below (ANY, 0)",
+ new ScheduledCommand() {
+ @Override
+ public void execute() {
+ escalator.scrollToRowAndSpacer(rowIndex,
+ ScrollDestination.ANY, 0);
+ }
+ }, menupath);
+ }
+
private void insertRows(final RowContainer container, int offset, int number) {
if (container == escalator.getBody()) {
data.insertRows(offset, number);
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorProxy.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorProxy.java
index 7f813b9d0f..e7ebcfeb51 100644
--- a/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorProxy.java
+++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorProxy.java
@@ -24,6 +24,8 @@ import com.vaadin.client.widget.escalator.Cell;
import com.vaadin.client.widget.escalator.ColumnConfiguration;
import com.vaadin.client.widget.escalator.EscalatorUpdater;
import com.vaadin.client.widget.escalator.RowContainer;
+import com.vaadin.client.widget.escalator.RowContainer.BodyRowContainer;
+import com.vaadin.client.widget.escalator.SpacerUpdater;
import com.vaadin.client.widgets.Escalator;
import com.vaadin.tests.widgetset.client.grid.EscalatorBasicClientFeaturesWidget.LogWidget;
@@ -97,6 +99,33 @@ public class EscalatorProxy extends Escalator {
}
}
+ private class BodyRowContainerProxy extends RowContainerProxy implements
+ BodyRowContainer {
+ private BodyRowContainer rowContainer;
+
+ public BodyRowContainerProxy(BodyRowContainer rowContainer) {
+ super(rowContainer);
+ this.rowContainer = rowContainer;
+ }
+
+ @Override
+ public void setSpacer(int rowIndex, double height)
+ throws IllegalArgumentException {
+ rowContainer.setSpacer(rowIndex, height);
+ }
+
+ @Override
+ public void setSpacerUpdater(SpacerUpdater spacerUpdater)
+ throws IllegalArgumentException {
+ rowContainer.setSpacerUpdater(spacerUpdater);
+ }
+
+ @Override
+ public SpacerUpdater getSpacerUpdater() {
+ return rowContainer.getSpacerUpdater();
+ }
+ }
+
private class RowContainerProxy implements RowContainer {
private final RowContainer rowContainer;
@@ -176,7 +205,7 @@ public class EscalatorProxy extends Escalator {
}
private RowContainer headerProxy = null;
- private RowContainer bodyProxy = null;
+ private BodyRowContainer bodyProxy = null;
private RowContainer footerProxy = null;
private ColumnConfiguration columnProxy = null;
private LogWidget logWidget;
@@ -198,9 +227,9 @@ public class EscalatorProxy extends Escalator {
}
@Override
- public RowContainer getBody() {
+ public BodyRowContainer getBody() {
if (bodyProxy == null) {
- bodyProxy = new RowContainerProxy(super.getBody());
+ bodyProxy = new BodyRowContainerProxy(super.getBody());
}
return bodyProxy;
}
diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java
index 4dc0195f22..81f000c44e 100644
--- a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java
+++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java
@@ -33,9 +33,13 @@ import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.MenuItem;
+import com.google.gwt.user.client.ui.MenuItemSeparator;
import com.google.gwt.user.client.ui.TextBox;
+import com.google.gwt.user.client.ui.Widget;
import com.vaadin.client.data.DataSource;
import com.vaadin.client.data.DataSource.RowHandle;
import com.vaadin.client.renderers.DateRenderer;
@@ -46,6 +50,7 @@ import com.vaadin.client.renderers.TextRenderer;
import com.vaadin.client.ui.VLabel;
import com.vaadin.client.widget.grid.CellReference;
import com.vaadin.client.widget.grid.CellStyleGenerator;
+import com.vaadin.client.widget.grid.DetailsGenerator;
import com.vaadin.client.widget.grid.EditorHandler;
import com.vaadin.client.widget.grid.RendererCellReference;
import com.vaadin.client.widget.grid.RowReference;
@@ -55,6 +60,10 @@ import com.vaadin.client.widget.grid.datasources.ListSorter;
import com.vaadin.client.widget.grid.events.BodyKeyDownHandler;
import com.vaadin.client.widget.grid.events.BodyKeyPressHandler;
import com.vaadin.client.widget.grid.events.BodyKeyUpHandler;
+import com.vaadin.client.widget.grid.events.ColumnReorderEvent;
+import com.vaadin.client.widget.grid.events.ColumnReorderHandler;
+import com.vaadin.client.widget.grid.events.ColumnVisibilityChangeEvent;
+import com.vaadin.client.widget.grid.events.ColumnVisibilityChangeHandler;
import com.vaadin.client.widget.grid.events.FooterKeyDownHandler;
import com.vaadin.client.widget.grid.events.FooterKeyPressHandler;
import com.vaadin.client.widget.grid.events.FooterKeyUpHandler;
@@ -73,6 +82,7 @@ import com.vaadin.client.widgets.Grid.Column;
import com.vaadin.client.widgets.Grid.FooterRow;
import com.vaadin.client.widgets.Grid.HeaderRow;
import com.vaadin.client.widgets.Grid.SelectionMode;
+import com.vaadin.shared.ui.grid.ScrollDestination;
import com.vaadin.tests.widgetset.client.grid.GridBasicClientFeaturesWidget.Data;
/**
@@ -400,6 +410,8 @@ public class GridBasicClientFeaturesWidget extends
createEditorMenu();
createInternalsMenu();
createDataSourceMenu();
+ createDetailsMenu();
+ createSidebarMenu();
grid.getElement().getStyle().setZIndex(0);
@@ -444,6 +456,71 @@ public class GridBasicClientFeaturesWidget extends
});
}
}, listenersPath);
+ addMenuCommand("Add ColumnReorder listener", new ScheduledCommand() {
+ private HandlerRegistration columnReorderHandler = null;
+
+ @Override
+ public void execute() {
+ if (columnReorderHandler != null) {
+ return;
+ }
+ final Label columnOrderLabel = new Label();
+ columnOrderLabel.getElement().setId("columnreorder");
+ addLineEnd(columnOrderLabel, 300);
+ columnReorderHandler = grid
+ .addColumnReorderHandler(new ColumnReorderHandler<List<Data>>() {
+
+ private int eventIndex = 0;
+
+ @Override
+ public void onColumnReorder(
+ ColumnReorderEvent<List<Data>> event) {
+ columnOrderLabel.getElement().setAttribute(
+ "columns", "" + (++eventIndex));
+ }
+ });
+ }
+ }, listenersPath);
+ addMenuCommand("Add Column Visibility Change listener",
+ new ScheduledCommand() {
+ private HandlerRegistration columnVisibilityHandler = null;
+
+ @Override
+ public void execute() {
+ if (columnVisibilityHandler != null) {
+ return;
+ }
+ final Label columnOrderLabel = new Label();
+ columnOrderLabel.getElement().setId("columnvisibility");
+ addLineEnd(columnOrderLabel, 250);
+ ColumnVisibilityChangeHandler handler = new ColumnVisibilityChangeHandler<List<Data>>() {
+
+ private int eventIndex = 0;
+
+ @Override
+ public void onVisibilityChange(
+ ColumnVisibilityChangeEvent<List<Data>> event) {
+ columnOrderLabel.getElement().setAttribute(
+ "counter", "" + (++eventIndex));
+ columnOrderLabel.getElement().setAttribute(
+ "useroriginated",
+ (Boolean.toString(event
+ .isUserOriginated())));
+ columnOrderLabel.getElement().setAttribute(
+ "ishidden",
+ (Boolean.toString(event.isHidden())));
+ columnOrderLabel.getElement().setAttribute(
+ "columnindex",
+ ""
+ + grid.getColumns().indexOf(
+ event.getColumn()));
+ }
+ };
+
+ columnVisibilityHandler = grid
+ .addColumnVisibilityChangeHandler(handler);
+ }
+ }, listenersPath);
}
private void createStateMenu() {
@@ -658,6 +735,79 @@ public class GridBasicClientFeaturesWidget extends
grid.setColumnOrder(columns.toArray(new Column[columns.size()]));
}
}, "Component", "State");
+ addMenuCommand("Column Reordering", new ScheduledCommand() {
+
+ @Override
+ public void execute() {
+ grid.setColumnReorderingAllowed(!grid
+ .isColumnReorderingAllowed());
+ }
+ }, "Component", "State");
+ addMenuCommand("250px", new ScheduledCommand() {
+
+ @Override
+ public void execute() {
+ grid.setWidth("250px");
+ }
+ }, "Component", "State", "Width");
+ addMenuCommand("500px", new ScheduledCommand() {
+
+ @Override
+ public void execute() {
+ grid.setWidth("500px");
+ }
+ }, "Component", "State", "Width");
+ addMenuCommand("750px", new ScheduledCommand() {
+
+ @Override
+ public void execute() {
+ grid.setWidth("750px");
+ }
+ }, "Component", "State", "Width");
+ addMenuCommand("1000px", new ScheduledCommand() {
+
+ @Override
+ public void execute() {
+ grid.setWidth("1000px");
+ }
+ }, "Component", "State", "Width");
+
+ createScrollToRowMenu();
+ }
+
+ private void createScrollToRowMenu() {
+ String[] menupath = new String[] { "Component", "State",
+ "Scroll to...", null };
+
+ for (int i = 0; i < ROWS; i += 100) {
+ menupath[3] = "Row " + i + "...";
+ for (final ScrollDestination scrollDestination : ScrollDestination
+ .values()) {
+ final int row = i;
+ addMenuCommand("Destination " + scrollDestination,
+ new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.scrollToRow(row, scrollDestination);
+ }
+ }, menupath);
+ }
+ }
+
+ int i = ROWS - 1;
+ menupath[3] = "Row " + i + "...";
+ for (final ScrollDestination scrollDestination : ScrollDestination
+ .values()) {
+ final int row = i;
+ addMenuCommand("Destination " + scrollDestination,
+ new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.scrollToRow(row, scrollDestination);
+ }
+ }, menupath);
+ }
+
}
private void createColumnsMenu() {
@@ -671,7 +821,18 @@ public class GridBasicClientFeaturesWidget extends
column.setSortable(!column.isSortable());
}
}, "Component", "Columns", "Column " + i);
-
+ addMenuCommand("Hidden", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ column.setHidden(!column.isHidden());
+ }
+ }, "Component", "Columns", "Column " + i);
+ addMenuCommand("Hidable", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ column.setHidable(!column.isHidable());
+ }
+ }, "Component", "Columns", "Column " + i);
addMenuCommand("auto", new ScheduledCommand() {
@Override
public void execute() {
@@ -768,6 +929,25 @@ public class GridBasicClientFeaturesWidget extends
});
}
}, "Component", "Columns", "Column " + i);
+ addMenuCommand("Move column left", new ScheduledCommand() {
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void execute() {
+ List<Column<?, List<Data>>> cols = grid.getColumns();
+ ArrayList<Column> reordered = new ArrayList<Column>(cols);
+ final int index = cols.indexOf(column);
+ if (index == 0) {
+ Column<?, List<Data>> col = reordered.remove(0);
+ reordered.add(col);
+ } else {
+ Column<?, List<Data>> col = reordered.remove(index);
+ reordered.add(index - 1, col);
+ }
+ grid.setColumnOrder(reordered.toArray(new Column[reordered
+ .size()]));
+ }
+ }, "Component", "Columns", "Column " + i);
}
}
@@ -1223,4 +1403,166 @@ public class GridBasicClientFeaturesWidget extends
String coords = "(" + object + ", " + column + ")";
label.setText(coords + " " + output);
}
+
+ private void createDetailsMenu() {
+ String[] menupath = new String[] { "Component", "Row details" };
+ addMenuCommand("Set generator", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.setDetailsGenerator(new DetailsGenerator() {
+ @Override
+ public Widget getDetails(int rowIndex) {
+ FlowPanel panel = new FlowPanel();
+
+ final Label label = new Label("Row: " + rowIndex + ".");
+ Button button = new Button("Button",
+ new ClickHandler() {
+ @Override
+ public void onClick(ClickEvent event) {
+ label.setText("clicked");
+ }
+ });
+
+ panel.add(label);
+ panel.add(button);
+ return panel;
+ }
+ });
+ }
+ }, menupath);
+
+ addMenuCommand("Set faulty generator", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.setDetailsGenerator(new DetailsGenerator() {
+ @Override
+ public Widget getDetails(int rowIndex) {
+ throw new RuntimeException("This is by design.");
+ }
+ });
+ }
+ }, menupath);
+
+ addMenuCommand("Set empty generator", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.setDetailsGenerator(new DetailsGenerator() {
+ /*
+ * While this is functionally equivalent to the NULL
+ * generator, it's good to be explicit, since the behavior
+ * isn't strictly tied between them. NULL generator might be
+ * changed to render something different by default, and an
+ * empty generator might behave differently also in the
+ * future.
+ */
+
+ @Override
+ public Widget getDetails(int rowIndex) {
+ return null;
+ }
+ });
+ }
+ }, menupath);
+
+ String[] togglemenupath = new String[] { menupath[0], menupath[1],
+ "Toggle details for..." };
+ for (int i : new int[] { 0, 1, 100, 200, 300, 400, 500, 600, 700, 800,
+ 900, 999 }) {
+ final int rowIndex = i;
+ addMenuCommand("Row " + rowIndex, new ScheduledCommand() {
+ boolean visible = false;
+
+ @Override
+ public void execute() {
+ visible = !visible;
+ grid.setDetailsVisible(rowIndex, visible);
+ }
+ }, togglemenupath);
+ }
+
+ }
+
+ private static Logger getLogger() {
+ return Logger.getLogger(GridBasicClientFeaturesWidget.class.getName());
+ }
+
+ private void createSidebarMenu() {
+ String[] menupath = new String[] { "Component", "Sidebar" };
+
+ final List<MenuItem> customMenuItems = new ArrayList<MenuItem>();
+ final List<MenuItemSeparator> separators = new ArrayList<MenuItemSeparator>();
+
+ addMenuCommand("Add item to end", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ MenuItem item = createSidebarMenuItem(customMenuItems.size());
+ customMenuItems.add(item);
+ grid.getSidebarMenu().addItem(item);
+ }
+ }, menupath);
+
+ addMenuCommand("Add item before index 1", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ MenuItem item = createSidebarMenuItem(customMenuItems.size());
+ customMenuItems.add(item);
+ grid.getSidebarMenu().insertItem(item, 1);
+ }
+ }, menupath);
+
+ addMenuCommand("Remove last added item", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.getSidebarMenu().removeItem(
+ customMenuItems.remove(customMenuItems.size() - 1));
+ }
+ }, menupath);
+
+ addMenuCommand("Add separator to end", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ MenuItemSeparator separator = new MenuItemSeparator();
+ separators.add(separator);
+ grid.getSidebarMenu().addSeparator(separator);
+ }
+ }, menupath);
+
+ addMenuCommand("Add separator before index 1", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ MenuItemSeparator separator = new MenuItemSeparator();
+ separators.add(separator);
+ grid.getSidebarMenu().insertSeparator(separator, 1);
+ }
+ }, menupath);
+
+ addMenuCommand("Remove last added separator", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.getSidebarMenu().removeSeparator(
+ separators.remove(separators.size() - 1));
+ }
+ }, menupath);
+
+ addMenuCommand("Toggle sidebar visibility", new ScheduledCommand() {
+ @Override
+ public void execute() {
+ grid.setSidebarOpen(!grid.isSidebarOpen());
+ }
+ }, menupath);
+ }
+
+ private MenuItem createSidebarMenuItem(final int index) {
+ final MenuItem menuItem = new MenuItem("Custom menu item " + index,
+ new ScheduledCommand() {
+ @Override
+ public void execute() {
+ if (index % 2 == 0) {
+ grid.setSidebarOpen(false);
+ }
+ getLogger().info("Menu item " + index + " selected");
+ }
+ });
+ return menuItem;
+ }
}