diff options
author | Leif Åstrand <leif@vaadin.com> | 2014-09-20 10:01:44 +0300 |
---|---|---|
committer | Leif Åstrand <leif@vaadin.com> | 2014-09-20 10:15:37 +0300 |
commit | 9542a79187efc287e0ac5d1c7ca3911587e6f059 (patch) | |
tree | 175e18bd43f3d4c73d7d2eb6a277f81be8dd8488 /uitest/src | |
parent | 526b23cd86ccc7603e280da45d48f3f4bfcc4ecd (diff) | |
parent | 48e208c78e1ca2227d422985e4084a8b1ed7304f (diff) | |
download | vaadin-framework-9542a79187efc287e0ac5d1c7ca3911587e6f059.tar.gz vaadin-framework-9542a79187efc287e0ac5d1c7ca3911587e6f059.zip |
Merge remote-tracking branch 'origin/master' into grid
Change-Id: I8a35a090619778b1cfbff55e112ab2f30e6881a2
Diffstat (limited to 'uitest/src')
50 files changed, 8125 insertions, 0 deletions
diff --git a/uitest/src/com/vaadin/tests/components/grid/CustomRenderer.java b/uitest/src/com/vaadin/tests/components/grid/CustomRenderer.java new file mode 100644 index 0000000000..d217829bcb --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/CustomRenderer.java @@ -0,0 +1,76 @@ +/* + * 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.Widgetset; +import com.vaadin.data.Item; +import com.vaadin.data.Property; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.tests.widgetset.TestingWidgetSet; +import com.vaadin.ui.Label; +import com.vaadin.ui.components.grid.Grid; +import com.vaadin.ui.components.grid.Grid.SelectionMode; + +@Widgetset(TestingWidgetSet.NAME) +public class CustomRenderer extends AbstractTestUI { + + private static final Object INT_ARRAY_PROPERTY = "int array"; + private static final Object VOID_PROPERTY = "void"; + + static final Object ITEM_ID = "itemId1"; + static final String DEBUG_LABEL_ID = "debuglabel"; + static final String INIT_DEBUG_LABEL_CAPTION = "Debug label placeholder"; + + @Override + protected void setup(VaadinRequest request) { + IndexedContainer container = new IndexedContainer(); + container.addContainerProperty(INT_ARRAY_PROPERTY, int[].class, + new int[] {}); + container.addContainerProperty(VOID_PROPERTY, Void.class, null); + + Item item = container.addItem(ITEM_ID); + + @SuppressWarnings("unchecked") + Property<int[]> propertyIntArray = item + .getItemProperty(INT_ARRAY_PROPERTY); + propertyIntArray.setValue(new int[] { 1, 1, 2, 3, 5, 8, 13 }); + + Label debugLabel = new Label(INIT_DEBUG_LABEL_CAPTION); + debugLabel.setId(DEBUG_LABEL_ID); + + Grid grid = new Grid(container); + grid.getColumn(INT_ARRAY_PROPERTY).setRenderer(new IntArrayRenderer()); + grid.getColumn(VOID_PROPERTY).setRenderer( + new RowAwareRenderer(debugLabel)); + grid.setSelectionMode(SelectionMode.NONE); + addComponent(grid); + addComponent(debugLabel); + } + + @Override + protected String getTestDescription() { + return "Verifies that renderers operating on other data than " + + "just Strings also work "; + } + + @Override + protected Integer getTicketNumber() { + return Integer.valueOf(13334); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/grid/CustomRendererTest.java b/uitest/src/com/vaadin/tests/components/grid/CustomRendererTest.java new file mode 100644 index 0000000000..571a929c7e --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/CustomRendererTest.java @@ -0,0 +1,62 @@ +/* + * 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 static org.junit.Assert.assertEquals; + +import java.util.List; + +import org.junit.Test; + +import com.vaadin.testbench.elements.LabelElement; +import com.vaadin.tests.annotations.TestCategory; +import com.vaadin.tests.tb3.MultiBrowserTest; + +@TestCategory("grid") +public class CustomRendererTest extends MultiBrowserTest { + @Test + public void testIntArrayIsRendered() throws Exception { + openTestURL(); + + GridElement grid = findGrid(); + assertEquals("1 :: 1 :: 2 :: 3 :: 5 :: 8 :: 13", grid.getCell(0, 0) + .getText()); + } + + @Test + public void testRowAwareRenderer() throws Exception { + openTestURL(); + + GridElement grid = findGrid(); + assertEquals("Click me!", grid.getCell(0, 1).getText()); + assertEquals(CustomRenderer.INIT_DEBUG_LABEL_CAPTION, findDebugLabel() + .getText()); + + grid.getCell(0, 1).click(); + assertEquals("row: 0, key: 0", grid.getCell(0, 1).getText()); + assertEquals("key: 0, itemId: " + CustomRenderer.ITEM_ID, + findDebugLabel().getText()); + } + + private GridElement findGrid() { + List<GridElement> elements = $(GridElement.class).all(); + return elements.get(0); + } + + private LabelElement findDebugLabel() { + return $(LabelElement.class).id(CustomRenderer.DEBUG_LABEL_ID); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/GridClientRenderers.java b/uitest/src/com/vaadin/tests/components/grid/GridClientRenderers.java new file mode 100644 index 0000000000..2656407023 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/GridClientRenderers.java @@ -0,0 +1,281 @@ +/* + * 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 static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.openqa.selenium.Keys; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; +import org.openqa.selenium.remote.DesiredCapabilities; + +import com.vaadin.testbench.By; +import com.vaadin.testbench.TestBenchElement; +import com.vaadin.testbench.elements.LabelElement; +import com.vaadin.testbench.elements.NativeButtonElement; +import com.vaadin.testbench.elements.NativeSelectElement; +import com.vaadin.testbench.elements.ServerClass; +import com.vaadin.tests.annotations.TestCategory; +import com.vaadin.tests.components.grid.GridElement.GridCellElement; +import com.vaadin.tests.tb3.MultiBrowserTest; +import com.vaadin.tests.widgetset.client.grid.GridClientColumnRendererConnector.Renderers; +import com.vaadin.tests.widgetset.server.grid.GridClientColumnRenderers; + +/** + * Tests Grid client side renderers + * + * @since + * @author Vaadin Ltd + */ +@TestCategory("grid") +public class GridClientRenderers extends MultiBrowserTest { + + private static final double SLEEP_MULTIPLIER = 1.2; + private int latency = 0; + + @Override + protected Class<?> getUIClass() { + return GridClientColumnRenderers.class; + } + + @Override + protected String getDeploymentPath() { + String path = super.getDeploymentPath(); + if (latency > 0) { + path += (path.contains("?") ? "&" : "?") + "latency=" + latency; + } + return path; + } + + @ServerClass("com.vaadin.tests.widgetset.server.grid.GridClientColumnRenderers.GridController") + public static class MyClientGridElement extends GridElement { + } + + @Override + public void setup() throws Exception { + latency = 0; // reset + super.setup(); + } + + @Test + public void addWidgetRenderer() throws Exception { + openTestURL(); + + // Add widget renderer column + $(NativeSelectElement.class).first().selectByText( + Renderers.WIDGET_RENDERER.toString()); + $(NativeButtonElement.class).caption("Add").first().click(); + + // Click the button in cell 1,1 + TestBenchElement cell = getGrid().getCell(1, 2); + WebElement gwtButton = cell.findElement(By.tagName("button")); + gwtButton.click(); + + // Should be an alert visible + assertEquals("Button did not contain text \"Clicked\"", "Clicked", + gwtButton.getText()); + } + + @Test + public void detachAndAttachGrid() { + openTestURL(); + + // Add widget renderer column + $(NativeSelectElement.class).first().selectByText( + Renderers.WIDGET_RENDERER.toString()); + $(NativeButtonElement.class).caption("Add").first().click(); + + // Detach and re-attach the Grid + $(NativeButtonElement.class).caption("DetachAttach").first().click(); + + // Click the button in cell 1,1 + TestBenchElement cell = getGrid().getCell(1, 2); + WebElement gwtButton = cell.findElement(By.tagName("button")); + gwtButton.click(); + + // Should be an alert visible + assertEquals("Button did not contain text \"Clicked\"", + gwtButton.getText(), "Clicked"); + } + + @Test + public void rowsWithDataHasStyleName() throws Exception { + + // Simulate network latency with 2000ms + latency = 2000; + + openTestURL(); + + sleep((int) (latency * SLEEP_MULTIPLIER)); + + TestBenchElement row = getGrid().getRow(51); + String className = row.getAttribute("class"); + assertFalse( + "Row should not yet contain style name v-grid-row-has-data", + className.contains("v-grid-row-has-data")); + + // Wait for data to arrive + sleep((int) (latency * SLEEP_MULTIPLIER)); + + row = getGrid().getRow(51); + className = row.getAttribute("class"); + assertTrue("Row should now contain style name v-grid-row-has-data", + className.contains("v-grid-row-has-data")); + } + + @Test + public void complexRendererSetVisibleContent() throws Exception { + + DesiredCapabilities desiredCapabilities = getDesiredCapabilities(); + + // Simulate network latency with 2000ms + latency = 2000; + if (BrowserUtil.isIE8(desiredCapabilities)) { + // IE8 is slower than other browsers. Bigger latency is needed for + // stability in this test. + latency = 3000; + } + + // Chrome uses RGB instead of RGBA + String colorRed = "rgba(255, 0, 0, 1)"; + String colorWhite = "rgba(255, 255, 255, 1)"; + if (BrowserUtil.isChrome(desiredCapabilities)) { + colorRed = "rgb(255, 0, 0)"; + colorWhite = "rgb(255, 255, 255)"; + } + + openTestURL(); + + // Test initial renderering with contentVisible = False + TestBenchElement cell = getGrid().getCell(51, 1); + String backgroundColor = cell.getCssValue("backgroundColor"); + assertEquals("Background color was not red.", colorRed, backgroundColor); + + // data arrives... + sleep((int) (latency * SLEEP_MULTIPLIER)); + + // Content becomes visible + cell = getGrid().getCell(51, 1); + backgroundColor = cell.getCssValue("backgroundColor"); + assertNotEquals("Background color was red.", colorRed, backgroundColor); + + // scroll down, new cells becomes contentVisible = False + getGrid().scrollToRow(60); + + // Cell should be red (setContentVisible set cell red) + cell = getGrid().getCell(55, 1); + backgroundColor = cell.getCssValue("backgroundColor"); + assertEquals("Background color was not red.", colorRed, backgroundColor); + + // data arrives... + sleep((int) (latency * SLEEP_MULTIPLIER)); + + // Cell should no longer be red + backgroundColor = cell.getCssValue("backgroundColor"); + assertEquals("Background color was not white", colorWhite, + backgroundColor); + } + + @Test + public void testSortingEvent() throws Exception { + openTestURL(); + + $(NativeButtonElement.class).caption("Trigger sorting event").first() + .click(); + + String consoleText = $(LabelElement.class).id("testDebugConsole") + .getText(); + + assertTrue("Console text as expected", + consoleText.contains("Columns: 1, order: Column 1: ASCENDING")); + + } + + @Test + public void testListSorter() throws Exception { + openTestURL(); + + $(NativeButtonElement.class).caption("Shuffle").first().click(); + + GridElement gridElem = $(MyClientGridElement.class).first(); + + // XXX: DANGER! We'll need to know how many rows the Grid has! + // XXX: Currently, this is impossible; hence the hardcoded value of 70. + + boolean shuffled = false; + for (int i = 1, l = 70; i < l; ++i) { + + String str_a = gridElem.getCell(i - 1, 0).getAttribute("innerHTML"); + String str_b = gridElem.getCell(i, 0).getAttribute("innerHTML"); + + int value_a = Integer.parseInt(str_a); + int value_b = Integer.parseInt(str_b); + + if (value_a > value_b) { + shuffled = true; + break; + } + } + assertTrue("Grid shuffled", shuffled); + + $(NativeButtonElement.class).caption("Test sorting").first().click(); + + for (int i = 1, l = 70; i < l; ++i) { + + String str_a = gridElem.getCell(i - 1, 0).getAttribute("innerHTML"); + String str_b = gridElem.getCell(i, 0).getAttribute("innerHTML"); + + int value_a = Integer.parseInt(str_a); + int value_b = Integer.parseInt(str_b); + + if (value_a > value_b) { + assertTrue("Grid sorted", false); + } + } + } + + @Test + public void testComplexRendererOnActivate() { + openTestURL(); + + GridCellElement cell = getGrid().getCell(3, 1); + cell.click(); + new Actions(getDriver()).sendKeys(Keys.ENTER).perform(); + + assertEquals("onActivate was not called on KeyDown Enter.", + "Activated!", cell.getText()); + + cell = getGrid().getCell(4, 1); + cell.click(); + new Actions(getDriver()).moveToElement(cell).doubleClick().perform(); + assertEquals("onActivate was not called on double click.", + "Activated!", cell.getText()); + } + + private GridElement getGrid() { + return $(MyClientGridElement.class).first(); + } + + private void addColumn(Renderers renderer) { + // Add widget renderer column + $(NativeSelectElement.class).first().selectByText(renderer.toString()); + $(NativeButtonElement.class).caption("Add").first().click(); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/GridColspans.java b/uitest/src/com/vaadin/tests/components/grid/GridColspans.java new file mode 100644 index 0000000000..7b905d5404 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/GridColspans.java @@ -0,0 +1,79 @@ +/* + * 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.data.Container.Indexed; +import com.vaadin.data.Item; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.components.grid.Grid; +import com.vaadin.ui.components.grid.GridFooter; +import com.vaadin.ui.components.grid.GridFooter.FooterRow; +import com.vaadin.ui.components.grid.GridHeader; +import com.vaadin.ui.components.grid.GridHeader.HeaderRow; +import com.vaadin.ui.components.grid.renderers.NumberRenderer; + +public class GridColspans extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + Indexed dataSource = new IndexedContainer(); + Grid grid; + + dataSource.addContainerProperty("firstName", String.class, ""); + dataSource.addContainerProperty("lastName", String.class, ""); + dataSource.addContainerProperty("streetAddress", String.class, ""); + dataSource.addContainerProperty("zipCode", Integer.class, null); + dataSource.addContainerProperty("city", String.class, ""); + Item i = dataSource.addItem(0); + i.getItemProperty("firstName").setValue("Rudolph"); + i.getItemProperty("lastName").setValue("Reindeer"); + i.getItemProperty("streetAddress").setValue("Ruukinkatu 2-4"); + i.getItemProperty("zipCode").setValue(20540); + i.getItemProperty("city").setValue("Turku"); + grid = new Grid(dataSource); + grid.setWidth("600px"); + grid.getColumn("zipCode").setRenderer(new NumberRenderer()); + addComponent(grid); + + GridHeader header = grid.getHeader(); + HeaderRow row = header.prependRow(); + row.join("firstName", "lastName").setText("Full Name"); + row.join("streetAddress", "zipCode", "city").setText("Address"); + header.prependRow() + .join(dataSource.getContainerPropertyIds().toArray()) + .setText("All the stuff"); + + GridFooter footer = grid.getFooter(); + FooterRow footerRow = footer.appendRow(); + footerRow.join("firstName", "lastName").setText("Full Name"); + footerRow.join("streetAddress", "zipCode", "city").setText("Address"); + footer.appendRow().join(dataSource.getContainerPropertyIds().toArray()) + .setText("All the stuff"); + } + + @Override + protected String getTestDescription() { + return "Grid header and footer colspans"; + } + + @Override + protected Integer getTicketNumber() { + return 13334; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/grid/GridColspansTest.java b/uitest/src/com/vaadin/tests/components/grid/GridColspansTest.java new file mode 100644 index 0000000000..dad9399466 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/GridColspansTest.java @@ -0,0 +1,73 @@ +/* + * 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 static org.junit.Assert.assertEquals; + +import java.io.IOException; + +import org.junit.Test; +import org.openqa.selenium.Keys; +import org.openqa.selenium.interactions.Actions; + +import com.vaadin.tests.annotations.TestCategory; +import com.vaadin.tests.tb3.MultiBrowserTest; + +@TestCategory("grid") +public class GridColspansTest extends MultiBrowserTest { + + @Test + public void testHeaderColSpans() { + openTestURL(); + + GridElement grid = $(GridElement.class).first(); + assertEquals("5", grid.getHeaderCell(0, 1).getAttribute("colspan")); + assertEquals("2", grid.getHeaderCell(1, 1).getAttribute("colspan")); + assertEquals("3", grid.getHeaderCell(1, 3).getAttribute("colspan")); + } + + @Test + public void testFooterColSpans() { + openTestURL(); + + GridElement grid = $(GridElement.class).first(); + assertEquals("5", grid.getFooterCell(1, 1).getAttribute("colspan")); + assertEquals("2", grid.getFooterCell(0, 1).getAttribute("colspan")); + assertEquals("3", grid.getFooterCell(0, 3).getAttribute("colspan")); + } + + @Test + public void testActiveHeaderColumnsWithNavigation() throws IOException { + openTestURL(); + + GridElement grid = $(GridElement.class).first(); + grid.getCell(0, 1).click(); + + compareScreen("beforeNavigation"); + + for (int i = 1; i <= 6; ++i) { + assertEquals(true, grid.getFooterCell(1, 1).isActiveHeader()); + assertEquals(i < 3, grid.getFooterCell(0, 1).isActiveHeader()); + assertEquals(i >= 3, grid.getFooterCell(0, 3).isActiveHeader()); + assertEquals(true, grid.getHeaderCell(0, 1).isActiveHeader()); + assertEquals(i < 3, grid.getHeaderCell(1, 1).isActiveHeader()); + assertEquals(i >= 3, grid.getHeaderCell(1, 3).isActiveHeader()); + new Actions(getDriver()).sendKeys(Keys.ARROW_RIGHT).perform(); + } + + compareScreen("afterNavigation"); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/GridElement.java b/uitest/src/com/vaadin/tests/components/grid/GridElement.java new file mode 100644 index 0000000000..27c552340a --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/GridElement.java @@ -0,0 +1,284 @@ +/* + * 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.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.elements.AbstractComponentElement; +import com.vaadin.testbench.elements.AbstractElement; +import com.vaadin.testbench.elements.ServerClass; + +/** + * TestBench Element API for Grid + * + * @since + * @author Vaadin Ltd + */ +@ServerClass("com.vaadin.ui.components.grid.Grid") +public class GridElement extends AbstractComponentElement { + + public static class GridCellElement extends AbstractElement { + + private String ACTIVE_CLASS_NAME = "-cell-active"; + private String ACTIVE_HEADER_CLASS_NAME = "-header-active"; + private String FROZEN_CLASS_NAME = "frozen"; + + public boolean isActive() { + return getAttribute("class").contains(ACTIVE_CLASS_NAME); + } + + public boolean isActiveHeader() { + return getAttribute("class").contains(ACTIVE_HEADER_CLASS_NAME); + } + + public boolean isFrozen() { + return getAttribute("class").contains(FROZEN_CLASS_NAME); + } + } + + public static class GridRowElement extends AbstractElement { + + private String ACTIVE_CLASS_NAME = "-row-active"; + private String SELECTED_CLASS_NAME = "-row-selected"; + + public boolean isActive() { + return getAttribute("class").contains(ACTIVE_CLASS_NAME); + } + + @Override + public boolean isSelected() { + return getAttribute("class").contains(SELECTED_CLASS_NAME); + } + } + + /** + * 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 WebElement 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 WebElement getFooterRow(int rowIndex) { + return getSubPart("#footer[" + rowIndex + "]"); + } + + /** + * Get the vertical scroll element + * + * @return The element representing the vertical scrollbar + */ + public WebElement getVerticalScroller() { + List<WebElement> rootElements = findElements(By.xpath("./div")); + return rootElements.get(0); + } + + /** + * Get the horizontal scroll element + * + * @return The element representing the horizontal scrollbar + */ + public WebElement getHorizontalScroller() { + List<WebElement> rootElements = findElements(By.xpath("./div")); + return rootElements.get(1); + } + + /** + * Get the header element + * + * @return The thead element + */ + public WebElement getHeader() { + return getSubPart("#header"); + } + + /** + * Get the body element + * + * @return the tbody element + */ + public WebElement getBody() { + return getSubPart("#cell"); + } + + /** + * Get the footer element + * + * @return the tfoot element + */ + public WebElement getFooter() { + return getSubPart("#footer"); + } + + /** + * Get the element wrapping the table element + * + * @return The element that wraps the table element + */ + public WebElement getTableWrapper() { + List<WebElement> rootElements = findElements(By.xpath("./div")); + return rootElements.get(2); + } + + /** + * 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/GridScrolling.java b/uitest/src/com/vaadin/tests/components/grid/GridScrolling.java new file mode 100644 index 0000000000..dd86d616b9 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/GridScrolling.java @@ -0,0 +1,112 @@ +/* + * 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.data.Item; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.server.VaadinRequest; +import com.vaadin.shared.ui.grid.ScrollDestination; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.VerticalLayout; +import com.vaadin.ui.components.grid.Grid; + +@SuppressWarnings("serial") +public class GridScrolling extends AbstractTestUI { + + private Grid grid; + + private IndexedContainer ds; + + @Override + @SuppressWarnings("unchecked") + protected void setup(VaadinRequest request) { + // Build data source + ds = new IndexedContainer(); + + for (int col = 0; col < 5; col++) { + ds.addContainerProperty("col" + col, String.class, ""); + } + + for (int row = 0; row < 65536; row++) { + Item item = ds.addItem(Integer.valueOf(row)); + for (int col = 0; col < 5; col++) { + item.getItemProperty("col" + col).setValue( + "(" + row + ", " + col + ")"); + } + } + + grid = new Grid(ds); + + HorizontalLayout hl = new HorizontalLayout(); + hl.addComponent(grid); + hl.setMargin(true); + hl.setSpacing(true); + + VerticalLayout vl = new VerticalLayout(); + vl.setSpacing(true); + + // Add scroll buttons + Button scrollUpButton = new Button("Top", new ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + grid.scrollToStart(); + } + }); + scrollUpButton.setSizeFull(); + vl.addComponent(scrollUpButton); + + for (int i = 1; i < 7; ++i) { + final int row = (ds.size() / 7) * i; + Button scrollButton = new Button("Scroll to row " + row, + new ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + grid.scrollTo(Integer.valueOf(row), + ScrollDestination.MIDDLE); + } + }); + scrollButton.setSizeFull(); + vl.addComponent(scrollButton); + } + + Button scrollDownButton = new Button("Bottom", new ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + grid.scrollToEnd(); + } + }); + scrollDownButton.setSizeFull(); + vl.addComponent(scrollDownButton); + + hl.addComponent(vl); + addComponent(hl); + } + + @Override + protected String getTestDescription() { + return "Test Grid programmatic scrolling features"; + } + + @Override + protected Integer getTicketNumber() { + return 13327; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/grid/GridSingleColumn.java b/uitest/src/com/vaadin/tests/components/grid/GridSingleColumn.java new file mode 100644 index 0000000000..75b83ea3aa --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/GridSingleColumn.java @@ -0,0 +1,59 @@ +/* + * 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.data.Item; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.components.grid.Grid; +import com.vaadin.ui.components.grid.Grid.SelectionMode; +import com.vaadin.ui.components.grid.GridColumn; + +public class GridSingleColumn extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + + IndexedContainer indexedContainer = new IndexedContainer(); + indexedContainer.addContainerProperty("column1", String.class, ""); + + for (int i = 0; i < 100; i++) { + Item addItem = indexedContainer.addItem(i); + addItem.getItemProperty("column1").setValue("cell"); + } + + Grid grid = new Grid(indexedContainer); + grid.setSelectionMode(SelectionMode.NONE); + + GridColumn column = grid.getColumn("column1"); + + column.setHeaderCaption("Header"); + + addComponent(grid); + } + + @Override + protected String getTestDescription() { + return "Tests a single column grid"; + } + + @Override + protected Integer getTicketNumber() { + return null; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/grid/GridSingleColumnTest.java b/uitest/src/com/vaadin/tests/components/grid/GridSingleColumnTest.java new file mode 100644 index 0000000000..2e062f36c6 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/GridSingleColumnTest.java @@ -0,0 +1,45 @@ +/* + * 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 static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; + +import org.junit.Ignore; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.tests.annotations.TestCategory; +import com.vaadin.tests.tb3.MultiBrowserTest; + +@TestCategory("grid") +public class GridSingleColumnTest extends MultiBrowserTest { + + /* + * TODO unignore once column header captions are reimplemented + */ + @Test + @Ignore + public void headerIsVisible() { + openTestURL(); + + WebElement header = getDriver().findElement( + By.className("v-grid-header")); + WebElement cell = header.findElement(By.className("v-grid-cell")); + assertThat(cell.getText(), is("Header")); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/IntArrayRenderer.java b/uitest/src/com/vaadin/tests/components/grid/IntArrayRenderer.java new file mode 100644 index 0000000000..ccedcc908a --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/IntArrayRenderer.java @@ -0,0 +1,37 @@ +/* + * 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.ui.components.grid.AbstractRenderer; + +import elemental.json.Json; +import elemental.json.JsonArray; +import elemental.json.JsonValue; + +public class IntArrayRenderer extends AbstractRenderer<int[]> { + public IntArrayRenderer() { + super(int[].class); + } + + @Override + public JsonValue encode(int[] value) { + JsonArray valueArray = Json.createArray(); + for (int i = 0; i < value.length; ++i) { + valueArray.set(i, value[i]); + } + return valueArray; + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/RowAwareRenderer.java b/uitest/src/com/vaadin/tests/components/grid/RowAwareRenderer.java new file mode 100644 index 0000000000..41ccddc2cf --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/RowAwareRenderer.java @@ -0,0 +1,42 @@ +/* + * 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.tests.widgetset.client.grid.RowAwareRendererConnector.RowAwareRendererRpc; +import com.vaadin.ui.Label; +import com.vaadin.ui.components.grid.AbstractRenderer; + +import elemental.json.Json; +import elemental.json.JsonValue; + +public class RowAwareRenderer extends AbstractRenderer<Void> { + public RowAwareRenderer(final Label debugLabel) { + super(Void.class); + registerRpc(new RowAwareRendererRpc() { + @Override + public void clicky(String key) { + Object itemId = getItemId(key); + debugLabel.setValue("key: " + key + ", itemId: " + itemId); + } + }); + } + + @Override + public JsonValue encode(Void value) { + return Json.createNull(); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorBasicClientFeatures.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorBasicClientFeatures.java new file mode 100644 index 0000000000..478fa53893 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorBasicClientFeatures.java @@ -0,0 +1,36 @@ +/* + * 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 com.vaadin.annotations.Widgetset; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.widgetset.TestingWidgetSet; +import com.vaadin.ui.AbstractComponent; +import com.vaadin.ui.UI; + +@Widgetset(TestingWidgetSet.NAME) +public class EscalatorBasicClientFeatures extends UI { + + public class EscalatorTestComponent extends AbstractComponent { + // empty + } + + @Override + public void init(VaadinRequest request) { + setContent(new EscalatorTestComponent()); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorBasicClientFeaturesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorBasicClientFeaturesTest.java new file mode 100644 index 0000000000..eff964bd4f --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorBasicClientFeaturesTest.java @@ -0,0 +1,194 @@ +/* + * 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.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.openqa.selenium.By; +import org.openqa.selenium.Dimension; +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.NoSuchElementException; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; + +import com.vaadin.tests.annotations.TestCategory; +import com.vaadin.tests.tb3.MultiBrowserTest; + +@TestCategory("grid") +public abstract class EscalatorBasicClientFeaturesTest extends MultiBrowserTest { + 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 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 HEADER_ROWS = "Header Rows"; + protected static final String BODY_ROWS = "Body Rows"; + protected static final String FOOTER_ROWS = "Footer Rows"; + + protected static final String GENERAL = "General"; + protected static final String POPULATE_COLUMN_ROW = "Populate Escalator (columns, then rows)"; + protected static final String POPULATE_ROW_COLUMN = "Populate Escalator (rows, then columns)"; + protected static final String CLEAR_COLUMN_ROW = "Clear (columns, then rows)"; + protected static final String CLEAR_ROW_COLUMN = "Clear (rows, then columns)"; + + protected static final String FEATURES = "Features"; + protected static final String FROZEN_COLUMNS = "Frozen columns"; + protected static final String FREEZE_1_COLUMN = "Freeze 1 column"; + protected static final String FREEZE_0_COLUMNS = "Freeze 0 columns"; + 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"; + + @Override + protected Class<?> getUIClass() { + return EscalatorBasicClientFeatures.class; + } + + protected WebElement getEscalator() { + return getDriver().findElement(By.className("v-escalator")); + } + + protected WebElement getHeaderRow(int row) { + return getRow("thead", row); + } + + protected WebElement getBodyRow(int row) { + return getRow("tbody", row); + } + + protected WebElement getFooterRow(int row) { + return getRow("tfoot", row); + } + + protected WebElement getHeaderCell(int row, int col) { + return getCell("thead", row, col); + } + + protected WebElement getBodyCell(int row, int col) { + return getCell("tbody", row, col); + } + + protected WebElement getFooterCell(int row, int col) { + return getCell("tfoot", row, col); + } + + private WebElement getCell(String sectionTag, int row, int col) { + WebElement rowElement = getRow(sectionTag, row); + if (rowElement != null) { + try { + return rowElement.findElement(By.xpath("*[" + (col + 1) + "]")); + } catch (NoSuchElementException e) { + return null; + } + } else { + return null; + } + } + + private WebElement getRow(String sectionTag, int row) { + WebElement escalator = getEscalator(); + WebElement tableSection = escalator.findElement(By.tagName(sectionTag)); + + try { + return tableSection.findElement(By.xpath("tr[" + (row + 1) + "]")); + } catch (NoSuchElementException e) { + return null; + } + } + + protected void selectMenu(String menuCaption) { + WebElement menuElement = getMenuElement(menuCaption); + Dimension size = menuElement.getSize(); + new Actions(getDriver()).moveToElement(menuElement, size.width - 10, + size.height / 2).perform(); + } + + private WebElement getMenuElement(String menuCaption) { + return getDriver().findElement( + By.xpath("//td[text() = '" + menuCaption + "']")); + } + + protected void selectMenuPath(String... menuCaptions) { + new Actions(getDriver()).moveToElement(getMenuElement(menuCaptions[0])) + .click().perform(); + for (int i = 1; i < menuCaptions.length - 1; ++i) { + selectMenu(menuCaptions[i]); + new Actions(getDriver()).moveByOffset(20, 0).perform(); + } + new Actions(getDriver()) + .moveToElement( + getMenuElement(menuCaptions[menuCaptions.length - 1])) + .click().perform(); + } + + protected void assertLogContains(String substring) { + assertTrue("log should've contained, but didn't: " + substring, + getLogText().contains(substring)); + } + + protected void assertLogDoesNotContain(String substring) { + assertFalse("log shouldn't have contained, but did: " + substring, + getLogText().contains(substring)); + } + + private String getLogText() { + WebElement log = getDriver().findElement(By.cssSelector("#log")); + return log.getText(); + } + + protected void assertLogContainsInOrder(String... substrings) { + String log = getLogText(); + int cursor = 0; + for (String substring : substrings) { + String remainingLog = log.substring(cursor, log.length()); + int substringIndex = remainingLog.indexOf(substring); + if (substringIndex == -1) { + fail("substring \"" + substring + + "\" was not found in order from log."); + } + + cursor += substringIndex + substring.length(); + } + } + + protected void scrollVerticallyTo(int px) { + executeScript("arguments[0].scrollTop = " + px, getVeticalScrollbar()); + } + + private WebElement getVeticalScrollbar() { + return getEscalator().findElement( + By.className("v-escalator-scroller-vertical")); + } + + protected void scrollHorizontallyTo(int px) { + executeScript("arguments[0].scrollLeft = " + px, + getHorizontalScrollbar()); + } + + private WebElement getHorizontalScrollbar() { + return getEscalator().findElement( + By.className("v-escalator-scroller-horizontal")); + } + + protected Object executeScript(String script, Object... args) { + return ((JavascriptExecutor) getDriver()).executeScript(script, args); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorColspanTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorColspanTest.java new file mode 100644 index 0000000000..8cbba35faa --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorColspanTest.java @@ -0,0 +1,91 @@ +/* + * 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 org.junit.Test; +import org.openqa.selenium.WebElement; + +public class EscalatorColspanTest extends EscalatorBasicClientFeaturesTest { + private static final int NO_COLSPAN = 1; + + @Test + public void testNoColspan() { + openTestURL(); + populate(); + + assertEquals(NO_COLSPAN, getColSpan(getHeaderCell(0, 0))); + assertEquals(NO_COLSPAN, getColSpan(getBodyCell(0, 0))); + assertEquals(NO_COLSPAN, getColSpan(getFooterCell(0, 0))); + } + + @Test + public void testColspan() { + openTestURL(); + populate(); + + int singleCellWidth = getWidth(getBodyCell(0, 0)); + int doubleCellWidth = singleCellWidth * 2; + + selectMenuPath(FEATURES, COLUMN_SPANNING, COLSPAN_NORMAL); + + WebElement bodyCell = getBodyCell(0, 0); + assertEquals(2, getColSpan(bodyCell)); + assertEquals(doubleCellWidth, getWidth(bodyCell)); + } + + @Test + public void testColspanToggle() { + openTestURL(); + populate(); + + int singleCellWidth = getWidth(getBodyCell(0, 0)); + + selectMenuPath(FEATURES, COLUMN_SPANNING, COLSPAN_NORMAL); + selectMenuPath(FEATURES, COLUMN_SPANNING, COLSPAN_NONE); + + WebElement bodyCell = getBodyCell(0, 0); + assertEquals(NO_COLSPAN, getColSpan(bodyCell)); + assertEquals(singleCellWidth, getWidth(bodyCell)); + } + + private static int getWidth(WebElement element) { + String widthString = element.getCssValue("width"); // e.g. 100px + if ("0".equals(widthString)) { + return 0; + } else if (widthString.endsWith("px")) { + return Integer.parseInt(widthString.substring(0, + widthString.length() - 2)); + } else { + throw new IllegalStateException("Element width expressed " + + "in an unsupported format: " + widthString); + } + } + + private static int getColSpan(WebElement cell) { + String attribute = cell.getAttribute("colspan"); + if (attribute == null) { + return NO_COLSPAN; + } else { + return Integer.parseInt(attribute); + } + } + + private void populate() { + selectMenuPath(GENERAL, POPULATE_COLUMN_ROW); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorColumnFreezingTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorColumnFreezingTest.java new file mode 100644 index 0000000000..fb217789c2 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorColumnFreezingTest.java @@ -0,0 +1,112 @@ +/* + * 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.assertTrue; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.junit.Test; +import org.openqa.selenium.WebElement; + +public class EscalatorColumnFreezingTest extends EscalatorBasicClientFeaturesTest { + + private final static Pattern TRANSFORM_PATTERN = Pattern.compile(// @formatter:off + // any start of the string + ".*" + + // non-capturing group for "webkitTransform: " or "transform: " + + "(?:webkitT|t)ransform: " + + // non-capturing group for "translate" or "translate3d" + + "translate(?:3d)?" + + // capturing the digits in e.g "(100px," + + "\\((\\d+)px," + + // any end of the string + + ".*"); + + // @formatter:on + + private final static Pattern LEFT_PATTERN = Pattern + .compile(".*left: (\\d+)px.*"); + + private static final int NO_FREEZE = -1; + + @Test + public void testNoFreeze() { + openTestURL(); + populate(); + + WebElement bodyCell = getBodyCell(0, 0); + assertFalse(isFrozen(bodyCell)); + assertEquals(NO_FREEZE, getFrozenScrollCompensation(bodyCell)); + } + + @Test + public void testOneFreeze() { + openTestURL(); + populate(); + + selectMenuPath(FEATURES, FROZEN_COLUMNS, FREEZE_1_COLUMN); + int scrollPx = 100; + scrollHorizontallyTo(scrollPx); + + WebElement bodyCell = getBodyCell(0, 0); + assertTrue(isFrozen(bodyCell)); + assertEquals(scrollPx, getFrozenScrollCompensation(bodyCell)); + } + + @Test + public void testFreezeToggle() { + openTestURL(); + populate(); + + selectMenuPath(FEATURES, FROZEN_COLUMNS, FREEZE_1_COLUMN); + scrollHorizontallyTo(100); + selectMenuPath(FEATURES, FROZEN_COLUMNS, FREEZE_0_COLUMNS); + + WebElement bodyCell = getBodyCell(0, 0); + assertFalse(isFrozen(bodyCell)); + assertEquals(NO_FREEZE, getFrozenScrollCompensation(bodyCell)); + } + + private void populate() { + selectMenuPath(GENERAL, POPULATE_COLUMN_ROW); + } + + private static boolean isFrozen(WebElement cell) { + return cell.getAttribute("class").contains("frozen"); + } + + private static int getFrozenScrollCompensation(WebElement cell) { + String styleAttribute = cell.getAttribute("style"); + Matcher transformMatcher = TRANSFORM_PATTERN.matcher(styleAttribute); + Matcher leftMatcher = LEFT_PATTERN.matcher(styleAttribute); + + if (transformMatcher.find()) { + return Integer.parseInt(transformMatcher.group(1)); + } else if (leftMatcher.find()) { + return Integer.parseInt(leftMatcher.group(1)); + } else { + return NO_FREEZE; + } + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorRowColumnTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorRowColumnTest.java new file mode 100644 index 0000000000..f45eec07f8 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorRowColumnTest.java @@ -0,0 +1,203 @@ +/* + * 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.assertNotNull; +import static org.junit.Assert.assertNull; + +import org.junit.Test; +import org.openqa.selenium.By; + +public class EscalatorRowColumnTest extends EscalatorBasicClientFeaturesTest { + + @Test + public void testInit() { + openTestURL(); + assertNotNull(getEscalator()); + assertNull(getHeaderRow(0)); + assertNull(getBodyRow(0)); + assertNull(getFooterRow(0)); + + assertLogContains("Columns: 0"); + assertLogContains("Header rows: 0"); + assertLogContains("Body rows: 0"); + assertLogContains("Footer rows: 0"); + } + + @Test + public void testInsertAColumn() { + openTestURL(); + + selectMenuPath(COLUMNS_AND_ROWS, COLUMNS, ADD_ONE_COLUMN_TO_BEGINNING); + assertNull(getHeaderRow(0)); + assertNull(getBodyRow(0)); + assertNull(getFooterRow(0)); + assertLogContains("Columns: 1"); + } + + @Test + public void testInsertAHeaderRow() { + openTestURL(); + + selectMenuPath(COLUMNS_AND_ROWS, HEADER_ROWS, ADD_ONE_ROW_TO_BEGINNING); + assertNull(getHeaderCell(0, 0)); + assertNull(getBodyCell(0, 0)); + assertNull(getFooterCell(0, 0)); + assertLogContains("Header rows: 1"); + } + + @Test + public void testInsertABodyRow() { + openTestURL(); + + selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, ADD_ONE_ROW_TO_BEGINNING); + assertNull(getHeaderCell(0, 0)); + assertNull(getBodyCell(0, 0)); + assertNull(getFooterCell(0, 0)); + assertLogContains("Body rows: 1"); + } + + @Test + public void testInsertAFooterRow() { + openTestURL(); + + selectMenuPath(COLUMNS_AND_ROWS, FOOTER_ROWS, ADD_ONE_ROW_TO_BEGINNING); + assertNull(getHeaderCell(0, 0)); + assertNull(getBodyCell(0, 0)); + assertNull(getFooterCell(0, 0)); + assertLogContains("Footer rows: 1"); + } + + @Test + public void testInsertAColumnAndAHeaderRow() { + openTestURL(); + + selectMenuPath(COLUMNS_AND_ROWS, COLUMNS, ADD_ONE_COLUMN_TO_BEGINNING); + selectMenuPath(COLUMNS_AND_ROWS, HEADER_ROWS, ADD_ONE_ROW_TO_BEGINNING); + assertNotNull(getHeaderCell(0, 0)); + assertNull(getBodyCell(0, 0)); + assertNull(getFooterCell(0, 0)); + assertLogContains("Columns: 1"); + assertLogContains("Header rows: 1"); + } + + @Test + public void testInsertAColumnAndABodyRow() { + openTestURL(); + + selectMenuPath(COLUMNS_AND_ROWS, COLUMNS, ADD_ONE_COLUMN_TO_BEGINNING); + selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, ADD_ONE_ROW_TO_BEGINNING); + assertNull(getHeaderCell(0, 0)); + assertNotNull(getBodyCell(0, 0)); + assertNull(getFooterCell(0, 0)); + assertLogContains("Columns: 1"); + assertLogContains("Body rows: 1"); + } + + @Test + public void testInsertAColumnAndAFooterRow() { + openTestURL(); + + selectMenuPath(COLUMNS_AND_ROWS, COLUMNS, ADD_ONE_COLUMN_TO_BEGINNING); + selectMenuPath(COLUMNS_AND_ROWS, FOOTER_ROWS, ADD_ONE_ROW_TO_BEGINNING); + assertNull(getHeaderCell(0, 0)); + assertNull(getBodyCell(0, 0)); + assertNotNull(getFooterCell(0, 0)); + assertLogContains("Columns: 1"); + assertLogContains("Footer rows: 1"); + } + + @Test + public void testInsertAHeaderRowAndAColumn() { + openTestURL(); + + selectMenuPath(COLUMNS_AND_ROWS, HEADER_ROWS, ADD_ONE_ROW_TO_BEGINNING); + selectMenuPath(COLUMNS_AND_ROWS, COLUMNS, ADD_ONE_COLUMN_TO_BEGINNING); + assertNotNull(getHeaderCell(0, 0)); + assertNull(getBodyCell(0, 0)); + assertNull(getFooterCell(0, 0)); + assertLogContains("Columns: 1"); + assertLogContains("Header rows: 1"); + } + + @Test + public void testInsertABodyRowAndAColumn() { + openTestURL(); + + selectMenuPath(COLUMNS_AND_ROWS, BODY_ROWS, ADD_ONE_ROW_TO_BEGINNING); + selectMenuPath(COLUMNS_AND_ROWS, COLUMNS, ADD_ONE_COLUMN_TO_BEGINNING); + assertNull(getHeaderCell(0, 0)); + assertNotNull(getBodyCell(0, 0)); + assertNull(getFooterCell(0, 0)); + assertLogContains("Columns: 1"); + assertLogContains("Body rows: 1"); + } + + @Test + public void testInsertAFooterRowAndAColumn() { + openTestURL(); + + selectMenuPath(COLUMNS_AND_ROWS, FOOTER_ROWS, ADD_ONE_ROW_TO_BEGINNING); + selectMenuPath(COLUMNS_AND_ROWS, COLUMNS, ADD_ONE_COLUMN_TO_BEGINNING); + assertNull(getHeaderCell(0, 0)); + assertNull(getBodyCell(0, 0)); + assertNotNull(getFooterCell(0, 0)); + assertLogContains("Columns: 1"); + assertLogContains("Footer rows: 1"); + } + + @Test + public void testFillColRow() { + openTestURL(); + + selectMenuPath(GENERAL, POPULATE_COLUMN_ROW); + scrollVerticallyTo(2000); // more like 1857, but this should be enough. + + // if not found, an exception is thrown here + findElement(By.xpath("//td[text()='Cell: 9,99']")); + } + + @Test + public void testFillRowCol() { + openTestURL(); + + selectMenuPath(GENERAL, POPULATE_ROW_COLUMN); + scrollVerticallyTo(2000); // more like 1857, but this should be enough. + + // if not found, an exception is thrown here + findElement(By.xpath("//td[text()='Cell: 9,99']")); + } + + @Test + public void testClearColRow() { + openTestURL(); + + selectMenuPath(GENERAL, POPULATE_COLUMN_ROW); + selectMenuPath(GENERAL, CLEAR_COLUMN_ROW); + + assertNull(getBodyCell(0, 0)); + } + + @Test + public void testClearRowCol() { + openTestURL(); + + selectMenuPath(GENERAL, POPULATE_COLUMN_ROW); + selectMenuPath(GENERAL, CLEAR_ROW_COLUMN); + + assertNull(getBodyCell(0, 0)); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorUpdaterUi.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorUpdaterUi.java new file mode 100644 index 0000000000..7e822e41ba --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorUpdaterUi.java @@ -0,0 +1,35 @@ +/* + * 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 com.vaadin.annotations.Widgetset; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.widgetset.TestingWidgetSet; +import com.vaadin.ui.AbstractComponent; +import com.vaadin.ui.UI; + +@Widgetset(TestingWidgetSet.NAME) +public class EscalatorUpdaterUi extends UI { + + public class EscalatorUpdaterTestComponent extends AbstractComponent { + // empty + } + + @Override + protected void init(VaadinRequest request) { + setContent(new EscalatorUpdaterTestComponent()); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorUpdaterUiTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorUpdaterUiTest.java new file mode 100644 index 0000000000..c1c3a31b77 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorUpdaterUiTest.java @@ -0,0 +1,148 @@ +/* + * 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 org.junit.Test; + +public class EscalatorUpdaterUiTest extends EscalatorBasicClientFeaturesTest { + @Override + protected Class<?> getUIClass() { + return EscalatorUpdaterUi.class; + } + + @Test + public void testHeaderPaintOrderRowColRowCol() { + boolean addColumnFirst = false; + boolean removeColumnFirst = false; + testPaintOrder(HEADER_ROWS, addColumnFirst, removeColumnFirst); + } + + @Test + public void testHeaderPaintOrderRowColColRow() { + boolean addColumnFirst = false; + boolean removeColumnFirst = true; + testPaintOrder(HEADER_ROWS, addColumnFirst, removeColumnFirst); + } + + @Test + public void testHeaderPaintOrderColRowColRow() { + boolean addColumnFirst = true; + boolean removeColumnFirst = true; + testPaintOrder(HEADER_ROWS, addColumnFirst, removeColumnFirst); + } + + @Test + public void testHeaderPaintOrderColRowRowCol() { + boolean addColumnFirst = true; + boolean removeColumnFirst = false; + testPaintOrder(HEADER_ROWS, addColumnFirst, removeColumnFirst); + } + + @Test + public void testBodyPaintOrderRowColRowCol() { + boolean addColumnFirst = false; + boolean removeColumnFirst = false; + testPaintOrder(BODY_ROWS, addColumnFirst, removeColumnFirst); + } + + @Test + public void testBodyPaintOrderRowColColRow() { + boolean addColumnFirst = false; + boolean removeColumnFirst = true; + testPaintOrder(BODY_ROWS, addColumnFirst, removeColumnFirst); + } + + @Test + public void testBodyPaintOrderColRowColRow() { + boolean addColumnFirst = true; + boolean removeColumnFirst = true; + testPaintOrder(BODY_ROWS, addColumnFirst, removeColumnFirst); + } + + @Test + public void testBodyPaintOrderColRowRowCol() { + boolean addColumnFirst = true; + boolean removeColumnFirst = false; + testPaintOrder(BODY_ROWS, addColumnFirst, removeColumnFirst); + } + + @Test + public void testFooterPaintOrderRowColRowCol() { + boolean addColumnFirst = false; + boolean removeColumnFirst = false; + testPaintOrder(FOOTER_ROWS, addColumnFirst, removeColumnFirst); + } + + @Test + public void testFooterPaintOrderRowColColRow() { + boolean addColumnFirst = false; + boolean removeColumnFirst = true; + testPaintOrder(FOOTER_ROWS, addColumnFirst, removeColumnFirst); + } + + @Test + public void testFooterPaintOrderColRowColRow() { + boolean addColumnFirst = true; + boolean removeColumnFirst = true; + testPaintOrder(FOOTER_ROWS, addColumnFirst, removeColumnFirst); + } + + @Test + public void testFooterPaintOrderColRowRowCol() { + boolean addColumnFirst = true; + boolean removeColumnFirst = false; + testPaintOrder(FOOTER_ROWS, addColumnFirst, removeColumnFirst); + } + + private void testPaintOrder(String tableSection, boolean addColumnFirst, + boolean removeColumnFirst) { + openTestURL(); + + if (addColumnFirst) { + selectMenuPath(COLUMNS_AND_ROWS, COLUMNS, + ADD_ONE_COLUMN_TO_BEGINNING); + selectMenuPath(COLUMNS_AND_ROWS, tableSection, + ADD_ONE_ROW_TO_BEGINNING); + } else { + selectMenuPath(COLUMNS_AND_ROWS, tableSection, + ADD_ONE_ROW_TO_BEGINNING); + selectMenuPath(COLUMNS_AND_ROWS, COLUMNS, + ADD_ONE_COLUMN_TO_BEGINNING); + } + + assertLogContainsInOrder("preAttach: elementIsAttached == false", + "postAttach: elementIsAttached == true", + "update: elementIsAttached == true"); + assertLogDoesNotContain("preDetach"); + assertLogDoesNotContain("postDetach"); + + if (removeColumnFirst) { + selectMenuPath(COLUMNS_AND_ROWS, COLUMNS, + REMOVE_ONE_COLUMN_FROM_BEGINNING); + selectMenuPath(COLUMNS_AND_ROWS, tableSection, + REMOVE_ONE_ROW_FROM_BEGINNING); + } else { + selectMenuPath(COLUMNS_AND_ROWS, tableSection, + REMOVE_ONE_ROW_FROM_BEGINNING); + selectMenuPath(COLUMNS_AND_ROWS, COLUMNS, + REMOVE_ONE_COLUMN_FROM_BEGINNING); + } + + assertLogContainsInOrder("preDetach: elementIsAttached == true", + "postDetach: elementIsAttached == false"); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeatures.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeatures.java new file mode 100644 index 0000000000..4c5e703b82 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeatures.java @@ -0,0 +1,41 @@ +/* + * 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 com.vaadin.annotations.Widgetset; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.widgetset.TestingWidgetSet; +import com.vaadin.ui.AbstractComponent; +import com.vaadin.ui.UI; + +/** + * Initializer shell for GridClientBasicFeatures test application + * + * @since + * @author Vaadin Ltd + */ +@Widgetset(TestingWidgetSet.NAME) +public class GridBasicClientFeatures extends UI { + + public class GridTestComponent extends AbstractComponent { + } + + @Override + protected void init(VaadinRequest request) { + setContent(new GridTestComponent()); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java new file mode 100644 index 0000000000..e3318fe650 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java @@ -0,0 +1,63 @@ +/* + * 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 org.openqa.selenium.By; +import org.openqa.selenium.Dimension; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; + +/** + * Variant of GridBasicFeaturesTest to be used with GridBasicClientFeatures. + * + * @since + * @author Vaadin Ltd + */ +public abstract class GridBasicClientFeaturesTest extends GridBasicFeaturesTest { + + @Override + protected Class<?> getUIClass() { + return GridBasicClientFeatures.class; + } + + @Override + protected void selectMenu(String menuCaption) { + WebElement menuElement = getMenuElement(menuCaption); + Dimension size = menuElement.getSize(); + new Actions(getDriver()).moveToElement(menuElement, size.width - 10, + size.height / 2).perform(); + } + + private WebElement getMenuElement(String menuCaption) { + return getDriver().findElement( + By.xpath("//td[text() = '" + menuCaption + "']")); + } + + @Override + protected void selectMenuPath(String... menuCaptions) { + new Actions(getDriver()).moveToElement(getMenuElement(menuCaptions[0])) + .click().perform(); + for (int i = 1; i < menuCaptions.length - 1; ++i) { + selectMenu(menuCaptions[i]); + new Actions(getDriver()).moveByOffset(20, 0).perform(); + } + new Actions(getDriver()) + .moveToElement( + getMenuElement(menuCaptions[menuCaptions.length - 1])) + .click().perform(); + } + +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java new file mode 100644 index 0000000000..ae8a0d5eb8 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java @@ -0,0 +1,750 @@ +/* + * 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 java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Locale; +import java.util.Random; + +import com.vaadin.data.Item; +import com.vaadin.data.Property; +import com.vaadin.data.util.IndexedContainer; +import com.vaadin.shared.ui.grid.GridStaticCellType; +import com.vaadin.shared.ui.grid.HeightMode; +import com.vaadin.shared.ui.grid.SortDirection; +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.components.grid.Grid; +import com.vaadin.ui.components.grid.Grid.SelectionMode; +import com.vaadin.ui.components.grid.GridColumn; +import com.vaadin.ui.components.grid.GridFooter; +import com.vaadin.ui.components.grid.GridFooter.FooterCell; +import com.vaadin.ui.components.grid.GridHeader; +import com.vaadin.ui.components.grid.GridHeader.HeaderCell; +import com.vaadin.ui.components.grid.GridHeader.HeaderRow; +import com.vaadin.ui.components.grid.SortOrderChangeEvent; +import com.vaadin.ui.components.grid.SortOrderChangeListener; +import com.vaadin.ui.components.grid.renderers.DateRenderer; +import com.vaadin.ui.components.grid.renderers.HtmlRenderer; +import com.vaadin.ui.components.grid.renderers.NumberRenderer; +import com.vaadin.ui.components.grid.sort.Sort; +import com.vaadin.ui.components.grid.sort.SortOrder; + +/** + * Tests the basic features like columns, footers and headers + * + * @since + * @author Vaadin Ltd + */ +public class GridBasicFeatures extends AbstractComponentTest<Grid> { + + private static final int MANUALLY_FORMATTED_COLUMNS = 5; + public static final int COLUMNS = 12; + public static final int ROWS = 1000; + + private int columnGroupRows = 0; + private IndexedContainer ds; + + @Override + @SuppressWarnings("unchecked") + protected Grid constructComponent() { + + // Build data source + ds = new IndexedContainer() { + @Override + public List<Object> getItemIds(int startIndex, int numberOfIds) { + log("Requested items " + startIndex + " - " + + (startIndex + numberOfIds)); + return super.getItemIds(startIndex, numberOfIds); + } + }; + + { + int col = 0; + for (; col < COLUMNS - MANUALLY_FORMATTED_COLUMNS; col++) { + ds.addContainerProperty(getColumnProperty(col), String.class, + ""); + } + + ds.addContainerProperty(getColumnProperty(col++), Integer.class, + Integer.valueOf(0)); + ds.addContainerProperty(getColumnProperty(col++), Date.class, + new Date()); + ds.addContainerProperty(getColumnProperty(col++), String.class, ""); + + // Random numbers + ds.addContainerProperty(getColumnProperty(col++), Integer.class, 0); + ds.addContainerProperty(getColumnProperty(col++), Integer.class, 0); + + } + + { + Random rand = new Random(); + rand.setSeed(13334); + long timestamp = 0; + for (int row = 0; row < ROWS; row++) { + Item item = ds.addItem(Integer.valueOf(row)); + int col = 0; + for (; col < COLUMNS - MANUALLY_FORMATTED_COLUMNS; col++) { + item.getItemProperty(getColumnProperty(col)).setValue( + "(" + row + ", " + col + ")"); + } + item.getItemProperty(getColumnProperty(1)).setReadOnly(true); + + item.getItemProperty(getColumnProperty(col++)).setValue( + Integer.valueOf(row)); + item.getItemProperty(getColumnProperty(col++)).setValue( + new Date(timestamp)); + timestamp += 91250000; // a bit over a day, just to get + // variation + item.getItemProperty(getColumnProperty(col++)).setValue( + "<b>" + row + "</b>"); + + // Random numbers + item.getItemProperty(getColumnProperty(col++)).setValue( + rand.nextInt()); + // Random between 0 - 5 to test multisorting + item.getItemProperty(getColumnProperty(col++)).setValue( + rand.nextInt(5)); + } + } + + // Create grid + Grid grid = new Grid(ds); + + { + int col = grid.getContainerDatasource().getContainerPropertyIds() + .size() + - MANUALLY_FORMATTED_COLUMNS; + grid.getColumn(getColumnProperty(col++)).setRenderer( + new NumberRenderer(new DecimalFormat("0,000.00", + DecimalFormatSymbols.getInstance(new Locale("fi", + "FI"))))); + grid.getColumn(getColumnProperty(col++)).setRenderer( + new DateRenderer(new SimpleDateFormat("dd.MM.yy HH:mm"))); + grid.getColumn(getColumnProperty(col++)).setRenderer( + new HtmlRenderer()); + grid.getColumn(getColumnProperty(col++)).setRenderer( + new NumberRenderer()); + grid.getColumn(getColumnProperty(col++)).setRenderer( + new NumberRenderer()); + } + + // Create footer + GridFooter footer = grid.getFooter(); + footer.appendRow(); + footer.setVisible(false); + + // Add footer values (header values are automatically created) + for (int col = 0; col < COLUMNS; col++) { + footer.getRow(0).getCell(getColumnProperty(col)) + .setText("Footer " + col); + } + + // Set varying column widths + for (int col = 0; col < COLUMNS; col++) { + grid.getColumn(getColumnProperty(col)).setWidth(100 + col * 50); + } + + grid.addSortOrderChangeListener(new SortOrderChangeListener() { + @Override + public void sortOrderChange(SortOrderChangeEvent event) { + + String origin; + switch (event.getOriginator()) { + case API: + origin = "API"; + break; + case INTERNAL: + origin = "INTERNAL"; + break; + case USER: + origin = "USER"; + break; + default: + origin = "!!! ERROR !!!"; + break; + } + + log("Sort order: " + event.getSortOrder() + " by " + origin); + } + }); + + grid.setSelectionMode(SelectionMode.NONE); + + grid.getEditorRow().setPropertyEditable(getColumnProperty(3), false); + + createGridActions(); + + createColumnActions(); + + createHeaderActions(); + + createFooterActions(); + + createRowActions(); + + createEditorRowActions(); + + addHeightActions(); + + return grid; + } + + protected void createGridActions() { + LinkedHashMap<String, String> primaryStyleNames = new LinkedHashMap<String, String>(); + primaryStyleNames.put("v-grid", "v-grid"); + primaryStyleNames.put("v-escalator", "v-escalator"); + primaryStyleNames.put("my-grid", "my-grid"); + + createMultiClickAction("Primary style name", "State", + primaryStyleNames, new Command<Grid, String>() { + + @Override + public void execute(Grid grid, String value, Object data) { + grid.setPrimaryStyleName(value); + + } + }, primaryStyleNames.get("v-grid")); + + LinkedHashMap<String, SelectionMode> selectionModes = new LinkedHashMap<String, Grid.SelectionMode>(); + selectionModes.put("single", SelectionMode.SINGLE); + selectionModes.put("multi", SelectionMode.MULTI); + selectionModes.put("none", SelectionMode.NONE); + createSelectAction("Selection mode", "State", selectionModes, "none", + new Command<Grid, Grid.SelectionMode>() { + @Override + public void execute(Grid grid, SelectionMode selectionMode, + Object data) { + grid.setSelectionMode(selectionMode); + } + }); + + LinkedHashMap<String, List<SortOrder>> sortableProperties = new LinkedHashMap<String, List<SortOrder>>(); + for (Object propertyId : ds.getSortableContainerPropertyIds()) { + sortableProperties.put(propertyId + ", ASC", Sort.by(propertyId) + .build()); + sortableProperties.put(propertyId + ", DESC", + Sort.by(propertyId, SortDirection.DESCENDING).build()); + } + createSelectAction("Sort by column", "State", sortableProperties, + "Column 9, ascending", new Command<Grid, List<SortOrder>>() { + @Override + public void execute(Grid grid, List<SortOrder> sortOrder, + Object data) { + grid.setSortOrder(sortOrder); + } + }); + } + + protected void createHeaderActions() { + createCategory("Header", null); + + createBooleanAction("Visible", "Header", true, + new Command<Grid, Boolean>() { + + @Override + public void execute(Grid grid, Boolean value, Object data) { + grid.getHeader().setVisible(value); + } + }); + + LinkedHashMap<String, String> defaultRows = new LinkedHashMap<String, String>(); + defaultRows.put("Top", "Top"); + defaultRows.put("Bottom", "Bottom"); + defaultRows.put("Unset", "Unset"); + + createMultiClickAction("Default row", "Header", defaultRows, + new Command<Grid, String>() { + + @Override + public void execute(Grid grid, String value, Object data) { + HeaderRow defaultRow = null; + GridHeader header = grid.getHeader(); + if (value.equals("Top")) { + defaultRow = header.getRow(0); + } else if (value.equals("Bottom")) { + defaultRow = header.getRow(header.getRowCount() - 1); + } + header.setDefaultRow(defaultRow); + } + + }, defaultRows.get("Top")); + + createClickAction("Prepend row", "Header", new Command<Grid, Object>() { + + @Override + public void execute(Grid grid, Object value, Object data) { + grid.getHeader().prependRow(); + } + + }, null); + createClickAction("Append row", "Header", new Command<Grid, Object>() { + + @Override + public void execute(Grid grid, Object value, Object data) { + grid.getHeader().appendRow(); + } + + }, null); + + createClickAction("Remove top row", "Header", + new Command<Grid, Object>() { + + @Override + public void execute(Grid grid, Object value, Object data) { + grid.getHeader().removeRow(0); + } + + }, null); + createClickAction("Remove bottom row", "Header", + new Command<Grid, Object>() { + + @Override + public void execute(Grid grid, Object value, Object data) { + grid.getHeader().removeRow( + grid.getHeader().getRowCount() - 1); + } + + }, null); + } + + protected void createFooterActions() { + createCategory("Footer", null); + + createBooleanAction("Visible", "Footer", false, + new Command<Grid, Boolean>() { + + @Override + public void execute(Grid grid, Boolean value, Object data) { + grid.getFooter().setVisible(value); + } + }); + + createClickAction("Prepend row", "Footer", new Command<Grid, Object>() { + + @Override + public void execute(Grid grid, Object value, Object data) { + grid.getFooter().prependRow(); + } + + }, null); + createClickAction("Append row", "Footer", new Command<Grid, Object>() { + + @Override + public void execute(Grid grid, Object value, Object data) { + grid.getFooter().appendRow(); + } + + }, null); + + createClickAction("Remove top row", "Footer", + new Command<Grid, Object>() { + + @Override + public void execute(Grid grid, Object value, Object data) { + grid.getFooter().removeRow(0); + } + + }, null); + createClickAction("Remove bottom row", "Footer", + new Command<Grid, Object>() { + + @Override + public void execute(Grid grid, Object value, Object data) { + grid.getFooter().removeRow( + grid.getFooter().getRowCount() - 1); + } + + }, null); + } + + protected void createColumnActions() { + createCategory("Columns", null); + + for (int c = 0; c < COLUMNS; c++) { + createCategory(getColumnProperty(c), "Columns"); + + createBooleanAction("Visible", getColumnProperty(c), true, + new Command<Grid, Boolean>() { + + @Override + public void execute(Grid grid, Boolean value, + Object columnIndex) { + Object propertyId = getColumnProperty((Integer) columnIndex); + GridColumn column = grid.getColumn(propertyId); + column.setVisible(!column.isVisible()); + } + }, c); + + createClickAction("Remove", getColumnProperty(c), + new Command<Grid, String>() { + + @Override + public void execute(Grid grid, String value, Object data) { + grid.getContainerDatasource() + .removeContainerProperty( + getColumnProperty((Integer) data)); + removeCategory("Column " + data); + } + }, null, c); + + createClickAction("Freeze", getColumnProperty(c), + new Command<Grid, String>() { + + @Override + public void execute(Grid grid, String value, Object data) { + grid.setLastFrozenPropertyId(getColumnProperty((Integer) data)); + } + }, null, c); + + createBooleanAction("Sortable", getColumnProperty(c), true, + new Command<Grid, Boolean>() { + + @Override + public void execute(Grid grid, Boolean value, + Object columnIndex) { + Object propertyId = getColumnProperty((Integer) columnIndex); + GridColumn column = grid.getColumn(propertyId); + column.setSortable(value); + } + }, c); + + createCategory("Column " + c + " Width", getColumnProperty(c)); + + createClickAction("Auto", "Column " + c + " Width", + new Command<Grid, Integer>() { + + @Override + public void execute(Grid grid, Integer value, + Object columnIndex) { + Object propertyId = getColumnProperty((Integer) columnIndex); + GridColumn column = grid.getColumn(propertyId); + column.setWidthUndefined(); + } + }, -1, c); + + for (int w = 50; w < 300; w += 50) { + createClickAction(w + "px", "Column " + c + " Width", + new Command<Grid, Integer>() { + + @Override + public void execute(Grid grid, Integer value, + Object columnIndex) { + Object propertyId = getColumnProperty((Integer) columnIndex); + GridColumn column = grid.getColumn(propertyId); + column.setWidth(value); + } + }, w, c); + } + + LinkedHashMap<String, GridStaticCellType> defaultRows = new LinkedHashMap<String, GridStaticCellType>(); + defaultRows.put("Text Header", GridStaticCellType.TEXT); + defaultRows.put("Html Header ", GridStaticCellType.HTML); + defaultRows.put("Widget Header", GridStaticCellType.WIDGET); + + createMultiClickAction("Header Type", getColumnProperty(c), + defaultRows, new Command<Grid, GridStaticCellType>() { + + @Override + public void execute(Grid grid, + GridStaticCellType value, Object columnIndex) { + final Object propertyId = getColumnProperty((Integer) columnIndex); + final HeaderCell cell = grid.getHeader() + .getDefaultRow().getCell(propertyId); + switch (value) { + case TEXT: + cell.setText("Text Header"); + break; + case HTML: + cell.setHtml("HTML Header"); + break; + case WIDGET: + cell.setComponent(new Button("Button Header", + new ClickListener() { + + @Override + public void buttonClick( + ClickEvent event) { + log("Button clicked!"); + } + })); + default: + break; + } + } + + }, c); + + defaultRows = new LinkedHashMap<String, GridStaticCellType>(); + defaultRows.put("Text Footer", GridStaticCellType.TEXT); + defaultRows.put("Html Footer", GridStaticCellType.HTML); + defaultRows.put("Widget Footer", GridStaticCellType.WIDGET); + + createMultiClickAction("Footer Type", getColumnProperty(c), + defaultRows, new Command<Grid, GridStaticCellType>() { + + @Override + public void execute(Grid grid, + GridStaticCellType value, Object columnIndex) { + final Object propertyId = getColumnProperty((Integer) columnIndex); + final FooterCell cell = grid.getFooter().getRow(0) + .getCell(propertyId); + switch (value) { + case TEXT: + cell.setText("Text Footer"); + break; + case HTML: + cell.setHtml("HTML Footer"); + break; + case WIDGET: + cell.setComponent(new Button("Button Footer", + new ClickListener() { + + @Override + public void buttonClick( + ClickEvent event) { + log("Button clicked!"); + } + })); + default: + break; + } + } + + }, c); + } + } + + private static String getColumnProperty(int c) { + return "Column " + c; + } + + protected void createRowActions() { + createCategory("Body rows", null); + + final Command<Grid, String> newRowCommand = new Command<Grid, String>() { + @Override + public void execute(Grid c, String value, Object data) { + Item item = ds.addItemAt(0, new Object()); + for (int i = 0; i < COLUMNS; i++) { + Class<?> type = ds.getType(getColumnProperty(i)); + if (String.class.isAssignableFrom(type)) { + Property<String> itemProperty = getProperty(item, i); + itemProperty.setValue("newcell: " + i); + } else if (Integer.class.isAssignableFrom(type)) { + Property<Integer> itemProperty = getProperty(item, i); + itemProperty.setValue(Integer.valueOf(i)); + } else { + // let the default value be taken implicitly. + } + } + } + + private <T extends Object> Property<T> getProperty(Item item, int i) { + @SuppressWarnings("unchecked") + Property<T> itemProperty = item + .getItemProperty(getColumnProperty(i)); + return itemProperty; + } + }; + + createClickAction("Add 18 rows", "Body rows", + new Command<Grid, String>() { + @Override + public void execute(Grid c, String value, Object data) { + for (int i = 0; i < 18; i++) { + newRowCommand.execute(c, value, data); + } + } + }, null); + + createClickAction("Add first row", "Body rows", newRowCommand, null); + + createClickAction("Remove first row", "Body rows", + new Command<Grid, String>() { + @Override + public void execute(Grid c, String value, Object data) { + Object firstItemId = ds.getIdByIndex(0); + ds.removeItem(firstItemId); + } + }, null); + + createClickAction("Modify first row (getItemProperty)", "Body rows", + new Command<Grid, String>() { + @SuppressWarnings("unchecked") + @Override + public void execute(Grid c, String value, Object data) { + Object firstItemId = ds.getIdByIndex(0); + Item item = ds.getItem(firstItemId); + for (int i = 0; i < COLUMNS; i++) { + Property<?> property = item + .getItemProperty(getColumnProperty(i)); + if (property.getType().equals(String.class)) { + ((Property<String>) property) + .setValue("modified: " + i); + } + } + } + }, null); + + createClickAction("Modify first row (getContainerProperty)", + "Body rows", new Command<Grid, String>() { + @SuppressWarnings("unchecked") + @Override + public void execute(Grid c, String value, Object data) { + Object firstItemId = ds.getIdByIndex(0); + for (Object containerPropertyId : ds + .getContainerPropertyIds()) { + Property<?> property = ds.getContainerProperty( + firstItemId, containerPropertyId); + if (property.getType().equals(String.class)) { + ((Property<String>) property) + .setValue("modified: " + + containerPropertyId); + } + } + } + }, null); + + createBooleanAction("Select first row", "Body rows", false, + new Command<Grid, Boolean>() { + @Override + public void execute(Grid grid, Boolean select, Object data) { + final Object firstItemId = grid + .getContainerDatasource().firstItemId(); + if (select.booleanValue()) { + grid.select(firstItemId); + } else { + grid.deselect(firstItemId); + } + } + }); + + createClickAction("Remove all rows", "Body rows", + new Command<Grid, String>() { + @SuppressWarnings("unchecked") + @Override + public void execute(Grid c, String value, Object data) { + ds.removeAllItems(); + } + }, null); + } + + protected void createEditorRowActions() { + createBooleanAction("Enabled", "Editor row", false, + new Command<Grid, Boolean>() { + @Override + public void execute(Grid c, Boolean value, Object data) { + c.getEditorRow().setEnabled(value); + } + }); + + createClickAction("Edit item 5", "Editor row", + new Command<Grid, String>() { + @Override + public void execute(Grid c, String value, Object data) { + c.getEditorRow().editItem(5); + } + }, null); + + createClickAction("Edit item 100", "Editor row", + new Command<Grid, String>() { + @Override + public void execute(Grid c, String value, Object data) { + c.getEditorRow().editItem(100); + } + }, null); + + createClickAction("Cancel edit", "Editor row", + new Command<Grid, String>() { + @Override + public void execute(Grid c, String value, Object data) { + c.getEditorRow().cancel(); + } + }, null); + + } + + @SuppressWarnings("boxing") + protected void addHeightActions() { + createCategory("Height by Rows", "Size"); + + createBooleanAction("HeightMode Row", "Size", false, + new Command<Grid, Boolean>() { + @Override + public void execute(Grid c, Boolean heightModeByRows, + Object data) { + c.setHeightMode(heightModeByRows ? HeightMode.ROW + : HeightMode.CSS); + } + }, null); + + addActionForHeightByRows(1d / 3d); + addActionForHeightByRows(2d / 3d); + + for (double i = 1; i < 5; i++) { + addActionForHeightByRows(i); + addActionForHeightByRows(i + 1d / 3d); + addActionForHeightByRows(i + 2d / 3d); + } + + Command<Grid, String> sizeCommand = new Command<Grid, String>() { + @Override + public void execute(Grid grid, String height, Object data) { + grid.setHeight(height); + } + }; + + createCategory("Height", "Size"); + // header 20px + scrollbar 16px = 36px baseline + createClickAction("86px (no drag scroll select)", "Height", + sizeCommand, "86px"); + createClickAction("96px (drag scroll select limit)", "Height", + sizeCommand, "96px"); + createClickAction("106px (drag scroll select enabled)", "Height", + sizeCommand, "106px"); + } + + private void addActionForHeightByRows(final Double i) { + DecimalFormat df = new DecimalFormat("0.00"); + createClickAction(df.format(i) + " rows", "Height by Rows", + new Command<Grid, String>() { + @Override + public void execute(Grid c, String value, Object data) { + c.setHeightByRows(i); + } + }, null); + } + + @Override + protected Integer getTicketNumber() { + return 12829; + } + + @Override + protected Class<Grid> getTestClass() { + return Grid.class; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java new file mode 100644 index 0000000000..56f5f63c39 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java @@ -0,0 +1,119 @@ +/* + * 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 java.util.ArrayList; +import java.util.List; + +import org.openqa.selenium.By; +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; +import org.openqa.selenium.remote.DesiredCapabilities; + +import com.vaadin.testbench.TestBenchElement; +import com.vaadin.tests.annotations.TestCategory; +import com.vaadin.tests.components.grid.GridElement; +import com.vaadin.tests.tb3.MultiBrowserTest; + +@TestCategory("grid") +public abstract class GridBasicFeaturesTest extends MultiBrowserTest { + + @Override + protected DesiredCapabilities getDesiredCapabilities() { + DesiredCapabilities dCap = super.getDesiredCapabilities(); + if (BrowserUtil.isIE(dCap)) { + dCap.setCapability("requireWindowFocus", true); + } + return super.getDesiredCapabilities(); + } + + @Override + protected Class<?> getUIClass() { + return GridBasicFeatures.class; + } + + protected void selectSubMenu(String menuCaption) { + selectMenu(menuCaption); + new Actions(getDriver()).moveByOffset(100, 0).build().perform(); + } + + protected void selectMenu(String menuCaption) { + getDriver().findElement( + By.xpath("//span[text() = '" + menuCaption + "']")).click(); + } + + protected void selectMenuPath(String... menuCaptions) { + selectMenu(menuCaptions[0]); + for (int i = 1; i < menuCaptions.length; i++) { + selectSubMenu(menuCaptions[i]); + } + } + + protected GridElement getGridElement() { + return ((TestBenchElement) findElement(By.id("testComponent"))) + .wrap(GridElement.class); + } + + protected void scrollGridVerticallyTo(double px) { + executeScript("arguments[0].scrollTop = " + px, + getGridVerticalScrollbar()); + } + + protected List<TestBenchElement> getGridHeaderRowCells() { + List<TestBenchElement> headerCells = new ArrayList<TestBenchElement>(); + for (int i = 0; i < getGridElement().getHeaderCount(); ++i) { + headerCells.addAll(getGridElement().getHeaderCells(i)); + } + return headerCells; + } + + protected List<TestBenchElement> getGridFooterRowCells() { + List<TestBenchElement> footerCells = new ArrayList<TestBenchElement>(); + for (int i = 0; i < getGridElement().getFooterCount(); ++i) { + footerCells.addAll(getGridElement().getFooterCells(i)); + } + return footerCells; + } + + protected WebElement getEditorRow() { + List<WebElement> elems = getGridElement().findElements( + By.className("v-grid-editor-row")); + + assertLessThanOrEqual("number of editor rows", elems.size(), 1); + + return elems.isEmpty() ? null : elems.get(0); + } + + private Object executeScript(String script, WebElement element) { + final WebDriver driver = getDriver(); + if (driver instanceof JavascriptExecutor) { + final JavascriptExecutor je = (JavascriptExecutor) driver; + return je.executeScript(script, element); + } else { + throw new IllegalStateException("current driver " + + getDriver().getClass().getName() + " is not a " + + JavascriptExecutor.class.getSimpleName()); + } + } + + protected WebElement getGridVerticalScrollbar() { + return getDriver() + .findElement( + By.xpath("//div[contains(@class, \"v-grid-scroller-vertical\")]")); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientColumnPropertiesTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientColumnPropertiesTest.java new file mode 100644 index 0000000000..ea46ee24a5 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientColumnPropertiesTest.java @@ -0,0 +1,77 @@ +/* + * 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.assertTrue; + +import org.junit.Test; + +import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest; +import com.vaadin.tests.widgetset.client.grid.GridBasicClientFeaturesWidget; + +public class GridClientColumnPropertiesTest extends GridBasicClientFeaturesTest { + + @Test + public void initialColumnWidths() { + openTestURL(); + + for (int col = 0; col < GridBasicClientFeaturesWidget.COLUMNS; col++) { + int width = getGridElement().getCell(0, col).getSize().getWidth(); + if (col <= 6) { + // Growing column widths + assertEquals(50 + col * 25, width); + } else { + assertEquals(100, width); + } + } + } + + @Test + public void testChangingColumnWidth() { + openTestURL(); + + selectMenuPath("Component", "Columns", "Column 0", "Width", "50px"); + int width = getGridElement().getCell(0, 0).getSize().getWidth(); + assertEquals(50, width); + + selectMenuPath("Component", "Columns", "Column 0", "Width", "200px"); + width = getGridElement().getCell(0, 0).getSize().getWidth(); + assertEquals(200, width); + + selectMenuPath("Component", "Columns", "Column 0", "Width", "auto"); + width = getGridElement().getCell(0, 0).getSize().getWidth(); + assertEquals(100, width); + } + + @Test + public void testFrozenColumns() { + openTestURL(); + + assertFalse(cellIsFrozen(0, 0)); + assertFalse(cellIsFrozen(0, 1)); + + selectMenuPath("Component", "Columns", "Column 0", "Frozen"); + + assertTrue(cellIsFrozen(1, 0)); + assertFalse(cellIsFrozen(1, 1)); + } + + private boolean cellIsFrozen(int row, int col) { + return getGridElement().getCell(row, col).isFrozen(); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientKeyEventsTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientKeyEventsTest.java new file mode 100644 index 0000000000..47bd9f6cb7 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientKeyEventsTest.java @@ -0,0 +1,127 @@ +/* + * 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.assertTrue; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +import org.junit.Test; +import org.openqa.selenium.Keys; +import org.openqa.selenium.interactions.Actions; + +import com.vaadin.testbench.By; +import com.vaadin.tests.components.grid.GridElement.GridCellElement; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest; + +public class GridClientKeyEventsTest extends GridBasicClientFeaturesTest { + + private List<String> eventOrder = Arrays.asList("keydown", "keyup", + "keypress"); + + @Test + public void testBodyKeyEvents() throws IOException { + openTestURL(); + + getGridElement().getCell(2, 2).click(); + + new Actions(getDriver()).sendKeys(Keys.ENTER).perform(); + + for (int i = 0; i < 3; ++i) { + assertEquals("Body key event handler was not called.", "(2, 2) " + + eventOrder.get(i) + " 13", + findElements(By.className("v-label")).get(i * 3).getText()); + + assertTrue("Header key event handler got called unexpectedly.", + findElements(By.className("v-label")).get(i * 3 + 1) + .getText().isEmpty()); + assertTrue("Footer key event handler got called unexpectedly.", + findElements(By.className("v-label")).get(i * 3 + 2) + .getText().isEmpty()); + } + + } + + @Test + public void testHeaderKeyEvents() throws IOException { + openTestURL(); + + getGridElement().getHeaderCell(0, 2).click(); + + new Actions(getDriver()).sendKeys(Keys.ENTER).perform(); + + for (int i = 0; i < 3; ++i) { + assertEquals("Header key event handler was not called.", "(0, 2) " + + eventOrder.get(i) + " 13", + findElements(By.className("v-label")).get(i * 3 + 1) + .getText()); + + assertTrue("Body key event handler got called unexpectedly.", + findElements(By.className("v-label")).get(i * 3).getText() + .isEmpty()); + assertTrue("Footer key event handler got called unexpectedly.", + findElements(By.className("v-label")).get(i * 3 + 2) + .getText().isEmpty()); + } + } + + @Test + public void testFooterKeyEvents() throws IOException { + openTestURL(); + + selectMenuPath("Component", "Footer", "Append row"); + getGridElement().getFooterCell(0, 2).click(); + + new Actions(getDriver()).sendKeys(Keys.ENTER).perform(); + + for (int i = 0; i < 3; ++i) { + assertEquals("Footer key event handler was not called.", "(0, 2) " + + eventOrder.get(i) + " 13", + findElements(By.className("v-label")).get(i * 3 + 2) + .getText()); + + assertTrue("Body key event handler got called unexpectedly.", + findElements(By.className("v-label")).get(i * 3).getText() + .isEmpty()); + assertTrue("Header key event handler got called unexpectedly.", + findElements(By.className("v-label")).get(i * 3 + 1) + .getText().isEmpty()); + + } + } + + @Test + public void testNoKeyEventsFromWidget() { + openTestURL(); + + selectMenuPath("Component", "Columns", "Column 2", "Header Type", + "Widget Header"); + GridCellElement header = getGridElement().getHeaderCell(0, 2); + header.findElement(By.tagName("button")).click(); + new Actions(getDriver()).sendKeys(Keys.ENTER).perform(); + + for (int i = 0; i < 3; ++i) { + assertTrue("Header key event handler got called unexpectedly.", + findElements(By.className("v-label")).get(i * 3 + 1) + .getText().isEmpty()); + + } + } + +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientSelectionTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientSelectionTest.java new file mode 100644 index 0000000000..4b47837887 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientSelectionTest.java @@ -0,0 +1,37 @@ +/* + * 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.assertTrue; + +import org.junit.Test; + +import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest; + +public class GridClientSelectionTest extends GridBasicClientFeaturesTest { + + @Test + public void testChangeSelectionMode() { + openTestURL(); + + selectMenuPath("Component", "State", "Selection mode", "none"); + assertTrue("First column was selection column", getGridElement() + .getCell(0, 0).getText().equals("(0, 0)")); + selectMenuPath("Component", "State", "Selection mode", "multi"); + assertTrue("First column was not selection column", getGridElement() + .getCell(0, 1).getText().equals("(0, 0)")); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorRowClientTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorRowClientTest.java new file mode 100644 index 0000000000..4c64eac6e5 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorRowClientTest.java @@ -0,0 +1,154 @@ +/* + * 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.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.Keys; +import org.openqa.selenium.NoSuchElementException; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; + +import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures; + +public class GridEditorRowClientTest extends GridBasicClientFeaturesTest { + + @Before + public void setUp() { + openTestURL(); + selectMenuPath("Component", "Editor row", "Enabled"); + } + + @Test + public void testProgrammaticOpeningClosing() { + selectMenuPath("Component", "Editor row", "Edit row 5"); + assertNotNull(getEditorRow()); + + selectMenuPath("Component", "Editor row", "Cancel edit"); + assertNull(getEditorRow()); + assertEquals("Row 5 edit cancelled", + findElement(By.className("editor-row-log")).getText()); + } + + @Test + public void testProgrammaticOpeningWithScroll() { + selectMenuPath("Component", "Editor row", "Edit row 100"); + assertNotNull(getEditorRow()); + } + + @Test(expected = NoSuchElementException.class) + public void testVerticalScrollLocking() { + selectMenuPath("Component", "Editor row", "Edit row 5"); + getGridElement().getCell(200, 0); + } + + @Test + public void testKeyboardOpeningClosing() { + + getGridElement().getCell(4, 0).click(); + + new Actions(getDriver()).sendKeys(Keys.ENTER).perform(); + + assertNotNull(getEditorRow()); + + new Actions(getDriver()).sendKeys(Keys.ESCAPE).perform(); + assertNull(getEditorRow()); + assertEquals("Row 4 edit cancelled", + findElement(By.className("editor-row-log")).getText()); + + // Disable editor row + selectMenuPath("Component", "Editor row", "Enabled"); + + getGridElement().getCell(5, 0).click(); + new Actions(getDriver()).sendKeys(Keys.ENTER).perform(); + assertNull(getEditorRow()); + } + + @Test + public void testWidgetBinding() throws Exception { + selectMenuPath("Component", "Editor row", "Edit row 100"); + WebElement editorRow = getEditorRow(); + + List<WebElement> widgets = editorRow.findElements(By + .className("gwt-TextBox")); + + assertEquals(GridBasicFeatures.COLUMNS, widgets.size()); + + assertEquals("(100, 0)", widgets.get(0).getAttribute("value")); + assertEquals("(100, 1)", widgets.get(1).getAttribute("value")); + assertEquals("(100, 2)", widgets.get(2).getAttribute("value")); + + assertEquals("100", widgets.get(7).getAttribute("value")); + assertEquals("<b>100</b>", widgets.get(9).getAttribute("value")); + } + + @Test + public void testWithSelectionColumn() throws Exception { + selectMenuPath("Component", "State", "Selection mode", "multi"); + selectMenuPath("Component", "State", "Editor row", "Edit row 5"); + + WebElement editorRow = getEditorRow(); + List<WebElement> selectorDivs = editorRow.findElements(By + .cssSelector("div")); + + assertTrue("selector column cell should've been empty", selectorDivs + .get(0).getAttribute("innerHTML").isEmpty()); + assertFalse("normal column cell shoul've had contents", selectorDivs + .get(1).getAttribute("innerHTML").isEmpty()); + } + + @Test + public void testCommit() { + selectMenuPath("Component", "Editor row", "Edit row 100"); + + List<WebElement> widgets = getEditorRow().findElements( + By.className("gwt-TextBox")); + + widgets.get(0).sendKeys(" changed"); + + WebElement saveButton = getEditorRow().findElement( + By.className("v-editor-row-save")); + + saveButton.click(); + + assertEquals("(100, 0) changed", getGridElement().getCell(100, 0) + .getText()); + } + + @Test + public void testDiscard() { + selectMenuPath("Component", "Editor row", "Edit row 100"); + + List<WebElement> widgets = getEditorRow().findElements( + By.className("gwt-TextBox")); + + widgets.get(0).sendKeys(" changed"); + + selectMenuPath("Component", "Editor row", "Discard"); + + assertEquals("(100, 0)", getGridElement().getCell(100, 0).getText()); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorRowTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorRowTest.java new file mode 100644 index 0000000000..7ca3894060 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridEditorRowTest.java @@ -0,0 +1,119 @@ +/* + * 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.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.Keys; +import org.openqa.selenium.NoSuchElementException; +import org.openqa.selenium.WebElement; +import org.openqa.selenium.interactions.Actions; + +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest; + +public class GridEditorRowTest extends GridBasicFeaturesTest { + + @Before + public void setUp() { + openTestURL(); + selectMenuPath("Component", "Editor row", "Enabled"); + } + + @Test + public void testProgrammaticOpeningClosing() { + selectMenuPath("Component", "Editor row", "Edit item 5"); + assertNotNull(getEditorRow()); + + selectMenuPath("Component", "Editor row", "Cancel edit"); + assertNull(getEditorRow()); + } + + @Test + public void testProgrammaticOpeningWhenDisabled() { + selectMenuPath("Component", "Editor row", "Enabled"); + selectMenuPath("Component", "Editor row", "Edit item 5"); + assertNull(getEditorRow()); + assertEquals( + "4. Exception occured, java.lang.IllegalStateExceptionThis EditorRow is not enabled", + getLogRow(0)); + } + + @Test + public void testDisablingWhileOpen() { + selectMenuPath("Component", "Editor row", "Edit item 5"); + selectMenuPath("Component", "Editor row", "Enabled"); + assertNotNull(getEditorRow()); + assertEquals( + "4. Exception occured, java.lang.IllegalStateExceptionCannot disable the editor row while an item (5) is being edited.", + getLogRow(0)); + + } + + @Test + public void testProgrammaticOpeningWithScroll() { + selectMenuPath("Component", "Editor row", "Edit item 100"); + assertNotNull(getEditorRow()); + } + + @Test(expected = NoSuchElementException.class) + public void testVerticalScrollLocking() { + selectMenuPath("Component", "Editor row", "Edit item 5"); + getGridElement().getCell(200, 0); + } + + @Test + public void testKeyboardOpeningClosing() { + + getGridElement().getCell(4, 0).click(); + + new Actions(getDriver()).sendKeys(Keys.ENTER).perform(); + + assertNotNull(getEditorRow()); + + new Actions(getDriver()).sendKeys(Keys.ESCAPE).perform(); + assertNull(getEditorRow()); + + // Disable editor row + selectMenuPath("Component", "Editor row", "Enabled"); + + getGridElement().getCell(5, 0).click(); + new Actions(getDriver()).sendKeys(Keys.ENTER).perform(); + assertNull(getEditorRow()); + } + + @Test + public void testComponentBinding() { + selectMenuPath("Component", "State", "Editor row", "Edit item 100"); + + List<WebElement> widgets = getEditorRow().findElements( + By.className("v-widget")); + + assertEquals(GridBasicFeatures.COLUMNS, widgets.size()); + + assertEquals("(100, 0)", widgets.get(0).getAttribute("value")); + assertEquals("(100, 1)", widgets.get(1).getAttribute("value")); + assertEquals("(100, 2)", widgets.get(2).getAttribute("value")); + assertEquals("<b>100</b>", widgets.get(9).getAttribute("value")); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridFooterTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridFooterTest.java new file mode 100644 index 0000000000..8124e5361f --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridFooterTest.java @@ -0,0 +1,207 @@ +/* + * 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.assertTrue; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.tests.components.grid.GridElement.GridCellElement; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures; + +public class GridFooterTest extends GridStaticSectionTest { + + @Test + public void testDefaultFooter() { + openTestURL(); + + // Footer should have zero rows by default + assertFooterCount(0); + } + + @Test + public void testFooterVisibility() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Visible"); + + assertFooterCount(0); + + selectMenuPath("Component", "Footer", "Append row"); + + assertFooterCount(0); + + selectMenuPath("Component", "Footer", "Visible"); + + assertFooterCount(1); + } + + @Test + public void testAddRows() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Append row"); + + assertFooterCount(1); + assertFooterTexts(0, 0); + + selectMenuPath("Component", "Footer", "Prepend row"); + + assertFooterCount(2); + assertFooterTexts(1, 0); + assertFooterTexts(0, 1); + + selectMenuPath("Component", "Footer", "Append row"); + + assertFooterCount(3); + assertFooterTexts(1, 0); + assertFooterTexts(0, 1); + assertFooterTexts(2, 2); + } + + @Test + public void testRemoveRows() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Prepend row"); + selectMenuPath("Component", "Footer", "Append row"); + + selectMenuPath("Component", "Footer", "Remove top row"); + + assertFooterCount(1); + assertFooterTexts(1, 0); + + selectMenuPath("Component", "Footer", "Remove bottom row"); + assertFooterCount(0); + } + + @Test + public void joinColumnsByCells() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Append row"); + + selectMenuPath("Component", "Footer", "Row 1", "Join column cells 0, 1"); + + GridCellElement spannedCell = getGridElement().getFooterCell(0, 0); + assertTrue(spannedCell.isDisplayed()); + assertEquals("2", spannedCell.getAttribute("colspan")); + + GridCellElement hiddenCell = getGridElement().getFooterCell(0, 1); + assertFalse(hiddenCell.isDisplayed()); + } + + @Test + public void joinColumnsByColumns() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Append row"); + + selectMenuPath("Component", "Footer", "Row 1", "Join columns 1, 2"); + + GridCellElement spannedCell = getGridElement().getFooterCell(0, 1); + assertTrue(spannedCell.isDisplayed()); + assertEquals("2", spannedCell.getAttribute("colspan")); + + GridCellElement hiddenCell = getGridElement().getFooterCell(0, 2); + assertFalse(hiddenCell.isDisplayed()); + } + + @Test + public void joinAllColumnsInRow() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Append row"); + + selectMenuPath("Component", "Footer", "Row 1", "Join all columns"); + + GridCellElement spannedCell = getGridElement().getFooterCell(0, 0); + assertTrue(spannedCell.isDisplayed()); + assertEquals("" + GridBasicFeatures.COLUMNS, + spannedCell.getAttribute("colspan")); + + for (int columnIndex = 1; columnIndex < GridBasicFeatures.COLUMNS; columnIndex++) { + GridCellElement hiddenCell = getGridElement().getFooterCell(0, + columnIndex); + assertFalse(hiddenCell.isDisplayed()); + } + } + + @Test + public void testInitialCellTypes() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Append row"); + + GridCellElement textCell = getGridElement().getFooterCell(0, 0); + assertEquals("Footer (0,0)", textCell.getText()); + + GridCellElement widgetCell = getGridElement().getFooterCell(0, 1); + assertTrue(widgetCell.isElementPresent(By.className("gwt-HTML"))); + + GridCellElement htmlCell = getGridElement().getFooterCell(0, 2); + assertHTML("<b>Footer (0,2)</b>", htmlCell); + } + + @Test + public void testDynamicallyChangingCellType() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Append row"); + + selectMenuPath("Component", "Columns", "Column 0", "Footer Type", + "Widget Footer"); + GridCellElement widgetCell = getGridElement().getFooterCell(0, 0); + assertTrue(widgetCell.isElementPresent(By.className("gwt-Button"))); + + selectMenuPath("Component", "Columns", "Column 1", "Footer Type", + "HTML Footer"); + GridCellElement htmlCell = getGridElement().getFooterCell(0, 1); + assertHTML("<b>HTML Footer</b>", htmlCell); + + selectMenuPath("Component", "Columns", "Column 2", "Footer Type", + "Text Footer"); + GridCellElement textCell = getGridElement().getFooterCell(0, 2); + assertEquals("Text Footer", textCell.getText()); + } + + @Test + public void testCellWidgetInteraction() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Footer", "Append row"); + + selectMenuPath("Component", "Columns", "Column 0", "Footer Type", + "Widget Footer"); + GridCellElement widgetCell = getGridElement().getFooterCell(0, 0); + WebElement button = widgetCell.findElement(By.className("gwt-Button")); + + assertNotEquals("Clicked", button.getText()); + + button.click(); + + assertEquals("Clicked", button.getText()); + } + + private void assertFooterCount(int count) { + assertEquals("footer count", count, getGridElement().getFooterCount()); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridHeaderTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridHeaderTest.java new file mode 100644 index 0000000000..c528571a2e --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridHeaderTest.java @@ -0,0 +1,359 @@ +/* + * 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.assertTrue; + +import java.util.Arrays; +import java.util.List; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.TestBenchElement; +import com.vaadin.tests.components.grid.GridElement.GridCellElement; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures; + +public class GridHeaderTest extends GridStaticSectionTest { + + @Test + public void testDefaultHeader() throws Exception { + openTestURL(); + + assertHeaderCount(1); + assertHeaderTexts(0, 0); + } + + @Test + public void testHeaderVisibility() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Header", "Visible"); + + assertHeaderCount(0); + + selectMenuPath("Component", "Header", "Append row"); + + assertHeaderCount(0); + + selectMenuPath("Component", "Header", "Visible"); + + assertHeaderCount(2); + } + + @Test + public void testHeaderCaptions() throws Exception { + openTestURL(); + + assertHeaderTexts(0, 0); + } + + @Test + public void testHeadersWithInvisibleColumns() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Columns", "Column 1", "Visible"); + selectMenuPath("Component", "Columns", "Column 3", "Visible"); + + List<TestBenchElement> cells = getGridHeaderRowCells(); + assertEquals(GridBasicFeatures.COLUMNS - 2, cells.size()); + + assertText("Header (0,0)", cells.get(0)); + assertHTML("<b>Header (0,2)</b>", cells.get(1)); + assertHTML("<b>Header (0,4)</b>", cells.get(2)); + + selectMenuPath("Component", "Columns", "Column 3", "Visible"); + + cells = getGridHeaderRowCells(); + assertEquals(GridBasicFeatures.COLUMNS - 1, cells.size()); + + assertText("Header (0,0)", cells.get(0)); + assertHTML("<b>Header (0,2)</b>", cells.get(1)); + assertText("Header (0,3)", cells.get(2)); + assertHTML("<b>Header (0,4)</b>", cells.get(3)); + } + + @Test + public void testAddRows() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Header", "Append row"); + + assertHeaderCount(2); + assertHeaderTexts(0, 0); + assertHeaderTexts(1, 1); + + selectMenuPath("Component", "Header", "Prepend row"); + + assertHeaderCount(3); + assertHeaderTexts(2, 0); + assertHeaderTexts(0, 1); + assertHeaderTexts(1, 2); + + selectMenuPath("Component", "Header", "Append row"); + + assertHeaderCount(4); + assertHeaderTexts(2, 0); + assertHeaderTexts(0, 1); + assertHeaderTexts(1, 2); + assertHeaderTexts(3, 3); + } + + @Test + public void testRemoveRows() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Header", "Prepend row"); + selectMenuPath("Component", "Header", "Append row"); + + selectMenuPath("Component", "Header", "Remove top row"); + + assertHeaderCount(2); + assertHeaderTexts(0, 0); + assertHeaderTexts(2, 1); + + selectMenuPath("Component", "Header", "Remove bottom row"); + assertHeaderCount(1); + assertHeaderTexts(0, 0); + } + + @Test + public void testDefaultRow() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Columns", "Column 0", "Sortable"); + + GridCellElement headerCell = getGridElement().getHeaderCell(0, 0); + + headerCell.click(); + + assertTrue(hasClassName(headerCell, "sort-asc")); + + headerCell.click(); + + assertFalse(hasClassName(headerCell, "sort-asc")); + assertTrue(hasClassName(headerCell, "sort-desc")); + + selectMenuPath("Component", "Header", "Prepend row"); + selectMenuPath("Component", "Header", "Default row", "Top"); + + assertFalse(hasClassName(headerCell, "sort-desc")); + headerCell = getGridElement().getHeaderCell(0, 0); + assertTrue(hasClassName(headerCell, "sort-desc")); + + selectMenuPath("Component", "Header", "Default row", "Unset"); + + assertFalse(hasClassName(headerCell, "sort-desc")); + } + + @Test + public void joinHeaderColumnsByCells() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Header", "Append row"); + + selectMenuPath("Component", "Header", "Row 2", "Join column cells 0, 1"); + + GridCellElement spannedCell = getGridElement().getHeaderCell(1, 0); + assertTrue(spannedCell.isDisplayed()); + assertEquals("2", spannedCell.getAttribute("colspan")); + + GridCellElement hiddenCell = getGridElement().getHeaderCell(1, 1); + assertFalse(hiddenCell.isDisplayed()); + } + + @Test + public void joinHeaderColumnsByColumns() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Header", "Append row"); + + selectMenuPath("Component", "Header", "Row 2", "Join columns 1, 2"); + + GridCellElement spannedCell = getGridElement().getHeaderCell(1, 1); + assertTrue(spannedCell.isDisplayed()); + assertEquals("2", spannedCell.getAttribute("colspan")); + + GridCellElement hiddenCell = getGridElement().getHeaderCell(1, 2); + assertFalse(hiddenCell.isDisplayed()); + } + + @Test + public void joinAllColumnsInHeaderRow() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Header", "Append row"); + + selectMenuPath("Component", "Header", "Row 2", "Join all columns"); + + GridCellElement spannedCell = getGridElement().getHeaderCell(1, 0); + assertTrue(spannedCell.isDisplayed()); + assertEquals("" + GridBasicFeatures.COLUMNS, + spannedCell.getAttribute("colspan")); + + for (int columnIndex = 1; columnIndex < GridBasicFeatures.COLUMNS; columnIndex++) { + GridCellElement hiddenCell = getGridElement().getHeaderCell(1, + columnIndex); + assertFalse(hiddenCell.isDisplayed()); + } + } + + @Test + public void hideFirstColumnInColspan() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Header", "Append row"); + + selectMenuPath("Component", "Header", "Row 2", "Join all columns"); + + int visibleColumns = GridBasicFeatures.COLUMNS; + + GridCellElement spannedCell = getGridElement().getHeaderCell(1, 0); + assertTrue(spannedCell.isDisplayed()); + assertEquals("" + visibleColumns, spannedCell.getAttribute("colspan")); + + selectMenuPath("Component", "Columns", "Column 0", "Visible"); + visibleColumns--; + + spannedCell = getGridElement().getHeaderCell(1, 0); + assertTrue(spannedCell.isDisplayed()); + assertEquals("" + visibleColumns, spannedCell.getAttribute("colspan")); + } + + @Test + public void multipleColspanAndMultipleHiddenColumns() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Header", "Append row"); + + // Join columns [1,2] and [3,4,5] + selectMenuPath("Component", "Header", "Row 2", "Join columns 1, 2"); + GridCellElement spannedCell = getGridElement().getHeaderCell(1, 1); + assertEquals("2", spannedCell.getAttribute("colspan")); + + selectMenuPath("Component", "Header", "Row 2", "Join columns 3, 4, 5"); + spannedCell = getGridElement().getHeaderCell(1, 3); + assertEquals("3", spannedCell.getAttribute("colspan")); + + selectMenuPath("Component", "Columns", "Column 2", "Visible"); + spannedCell = getGridElement().getHeaderCell(1, 1); + assertEquals("1", spannedCell.getAttribute("colspan")); + + // Ensure the second colspan is preserved (shifts one index to the left) + spannedCell = getGridElement().getHeaderCell(1, 2); + assertEquals("3", spannedCell.getAttribute("colspan")); + + selectMenuPath("Component", "Columns", "Column 4", "Visible"); + + // First reduced colspan is reduced + spannedCell = getGridElement().getHeaderCell(1, 1); + assertEquals("1", spannedCell.getAttribute("colspan")); + + // Second colspan is also now reduced + spannedCell = getGridElement().getHeaderCell(1, 2); + assertEquals("2", spannedCell.getAttribute("colspan")); + + // Show columns again + selectMenuPath("Component", "Columns", "Column 2", "Visible"); + selectMenuPath("Component", "Columns", "Column 4", "Visible"); + + spannedCell = getGridElement().getHeaderCell(1, 1); + assertEquals("2", spannedCell.getAttribute("colspan")); + spannedCell = getGridElement().getHeaderCell(1, 3); + assertEquals("3", spannedCell.getAttribute("colspan")); + + } + + @Test + public void testInitialCellTypes() throws Exception { + openTestURL(); + + GridCellElement textCell = getGridElement().getHeaderCell(0, 0); + assertEquals("Header (0,0)", textCell.getText()); + + GridCellElement widgetCell = getGridElement().getHeaderCell(0, 1); + assertTrue(widgetCell.isElementPresent(By.className("gwt-HTML"))); + + GridCellElement htmlCell = getGridElement().getHeaderCell(0, 2); + assertHTML("<b>Header (0,2)</b>", htmlCell); + } + + @Test + public void testDynamicallyChangingCellType() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Columns", "Column 0", "Header Type", + "Widget Header"); + GridCellElement widgetCell = getGridElement().getHeaderCell(0, 0); + assertTrue(widgetCell.isElementPresent(By.className("gwt-Button"))); + + selectMenuPath("Component", "Columns", "Column 1", "Header Type", + "HTML Header"); + GridCellElement htmlCell = getGridElement().getHeaderCell(0, 1); + assertHTML("<b>HTML Header</b>", htmlCell); + + selectMenuPath("Component", "Columns", "Column 2", "Header Type", + "Text Header"); + GridCellElement textCell = getGridElement().getHeaderCell(0, 2); + assertEquals("Text Header", textCell.getText()); + } + + @Test + public void testCellWidgetInteraction() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Columns", "Column 0", "Header Type", + "Widget Header"); + GridCellElement widgetCell = getGridElement().getHeaderCell(0, 0); + WebElement button = widgetCell.findElement(By.className("gwt-Button")); + + button.click(); + + assertEquals("Clicked", button.getText()); + } + + @Test + public void widgetInSortableCellInteraction() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Columns", "Column 0", "Header Type", + "Widget Header"); + + selectMenuPath("Component", "Columns", "Column 0", "Sortable"); + + GridCellElement widgetCell = getGridElement().getHeaderCell(0, 0); + WebElement button = widgetCell.findElement(By.className("gwt-Button")); + + assertNotEquals("Clicked", button.getText()); + + button.click(); + + assertEquals("Clicked", button.getText()); + } + + private void assertHeaderCount(int count) { + assertEquals("header count", count, getGridElement().getHeaderCount()); + } + + private boolean hasClassName(TestBenchElement element, String name) { + return Arrays.asList(element.getAttribute("class").split(" ")) + .contains(name); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStaticSectionTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStaticSectionTest.java new file mode 100644 index 0000000000..cc801bf870 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStaticSectionTest.java @@ -0,0 +1,90 @@ +/* + * 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 com.vaadin.testbench.TestBenchElement; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures; + +/** + * Abstract base class for header and footer tests. + * + * @since + * @author Vaadin Ltd + */ +public abstract class GridStaticSectionTest extends GridBasicClientFeaturesTest { + + protected void assertHeaderTexts(int headerId, int rowIndex) { + int i = 0; + for (TestBenchElement cell : getGridElement().getHeaderCells(rowIndex)) { + + if (i % 3 == 0) { + assertText(String.format("Header (%d,%d)", headerId, i), cell); + } else if (i % 2 == 0) { + assertHTML(String.format("<b>Header (%d,%d)</b>", headerId, i), + cell); + } else { + assertHTML(String.format( + "<div class=\"gwt-HTML\">Header (%d,%d)</div>", + headerId, i), cell); + } + + i++; + } + assertEquals("number of header columns", GridBasicFeatures.COLUMNS, i); + } + + protected void assertFooterTexts(int footerId, int rowIndex) { + int i = 0; + for (TestBenchElement cell : getGridElement().getFooterCells(rowIndex)) { + if (i % 3 == 0) { + assertText(String.format("Footer (%d,%d)", footerId, i), cell); + } else if (i % 2 == 0) { + assertHTML(String.format("<b>Footer (%d,%d)</b>", footerId, i), + cell); + } else { + assertHTML(String.format( + "<div class=\"gwt-HTML\">Footer (%d,%d)</div>", + footerId, i), cell); + } + i++; + } + assertEquals("number of footer columns", GridBasicFeatures.COLUMNS, i); + } + + protected static void assertText(String text, TestBenchElement e) { + // TBE.getText returns "" if the element is scrolled out of view + assertEquals(text, e.getAttribute("innerHTML")); + } + + protected static void assertHTML(String text, TestBenchElement e) { + String html = e.getAttribute("innerHTML"); + + // IE 8 returns tags as upper case while other browsers do not, make the + // comparison non-casesensive + html = html.toLowerCase(); + text = text.toLowerCase(); + + // IE 8 returns attributes without quotes, make the comparison without + // quotes + html = html.replaceAll("\"", ""); + text = html.replaceAll("\"", ""); + + assertEquals(text, html); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStylingTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStylingTest.java new file mode 100644 index 0000000000..67e974bd0a --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridStylingTest.java @@ -0,0 +1,119 @@ +/* + * 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.assertTrue; + +import org.junit.Test; + +import com.vaadin.testbench.By; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures; + +public class GridStylingTest extends GridStaticSectionTest { + + @Test + public void testGridPrimaryStyle() throws Exception { + openTestURL(); + + validateStylenames("v-grid"); + } + + @Test + public void testChangingPrimaryStyleName() throws Exception { + openTestURL(); + + selectMenuPath("Component", "State", "Primary Stylename", + "v-custom-style"); + + validateStylenames("v-custom-style"); + } + + private void validateStylenames(String stylename) { + + String classNames = getGridElement().getAttribute("class"); + assertEquals(stylename, classNames); + + classNames = getGridElement().getVerticalScroller().getAttribute( + "class"); + assertTrue(classNames.contains(stylename + "-scroller")); + assertTrue(classNames.contains(stylename + "-scroller-vertical")); + + classNames = getGridElement().getHorizontalScroller().getAttribute( + "class"); + assertTrue(classNames.contains(stylename + "-scroller")); + assertTrue(classNames.contains(stylename + "-scroller-horizontal")); + + classNames = getGridElement().getTableWrapper().getAttribute("class"); + assertEquals(stylename + "-tablewrapper", classNames); + + classNames = getGridElement().getHeader().getAttribute("class"); + assertEquals(stylename + "-header", classNames); + + for (int row = 0; row < getGridElement().getHeaderCount(); row++) { + classNames = getGridElement().getHeaderRow(row).getAttribute( + "class"); + assertEquals(stylename + "-row", classNames); + + for (int col = 0; col < GridBasicFeatures.COLUMNS; col++) { + classNames = getGridElement().getHeaderCell(row, col) + .getAttribute("class"); + assertTrue(classNames.contains(stylename + "-cell")); + + if (row == 0 && col == 0) { + assertTrue(classNames, + classNames.contains(stylename + "-header-active")); + } + } + } + + classNames = getGridElement().getBody().getAttribute("class"); + assertEquals(stylename + "-body", classNames); + + int rowsInBody = getGridElement().getBody() + .findElements(By.tagName("tr")).size(); + for (int row = 0; row < rowsInBody; row++) { + classNames = getGridElement().getRow(row).getAttribute("class"); + assertTrue(classNames.contains(stylename + "-row")); + assertTrue(classNames.contains(stylename + "-row-has-data")); + + for (int col = 0; col < GridBasicFeatures.COLUMNS; col++) { + classNames = getGridElement().getCell(row, col).getAttribute( + "class"); + assertTrue(classNames.contains(stylename + "-cell")); + + if (row == 0 && col == 0) { + assertTrue(classNames.contains(stylename + "-cell-active")); + } + } + } + + classNames = getGridElement().getFooter().getAttribute("class"); + assertEquals(stylename + "-footer", classNames); + + for (int row = 0; row < getGridElement().getFooterCount(); row++) { + classNames = getGridElement().getFooterRow(row).getAttribute( + "class"); + assertEquals(stylename + "-row", classNames); + + for (int col = 0; col < GridBasicFeatures.COLUMNS; col++) { + classNames = getGridElement().getFooterCell(row, col) + .getAttribute("class"); + assertTrue(classNames.contains(stylename + "-cell")); + } + } + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridActiveCellAdjustmentTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridActiveCellAdjustmentTest.java new file mode 100644 index 0000000000..4fef839d2b --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridActiveCellAdjustmentTest.java @@ -0,0 +1,49 @@ +/* + * 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.assertTrue; + +import org.junit.Test; + +import com.vaadin.tests.components.grid.GridElement; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest; + +public class GridActiveCellAdjustmentTest extends GridBasicFeaturesTest { + + @Test + public void testActiveCellWithAddAndRemoveRows() { + openTestURL(); + GridElement grid = getGridElement(); + + grid.getCell(0, 0).click(); + + selectMenuPath("Component", "Body rows", "Add first row"); + assertTrue("Active cell was not moved when adding a row", + grid.getCell(1, 0).isActive()); + + selectMenuPath("Component", "Body rows", "Add 18 rows"); + assertTrue("Active cell was not moved when adding multiple rows", grid + .getCell(19, 0).isActive()); + + for (int i = 18; i <= 0; --i) { + selectMenuPath("Component", "Body rows", "Remove first row"); + assertTrue("Active cell was not moved when removing a row", grid + .getCell(i, 0).isActive()); + } + } + +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridKeyboardNavigationTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridKeyboardNavigationTest.java new file mode 100644 index 0000000000..0f9fd875d8 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridKeyboardNavigationTest.java @@ -0,0 +1,225 @@ +/* + * 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 org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.Keys; +import org.openqa.selenium.interactions.Actions; + +import com.vaadin.tests.components.grid.GridElement; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest; + +public class GridKeyboardNavigationTest extends GridBasicFeaturesTest { + + @Test + public void testCellActiveOnClick() { + openTestURL(); + + GridElement grid = getGridElement(); + assertTrue("Body cell 0, 0 is not active on init.", grid.getCell(0, 0) + .isActive()); + grid.getCell(5, 2).click(); + assertFalse("Body cell 0, 0 was still active after clicking", grid + .getCell(0, 0).isActive()); + assertTrue("Body cell 5, 2 is not active after clicking", + grid.getCell(5, 2).isActive()); + } + + @Test + public void testCellNotActiveWhenRendererHandlesEvent() { + openTestURL(); + + GridElement grid = getGridElement(); + assertTrue("Body cell 0, 0 is not active on init.", grid.getCell(0, 0) + .isActive()); + grid.getHeaderCell(0, 3).click(); + assertFalse("Body cell 0, 0 is active after click on header.", grid + .getCell(0, 0).isActive()); + assertTrue("Header cell 0, 3 is not active after click on header.", + grid.getHeaderCell(0, 3).isActive()); + } + + @Test + public void testSimpleKeyboardNavigation() { + openTestURL(); + + GridElement grid = getGridElement(); + grid.getCell(0, 0).click(); + + new Actions(getDriver()).sendKeys(Keys.ARROW_DOWN).perform(); + assertTrue("Body cell 1, 0 is not active after keyboard navigation.", + grid.getCell(1, 0).isActive()); + + new Actions(getDriver()).sendKeys(Keys.ARROW_RIGHT).perform(); + assertTrue("Body cell 1, 1 is not active after keyboard navigation.", + grid.getCell(1, 1).isActive()); + + int i; + for (i = 1; i < 40; ++i) { + new Actions(getDriver()).sendKeys(Keys.ARROW_DOWN).perform(); + } + + assertFalse("Grid has not scrolled with active cell", + isElementPresent(By.xpath("//td[text() = '(0, 0)']"))); + assertTrue("Active cell is not visible", + isElementPresent(By.xpath("//td[text() = '(" + i + ", 0)']"))); + assertTrue("Body cell " + i + ", 1 is not active", grid.getCell(i, 1) + .isActive()); + } + + @Test + public void testNavigateFromHeaderToBody() { + openTestURL(); + + GridElement grid = getGridElement(); + grid.scrollToRow(300); + new Actions(driver).moveToElement(grid.getHeaderCell(0, 7)).click() + .perform(); + grid.scrollToRow(280); + + assertTrue("Header cell is not active.", grid.getHeaderCell(0, 7) + .isActive()); + new Actions(getDriver()).sendKeys(Keys.ARROW_DOWN).perform(); + assertTrue("Body cell 280, 7 is not active", grid.getCell(280, 7) + .isActive()); + } + + @Test + public void testNavigationFromFooterToBody() { + openTestURL(); + + selectMenuPath("Component", "Footer", "Visible"); + + GridElement grid = getGridElement(); + grid.scrollToRow(300); + grid.getFooterCell(0, 2).click(); + + assertTrue("Footer cell is not active.", grid.getFooterCell(0, 2) + .isActive()); + new Actions(getDriver()).sendKeys(Keys.ARROW_UP).perform(); + assertTrue("Body cell 300, 2 is not active", grid.getCell(300, 2) + .isActive()); + } + + @Test + public void testNavigateBetweenHeaderAndBodyWithTab() { + openTestURL(); + + GridElement grid = getGridElement(); + grid.getCell(10, 2).click(); + + assertTrue("Body cell 10, 2 is not active", grid.getCell(10, 2) + .isActive()); + new Actions(getDriver()).keyDown(Keys.SHIFT).sendKeys(Keys.TAB) + .keyUp(Keys.SHIFT).perform(); + assertTrue("Header cell 0, 2 is not active", grid.getHeaderCell(0, 2) + .isActive()); + new Actions(getDriver()).sendKeys(Keys.TAB).perform(); + assertTrue("Body cell 10, 2 is not active", grid.getCell(10, 2) + .isActive()); + + // Navigate out of the Grid and try to navigate with arrow keys. + new Actions(getDriver()).keyDown(Keys.SHIFT).sendKeys(Keys.TAB) + .sendKeys(Keys.TAB).keyUp(Keys.SHIFT).sendKeys(Keys.ARROW_DOWN) + .perform(); + assertTrue("Header cell 0, 2 is not active", grid.getHeaderCell(0, 2) + .isActive()); + } + + @Test + public void testNavigateBetweenFooterAndBodyWithTab() { + openTestURL(); + + selectMenuPath("Component", "Footer", "Visible"); + + GridElement grid = getGridElement(); + grid.getCell(10, 2).click(); + + assertTrue("Body cell 10, 2 is not active", grid.getCell(10, 2) + .isActive()); + new Actions(getDriver()).sendKeys(Keys.TAB).perform(); + assertTrue("Footer cell 0, 2 is not active", grid.getFooterCell(0, 2) + .isActive()); + new Actions(getDriver()).keyDown(Keys.SHIFT).sendKeys(Keys.TAB) + .keyUp(Keys.SHIFT).perform(); + assertTrue("Body cell 10, 2 is not active", grid.getCell(10, 2) + .isActive()); + + // Navigate out of the Grid and try to navigate with arrow keys. + new Actions(getDriver()).sendKeys(Keys.TAB).sendKeys(Keys.TAB) + .sendKeys(Keys.ARROW_UP).perform(); + assertTrue("Footer cell 0, 2 is not active", grid.getFooterCell(0, 2) + .isActive()); + } + + @Test + public void testHomeEnd() throws Exception { + openTestURL(); + + getGridElement().getCell(100, 2).click(); + + new Actions(getDriver()).sendKeys(Keys.HOME).perform(); + assertTrue("First row is not visible", getGridElement().getCell(0, 2) + .isDisplayed()); + + new Actions(getDriver()).sendKeys(Keys.END).perform(); + assertTrue("Last row cell not visible", + getGridElement().getCell(GridBasicFeatures.ROWS - 1, 2) + .isDisplayed()); + } + + @Test + public void testPageUpPageDown() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Size", "HeightMode Row"); + + getGridElement().getCell(5, 2).click(); + + new Actions(getDriver()).sendKeys(Keys.PAGE_DOWN).perform(); + assertTrue("Row 5 did not remain active", getGridElement() + .getCell(5, 2).isActive()); + assertTrue("Row 20 did not become visible", + getGridElement().getCell(20, 2).isDisplayed()); + + new Actions(getDriver()).sendKeys(Keys.PAGE_DOWN).perform(); + assertTrue("Row 5 did not remain active", getGridElement() + .getCell(5, 2).isActive()); + assertTrue("Row 40 did not become visible", + getGridElement().getCell(40, 2).isDisplayed()); + + getGridElement().getCell(50, 2).click(); + + new Actions(getDriver()).sendKeys(Keys.PAGE_UP).perform(); + assertTrue("Row 50 did not remain active", + getGridElement().getCell(50, 2).isActive()); + assertTrue("Row 20 did not become visible", + getGridElement().getCell(20, 2).isDisplayed()); + + new Actions(getDriver()).sendKeys(Keys.PAGE_UP).perform(); + assertTrue("Row 50 did not remain active", + getGridElement().getCell(50, 2).isActive()); + assertTrue("Row 0 did not become visible", + getGridElement().getCell(0, 2).isDisplayed()); + + } + +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java new file mode 100644 index 0000000000..6e2ac91df2 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSelectionTest.java @@ -0,0 +1,179 @@ +/* + * 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 org.junit.Test; +import org.openqa.selenium.Keys; +import org.openqa.selenium.interactions.Actions; + +import com.vaadin.testbench.TestBenchElement; +import com.vaadin.tests.components.grid.GridElement; +import com.vaadin.tests.components.grid.GridElement.GridRowElement; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest; + +public class GridSelectionTest extends GridBasicFeaturesTest { + + @Test + public void testSelectOnOff() throws Exception { + openTestURL(); + + setSelectionModelMulti(); + + assertFalse("row shouldn't start out as selected", getRow(0) + .isSelected()); + toggleFirstRowSelection(); + assertTrue("row should become selected", getRow(0).isSelected()); + toggleFirstRowSelection(); + assertFalse("row shouldn't remain selected", getRow(0).isSelected()); + } + + @Test + public void testSelectOnScrollOffScroll() throws Exception { + openTestURL(); + + setSelectionModelMulti(); + + assertFalse("row shouldn't start out as selected", getRow(0) + .isSelected()); + toggleFirstRowSelection(); + assertTrue("row should become selected", getRow(0).isSelected()); + + scrollGridVerticallyTo(10000); // make sure the row is out of cache + scrollGridVerticallyTo(0); // scroll it back into view + + assertTrue("row should still be selected when scrolling " + + "back into view", getRow(0).isSelected()); + } + + @Test + public void testSelectScrollOnScrollOff() throws Exception { + openTestURL(); + + setSelectionModelMulti(); + + assertFalse("row shouldn't start out as selected", getRow(0) + .isSelected()); + + scrollGridVerticallyTo(10000); // make sure the row is out of cache + toggleFirstRowSelection(); + + scrollGridVerticallyTo(0); // scroll it back into view + assertTrue("row should still be selected when scrolling " + + "back into view", getRow(0).isSelected()); + + toggleFirstRowSelection(); + assertFalse("row shouldn't remain selected", getRow(0).isSelected()); + } + + @Test + public void testSelectScrollOnOffScroll() throws Exception { + openTestURL(); + + setSelectionModelMulti(); + + assertFalse("row shouldn't start out as selected", getRow(0) + .isSelected()); + + scrollGridVerticallyTo(10000); // make sure the row is out of cache + toggleFirstRowSelection(); + toggleFirstRowSelection(); + + scrollGridVerticallyTo(0); // make sure the row is out of cache + assertFalse("row shouldn't be selected when scrolling " + + "back into view", getRow(0).isSelected()); + } + + @Test + public void testSingleSelectionUpdatesFromServer() { + openTestURL(); + setSelectionModelSingle(); + + GridElement grid = getGridElement(); + assertFalse("First row was selected from start", grid.getRow(0) + .isSelected()); + toggleFirstRowSelection(); + assertTrue("First row was not selected.", getRow(0).isSelected()); + grid.getCell(5, 0).click(); + assertTrue("Fifth row was not selected.", getRow(5).isSelected()); + assertFalse("First row was still selected.", getRow(0).isSelected()); + grid.getCell(0, 0).click(); + toggleFirstRowSelection(); + assertFalse("First row was still selected.", getRow(0).isSelected()); + assertFalse("Fifth row was still selected.", getRow(5).isSelected()); + + grid.scrollToRow(600); + grid.getCell(595, 0).click(); + assertTrue("Row 595 was not selected.", getRow(595).isSelected()); + toggleFirstRowSelection(); + assertFalse("Row 595 was still selected.", getRow(595).isSelected()); + assertTrue("First row was not selected.", getRow(0).isSelected()); + } + + @Test + public void testKeyboardSelection() { + openTestURL(); + setSelectionModelMulti(); + + GridElement grid = getGridElement(); + grid.getCell(3, 1).click(); + new Actions(getDriver()).sendKeys(Keys.SPACE).perform(); + + assertTrue("Grid row 3 was not selected with space key.", grid + .getRow(3).isSelected()); + + new Actions(getDriver()).sendKeys(Keys.SPACE).perform(); + + assertTrue("Grid row 3 was not deselected with space key.", !grid + .getRow(3).isSelected()); + + grid.scrollToRow(500); + + new Actions(getDriver()).sendKeys(Keys.SPACE).perform(); + + assertTrue("Grid row 3 was not selected with space key.", grid + .getRow(3).isSelected()); + + } + + private void setSelectionModelMulti() { + selectMenuPath("Component", "State", "Selection mode", "multi"); + } + + private void setSelectionModelSingle() { + selectMenuPath("Component", "State", "Selection mode", "single"); + } + + @SuppressWarnings("static-method") + private boolean isSelected(TestBenchElement row) { + /* + * FIXME We probably should get a GridRow instead of a plain + * TestBenchElement, that has an "isSelected" thing integrated. (henrik + * paul 26.6.2014) + */ + return row.getAttribute("class").contains("-row-selected"); + } + + private void toggleFirstRowSelection() { + selectMenuPath("Component", "Body rows", "Select first row"); + } + + private GridRowElement getRow(int i) { + return getGridElement().getRow(i); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSortingTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSortingTest.java new file mode 100644 index 0000000000..acc5bfe51a --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSortingTest.java @@ -0,0 +1,273 @@ +/* + * 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.assertTrue; + +import java.io.IOException; + +import org.junit.Test; +import org.openqa.selenium.Keys; +import org.openqa.selenium.interactions.Actions; + +import com.vaadin.tests.components.grid.GridElement; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeatures; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest; + +public class GridSortingTest extends GridBasicFeaturesTest { + + @Test + public void testProgrammaticSorting() throws IOException { + openTestURL(); + + GridElement grid = getGridElement(); + + // Sorting by column 9 is sorting by row index that is represented as a + // String. + // First cells for first 3 rows are (9, 0), (99, 0) and (999, 0) + sortBy("Column 9, DESC"); + + // Verify that programmatic sorting calls are identified as originating + // from API + assertEquals("3. Sort order: [Column 9 DESCENDING] by API", + getLogRow(0)); + + assertTrue("Column 9 should have the sort-desc stylename", grid + .getHeaderCell(0, 9).getAttribute("class") + .contains("sort-desc")); + + String row = ""; + for (int i = 0; i < 3; ++i) { + row += "9"; + assertEquals( + "Grid is not sorted by Column 9 using descending direction.", + "(" + row + ", 0)", grid.getCell(i, 0).getText()); + } + + // Column 10 is random numbers from Random with seed 13334 + sortBy("Column 10, ASC"); + + assertFalse( + "Column 9 should no longer have the sort-desc stylename", + grid.getHeaderCell(0, 9).getAttribute("class") + .contains("sort-desc")); + assertTrue("Column 10 should have the sort-asc stylename", grid + .getHeaderCell(0, 10).getAttribute("class") + .contains("sort-asc")); + + // Not cleaning up correctly causes exceptions when scrolling. + grid.scrollToRow(50); + assertFalse("Scrolling caused and exception when shuffled.", + getLogRow(0).contains("Exception")); + + for (int i = 0; i < 5; ++i) { + assertGreater( + "Grid is not sorted by Column 10 using ascending direction", + Integer.parseInt(grid.getCell(i + 1, 10).getText()), + Integer.parseInt(grid.getCell(i, 10).getText())); + + } + + // Column 7 is row index as a number. Last three row are original rows + // 2, 1 and 0. + sortBy("Column 7, DESC"); + for (int i = 0; i < 3; ++i) { + assertEquals( + "Grid is not sorted by Column 7 using descending direction", + "(" + i + ", 0)", + grid.getCell(GridBasicFeatures.ROWS - (i + 1), 0).getText()); + } + + assertFalse( + "Column 10 should no longer have the sort-asc stylename", + grid.getHeaderCell(0, 10).getAttribute("class") + .contains("sort-asc")); + assertTrue("Column 7 should have the sort-desc stylename", grid + .getHeaderCell(0, 7).getAttribute("class") + .contains("sort-desc")); + + } + + @Test + public void testUserSorting() throws InterruptedException { + openTestURL(); + + GridElement grid = getGridElement(); + + // Sorting by column 9 is sorting by row index that is represented as a + // String. + // First cells for first 3 rows are (9, 0), (99, 0) and (999, 0) + + // Click header twice to sort descending + grid.getHeaderCell(0, 9).click(); + grid.getHeaderCell(0, 9).click(); + String row = ""; + for (int i = 0; i < 3; ++i) { + row += "9"; + assertEquals( + "Grid is not sorted by Column 9 using descending direction.", + "(" + row + ", 0)", grid.getCell(i, 0).getText()); + } + + assertEquals("2. Sort order: [Column 9 ASCENDING] by USER", + getLogRow(2)); + assertEquals("4. Sort order: [Column 9 DESCENDING] by USER", + getLogRow(0)); + + // Column 10 is random numbers from Random with seed 13334 + // Click header to sort ascending + grid.getHeaderCell(0, 10).click(); + + assertEquals("6. Sort order: [Column 10 ASCENDING] by USER", + getLogRow(0)); + + // Not cleaning up correctly causes exceptions when scrolling. + grid.scrollToRow(50); + assertFalse("Scrolling caused and exception when shuffled.", + getLogRow(0).contains("Exception")); + + for (int i = 0; i < 5; ++i) { + assertGreater( + "Grid is not sorted by Column 10 using ascending direction", + Integer.parseInt(grid.getCell(i + 1, 10).getText()), + Integer.parseInt(grid.getCell(i, 10).getText())); + + } + + // Column 7 is row index as a number. Last three row are original rows + // 2, 1 and 0. + // Click header twice to sort descending + grid.getHeaderCell(0, 7).click(); + grid.getHeaderCell(0, 7).click(); + for (int i = 0; i < 3; ++i) { + assertEquals( + "Grid is not sorted by Column 7 using descending direction", + "(" + i + ", 0)", + grid.getCell(GridBasicFeatures.ROWS - (i + 1), 0).getText()); + } + + assertEquals("9. Sort order: [Column 7 ASCENDING] by USER", + getLogRow(3)); + assertEquals("11. Sort order: [Column 7 DESCENDING] by USER", + getLogRow(1)); + } + + @Test + public void testUserMultiColumnSorting() { + openTestURL(); + + getGridElement().getHeaderCell(0, 0).click(); + new Actions(driver).keyDown(Keys.SHIFT).perform(); + getGridElement().getHeaderCell(0, 11).click(); + new Actions(driver).keyUp(Keys.SHIFT).perform(); + + String prev = getGridElement().getCell(0, 11).getAttribute("innerHTML"); + for (int i = 1; i <= 6; ++i) { + assertEquals("Column 11 should contain same values.", prev, + getGridElement().getCell(i, 11).getAttribute("innerHTML")); + } + + prev = getGridElement().getCell(0, 0).getText(); + for (int i = 1; i <= 6; ++i) { + assertTrue( + "Grid is not sorted by column 0.", + prev.compareTo(getGridElement().getCell(i, 0).getText()) < 0); + } + + } + + private void sendKeys(CharSequence... seq) { + new Actions(getDriver()).sendKeys(seq).perform(); + } + + private void holdKey(Keys key) { + new Actions(getDriver()).keyDown(key).perform(); + } + + private void releaseKey(Keys key) { + new Actions(getDriver()).keyUp(key).perform(); + } + + private void assertLog(String expected) { + assertEquals(expected, getLogRow(0)); + } + + @Test + public void testKeyboardSorting() { + openTestURL(); + + // + // NOTE: This is a work-around to get the focus to the first header + // cell. + // We can't use element.focus() because TestBench (or, rather, Selenium + // beneath it) has rather interesting bugs regarding focus handling. + // + getGridElement().getCell(0, 0).click(); + sendKeys(Keys.ARROW_UP); + + // Sort ASCENDING on first column + sendKeys(Keys.ENTER); + assertLog("2. Sort order: [Column 0 ASCENDING] by USER"); + + // Move to next column + sendKeys(Keys.RIGHT); + + // Add this column to the existing sorting group + holdKey(Keys.SHIFT); + sendKeys(Keys.ENTER); + releaseKey(Keys.SHIFT); + assertLog("4. Sort order: [Column 0 ASCENDING, Column 1 ASCENDING] by USER"); + + // Move to next column + sendKeys(Keys.RIGHT); + + // Add a third column to the sorting group + holdKey(Keys.SHIFT); + sendKeys(Keys.ENTER); + releaseKey(Keys.SHIFT); + assertLog("6. Sort order: [Column 0 ASCENDING, Column 1 ASCENDING, Column 2 ASCENDING] by USER"); + + // Move back to the second column + sendKeys(Keys.LEFT); + + // Change sort direction of the second column to DESCENDING + holdKey(Keys.SHIFT); + sendKeys(Keys.ENTER); + releaseKey(Keys.SHIFT); + assertLog("8. Sort order: [Column 0 ASCENDING, Column 1 DESCENDING, Column 2 ASCENDING] by USER"); + + // Move back to the third column + sendKeys(Keys.RIGHT); + + // Set sorting to third column, ASCENDING + sendKeys(Keys.ENTER); + assertLog("10. Sort order: [Column 2 ASCENDING] by USER"); + + // Move to the fourth column + sendKeys(Keys.RIGHT); + + // Make sure that single-column sorting also works as expected + sendKeys(Keys.ENTER); + assertLog("12. Sort order: [Column 3 ASCENDING] by USER"); + + } + + private void sortBy(String column) { + selectMenuPath("Component", "State", "Sort by column", column); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStaticSectionComponentTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStaticSectionComponentTest.java new file mode 100644 index 0000000000..21bf667bae --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStaticSectionComponentTest.java @@ -0,0 +1,54 @@ +/* + * 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 java.io.IOException; + +import org.junit.Test; + +import com.vaadin.testbench.elements.ButtonElement; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest; + +public class GridStaticSectionComponentTest extends GridBasicFeaturesTest { + + @Test + public void testNativeButtonInHeader() throws IOException { + openTestURL(); + + selectMenuPath("Component", "Columns", "Column 1", "Header Type", + "Widget Header"); + + getGridElement().$(ButtonElement.class).first().click(); + + assertEquals("2. Button clicked!", getLogRow(0)); + } + + @Test + public void testNativeButtonInFooter() throws IOException { + openTestURL(); + + selectMenuPath("Component", "Footer", "Visible"); + selectMenuPath("Component", "Footer", "Append row"); + selectMenuPath("Component", "Columns", "Column 1", "Footer Type", + "Widget Footer"); + + getGridElement().$(ButtonElement.class).first().click(); + + assertEquals("4. Button clicked!", getLogRow(0)); + } +} diff --git a/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStructureTest.java b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStructureTest.java new file mode 100644 index 0000000000..a3cbaa980d --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStructureTest.java @@ -0,0 +1,252 @@ +/* + * 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.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.IsNot.not; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.WebElement; + +import com.vaadin.testbench.TestBenchElement; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicFeaturesTest; + +public class GridStructureTest extends GridBasicFeaturesTest { + + @Test + public void testHidingColumn() throws Exception { + openTestURL(); + + // Column 0 should be visible + List<TestBenchElement> cells = getGridHeaderRowCells(); + assertEquals("Column 0", cells.get(0).getText()); + + // Hide column 0 + selectMenuPath("Component", "Columns", "Column 0", "Visible"); + + // Column 1 should now be the first cell + cells = getGridHeaderRowCells(); + assertEquals("Column 1", cells.get(0).getText()); + } + + @Test + public void testRemovingColumn() throws Exception { + openTestURL(); + + // Column 0 should be visible + List<TestBenchElement> cells = getGridHeaderRowCells(); + assertEquals("Column 0", cells.get(0).getText()); + + // Hide column 0 + selectMenuPath("Component", "Columns", "Column 0", "Remove"); + + // Column 1 should now be the first cell + cells = getGridHeaderRowCells(); + assertEquals("Column 1", cells.get(0).getText()); + } + + @Test + public void testDataLoadingAfterRowRemoval() throws Exception { + openTestURL(); + + // Remove columns 2,3,4 + selectMenuPath("Component", "Columns", "Column 2", "Remove"); + selectMenuPath("Component", "Columns", "Column 3", "Remove"); + selectMenuPath("Component", "Columns", "Column 4", "Remove"); + + // Scroll so new data is lazy loaded + scrollGridVerticallyTo(1000); + + // Let lazy loading do its job + sleep(1000); + + // Check that row is loaded + assertThat(getGridElement().getCell(11, 0).getText(), not("...")); + } + + @Test + public void testFreezingColumn() throws Exception { + openTestURL(); + + // Freeze column 2 + selectMenuPath("Component", "Columns", "Column 2", "Freeze"); + + WebElement cell = getGridElement().getCell(0, 0); + assertTrue(cell.getAttribute("class").contains("frozen")); + + cell = getGridElement().getCell(0, 1); + assertTrue(cell.getAttribute("class").contains("frozen")); + } + + @Test + public void testInitialColumnWidths() throws Exception { + openTestURL(); + + WebElement cell = getGridElement().getCell(0, 0); + assertEquals(100, cell.getSize().getWidth()); + + cell = getGridElement().getCell(0, 1); + assertEquals(150, cell.getSize().getWidth()); + + cell = getGridElement().getCell(0, 2); + assertEquals(200, cell.getSize().getWidth()); + } + + @Test + public void testColumnWidths() throws Exception { + openTestURL(); + + // Default column width is 100px + WebElement cell = getGridElement().getCell(0, 0); + assertEquals(100, cell.getSize().getWidth()); + + // Set first column to be 200px wide + selectMenuPath("Component", "Columns", "Column 0", "Column 0 Width", + "200px"); + + cell = getGridElement().getCell(0, 0); + assertEquals(200, cell.getSize().getWidth()); + + // Set second column to be 150px wide + selectMenuPath("Component", "Columns", "Column 1", "Column 1 Width", + "150px"); + cell = getGridElement().getCell(0, 1); + assertEquals(150, cell.getSize().getWidth()); + + // Set first column to be auto sized (defaults to 100px currently) + selectMenuPath("Component", "Columns", "Column 0", "Column 0 Width", + "Auto"); + + cell = getGridElement().getCell(0, 0); + assertEquals(100, cell.getSize().getWidth()); + } + + @Test + public void testPrimaryStyleNames() throws Exception { + openTestURL(); + + // v-grid is default primary style namea + assertPrimaryStylename("v-grid"); + + selectMenuPath("Component", "State", "Primary style name", + "v-escalator"); + assertPrimaryStylename("v-escalator"); + + selectMenuPath("Component", "State", "Primary style name", "my-grid"); + assertPrimaryStylename("my-grid"); + + selectMenuPath("Component", "State", "Primary style name", "v-grid"); + assertPrimaryStylename("v-grid"); + } + + /** + * Test that the current view is updated when a server-side container change + * occurs (without scrolling back and forth) + */ + @Test + public void testItemSetChangeEvent() throws Exception { + openTestURL(); + + final By newRow = By.xpath("//td[text()='newcell: 0']"); + + assertTrue("Unexpected initial state", !isElementPresent(newRow)); + + selectMenuPath("Component", "Body rows", "Add first row"); + assertTrue("Add row failed", isElementPresent(newRow)); + + selectMenuPath("Component", "Body rows", "Remove first row"); + assertTrue("Remove row failed", !isElementPresent(newRow)); + } + + /** + * Test that the current view is updated when a property's value is reflect + * to the client, when the value is modified server-side. + */ + @Test + public void testPropertyValueChangeEvent() throws Exception { + openTestURL(); + + assertEquals("Unexpected cell initial state", "(0, 0)", + getGridElement().getCell(0, 0).getText()); + + selectMenuPath("Component", "Body rows", + "Modify first row (getItemProperty)"); + assertEquals("(First) modification with getItemProperty failed", + "modified: 0", getGridElement().getCell(0, 0).getText()); + + selectMenuPath("Component", "Body rows", + "Modify first row (getContainerProperty)"); + assertEquals("(Second) modification with getItemProperty failed", + "modified: Column 0", getGridElement().getCell(0, 0).getText()); + } + + @Test + public void testRemovingAllItems() throws Exception { + openTestURL(); + + selectMenuPath("Component", "Body rows", "Remove all rows"); + + assertEquals(0, getGridElement().findElement(By.tagName("tbody")) + .findElements(By.tagName("tr")).size()); + } + + @Test + public void testVerticalScrollBarVisibilityWhenEnoughRows() + throws Exception { + openTestURL(); + + assertTrue(verticalScrollbarIsPresent()); + + selectMenuPath("Component", "Body rows", "Remove all rows"); + assertFalse(verticalScrollbarIsPresent()); + + selectMenuPath("Component", "Body rows", "Add 18 rows"); + assertFalse(verticalScrollbarIsPresent()); + + selectMenuPath("Component", "Body rows", "Add first row"); + assertTrue(verticalScrollbarIsPresent()); + } + + private boolean verticalScrollbarIsPresent() { + return "scroll".equals(getGridVerticalScrollbar().getCssValue( + "overflow-y")); + } + + private void assertPrimaryStylename(String stylename) { + assertTrue(getGridElement().getAttribute("class").contains(stylename)); + + String tableWrapperStyleName = getGridElement().getTableWrapper() + .getAttribute("class"); + assertTrue(tableWrapperStyleName.contains(stylename + "-tablewrapper")); + + String hscrollStyleName = getGridElement().getHorizontalScroller() + .getAttribute("class"); + assertTrue(hscrollStyleName.contains(stylename + "-scroller")); + assertTrue(hscrollStyleName + .contains(stylename + "-scroller-horizontal")); + + String vscrollStyleName = getGridElement().getVerticalScroller() + .getAttribute("class"); + assertTrue(vscrollStyleName.contains(stylename + "-scroller")); + assertTrue(vscrollStyleName.contains(stylename + "-scroller-vertical")); + } +} diff --git a/uitest/src/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml b/uitest/src/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml index 2c25c54e04..d23903f9db 100644 --- a/uitest/src/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml +++ b/uitest/src/com/vaadin/tests/widgetset/TestingWidgetSet.gwt.xml @@ -4,6 +4,8 @@ <!-- Inherit the DefaultWidgetSet --> <inherits name="com.vaadin.DefaultWidgetSet" /> + <inherits name="com.google.gwt.user.theme.standard.Standard" /> + <replace-with class="com.vaadin.tests.widgetset.client.CustomUIConnector"> <when-type-is class="com.vaadin.client.ui.ui.UIConnector" /> </replace-with> diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorBasicClientFeaturesConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorBasicClientFeaturesConnector.java new file mode 100644 index 0000000000..f065d4c7f6 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorBasicClientFeaturesConnector.java @@ -0,0 +1,37 @@ +/* + * 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.widgetset.client.grid; + +import com.vaadin.client.ui.AbstractComponentConnector; +import com.vaadin.shared.ui.Connect; +import com.vaadin.tests.components.grid.basicfeatures.EscalatorBasicClientFeatures.EscalatorTestComponent; + +/** + * Connector for the EscalatorClientBasicFeatures ApplicationWidget + * + * @since + * @author Vaadin Ltd + */ +@Connect(EscalatorTestComponent.class) +public class EscalatorBasicClientFeaturesConnector extends + AbstractComponentConnector { + + @Override + public EscalatorBasicClientFeaturesWidget getWidget() { + return (EscalatorBasicClientFeaturesWidget) super.getWidget(); + } + +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorBasicClientFeaturesWidget.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorBasicClientFeaturesWidget.java new file mode 100644 index 0000000000..54c870b8f7 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorBasicClientFeaturesWidget.java @@ -0,0 +1,608 @@ +package com.vaadin.tests.widgetset.client.grid; + +import java.util.ArrayList; +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.ui.Composite; +import com.google.gwt.user.client.ui.HTML; +import com.vaadin.client.ui.grid.Escalator; +import com.vaadin.client.ui.grid.EscalatorUpdater; +import com.vaadin.client.ui.grid.FlyweightCell; +import com.vaadin.client.ui.grid.Row; +import com.vaadin.client.ui.grid.RowContainer; + +public class EscalatorBasicClientFeaturesWidget extends + PureGWTTestApplication<Escalator> { + + public static class LogWidget extends Composite { + + private static final int MAX_LOG = 9; + + private final HTML html = new HTML(); + private final List<String> logs = new ArrayList<String>(); + private Escalator escalator; + + public LogWidget() { + initWidget(html); + getElement().setId("log"); + } + + public void setEscalator(Escalator escalator) { + this.escalator = escalator; + } + + public void updateDebugLabel() { + int headers = escalator.getHeader().getRowCount(); + int bodys = escalator.getBody().getRowCount(); + int footers = escalator.getFooter().getRowCount(); + int columns = escalator.getColumnConfiguration().getColumnCount(); + + while (logs.size() > MAX_LOG) { + logs.remove(0); + } + + String logString = "<hr>"; + for (String log : logs) { + logString += log + "<br>"; + } + + html.setHTML("Columns: " + columns + "<br>" + // + "Header rows: " + headers + "<br>" + // + "Body rows: " + bodys + "<br>" + // + "Footer rows: " + footers + "<br>" + // + logString); + } + + public void log(String string) { + logs.add((Duration.currentTimeMillis() % 10000) + ": " + string); + } + } + + public static class UpdaterLifetimeWidget extends + EscalatorBasicClientFeaturesWidget { + + private final EscalatorUpdater debugUpdater = new EscalatorUpdater() { + @Override + public void preAttach(Row row, Iterable<FlyweightCell> cellsToAttach) { + log("preAttach", cellsToAttach); + } + + @Override + public void postAttach(Row row, + Iterable<FlyweightCell> attachedCells) { + log("postAttach", attachedCells); + } + + @Override + public void update(Row row, Iterable<FlyweightCell> cellsToUpdate) { + log("update", cellsToUpdate); + } + + @Override + public void preDetach(Row row, Iterable<FlyweightCell> cellsToDetach) { + log("preDetach", cellsToDetach); + } + + @Override + public void postDetach(Row row, + Iterable<FlyweightCell> detachedCells) { + log("postDetach", detachedCells); + } + + private void log(String methodName, Iterable<FlyweightCell> cells) { + if (!cells.iterator().hasNext()) { + return; + } + + TableCellElement cellElement = cells.iterator().next() + .getElement(); + boolean isAttached = cellElement.getParentElement() != null + && cellElement.getParentElement().getParentElement() != null; + logWidget.log(methodName + ": elementIsAttached == " + + isAttached); + } + }; + + public UpdaterLifetimeWidget() { + super(); + escalator.getHeader().setEscalatorUpdater(debugUpdater); + escalator.getBody().setEscalatorUpdater(debugUpdater); + escalator.getFooter().setEscalatorUpdater(debugUpdater); + } + } + + private static final String COLUMNS_AND_ROWS_MENU = "Columns and Rows"; + private static final String GENERAL_MENU = "General"; + private static final String FEATURES_MENU = "Features"; + + private static abstract class TestEscalatorUpdater implements + EscalatorUpdater { + + @Override + public void preAttach(Row row, Iterable<FlyweightCell> cellsToAttach) { + // noop + } + + @Override + public void postAttach(Row row, Iterable<FlyweightCell> attachedCells) { + // noop + } + + @Override + public void preDetach(Row row, Iterable<FlyweightCell> cellsToDetach) { + // noop + } + + @Override + public void postDetach(Row row, Iterable<FlyweightCell> detachedCells) { + // noop + } + } + + private class Data { + private int columnCounter = 0; + private int rowCounter = 0; + private final List<Integer> columns = new ArrayList<Integer>(); + private final List<Integer> rows = new ArrayList<Integer>(); + + @SuppressWarnings("boxing") + public void insertRows(final int offset, final int amount) { + final List<Integer> newRows = new ArrayList<Integer>(); + for (int i = 0; i < amount; i++) { + newRows.add(rowCounter++); + } + rows.addAll(offset, newRows); + } + + @SuppressWarnings("boxing") + public void insertColumns(final int offset, final int amount) { + final List<Integer> newColumns = new ArrayList<Integer>(); + for (int i = 0; i < amount; i++) { + newColumns.add(columnCounter++); + } + columns.addAll(offset, newColumns); + } + + public EscalatorUpdater createHeaderUpdater() { + return new TestEscalatorUpdater() { + @Override + public void update(final Row row, + final Iterable<FlyweightCell> cellsToUpdate) { + for (final FlyweightCell cell : cellsToUpdate) { + final Integer columnName = columns + .get(cell.getColumn()); + cell.getElement().setInnerText("Header " + columnName); + + if (colspan == Colspan.NORMAL) { + if (cell.getColumn() % 2 == 0) { + cell.setColSpan(2); + } + } else if (colspan == Colspan.CRAZY) { + if (cell.getColumn() % 3 == 0) { + cell.setColSpan(2); + } + } + } + } + }; + } + + public EscalatorUpdater createFooterUpdater() { + return new TestEscalatorUpdater() { + @Override + public void update(final Row row, + final Iterable<FlyweightCell> cellsToUpdate) { + for (final FlyweightCell cell : cellsToUpdate) { + final Integer columnName = columns + .get(cell.getColumn()); + cell.getElement().setInnerText("Footer " + columnName); + + if (colspan == Colspan.NORMAL) { + if (cell.getColumn() % 2 == 0) { + cell.setColSpan(2); + } + } else if (colspan == Colspan.CRAZY) { + if (cell.getColumn() % 3 == 1) { + cell.setColSpan(2); + } + } + } + } + }; + } + + public EscalatorUpdater createBodyUpdater() { + return new TestEscalatorUpdater() { + + public void renderCell(final FlyweightCell cell) { + final Integer columnName = columns.get(cell.getColumn()); + final Integer rowName = rows.get(cell.getRow()); + String cellInfo = columnName + "," + rowName; + + if (cell.getColumn() > 0) { + cell.getElement().setInnerText("Cell: " + cellInfo); + } else { + cell.getElement().setInnerText( + "Row " + cell.getRow() + ": " + cellInfo); + } + + if (colspan == Colspan.NORMAL) { + if (cell.getColumn() % 2 == 0) { + cell.setColSpan(2); + } + } else if (colspan == Colspan.CRAZY) { + if (cell.getColumn() % 3 == cell.getRow() % 3) { + cell.setColSpan(2); + } + } + } + + @Override + public void update(final Row row, + final Iterable<FlyweightCell> cellsToUpdate) { + for (final FlyweightCell cell : cellsToUpdate) { + renderCell(cell); + } + } + }; + } + + public void removeRows(final int offset, final int amount) { + for (int i = 0; i < amount; i++) { + rows.remove(offset); + } + } + + public void removeColumns(final int offset, final int amount) { + for (int i = 0; i < amount; i++) { + columns.remove(offset); + } + } + } + + protected final Escalator escalator; + private final Data data = new Data(); + + private enum Colspan { + NONE, NORMAL, CRAZY; + } + + private Colspan colspan = Colspan.NONE; + protected final LogWidget logWidget = new LogWidget(); + + public EscalatorBasicClientFeaturesWidget() { + super(new EscalatorProxy()); + escalator = getTestedWidget(); + logWidget.setEscalator(escalator); + + ((EscalatorProxy) escalator).setLogWidget(logWidget); + addNorth(logWidget, 200); + + final RowContainer header = escalator.getHeader(); + header.setEscalatorUpdater(data.createHeaderUpdater()); + + final RowContainer footer = escalator.getFooter(); + footer.setEscalatorUpdater(data.createFooterUpdater()); + + escalator.getBody().setEscalatorUpdater(data.createBodyUpdater()); + + setWidth("500px"); + setHeight("500px"); + + escalator.getElement().getStyle().setZIndex(0); + addNorth(escalator, 500); + + createGeneralMenu(); + createColumnMenu(); + createHeaderRowsMenu(); + createBodyRowsMenu(); + createFooterRowsMenu(); + createColumnsAndRowsMenu(); + createFrozenMenu(); + createColspanMenu(); + } + + private void createFrozenMenu() { + String[] menupath = { FEATURES_MENU, "Frozen columns" }; + addMenuCommand("Freeze 1 column", new ScheduledCommand() { + @Override + public void execute() { + escalator.getColumnConfiguration().setFrozenColumnCount(1); + } + }, menupath); + addMenuCommand("Freeze 0 columns", new ScheduledCommand() { + @Override + public void execute() { + escalator.getColumnConfiguration().setFrozenColumnCount(0); + } + }, menupath); + } + + private void createColspanMenu() { + String[] menupath = { FEATURES_MENU, "Column spanning" }; + addMenuCommand("Apply normal colspan", new ScheduledCommand() { + @Override + public void execute() { + colspan = Colspan.NORMAL; + refreshEscalator(); + } + }, menupath); + addMenuCommand("Apply crazy colspan", new ScheduledCommand() { + @Override + public void execute() { + colspan = Colspan.CRAZY; + refreshEscalator(); + } + }, menupath); + addMenuCommand("Apply no colspan", new ScheduledCommand() { + @Override + public void execute() { + colspan = Colspan.NONE; + refreshEscalator(); + } + }, menupath); + } + + private void createColumnsAndRowsMenu() { + String[] menupath = { COLUMNS_AND_ROWS_MENU }; + addMenuCommand("Add one of each row", new ScheduledCommand() { + @Override + public void execute() { + insertRows(escalator.getHeader(), 0, 1); + insertRows(escalator.getBody(), 0, 1); + insertRows(escalator.getFooter(), 0, 1); + } + }, menupath); + addMenuCommand("Remove one of each row", new ScheduledCommand() { + @Override + public void execute() { + removeRows(escalator.getHeader(), 0, 1); + removeRows(escalator.getBody(), 0, 1); + removeRows(escalator.getFooter(), 0, 1); + } + }, menupath); + } + + private void createGeneralMenu() { + String[] menupath = { GENERAL_MENU }; + addMenuCommand("Clear (columns, then rows)", new ScheduledCommand() { + @Override + public void execute() { + resetColRow(); + } + }, menupath); + addMenuCommand("Clear (rows, then columns)", new ScheduledCommand() { + @Override + public void execute() { + resetRowCol(); + } + }, menupath); + addMenuCommand("Populate Escalator (columns, then rows)", + new ScheduledCommand() { + @Override + public void execute() { + resetColRow(); + insertColumns(0, 10); + insertRows(escalator.getHeader(), 0, 1); + insertRows(escalator.getBody(), 0, 100); + insertRows(escalator.getFooter(), 0, 1); + } + }, menupath); + addMenuCommand("Populate Escalator (rows, then columns)", + new ScheduledCommand() { + @Override + public void execute() { + resetColRow(); + insertRows(escalator.getHeader(), 0, 1); + insertRows(escalator.getBody(), 0, 100); + insertRows(escalator.getFooter(), 0, 1); + insertColumns(0, 10); + } + }, menupath); + } + + private void createColumnMenu() { + String[] menupath = { COLUMNS_AND_ROWS_MENU, "Columns" }; + addMenuCommand("Add one column to beginning", new ScheduledCommand() { + @Override + public void execute() { + insertColumns(0, 1); + } + }, menupath); + addMenuCommand("Add one column to end", new ScheduledCommand() { + @Override + public void execute() { + insertColumns(escalator.getColumnConfiguration() + .getColumnCount(), 1); + } + }, menupath); + addMenuCommand("Add ten columns", new ScheduledCommand() { + @Override + public void execute() { + insertColumns(0, 10); + } + }, menupath); + addMenuCommand("Remove one column from beginning", + new ScheduledCommand() { + @Override + public void execute() { + removeColumns(0, 1); + } + }, menupath); + addMenuCommand("Remove one column from end", new ScheduledCommand() { + @Override + public void execute() { + removeColumns(escalator.getColumnConfiguration() + .getColumnCount() - 1, 1); + } + }, menupath); + } + + private void createHeaderRowsMenu() { + String[] menupath = { COLUMNS_AND_ROWS_MENU, "Header Rows" }; + createRowsMenu(escalator.getHeader(), menupath); + } + + private void createFooterRowsMenu() { + String[] menupath = { COLUMNS_AND_ROWS_MENU, "Footer Rows" }; + createRowsMenu(escalator.getFooter(), menupath); + } + + private void createBodyRowsMenu() { + String[] menupath = { COLUMNS_AND_ROWS_MENU, "Body Rows" }; + createRowsMenu(escalator.getBody(), menupath); + + addMenuCommand("Add 5 rows to top", new ScheduledCommand() { + @Override + public void execute() { + insertRows(escalator.getBody(), 0, 5); + } + }, menupath); + addMenuCommand("Add 50 rows to top", new ScheduledCommand() { + @Override + public void execute() { + insertRows(escalator.getBody(), 0, 50); + } + }, menupath); + addMenuCommand("Remove 5 rows from bottom", new ScheduledCommand() { + @Override + public void execute() { + removeRows(escalator.getBody(), escalator.getBody() + .getRowCount() - 5, 5); + } + }, menupath); + addMenuCommand("Remove 50 rows from bottom", new ScheduledCommand() { + @Override + public void execute() { + removeRows(escalator.getBody(), escalator.getBody() + .getRowCount() - 50, 50); + } + }, menupath); + } + + private void createRowsMenu(final RowContainer container, String[] menupath) { + addMenuCommand("Add one row to beginning", new ScheduledCommand() { + @Override + public void execute() { + int offset = 0; + int number = 1; + insertRows(container, offset, number); + } + }, menupath); + addMenuCommand("Add one row to end", new ScheduledCommand() { + @Override + public void execute() { + int offset = container.getRowCount(); + int number = 1; + insertRows(container, offset, number); + } + }, menupath); + addMenuCommand("Remove one row from beginning", new ScheduledCommand() { + @Override + public void execute() { + int offset = 0; + int number = 1; + removeRows(container, offset, number); + } + }, menupath); + addMenuCommand("Remove one row from end", new ScheduledCommand() { + @Override + public void execute() { + int offset = container.getRowCount() - 1; + int number = 1; + removeRows(container, offset, number); + } + }, menupath); + } + + private void insertRows(final RowContainer container, int offset, int number) { + if (container == escalator.getBody()) { + data.insertRows(offset, number); + escalator.getBody().insertRows(offset, number); + } else { + container.insertRows(offset, number); + } + } + + private void removeRows(final RowContainer container, int offset, int number) { + if (container == escalator.getBody()) { + data.removeRows(offset, number); + escalator.getBody().removeRows(offset, number); + } else { + container.removeRows(offset, number); + } + } + + private void insertColumns(final int offset, final int number) { + data.insertColumns(offset, number); + escalator.getColumnConfiguration().insertColumns(offset, number); + } + + private void removeColumns(final int offset, final int number) { + data.removeColumns(offset, number); + escalator.getColumnConfiguration().removeColumns(offset, number); + } + + private void resetColRow() { + if (escalator.getColumnConfiguration().getColumnCount() > 0) { + removeColumns(0, escalator.getColumnConfiguration() + .getColumnCount()); + } + if (escalator.getFooter().getRowCount() > 0) { + removeRows(escalator.getFooter(), 0, escalator.getFooter() + .getRowCount()); + } + + if (escalator.getBody().getRowCount() > 0) { + removeRows(escalator.getBody(), 0, escalator.getBody() + .getRowCount()); + } + + if (escalator.getHeader().getRowCount() > 0) { + removeRows(escalator.getHeader(), 0, escalator.getHeader() + .getRowCount()); + } + } + + private void resetRowCol() { + if (escalator.getFooter().getRowCount() > 0) { + removeRows(escalator.getFooter(), 0, escalator.getFooter() + .getRowCount()); + } + + if (escalator.getBody().getRowCount() > 0) { + removeRows(escalator.getBody(), 0, escalator.getBody() + .getRowCount()); + } + + if (escalator.getHeader().getRowCount() > 0) { + removeRows(escalator.getHeader(), 0, escalator.getHeader() + .getRowCount()); + } + + if (escalator.getColumnConfiguration().getColumnCount() > 0) { + removeColumns(0, escalator.getColumnConfiguration() + .getColumnCount()); + } + } + + private void refreshEscalator() { + if (escalator.getHeader().getRowCount() > 0) { + escalator.getHeader().refreshRows(0, + escalator.getHeader().getRowCount()); + } + + if (escalator.getBody().getRowCount() > 0) { + escalator.getBody().refreshRows(0, + escalator.getBody().getRowCount()); + } + + if (escalator.getFooter().getRowCount() > 0) { + escalator.getFooter().refreshRows(0, + escalator.getFooter().getRowCount()); + } + } +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorProxy.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorProxy.java new file mode 100644 index 0000000000..ac1de01f1e --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorProxy.java @@ -0,0 +1,206 @@ +/* + * 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.widgetset.client.grid; + +import com.google.gwt.dom.client.Element; +import com.google.gwt.dom.client.TableRowElement; +import com.vaadin.client.ui.grid.Cell; +import com.vaadin.client.ui.grid.ColumnConfiguration; +import com.vaadin.client.ui.grid.Escalator; +import com.vaadin.client.ui.grid.EscalatorUpdater; +import com.vaadin.client.ui.grid.RowContainer; +import com.vaadin.tests.widgetset.client.grid.EscalatorBasicClientFeaturesWidget.LogWidget; + +public class EscalatorProxy extends Escalator { + private class ColumnConfigurationProxy implements ColumnConfiguration { + private ColumnConfiguration columnConfiguration; + + public ColumnConfigurationProxy(ColumnConfiguration columnConfiguration) { + this.columnConfiguration = columnConfiguration; + } + + @Override + public void removeColumns(int index, int numberOfColumns) + throws IndexOutOfBoundsException, IllegalArgumentException { + columnConfiguration.removeColumns(index, numberOfColumns); + logWidget.log("removeColumns " + index + ", " + numberOfColumns); + logWidget.updateDebugLabel(); + } + + @Override + public void insertColumns(int index, int numberOfColumns) + throws IndexOutOfBoundsException, IllegalArgumentException { + columnConfiguration.insertColumns(index, numberOfColumns); + logWidget.log("insertColumns " + index + ", " + numberOfColumns); + logWidget.updateDebugLabel(); + } + + @Override + public int getColumnCount() { + return columnConfiguration.getColumnCount(); + } + + @Override + public void setFrozenColumnCount(int count) + throws IllegalArgumentException { + columnConfiguration.setFrozenColumnCount(count); + } + + @Override + public int getFrozenColumnCount() { + return columnConfiguration.getFrozenColumnCount(); + } + + @Override + public void setColumnWidth(int index, int px) + throws IllegalArgumentException { + columnConfiguration.setColumnWidth(index, px); + } + + @Override + public int getColumnWidth(int index) throws IllegalArgumentException { + return columnConfiguration.getColumnWidth(index); + } + + @Override + public int getColumnWidthActual(int index) + throws IllegalArgumentException { + return columnConfiguration.getColumnWidthActual(index); + } + } + + private class RowContainerProxy implements RowContainer { + private final RowContainer rowContainer; + + public RowContainerProxy(RowContainer rowContainer) { + this.rowContainer = rowContainer; + } + + @Override + public EscalatorUpdater getEscalatorUpdater() { + return rowContainer.getEscalatorUpdater(); + } + + @Override + public void setEscalatorUpdater(EscalatorUpdater escalatorUpdater) + throws IllegalArgumentException { + rowContainer.setEscalatorUpdater(escalatorUpdater); + } + + @Override + public void removeRows(int index, int numberOfRows) + throws IndexOutOfBoundsException, IllegalArgumentException { + rowContainer.removeRows(index, numberOfRows); + logWidget.log(rowContainer.getClass().getSimpleName() + + " removeRows " + index + ", " + numberOfRows); + logWidget.updateDebugLabel(); + } + + @Override + public void insertRows(int index, int numberOfRows) + throws IndexOutOfBoundsException, IllegalArgumentException { + rowContainer.insertRows(index, numberOfRows); + logWidget.log(rowContainer.getClass().getSimpleName() + + " insertRows " + index + ", " + numberOfRows); + logWidget.updateDebugLabel(); + } + + @Override + public void refreshRows(int index, int numberOfRows) + throws IndexOutOfBoundsException, IllegalArgumentException { + rowContainer.refreshRows(index, numberOfRows); + logWidget.log(rowContainer.getClass().getSimpleName() + + " refreshRows " + index + ", " + numberOfRows); + } + + @Override + public int getRowCount() { + return rowContainer.getRowCount(); + } + + @Override + public void setDefaultRowHeight(int px) throws IllegalArgumentException { + rowContainer.setDefaultRowHeight(px); + } + + @Override + public int getDefaultRowHeight() { + return rowContainer.getDefaultRowHeight(); + } + + @Override + public Cell getCell(Element element) { + return rowContainer.getCell(element); + } + + @Override + public TableRowElement getRowElement(int index) + throws IndexOutOfBoundsException, IllegalStateException { + return rowContainer.getRowElement(index); + } + + @Override + public Element getElement() { + return rowContainer.getElement(); + } + + } + + private RowContainer headerProxy = null; + private RowContainer bodyProxy = null; + private RowContainer footerProxy = null; + private ColumnConfiguration columnProxy = null; + private LogWidget logWidget; + + @Override + public RowContainer getHeader() { + if (headerProxy == null) { + headerProxy = new RowContainerProxy(super.getHeader()); + } + return headerProxy; + } + + @Override + public RowContainer getFooter() { + if (footerProxy == null) { + footerProxy = new RowContainerProxy(super.getFooter()); + } + return footerProxy; + } + + @Override + public RowContainer getBody() { + if (bodyProxy == null) { + bodyProxy = new RowContainerProxy(super.getBody()); + } + return bodyProxy; + } + + @Override + public ColumnConfiguration getColumnConfiguration() { + if (columnProxy == null) { + columnProxy = new ColumnConfigurationProxy( + super.getColumnConfiguration()); + } + return columnProxy; + } + + public void setLogWidget(LogWidget logWidget) { + this.logWidget = logWidget; + logWidget.updateDebugLabel(); + } + +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorUpdaterTestConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorUpdaterTestConnector.java new file mode 100644 index 0000000000..4ef8972e4f --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/EscalatorUpdaterTestConnector.java @@ -0,0 +1,30 @@ +/* + * 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.widgetset.client.grid; + +import com.vaadin.client.ui.AbstractComponentConnector; +import com.vaadin.shared.ui.Connect; +import com.vaadin.tests.components.grid.basicfeatures.EscalatorUpdaterUi.EscalatorUpdaterTestComponent; + +@Connect(EscalatorUpdaterTestComponent.class) +public class EscalatorUpdaterTestConnector extends AbstractComponentConnector { + + @Override + public EscalatorBasicClientFeaturesWidget.UpdaterLifetimeWidget getWidget() { + return (EscalatorBasicClientFeaturesWidget.UpdaterLifetimeWidget) super + .getWidget(); + } +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesConnector.java new file mode 100644 index 0000000000..b0841b69fb --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesConnector.java @@ -0,0 +1,37 @@ +/* + * 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.widgetset.client.grid; + +import com.vaadin.client.ui.AbstractComponentConnector; +import com.vaadin.shared.ui.Connect; +import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeatures.GridTestComponent; + +/** + * Connector for the GridClientBasicFeatures ApplicationWidget + * + * @since + * @author Vaadin Ltd + */ +@Connect(GridTestComponent.class) +public class GridBasicClientFeaturesConnector extends + AbstractComponentConnector { + + @Override + public GridBasicClientFeaturesWidget getWidget() { + return (GridBasicClientFeaturesWidget) super.getWidget(); + } + +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java new file mode 100644 index 0000000000..d5d276c7db --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java @@ -0,0 +1,931 @@ +/* + * 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.widgetset.client.grid; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import com.google.gwt.core.client.Scheduler.ScheduledCommand; +import com.google.gwt.dom.client.Style.Unit; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.shared.HandlerRegistration; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.HTML; +import com.google.gwt.user.client.ui.Label; +import com.google.gwt.user.client.ui.TextBox; +import com.vaadin.client.ui.VLabel; +import com.vaadin.client.ui.grid.Cell; +import com.vaadin.client.ui.grid.EditorRowHandler; +import com.vaadin.client.ui.grid.FlyweightCell; +import com.vaadin.client.ui.grid.Grid; +import com.vaadin.client.ui.grid.Grid.AbstractGridKeyEvent; +import com.vaadin.client.ui.grid.Grid.SelectionMode; +import com.vaadin.client.ui.grid.GridColumn; +import com.vaadin.client.ui.grid.GridFooter; +import com.vaadin.client.ui.grid.GridFooter.FooterRow; +import com.vaadin.client.ui.grid.GridHeader; +import com.vaadin.client.ui.grid.GridHeader.HeaderRow; +import com.vaadin.client.ui.grid.Renderer; +import com.vaadin.client.ui.grid.datasources.ListDataSource; +import com.vaadin.client.ui.grid.datasources.ListSorter; +import com.vaadin.client.ui.grid.events.BodyKeyDownHandler; +import com.vaadin.client.ui.grid.events.BodyKeyPressHandler; +import com.vaadin.client.ui.grid.events.BodyKeyUpHandler; +import com.vaadin.client.ui.grid.events.FooterKeyDownHandler; +import com.vaadin.client.ui.grid.events.FooterKeyPressHandler; +import com.vaadin.client.ui.grid.events.FooterKeyUpHandler; +import com.vaadin.client.ui.grid.events.GridKeyDownEvent; +import com.vaadin.client.ui.grid.events.GridKeyPressEvent; +import com.vaadin.client.ui.grid.events.GridKeyUpEvent; +import com.vaadin.client.ui.grid.events.HeaderKeyDownHandler; +import com.vaadin.client.ui.grid.events.HeaderKeyPressHandler; +import com.vaadin.client.ui.grid.events.HeaderKeyUpHandler; +import com.vaadin.client.ui.grid.events.ScrollEvent; +import com.vaadin.client.ui.grid.events.ScrollHandler; +import com.vaadin.client.ui.grid.renderers.DateRenderer; +import com.vaadin.client.ui.grid.renderers.HtmlRenderer; +import com.vaadin.client.ui.grid.renderers.NumberRenderer; +import com.vaadin.client.ui.grid.renderers.TextRenderer; +import com.vaadin.client.ui.grid.selection.SelectionModel.None; +import com.vaadin.tests.widgetset.client.grid.GridBasicClientFeaturesWidget.Data; + +/** + * Grid basic client features test application. + * + * @since + * @author Vaadin Ltd + */ +public class GridBasicClientFeaturesWidget extends + PureGWTTestApplication<Grid<List<Data>>> { + + public static enum Renderers { + TEXT_RENDERER, HTML_RENDERER, NUMBER_RENDERER, DATE_RENDERER; + } + + private class TestEditorRowHandler implements EditorRowHandler<List<Data>> { + + private Map<GridColumn<?, ?>, TextBox> widgets = new HashMap<GridColumn<?, ?>, TextBox>(); + + private Label log = new Label(); + + { + log.addStyleName("editor-row-log"); + addSouth(log, 20); + } + + @Override + public void bind(EditorRowRequest request) { + List<Data> rowData = ds.getRow(request.getRowIndex()); + + boolean hasSelectionColumn = !(grid.getSelectionModel() instanceof None); + for (int i = 0; i < rowData.size(); i++) { + int columnIndex = hasSelectionColumn ? i + 1 : i; + getWidget(columnIndex).setText(rowData.get(i).value.toString()); + } + + request.invokeCallback(); + } + + @Override + public void cancel(EditorRowRequest request) { + log.setText("Row " + request.getRowIndex() + " edit cancelled"); + request.invokeCallback(); + } + + @Override + public void commit(EditorRowRequest request) { + log.setText("Row " + request.getRowIndex() + " edit committed"); + List<Data> rowData = ds.getRow(request.getRowIndex()); + + int i = 0; + for (; i < COLUMNS - MANUALLY_FORMATTED_COLUMNS; i++) { + rowData.get(i).value = getWidget(i).getText(); + } + + rowData.get(i).value = Integer.valueOf(getWidget(i++).getText()); + rowData.get(i).value = new Date(getWidget(i++).getText()); + rowData.get(i).value = getWidget(i++).getText(); + rowData.get(i).value = Integer.valueOf(getWidget(i++).getText()); + rowData.get(i).value = Integer.valueOf(getWidget(i++).getText()); + + // notify data source of changes + ds.asList().set(request.getRowIndex(), rowData); + + request.invokeCallback(); + } + + @Override + public void discard(EditorRowRequest request) { + bind(request); + } + + @Override + public TextBox getWidget(GridColumn<?, List<Data>> column) { + if (grid.getColumns().indexOf(column) == 0 + && !(grid.getSelectionModel() instanceof None)) { + return null; + } + + TextBox w = widgets.get(column); + if (w == null) { + w = new TextBox(); + w.getElement().getStyle().setMargin(0, Unit.PX); + widgets.put(column, w); + } + return w; + } + + private TextBox getWidget(int i) { + return getWidget(grid.getColumn(i)); + } + } + + private static final int MANUALLY_FORMATTED_COLUMNS = 5; + public static final int COLUMNS = 12; + public static final int ROWS = 1000; + + private final Grid<List<Data>> grid; + private final List<List<Data>> data; + private final ListDataSource<List<Data>> ds; + private final ListSorter<List<Data>> sorter; + + /** + * Our basic data object + */ + public final static class Data { + Object value; + } + + /** + * Convenience method for creating a list of Data objects to be used as a + * Row in the data source + * + * @param cols + * number of columns (items) to include in the row + * @return + */ + private List<Data> createDataRow(int cols) { + List<Data> list = new ArrayList<Data>(cols); + for (int i = 0; i < cols; ++i) { + list.add(new Data()); + } + data.add(list); + return list; + } + + @SuppressWarnings("unchecked") + public GridBasicClientFeaturesWidget() { + super(new Grid<List<Data>>()); + + // Initialize data source + data = new ArrayList<List<Data>>(); + { + Random rand = new Random(); + rand.setSeed(13334); + long timestamp = 0; + for (int row = 0; row < ROWS; row++) { + + List<Data> datarow = createDataRow(COLUMNS); + Data d; + + int col = 0; + for (; col < COLUMNS - MANUALLY_FORMATTED_COLUMNS; ++col) { + d = datarow.get(col); + d.value = "(" + row + ", " + col + ")"; + } + + d = datarow.get(col++); + d.value = Integer.valueOf(row); + + d = datarow.get(col++); + d.value = new Date(timestamp); + timestamp += 91250000; // a bit over a day, just to get + // variation + + d = datarow.get(col++); + d.value = "<b>" + row + "</b>"; + + d = datarow.get(col++); + d.value = Integer.valueOf(rand.nextInt()); + + d = datarow.get(col++); + d.value = Integer.valueOf(rand.nextInt(5)); + } + } + + ds = new ListDataSource<List<Data>>(data); + grid = getTestedWidget(); + grid.getElement().setId("testComponent"); + grid.setDataSource(ds); + grid.setSelectionMode(SelectionMode.NONE); + grid.getEditorRow().setHandler(new TestEditorRowHandler()); + + sorter = new ListSorter<List<Data>>(grid); + + // Create a bunch of grid columns + + // Data source layout: + // text (String) * (COLUMNS - MANUALLY_FORMATTED_COLUMNS + 1) | + // rownumber (Integer) | some date (Date) | row number as HTML (String) + // | random value (Integer) + + int col = 0; + + // Text times COLUMNS - MANUALLY_FORMATTED_COLUMNS + for (col = 0; col < COLUMNS - MANUALLY_FORMATTED_COLUMNS; ++col) { + + final int c = col; + + GridColumn<String, List<Data>> column = new GridColumn<String, List<Data>>( + createRenderer(Renderers.TEXT_RENDERER)) { + @Override + public String getValue(List<Data> row) { + return (String) row.get(c).value; + } + }; + + column.setWidth(50 + c * 25); + + grid.addColumn(column); + + } + + // Integer row number + { + final int c = col++; + grid.addColumn(new GridColumn<Integer, List<Data>>( + createRenderer(Renderers.NUMBER_RENDERER)) { + @Override + public Integer getValue(List<Data> row) { + return (Integer) row.get(c).value; + } + }); + } + + // Some date + { + final int c = col++; + grid.addColumn(new GridColumn<Date, List<Data>>( + createRenderer(Renderers.DATE_RENDERER)) { + @Override + public Date getValue(List<Data> row) { + return (Date) row.get(c).value; + } + }); + } + + // Row number as a HTML string + { + final int c = col++; + grid.addColumn(new GridColumn<String, List<Data>>( + createRenderer(Renderers.HTML_RENDERER)) { + @Override + public String getValue(List<Data> row) { + return (String) row.get(c).value; + } + }); + } + + // Random integer value + { + final int c = col++; + grid.addColumn(new GridColumn<Integer, List<Data>>( + createRenderer(Renderers.NUMBER_RENDERER)) { + @Override + public Integer getValue(List<Data> row) { + return (Integer) row.get(c).value; + } + }); + } + + // Random integer value between 0 and 5 + { + final int c = col++; + grid.addColumn(new GridColumn<Integer, List<Data>>( + createRenderer(Renderers.NUMBER_RENDERER)) { + @Override + public Integer getValue(List<Data> row) { + return (Integer) row.get(c).value; + } + }); + } + + setHeaderTexts(grid.getHeader().getRow(0)); + + // + // Populate the menu + // + + createStateMenu(); + createColumnsMenu(); + createHeaderMenu(); + createFooterMenu(); + createEditorRowMenu(); + createInternalsMenu(); + + grid.getElement().getStyle().setZIndex(0); + addNorth(grid, 400); + + createKeyHandlers(); + } + + private void createInternalsMenu() { + String[] listenersPath = { "Component", "Internals", "Listeners" }; + final Label label = new Label(); + addSouth(label, 20); + + addMenuCommand("Add scroll listener", new ScheduledCommand() { + private HandlerRegistration scrollHandler = null; + + @Override + public void execute() { + if (scrollHandler != null) { + return; + } + scrollHandler = grid.addScrollHandler(new ScrollHandler() { + @Override + public void onScroll(ScrollEvent event) { + @SuppressWarnings("hiding") + final Grid<?> grid = (Grid<?>) event.getSource(); + label.setText("scrollTop: " + grid.getScrollTop() + + ", scrollLeft: " + grid.getScrollLeft()); + } + }); + } + }, listenersPath); + } + + private void createStateMenu() { + String[] selectionModePath = { "Component", "State", "Selection mode" }; + String[] primaryStyleNamePath = { "Component", "State", + "Primary Stylename" }; + + addMenuCommand("multi", new ScheduledCommand() { + @Override + public void execute() { + grid.setSelectionMode(SelectionMode.MULTI); + } + }, selectionModePath); + + addMenuCommand("single", new ScheduledCommand() { + @Override + public void execute() { + grid.setSelectionMode(SelectionMode.SINGLE); + } + }, selectionModePath); + + addMenuCommand("none", new ScheduledCommand() { + @Override + public void execute() { + grid.setSelectionMode(SelectionMode.NONE); + } + }, selectionModePath); + + addMenuCommand("v-grid", new ScheduledCommand() { + @Override + public void execute() { + grid.setStylePrimaryName("v-grid"); + + } + }, primaryStyleNamePath); + + addMenuCommand("v-escalator", new ScheduledCommand() { + @Override + public void execute() { + grid.setStylePrimaryName("v-escalator"); + + } + }, primaryStyleNamePath); + + addMenuCommand("v-custom-style", new ScheduledCommand() { + @Override + public void execute() { + grid.setStylePrimaryName("v-custom-style"); + + } + }, primaryStyleNamePath); + } + + private void createColumnsMenu() { + + for (int i = 0; i < COLUMNS; i++) { + final int index = i; + final GridColumn<?, List<Data>> column = grid.getColumn(index); + addMenuCommand("Visible", new ScheduledCommand() { + @Override + public void execute() { + column.setVisible(!column.isVisible()); + } + }, "Component", "Columns", "Column " + i); + addMenuCommand("Sortable", new ScheduledCommand() { + @Override + public void execute() { + column.setSortable(!column.isSortable()); + } + }, "Component", "Columns", "Column " + i); + addMenuCommand("Frozen", new ScheduledCommand() { + @Override + public void execute() { + if (column.equals(grid.getLastFrozenColumn())) { + grid.setLastFrozenColumn(null); + } else { + grid.setLastFrozenColumn(column); + } + } + }, "Component", "Columns", "Column " + i); + + addMenuCommand("auto", new ScheduledCommand() { + @Override + public void execute() { + column.setWidth(-1); + } + }, "Component", "Columns", "Column " + i, "Width"); + addMenuCommand("50px", new ScheduledCommand() { + @Override + public void execute() { + column.setWidth(50); + } + }, "Component", "Columns", "Column " + i, "Width"); + addMenuCommand("200px", new ScheduledCommand() { + @Override + public void execute() { + column.setWidth(200); + } + }, "Component", "Columns", "Column " + i, "Width"); + + // Header types + addMenuCommand("Text Header", new ScheduledCommand() { + @Override + public void execute() { + grid.getHeader().getRow(0).getCell(column) + .setText("Text Header"); + } + }, "Component", "Columns", "Column " + i, "Header Type"); + addMenuCommand("HTML Header", new ScheduledCommand() { + @Override + public void execute() { + grid.getHeader().getRow(0).getCell(column) + .setHtml("<b>HTML Header</b>"); + } + }, "Component", "Columns", "Column " + i, "Header Type"); + addMenuCommand("Widget Header", new ScheduledCommand() { + @Override + public void execute() { + final Button button = new Button("Button Header"); + button.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + button.setText("Clicked"); + } + }); + grid.getHeader().getRow(0).getCell(column) + .setWidget(button); + } + }, "Component", "Columns", "Column " + i, "Header Type"); + + // Footer types + addMenuCommand("Text Footer", new ScheduledCommand() { + @Override + public void execute() { + grid.getFooter().getRow(0).getCell(column) + .setText("Text Footer"); + } + }, "Component", "Columns", "Column " + i, "Footer Type"); + addMenuCommand("HTML Footer", new ScheduledCommand() { + @Override + public void execute() { + grid.getFooter().getRow(0).getCell(column) + .setHtml("<b>HTML Footer</b>"); + } + }, "Component", "Columns", "Column " + i, "Footer Type"); + addMenuCommand("Widget Footer", new ScheduledCommand() { + @Override + public void execute() { + final Button button = new Button("Button Footer"); + button.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + button.setText("Clicked"); + } + }); + grid.getFooter().getRow(0).getCell(column) + .setWidget(button); + } + }, "Component", "Columns", "Column " + i, "Footer Type"); + } + } + + private int headerCounter = 0; + private int footerCounter = 0; + + private void setHeaderTexts(HeaderRow row) { + for (int i = 0; i < COLUMNS; ++i) { + String caption = "Header (" + headerCounter + "," + i + ")"; + + // Lets use some different cell types + if (i % 3 == 0) { + row.getCell(grid.getColumn(i)).setText(caption); + } else if (i % 2 == 0) { + row.getCell(grid.getColumn(i)) + .setHtml("<b>" + caption + "</b>"); + } else { + row.getCell(grid.getColumn(i)).setWidget(new HTML(caption)); + } + } + headerCounter++; + } + + private void setFooterTexts(FooterRow row) { + for (int i = 0; i < COLUMNS; ++i) { + String caption = "Footer (" + footerCounter + "," + i + ")"; + + // Lets use some different cell types + if (i % 3 == 0) { + row.getCell(grid.getColumn(i)).setText(caption); + } else if (i % 2 == 0) { + row.getCell(grid.getColumn(i)) + .setHtml("<b>" + caption + "</b>"); + } else { + row.getCell(grid.getColumn(i)).setWidget(new HTML(caption)); + } + } + footerCounter++; + } + + private void createHeaderMenu() { + final GridHeader header = grid.getHeader(); + final String[] menuPath = { "Component", "Header" }; + + addMenuCommand("Visible", new ScheduledCommand() { + @Override + public void execute() { + header.setVisible(!header.isVisible()); + } + }, menuPath); + + addMenuCommand("Top", new ScheduledCommand() { + @Override + public void execute() { + header.setDefaultRow(header.getRow(0)); + } + }, "Component", "Header", "Default row"); + addMenuCommand("Bottom", new ScheduledCommand() { + @Override + public void execute() { + header.setDefaultRow(header.getRow(header.getRowCount() - 1)); + } + }, "Component", "Header", "Default row"); + addMenuCommand("Unset", new ScheduledCommand() { + @Override + public void execute() { + header.setDefaultRow(null); + } + }, "Component", "Header", "Default row"); + + addMenuCommand("Prepend row", new ScheduledCommand() { + @Override + public void execute() { + configureHeaderRow(header.prependRow()); + } + }, menuPath); + addMenuCommand("Append row", new ScheduledCommand() { + @Override + public void execute() { + configureHeaderRow(header.appendRow()); + } + }, menuPath); + addMenuCommand("Remove top row", new ScheduledCommand() { + @Override + public void execute() { + header.removeRow(0); + } + }, menuPath); + addMenuCommand("Remove bottom row", new ScheduledCommand() { + @Override + public void execute() { + header.removeRow(header.getRowCount() - 1); + } + }, menuPath); + + } + + private void configureHeaderRow(final HeaderRow row) { + final GridHeader header = grid.getHeader(); + setHeaderTexts(row); + String rowTitle = "Row " + header.getRowCount(); + final String[] menuPath = { "Component", "Header", rowTitle }; + + addMenuCommand("Join column cells 0, 1", new ScheduledCommand() { + + @Override + public void execute() { + row.join(row.getCell(grid.getColumn(0)), + row.getCell(grid.getColumn(1))); + + } + }, menuPath); + + addMenuCommand("Join columns 1, 2", new ScheduledCommand() { + + @Override + public void execute() { + row.join(grid.getColumn(1), grid.getColumn(2)); + + } + }, menuPath); + + addMenuCommand("Join columns 3, 4, 5", new ScheduledCommand() { + + @Override + public void execute() { + row.join(grid.getColumn(3), grid.getColumn(4), + grid.getColumn(5)); + + } + }, menuPath); + + addMenuCommand("Join all columns", new ScheduledCommand() { + + @Override + public void execute() { + row.join(grid.getColumns().toArray( + new GridColumn[grid.getColumnCount()])); + + } + }, menuPath); + } + + private void createFooterMenu() { + final GridFooter footer = grid.getFooter(); + final String[] menuPath = { "Component", "Footer" }; + + addMenuCommand("Visible", new ScheduledCommand() { + @Override + public void execute() { + footer.setVisible(!footer.isVisible()); + } + }, menuPath); + + addMenuCommand("Prepend row", new ScheduledCommand() { + @Override + public void execute() { + configureFooterRow(footer.prependRow()); + } + }, menuPath); + addMenuCommand("Append row", new ScheduledCommand() { + @Override + public void execute() { + configureFooterRow(footer.appendRow()); + } + }, menuPath); + addMenuCommand("Remove top row", new ScheduledCommand() { + @Override + public void execute() { + footer.removeRow(0); + } + }, menuPath); + addMenuCommand("Remove bottom row", new ScheduledCommand() { + @Override + public void execute() { + assert footer.getRowCount() > 0; + footer.removeRow(footer.getRowCount() - 1); + } + }, menuPath); + } + + private void createEditorRowMenu() { + addMenuCommand("Enabled", new ScheduledCommand() { + @Override + public void execute() { + grid.getEditorRow() + .setEnabled(!grid.getEditorRow().isEnabled()); + } + }, "Component", "Editor row"); + + addMenuCommand("Edit row 5", new ScheduledCommand() { + @Override + public void execute() { + grid.getEditorRow().editRow(5); + } + }, "Component", "Editor row"); + + addMenuCommand("Edit row 100", new ScheduledCommand() { + @Override + public void execute() { + grid.getEditorRow().editRow(100); + } + }, "Component", "Editor row"); + + addMenuCommand("Commit", new ScheduledCommand() { + @Override + public void execute() { + grid.getEditorRow().commit(); + } + }, "Component", "Editor row"); + + addMenuCommand("Discard", new ScheduledCommand() { + @Override + public void execute() { + grid.getEditorRow().discard(); + } + }, "Component", "Editor row"); + + addMenuCommand("Cancel edit", new ScheduledCommand() { + @Override + public void execute() { + grid.getEditorRow().cancel(); + } + }, "Component", "Editor row"); + + } + + private void configureFooterRow(final FooterRow row) { + final GridFooter footer = grid.getFooter(); + setFooterTexts(row); + String rowTitle = "Row " + footer.getRowCount(); + final String[] menuPath = { "Component", "Footer", rowTitle }; + + addMenuCommand("Join column cells 0, 1", new ScheduledCommand() { + + @Override + public void execute() { + row.join(row.getCell(grid.getColumn(0)), + row.getCell(grid.getColumn(1))); + + } + }, menuPath); + + addMenuCommand("Join columns 1, 2", new ScheduledCommand() { + + @Override + public void execute() { + row.join(grid.getColumn(1), grid.getColumn(2)); + + } + }, menuPath); + + addMenuCommand("Join all columns", new ScheduledCommand() { + + @Override + public void execute() { + row.join(grid.getColumns().toArray( + new GridColumn[grid.getColumnCount()])); + + } + }, menuPath); + } + + /** + * Creates a renderer for a {@link Renderers} + */ + @SuppressWarnings("rawtypes") + private final Renderer createRenderer(Renderers renderer) { + switch (renderer) { + case TEXT_RENDERER: + return new TextRenderer(); + + case HTML_RENDERER: + return new HtmlRenderer() { + + @Override + public void render(FlyweightCell cell, String htmlString) { + super.render(cell, "<b>" + htmlString + "</b>"); + } + }; + + case NUMBER_RENDERER: + return new NumberRenderer<Integer>(); + + case DATE_RENDERER: + return new DateRenderer(); + + default: + return new TextRenderer(); + } + } + + /** + * Creates a collection of handlers for all the grid key events + */ + private void createKeyHandlers() { + final List<VLabel> labels = new ArrayList<VLabel>(); + for (int i = 0; i < 9; ++i) { + VLabel tmp = new VLabel(); + addNorth(tmp, 20); + labels.add(tmp); + } + + // Key Down Events + grid.addBodyKeyDownHandler(new BodyKeyDownHandler() { + private final VLabel label = labels.get(0); + + @Override + public void onKeyDown(GridKeyDownEvent event) { + updateLabel(label, event); + } + }); + + grid.addHeaderKeyDownHandler(new HeaderKeyDownHandler() { + private final VLabel label = labels.get(1); + + @Override + public void onKeyDown(GridKeyDownEvent event) { + updateLabel(label, event); + } + }); + + grid.addFooterKeyDownHandler(new FooterKeyDownHandler() { + private final VLabel label = labels.get(2); + + @Override + public void onKeyDown(GridKeyDownEvent event) { + updateLabel(label, event); + } + }); + + // Key Up Events + grid.addBodyKeyUpHandler(new BodyKeyUpHandler() { + private final VLabel label = labels.get(3); + + @Override + public void onKeyUp(GridKeyUpEvent event) { + updateLabel(label, event); + } + }); + + grid.addHeaderKeyUpHandler(new HeaderKeyUpHandler() { + private final VLabel label = labels.get(4); + + @Override + public void onKeyUp(GridKeyUpEvent event) { + updateLabel(label, event); + } + }); + + grid.addFooterKeyUpHandler(new FooterKeyUpHandler() { + private final VLabel label = labels.get(5); + + @Override + public void onKeyUp(GridKeyUpEvent event) { + updateLabel(label, event); + } + }); + + // Key Press Events + grid.addBodyKeyPressHandler(new BodyKeyPressHandler() { + private final VLabel label = labels.get(6); + + @Override + public void onKeyPress(GridKeyPressEvent event) { + updateLabel(label, event); + } + }); + + grid.addHeaderKeyPressHandler(new HeaderKeyPressHandler() { + private final VLabel label = labels.get(7); + + @Override + public void onKeyPress(GridKeyPressEvent event) { + updateLabel(label, event); + } + }); + + grid.addFooterKeyPressHandler(new FooterKeyPressHandler() { + private final VLabel label = labels.get(8); + + @Override + public void onKeyPress(GridKeyPressEvent event) { + updateLabel(label, event); + } + }); + + } + + private void updateLabel(VLabel label, AbstractGridKeyEvent<?> event) { + String type = event.getNativeEvent().getType(); + Cell active = event.getActiveCell(); + String coords = "(" + active.getRow() + ", " + active.getColumn() + ")"; + String keyCode = "" + event.getNativeKeyCode(); + label.setText(coords + " " + type + " " + keyCode); + } +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridClientColumnRendererConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridClientColumnRendererConnector.java new file mode 100644 index 0000000000..f4ca1d0344 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridClientColumnRendererConnector.java @@ -0,0 +1,380 @@ +/* + * 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.widgetset.client.grid; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.Date; +import java.util.List; + +import com.google.gwt.dom.client.Document; +import com.google.gwt.dom.client.Element; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.user.client.Timer; +import com.google.gwt.user.client.Window.Location; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.HasWidgets; +import com.vaadin.client.data.DataChangeHandler; +import com.vaadin.client.data.DataSource; +import com.vaadin.client.ui.AbstractComponentConnector; +import com.vaadin.client.ui.grid.Cell; +import com.vaadin.client.ui.grid.FlyweightCell; +import com.vaadin.client.ui.grid.Grid; +import com.vaadin.client.ui.grid.GridColumn; +import com.vaadin.client.ui.grid.Renderer; +import com.vaadin.client.ui.grid.datasources.ListDataSource; +import com.vaadin.client.ui.grid.datasources.ListSorter; +import com.vaadin.client.ui.grid.renderers.ComplexRenderer; +import com.vaadin.client.ui.grid.renderers.DateRenderer; +import com.vaadin.client.ui.grid.renderers.HtmlRenderer; +import com.vaadin.client.ui.grid.renderers.NumberRenderer; +import com.vaadin.client.ui.grid.renderers.TextRenderer; +import com.vaadin.client.ui.grid.renderers.WidgetRenderer; +import com.vaadin.client.ui.grid.sort.Sort; +import com.vaadin.client.ui.grid.sort.SortEvent; +import com.vaadin.client.ui.grid.sort.SortEventHandler; +import com.vaadin.client.ui.grid.sort.SortOrder; +import com.vaadin.shared.ui.Connect; +import com.vaadin.tests.widgetset.server.grid.GridClientColumnRenderers; + +@Connect(GridClientColumnRenderers.GridController.class) +public class GridClientColumnRendererConnector extends + AbstractComponentConnector { + + public static enum Renderers { + TEXT_RENDERER, WIDGET_RENDERER, HTML_RENDERER, NUMBER_RENDERER, DATE_RENDERER, CPLX_RENDERER; + } + + /** + * Datasource for simulating network latency + */ + private class DelayedDataSource implements DataSource<String> { + + private DataSource<String> ds; + private int firstRowIndex = -1; + private int numberOfRows; + private DataChangeHandler dataChangeHandler; + private int latency; + + public DelayedDataSource(DataSource<String> ds, int latency) { + this.ds = ds; + this.latency = latency; + } + + @Override + public void ensureAvailability(final int firstRowIndex, + final int numberOfRows) { + new Timer() { + + @Override + public void run() { + DelayedDataSource.this.firstRowIndex = firstRowIndex; + DelayedDataSource.this.numberOfRows = numberOfRows; + dataChangeHandler.dataUpdated(firstRowIndex, numberOfRows); + dataChangeHandler + .dataAvailable(firstRowIndex, numberOfRows); + } + }.schedule(latency); + } + + @Override + public String getRow(int rowIndex) { + if (rowIndex >= firstRowIndex + && rowIndex <= firstRowIndex + numberOfRows) { + return ds.getRow(rowIndex); + } + return null; + } + + @Override + public int getEstimatedSize() { + return ds.getEstimatedSize(); + } + + @Override + public void setDataChangeHandler(DataChangeHandler dataChangeHandler) { + this.dataChangeHandler = dataChangeHandler; + } + + @Override + public RowHandle<String> getHandle(String row) { + // TODO Auto-generated method stub (henrik paul: 17.6.) + return null; + } + } + + @Override + protected void init() { + Grid<String> grid = getWidget(); + grid.setSelectionMode(Grid.SelectionMode.NONE); + + // Generated some column data + List<String> columnData = new ArrayList<String>(); + for (int i = 0; i < 100; i++) { + columnData.add(String.valueOf(i)); + } + + // Provide data as data source + if (Location.getParameter("latency") != null) { + grid.setDataSource(new DelayedDataSource( + new ListDataSource<String>(columnData), Integer + .parseInt(Location.getParameter("latency")))); + } else { + grid.setDataSource(new ListDataSource<String>(columnData)); + } + + // Add a column to display the data in + GridColumn<String, String> c = createColumnWithRenderer(Renderers.TEXT_RENDERER); + grid.addColumn(c); + grid.getHeader().getDefaultRow().getCell(c).setText("Column 1"); + + // Add another column with a custom complex renderer + c = createColumnWithRenderer(Renderers.CPLX_RENDERER); + grid.addColumn(c); + grid.getHeader().getDefaultRow().getCell(c).setText("Column 2"); + + // Add method for testing sort event firing + grid.addSortHandler(new SortEventHandler<String>() { + @Override + public void sort(SortEvent<String> event) { + Element console = Document.get().getElementById( + "testDebugConsole"); + String text = "Client-side sort event received<br>" + + "Columns: " + event.getOrder().size() + ", order: "; + for (SortOrder order : event.getOrder()) { + String columnHeader = getWidget().getHeader() + .getDefaultRow().getCell(order.getColumn()) + .getText(); + text += columnHeader + ": " + + order.getDirection().toString(); + } + console.setInnerHTML(text); + } + }); + + // Handle RPC calls + registerRpc(GridClientColumnRendererRpc.class, + new GridClientColumnRendererRpc() { + + @Override + public void addColumn(Renderers renderer) { + + GridColumn<?, String> column; + if (renderer == Renderers.NUMBER_RENDERER) { + column = createNumberColumnWithRenderer(renderer); + } else if (renderer == Renderers.DATE_RENDERER) { + column = createDateColumnWithRenderer(renderer); + } else { + column = createColumnWithRenderer(renderer); + } + getWidget().addColumn(column); + + getWidget() + .getHeader() + .getDefaultRow() + .getCell(column) + .setText( + "Column " + + String.valueOf(getWidget() + .getColumnCount() + 1)); + } + + @Override + public void detachAttach() { + + // Detach + HasWidgets parent = (HasWidgets) getWidget() + .getParent(); + parent.remove(getWidget()); + + // Re-attach + parent.add(getWidget()); + } + + @Override + public void triggerClientSorting() { + getWidget().sort(Sort.by(getWidget().getColumn(0))); + } + + @Override + @SuppressWarnings("unchecked") + public void triggerClientSortingTest() { + Grid<String> grid = getWidget(); + ListSorter<String> sorter = new ListSorter<String>(grid); + + // Make sorter sort the numbers in natural order + sorter.setComparator( + (GridColumn<String, String>) grid.getColumn(0), + new Comparator<String>() { + @Override + public int compare(String o1, String o2) { + return Integer.parseInt(o1) + - Integer.parseInt(o2); + } + }); + + // Sort along column 0 in ascending order + grid.sort(grid.getColumn(0)); + + // Remove the sorter once we're done + sorter.removeFromGrid(); + } + + @Override + @SuppressWarnings("unchecked") + public void shuffle() { + Grid<String> grid = getWidget(); + ListSorter<String> shuffler = new ListSorter<String>( + grid); + + // Make shuffler return random order + shuffler.setComparator( + (GridColumn<String, String>) grid.getColumn(0), + new Comparator<String>() { + @Override + public int compare(String o1, String o2) { + return com.google.gwt.user.client.Random + .nextInt(3) - 1; + } + }); + + // "Sort" (actually shuffle) along column 0 + grid.sort(grid.getColumn(0)); + + // Remove the shuffler when we're done so that it + // doesn't interfere with further operations + shuffler.removeFromGrid(); + } + }); + } + + /** + * Creates a a renderer for a {@link Renderers} + */ + private Renderer createRenderer(Renderers renderer) { + switch (renderer) { + case TEXT_RENDERER: + return new TextRenderer(); + + case WIDGET_RENDERER: + return new WidgetRenderer<String, Button>() { + + @Override + public Button createWidget() { + final Button button = new Button(""); + button.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + button.setText("Clicked"); + } + }); + return button; + } + + @Override + public void render(FlyweightCell cell, String data, + Button button) { + button.setHTML(data); + } + }; + + case HTML_RENDERER: + return new HtmlRenderer() { + + @Override + public void render(FlyweightCell cell, String htmlString) { + super.render(cell, "<b>" + htmlString + "</b>"); + } + }; + + case NUMBER_RENDERER: + return new NumberRenderer<Long>(); + + case DATE_RENDERER: + return new DateRenderer(); + + case CPLX_RENDERER: + return new ComplexRenderer<String>() { + + @Override + public void render(FlyweightCell cell, String data) { + cell.getElement().setInnerHTML("<span>" + data + "</span>"); + cell.getElement().getStyle().clearBackgroundColor(); + } + + @Override + public void setContentVisible(FlyweightCell cell, + boolean hasData) { + + // Visualize content visible property + cell.getElement().getStyle() + .setBackgroundColor(hasData ? "green" : "red"); + + super.setContentVisible(cell, hasData); + } + + @Override + public boolean onActivate(Cell cell) { + cell.getElement().setInnerHTML("<span>Activated!</span>"); + return true; + } + }; + + default: + return new TextRenderer(); + } + } + + private GridColumn<String, String> createColumnWithRenderer( + Renderers renderer) { + return new GridColumn<String, String>(createRenderer(renderer)) { + + @Override + public String getValue(String row) { + return row; + } + }; + } + + private GridColumn<Number, String> createNumberColumnWithRenderer( + Renderers renderer) { + return new GridColumn<Number, String>(createRenderer(renderer)) { + + @Override + public Number getValue(String row) { + return Long.parseLong(row); + } + }; + } + + private GridColumn<Date, String> createDateColumnWithRenderer( + Renderers renderer) { + return new GridColumn<Date, String>(createRenderer(renderer)) { + + @Override + public Date getValue(String row) { + return new Date(); + } + }; + } + + @Override + public Grid<String> getWidget() { + return (Grid<String>) super.getWidget(); + } +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/GridClientColumnRendererRpc.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridClientColumnRendererRpc.java new file mode 100644 index 0000000000..90eee9e1c6 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridClientColumnRendererRpc.java @@ -0,0 +1,48 @@ +/* + * 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.widgetset.client.grid; + +import com.vaadin.shared.communication.ClientRpc; +import com.vaadin.tests.widgetset.client.grid.GridClientColumnRendererConnector.Renderers; + +public interface GridClientColumnRendererRpc extends ClientRpc { + + /** + * Adds a new column with a specific renderer to the grid + * + */ + void addColumn(Renderers renderer); + + /** + * Detaches and attaches the client side Grid + */ + void detachAttach(); + + /** + * Used for client-side sorting API test + */ + void triggerClientSorting(); + + /** + * @since + */ + void triggerClientSortingTest(); + + /** + * @since + */ + void shuffle(); +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/IntArrayRendererConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/IntArrayRendererConnector.java new file mode 100644 index 0000000000..d6873ac0a5 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/IntArrayRendererConnector.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.widgetset.client.grid; + +import com.vaadin.client.ui.grid.FlyweightCell; +import com.vaadin.client.ui.grid.Renderer; +import com.vaadin.client.ui.grid.renderers.AbstractRendererConnector; +import com.vaadin.shared.ui.Connect; + +@Connect(com.vaadin.tests.components.grid.IntArrayRenderer.class) +public class IntArrayRendererConnector extends AbstractRendererConnector<int[]> { + + public static class IntArrayRenderer implements Renderer<int[]> { + private static final String JOINER = " :: "; + + @Override + public void render(FlyweightCell cell, int[] data) { + String text = ""; + for (int i : data) { + text += i + JOINER; + } + if (!text.isEmpty()) { + text = text.substring(0, text.length() - JOINER.length()); + } + cell.getElement().setInnerText(text); + } + } + + @Override + public IntArrayRenderer getRenderer() { + return (IntArrayRenderer) super.getRenderer(); + } +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/PureGWTTestApplication.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/PureGWTTestApplication.java new file mode 100644 index 0000000000..e9c126f232 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/PureGWTTestApplication.java @@ -0,0 +1,308 @@ +/* + * 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.widgetset.client.grid; + +import java.util.ArrayList; +import java.util.List; + +import com.google.gwt.core.client.Scheduler.ScheduledCommand; +import com.google.gwt.dom.client.Style.Unit; +import com.google.gwt.user.client.Element; +import com.google.gwt.user.client.ui.DockLayoutPanel; +import com.google.gwt.user.client.ui.LayoutPanel; +import com.google.gwt.user.client.ui.MenuBar; +import com.google.gwt.user.client.ui.Panel; +import com.vaadin.client.ui.SubPartAware; + +/** + * Pure GWT Test Application base for testing features of a single widget; + * provides a menu system and convenience method for adding items to it. + * + * @since + * @author Vaadin Ltd + */ +public abstract class PureGWTTestApplication<T> extends DockLayoutPanel + implements SubPartAware { + + /** + * Class describing a menu item with an associated action + */ + public static class Command { + private final String title; + private final ScheduledCommand command; + + /** + * Creates a Command object, which is used as an action entry in the + * Menu + * + * @param t + * a title string + * @param cmd + * a scheduled command that is executed when this item is + * selected + */ + public Command(String t, ScheduledCommand cmd) { + title = t; + command = cmd; + } + + /** + * Returns the title of this command item + * + * @return a title string + */ + public final String getTitle() { + return title; + } + + /** + * Returns the actual scheduled command of this command item + * + * @return a scheduled command + */ + public final ScheduledCommand getCommand() { + return command; + } + } + + /** + * A menu object, providing a complete system for building a hierarchical + * menu bar system. + */ + public static class Menu { + + private final String title; + private final MenuBar menubar; + private final List<Menu> children; + private final List<Command> items; + + /** + * Create base-level menu, without a title. This is the root menu bar, + * which can be attached to a client application window. All other Menus + * should be added as child menus to this Menu, in order to maintain a + * nice hierarchy. + */ + private Menu() { + title = ""; + menubar = new MenuBar(); + children = new ArrayList<Menu>(); + items = new ArrayList<Command>(); + } + + /** + * Create a sub-menu, with a title. + * + * @param title + */ + public Menu(String title) { + this.title = title; + menubar = new MenuBar(true); + children = new ArrayList<Menu>(); + items = new ArrayList<Command>(); + } + + /** + * Return the GWT {@link MenuBar} object that provides the widget for + * this Menu + * + * @return a menubar object + */ + public MenuBar getMenuBar() { + return menubar; + } + + /** + * Returns the title of this menu entry + * + * @return a title string + */ + public String getTitle() { + return title; + } + + /** + * Adds a child menu entry to this menu. The title for this entry is + * taken from the Menu object argument. + * + * @param m + * another Menu object + */ + public void addChildMenu(Menu m) { + menubar.addItem(m.title, m.menubar); + children.add(m); + } + + /** + * Tests for the existence of a child menu by title at this level of the + * menu hierarchy + * + * @param title + * a title string + * @return true, if this menu has a direct child menu with the specified + * title, otherwise false + */ + public boolean hasChildMenu(String title) { + return getChildMenu(title) != null; + } + + /** + * Gets a reference to a child menu with a certain title, that is a + * direct child of this menu level. + * + * @param title + * a title string + * @return a Menu object with the specified title string, or null, if + * this menu doesn't have a direct child with the specified + * title. + */ + public Menu getChildMenu(String title) { + for (Menu m : children) { + if (m.title.equals(title)) { + return m; + } + } + return null; + } + + /** + * Adds a command item to the menu. When the entry is clicked, the + * command is executed. + * + * @param cmd + * a command object. + */ + public void addCommand(Command cmd) { + menubar.addItem(cmd.title, cmd.command); + items.add(cmd); + } + + /** + * Tests for the existence of a {@link Command} that is the direct child + * of this level of menu. + * + * @param title + * the command's title + * @return true, if this menu level includes a command item with the + * specified title. Otherwise false. + */ + public boolean hasCommand(String title) { + return getCommand(title) != null; + } + + /** + * Gets a reference to a {@link Command} item that is the direct child + * of this level of menu. + * + * @param title + * the command's title + * @return a command, if found in this menu level, otherwise null. + */ + public Command getCommand(String title) { + for (Command c : items) { + if (c.title.equals(title)) { + return c; + } + } + return null; + } + } + + /** + * Base level menu object, provides visible menu bar + */ + private final Menu menu; + private final T testedWidget; + + /** + * This constructor creates the basic menu bar and adds it to the top of the + * parent {@link DockLayoutPanel} + */ + protected PureGWTTestApplication(T widget) { + super(Unit.PX); + Panel menuPanel = new LayoutPanel(); + menu = new Menu(); + menuPanel.add(menu.getMenuBar()); + addNorth(menuPanel, 25); + testedWidget = widget; + } + + /** + * Connect an item to the menu structure + * + * @param cmd + * a scheduled command; see google's docs + * @param menupath + * path to the item + */ + public void addMenuCommand(String title, ScheduledCommand cmd, + String... menupath) { + Menu m = createMenuPath(menupath); + + m.addCommand(new Command(title, cmd)); + } + + /** + * Create a menu path, if one doesn't already exist, and return the last + * menu in the series. + * + * @param path + * a varargs list or array of strings describing a menu path, + * e.g. "File", "Recent", "User Files", which would result in the + * File menu having a submenu called "Recent" which would have a + * submenu called "User Files". + * @return the last Menu object specified by the path + */ + private Menu createMenuPath(String... path) { + Menu m = menu; + + for (String p : path) { + Menu sub = m.getChildMenu(p); + + if (sub == null) { + sub = new Menu(p); + m.addChildMenu(sub); + } + m = sub; + } + + return m; + } + + @Override + public Element getSubPartElement(String subPart) { + if (testedWidget instanceof SubPartAware) { + return ((SubPartAware) testedWidget).getSubPartElement(subPart); + } + return null; + } + + @Override + public String getSubPartName(Element subElement) { + if (testedWidget instanceof SubPartAware) { + return ((SubPartAware) testedWidget).getSubPartName(subElement); + } + return null; + } + + /** + * Gets the tested widget. + * + * @return tested widget + */ + public T getTestedWidget() { + return testedWidget; + } +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/RowAwareRendererConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/RowAwareRendererConnector.java new file mode 100644 index 0000000000..3880bacae2 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/RowAwareRendererConnector.java @@ -0,0 +1,76 @@ +/* + * 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.widgetset.client.grid; + +import java.util.Arrays; +import java.util.Collection; + +import com.google.gwt.dom.client.BrowserEvents; +import com.google.gwt.dom.client.DivElement; +import com.google.gwt.dom.client.NativeEvent; +import com.google.gwt.user.client.DOM; +import com.vaadin.client.ui.grid.Cell; +import com.vaadin.client.ui.grid.FlyweightCell; +import com.vaadin.client.ui.grid.Renderer; +import com.vaadin.client.ui.grid.renderers.AbstractRendererConnector; +import com.vaadin.client.ui.grid.renderers.ComplexRenderer; +import com.vaadin.shared.communication.ServerRpc; +import com.vaadin.shared.ui.Connect; + +@Connect(com.vaadin.tests.components.grid.RowAwareRenderer.class) +public class RowAwareRendererConnector extends AbstractRendererConnector<Void> { + public interface RowAwareRendererRpc extends ServerRpc { + void clicky(String key); + } + + public class RowAwareRenderer extends ComplexRenderer<Void> { + + @Override + public Collection<String> getConsumedEvents() { + return Arrays.asList(BrowserEvents.CLICK); + } + + @Override + public void init(FlyweightCell cell) { + DivElement div = DivElement.as(DOM.createDiv()); + div.setAttribute("style", + "border: 1px solid red; background: pink;"); + div.setInnerText("Click me!"); + cell.getElement().appendChild(div); + } + + @Override + public void render(FlyweightCell cell, Void data) { + // NOOP + } + + @Override + public boolean onBrowserEvent(Cell cell, NativeEvent event) { + int row = cell.getRow(); + String key = getRowKey(row); + getRpcProxy(RowAwareRendererRpc.class).clicky(key); + cell.getElement().setInnerText("row: " + row + ", key: " + key); + return true; + } + } + + @Override + protected Renderer<Void> createRenderer() { + // cannot use the default createRenderer as RowAwareRenderer needs a + // reference to its connector - it has no "real" no-argument constructor + return new RowAwareRenderer(); + } +} diff --git a/uitest/src/com/vaadin/tests/widgetset/server/grid/GridClientColumnRenderers.java b/uitest/src/com/vaadin/tests/widgetset/server/grid/GridClientColumnRenderers.java new file mode 100644 index 0000000000..db931888bc --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/server/grid/GridClientColumnRenderers.java @@ -0,0 +1,153 @@ +/* + * 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.widgetset.server.grid; + +import java.util.Arrays; + +import com.vaadin.annotations.Widgetset; +import com.vaadin.server.VaadinRequest; +import com.vaadin.shared.ui.label.ContentMode; +import com.vaadin.tests.widgetset.TestingWidgetSet; +import com.vaadin.tests.widgetset.client.grid.GridClientColumnRendererConnector.Renderers; +import com.vaadin.tests.widgetset.client.grid.GridClientColumnRendererRpc; +import com.vaadin.ui.AbstractComponent; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.Button.ClickListener; +import com.vaadin.ui.CssLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.NativeButton; +import com.vaadin.ui.NativeSelect; +import com.vaadin.ui.UI; +import com.vaadin.ui.VerticalLayout; + +@Widgetset(TestingWidgetSet.NAME) +public class GridClientColumnRenderers extends UI { + + /** + * Controls the grid on the client side + */ + public static class GridController extends AbstractComponent { + + private GridClientColumnRendererRpc rpc() { + return getRpcProxy(GridClientColumnRendererRpc.class); + } + + /** + * Adds a new column with a renderer to the grid. + */ + public void addColumn(Renderers renderer) { + rpc().addColumn(renderer); + } + + /** + * Tests detaching and attaching grid + */ + public void detachAttach() { + rpc().detachAttach(); + } + + /** + * @since + */ + public void triggerClientSorting() { + rpc().triggerClientSorting(); + } + + /** + * @since + */ + public void triggerClientSortingTest() { + rpc().triggerClientSortingTest(); + } + + /** + * @since + */ + public void shuffle() { + rpc().shuffle(); + } + } + + @Override + protected void init(VaadinRequest request) { + final GridController controller = new GridController(); + final CssLayout controls = new CssLayout(); + final VerticalLayout content = new VerticalLayout(); + + content.addComponent(controller); + content.addComponent(controls); + setContent(content); + + final NativeSelect select = new NativeSelect( + "Add Column with Renderer", Arrays.asList(Renderers.values())); + select.setValue(Renderers.TEXT_RENDERER); + select.setNullSelectionAllowed(false); + controls.addComponent(select); + + NativeButton addColumnBtn = new NativeButton("Add"); + addColumnBtn.addClickListener(new ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + Renderers renderer = (Renderers) select.getValue(); + controller.addColumn(renderer); + } + }); + controls.addComponent(addColumnBtn); + + NativeButton detachAttachBtn = new NativeButton("DetachAttach"); + detachAttachBtn.addClickListener(new ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + controller.detachAttach(); + } + }); + controls.addComponent(detachAttachBtn); + + NativeButton shuffleButton = new NativeButton("Shuffle"); + shuffleButton.addClickListener(new ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + controller.shuffle(); + } + }); + controls.addComponent(shuffleButton); + + NativeButton sortButton = new NativeButton("Trigger sorting event"); + sortButton.addClickListener(new ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + controller.triggerClientSorting(); + } + }); + controls.addComponent(sortButton); + + NativeButton testSortingButton = new NativeButton("Test sorting"); + testSortingButton.addClickListener(new ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + controller.triggerClientSortingTest(); + } + }); + controls.addComponent(testSortingButton); + + Label console = new Label(); + console.setContentMode(ContentMode.HTML); + console.setId("testDebugConsole"); + content.addComponent(console); + } +} |