diff options
Diffstat (limited to 'uitest/src/com/vaadin')
43 files changed, 6880 insertions, 0 deletions
diff --git a/uitest/src/com/vaadin/tests/components/grid/BasicEscalator.java b/uitest/src/com/vaadin/tests/components/grid/BasicEscalator.java new file mode 100644 index 0000000000..f7af6a57e5 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/BasicEscalator.java @@ -0,0 +1,319 @@ +/* + * 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.Random; + +import com.vaadin.annotations.Widgetset; +import com.vaadin.server.VaadinRequest; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.tests.widgetset.TestingWidgetSet; +import com.vaadin.tests.widgetset.server.grid.TestGrid; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.HorizontalLayout; +import com.vaadin.ui.Layout; +import com.vaadin.ui.NativeSelect; +import com.vaadin.ui.TextField; + +@Widgetset(TestingWidgetSet.NAME) +public class BasicEscalator extends AbstractTestUI { + public static final String ESCALATOR = "escalator"; + + public static final String INSERT_ROWS_OFFSET = "iro"; + public static final String INSERT_ROWS_AMOUNT = "ira"; + public static final String INSERT_ROWS_BUTTON = "irb"; + + public static final String REMOVE_ROWS_OFFSET = "rro"; + public static final String REMOVE_ROWS_AMOUNT = "rra"; + public static final String REMOVE_ROWS_BUTTON = "rrb"; + + private final Random random = new Random(); + + @Override + protected void setup(final VaadinRequest request) { + final TestGrid grid = new TestGrid(); + grid.setId(ESCALATOR); + addComponent(grid); + + final Layout insertRowsLayout = new HorizontalLayout(); + final TextField insertRowsOffset = new TextField(); + insertRowsOffset.setId(INSERT_ROWS_OFFSET); + insertRowsLayout.addComponent(insertRowsOffset); + final TextField insertRowsAmount = new TextField(); + insertRowsAmount.setId(INSERT_ROWS_AMOUNT); + insertRowsLayout.addComponent(insertRowsAmount); + insertRowsLayout.addComponent(new Button("insert rows", + new Button.ClickListener() { + @Override + public void buttonClick(final ClickEvent event) { + final int offset = Integer.parseInt(insertRowsOffset + .getValue()); + final int amount = Integer.parseInt(insertRowsAmount + .getValue()); + grid.insertRows(offset, amount); + } + }) { + { + setId(INSERT_ROWS_BUTTON); + } + }); + addComponent(insertRowsLayout); + + final Layout removeRowsLayout = new HorizontalLayout(); + final TextField removeRowsOffset = new TextField(); + removeRowsOffset.setId(REMOVE_ROWS_OFFSET); + removeRowsLayout.addComponent(removeRowsOffset); + final TextField removeRowsAmount = new TextField(); + removeRowsAmount.setId(REMOVE_ROWS_AMOUNT); + removeRowsLayout.addComponent(removeRowsAmount); + removeRowsLayout.addComponent(new Button("remove rows", + new Button.ClickListener() { + @Override + public void buttonClick(final ClickEvent event) { + final int offset = Integer.parseInt(removeRowsOffset + .getValue()); + final int amount = Integer.parseInt(removeRowsAmount + .getValue()); + grid.removeRows(offset, amount); + } + }) { + { + setId(REMOVE_ROWS_BUTTON); + } + }); + addComponent(removeRowsLayout); + + final Layout insertColumnsLayout = new HorizontalLayout(); + final TextField insertColumnsOffset = new TextField(); + insertColumnsLayout.addComponent(insertColumnsOffset); + final TextField insertColumnsAmount = new TextField(); + insertColumnsLayout.addComponent(insertColumnsAmount); + insertColumnsLayout.addComponent(new Button("insert columns", + new Button.ClickListener() { + @Override + public void buttonClick(final ClickEvent event) { + final int offset = Integer.parseInt(insertColumnsOffset + .getValue()); + final int amount = Integer.parseInt(insertColumnsAmount + .getValue()); + grid.insertColumns(offset, amount); + } + })); + addComponent(insertColumnsLayout); + + final Layout removeColumnsLayout = new HorizontalLayout(); + final TextField removeColumnsOffset = new TextField(); + removeColumnsLayout.addComponent(removeColumnsOffset); + final TextField removeColumnsAmount = new TextField(); + removeColumnsLayout.addComponent(removeColumnsAmount); + removeColumnsLayout.addComponent(new Button("remove columns", + new Button.ClickListener() { + @Override + public void buttonClick(final ClickEvent event) { + final int offset = Integer.parseInt(removeColumnsOffset + .getValue()); + final int amount = Integer.parseInt(removeColumnsAmount + .getValue()); + grid.removeColumns(offset, amount); + } + })); + addComponent(removeColumnsLayout); + + final HorizontalLayout rowScroll = new HorizontalLayout(); + final NativeSelect destination = new NativeSelect(); + destination.setNullSelectionAllowed(false); + destination.addItem("any"); + destination.setValue("any"); + destination.addItem("start"); + destination.addItem("end"); + destination.addItem("middle"); + rowScroll.addComponent(destination); + final TextField rowIndex = new TextField(); + rowScroll.addComponent(rowIndex); + final TextField rowPadding = new TextField(); + rowScroll.addComponent(rowPadding); + rowScroll.addComponent(new Button("scroll to row", + new Button.ClickListener() { + @Override + public void buttonClick(final ClickEvent event) { + int index; + try { + index = Integer.parseInt(rowIndex.getValue()); + } catch (NumberFormatException e) { + index = 0; + } + + int padding; + try { + padding = Integer.parseInt(rowPadding.getValue()); + } catch (NumberFormatException e) { + padding = 0; + } + + grid.scrollToRow(index, + (String) destination.getValue(), padding); + } + })); + addComponent(rowScroll); + + final HorizontalLayout colScroll = new HorizontalLayout(); + final NativeSelect colDestination = new NativeSelect(); + colDestination.setNullSelectionAllowed(false); + colDestination.addItem("any"); + colDestination.setValue("any"); + colDestination.addItem("start"); + colDestination.addItem("end"); + colDestination.addItem("middle"); + colScroll.addComponent(colDestination); + final TextField colIndex = new TextField(); + colScroll.addComponent(colIndex); + final TextField colPadding = new TextField(); + colScroll.addComponent(colPadding); + colScroll.addComponent(new Button("scroll to column", + new Button.ClickListener() { + @Override + public void buttonClick(final ClickEvent event) { + int index; + try { + index = Integer.parseInt(colIndex.getValue()); + } catch (NumberFormatException e) { + index = 0; + } + + int padding; + try { + padding = Integer.parseInt(colPadding.getValue()); + } catch (NumberFormatException e) { + padding = 0; + } + + grid.scrollToColumn(index, + (String) colDestination.getValue(), padding); + } + })); + addComponent(colScroll); + + final TextField freezeCount = new TextField(); + freezeCount.setConverter(Integer.class); + freezeCount.setNullRepresentation(""); + addComponent(new HorizontalLayout(freezeCount, new Button( + "set frozen columns", new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + grid.setFrozenColumns(((Integer) freezeCount + .getConvertedValue()).intValue()); + freezeCount.setValue(null); + } + }))); + + addComponent(new Button("Resize randomly", new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + int width = random.nextInt(300) + 500; + int height = random.nextInt(300) + 200; + grid.setWidth(width + "px"); + grid.setHeight(height + "px"); + } + })); + + addComponent(new Button("Random headers count", + new Button.ClickListener() { + private int headers = 1; + + @Override + public void buttonClick(ClickEvent event) { + int diff = 0; + while (diff == 0) { + final int nextHeaders = random.nextInt(4); + diff = nextHeaders - headers; + headers = nextHeaders; + } + if (diff > 0) { + grid.insertHeaders(0, diff); + } else if (diff < 0) { + grid.removeHeaders(0, -diff); + } + } + })); + + addComponent(new Button("Random footers count", + new Button.ClickListener() { + private int footers = 1; + + @Override + public void buttonClick(ClickEvent event) { + int diff = 0; + while (diff == 0) { + final int nextFooters = random.nextInt(4); + diff = nextFooters - footers; + footers = nextFooters; + } + if (diff > 0) { + grid.insertFooters(0, diff); + } else if (diff < 0) { + grid.removeFooters(0, -diff); + } + } + })); + + final Layout resizeColumnsLayout = new HorizontalLayout(); + final TextField resizeColumnIndex = new TextField(); + resizeColumnsLayout.addComponent(resizeColumnIndex); + final TextField resizeColumnPx = new TextField(); + resizeColumnsLayout.addComponent(resizeColumnPx); + resizeColumnsLayout.addComponent(new Button("resize column", + new Button.ClickListener() { + @Override + public void buttonClick(final ClickEvent event) { + final int index = Integer.parseInt(resizeColumnIndex + .getValue()); + final int px = Integer.parseInt(resizeColumnPx + .getValue()); + grid.setColumnWidth(index, px); + } + })); + addComponent(resizeColumnsLayout); + + addComponent(new Button("Autoresize columns", + new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + grid.calculateColumnWidths(); + } + })); + + addComponent(new Button("Randomize row heights", + new Button.ClickListener() { + @Override + public void buttonClick(ClickEvent event) { + grid.randomizeDefaultRowHeight(); + } + })); + } + + @Override + protected String getTestDescription() { + return null; + } + + @Override + protected Integer getTicketNumber() { + return null; + } + +} diff --git a/uitest/src/com/vaadin/tests/components/grid/BasicEscalatorTest.java b/uitest/src/com/vaadin/tests/components/grid/BasicEscalatorTest.java new file mode 100644 index 0000000000..ba0b718f35 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/BasicEscalatorTest.java @@ -0,0 +1,295 @@ +/* + * 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.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.JavascriptExecutor; +import org.openqa.selenium.Keys; +import org.openqa.selenium.NoSuchElementException; +import org.openqa.selenium.WebDriver; +import org.openqa.selenium.WebElement; + +import com.vaadin.tests.annotations.TestCategory; +import com.vaadin.tests.tb3.MultiBrowserTest; + +@TestCategory("grid") +public class BasicEscalatorTest extends MultiBrowserTest { + + private static final int SLEEP = 300; + + private static final Pattern ROW_PATTERN = Pattern + .compile("Row (\\d+): \\d+,\\d+"); + + @Test + public void testInitialState() throws Exception { + openTestURL(); + + WebElement cell1 = getBodyRowCell(0, 0); + assertEquals("Top left body cell had unexpected content", "Row 0: 0,0", + cell1.getText()); + + WebElement cell2 = getBodyRowCell(15, 3); + assertEquals("Lower merged cell had unexpected content", "Cell: 3,15", + cell2.getText()); + } + + @Test + public void testScroll() throws Exception { + openTestURL(); + + /* + * let the DOM stabilize itself. TODO: remove once waitForVaadin + * supports lazy loaded components + */ + Thread.sleep(100); + + setScrollTop(getVerticalScrollbar(), 1000); + assertBodyCellWithContentIsFound("Row 50: 0,50"); + } + + @Test + public void testLastRow() throws Exception { + openTestURL(); + + /* + * let the DOM stabilize itself. TODO: remove once waitForVaadin + * supports lazy loaded components + */ + Thread.sleep(100); + + // scroll to bottom + setScrollTop(getVerticalScrollbar(), 100000000); + + /* + * this test does not test DOM reordering, therefore we don't rely on + * child indices - we simply seek by content. + */ + assertBodyCellWithContentIsFound("Row 99: 0,99"); + } + + @Test + public void testNormalRowHeight() throws Exception { + /* + * This is tested with screenshots instead of CSS queries, since some + * browsers report dimensions differently from each other, which is + * uninteresting for our purposes + */ + openTestURL(); + compareScreen("normalHeight"); + } + + @Test + public void testModifiedRowHeight() throws Exception { + /* + * This is tested with screenshots instead of CSS queries, since some + * browsers report dimensions differently from each other, which is + * uninteresting for our purposes + */ + openTestURLWithTheme("reindeer-tests"); + compareScreen("modifiedHeight"); + } + + private void assertBodyCellWithContentIsFound(String cellContent) { + String xpath = "//tbody/tr/td[.='" + cellContent + "']"; + try { + assertNotNull("received a null element with \"" + xpath + "\"", + getDriver().findElement(By.xpath(xpath))); + } catch (NoSuchElementException e) { + fail("Could not find '" + xpath + "'"); + } + } + + private WebElement getBodyRowCell(int row, int col) { + return getDriver().findElement( + By.xpath("//tbody/tr[@class='v-escalator-row'][" + (row + 1) + + "]/td[" + (col + 1) + "]")); + } + + private void openTestURLWithTheme(String themeName) { + String testUrl = getTestUrl(); + testUrl += (testUrl.contains("?")) ? "&" : "?"; + testUrl += "theme=" + themeName; + getDriver().get(testUrl); + } + + private Object executeScript(String script, WebElement element) { + @SuppressWarnings("hiding") + 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()); + } + } + + @Test + public void domIsInitiallySorted() throws Exception { + openTestURL(); + + final List<WebElement> rows = getBodyRows(); + assertTrue("no body rows found", !rows.isEmpty()); + for (int i = 0; i < rows.size(); i++) { + String text = rows.get(i).getText(); + String expected = "Row " + i; + assertTrue("Expected \"" + expected + "...\" but was " + text, + text.startsWith(expected)); + } + } + + @Test + public void domIsSortedAfterInsert() throws Exception { + openTestURL(); + + final int rowsToInsert = 5; + final int offset = 5; + insertRows(offset, rowsToInsert); + + final List<WebElement> rows = getBodyRows(); + int i = 0; + for (; i < offset + rowsToInsert; i++) { + final String expectedStart = "Row " + i; + final String text = rows.get(i).getText(); + assertTrue("Expected \"" + expectedStart + "...\" but was " + text, + text.startsWith(expectedStart)); + } + + for (; i < rows.size(); i++) { + final String expectedStart = "Row " + (i - rowsToInsert); + final String text = rows.get(i).getText(); + assertTrue("(post insert) Expected \"" + expectedStart + + "...\" but was " + text, text.startsWith(expectedStart)); + } + } + + @Test + public void domIsSortedAfterRemove() throws Exception { + openTestURL(); + + final int rowsToRemove = 5; + final int offset = 5; + removeRows(offset, rowsToRemove); + + final List<WebElement> rows = getBodyRows(); + int i = 0; + for (; i < offset; i++) { + final String expectedStart = "Row " + i; + final String text = rows.get(i).getText(); + assertTrue("Expected " + expectedStart + "... but was " + text, + text.startsWith(expectedStart)); + } + + /* + * We check only up to 10, since after that, the indices are again + * reset, because new rows have been generated. The row numbers that + * they are given depends on the widget size, and it's too fragile to + * rely on some special assumptions on that. + */ + for (; i < 10; i++) { + final String expectedStart = "Row " + (i + rowsToRemove); + final String text = rows.get(i).getText(); + assertTrue("(post remove) Expected " + expectedStart + + "... but was " + text, text.startsWith(expectedStart)); + } + } + + @Test + public void domIsSortedAfterScroll() throws Exception { + openTestURL(); + setScrollTop(getVerticalScrollbar(), 500); + + /* + * Let the DOM reorder itself. + * + * TODO TestBench currently doesn't know when Grid's DOM structure is + * stable. There are some plans regarding implementing support for this, + * so this test case can (should) be modified once that's implemented. + */ + sleep(SLEEP); + + List<WebElement> rows = getBodyRows(); + int firstRowNumber = parseFirstRowNumber(rows); + + for (int i = 0; i < rows.size(); i++) { + final String expectedStart = "Row " + (i + firstRowNumber); + final String text = rows.get(i).getText(); + assertTrue("(post remove) Expected " + expectedStart + + "... but was " + text, text.startsWith(expectedStart)); + } + } + + private static int parseFirstRowNumber(List<WebElement> rows) + throws NumberFormatException { + final WebElement firstRow = rows.get(0); + final String firstRowText = firstRow.getText(); + final Matcher matcher = ROW_PATTERN.matcher(firstRowText); + if (!matcher.find()) { + fail("could not find " + ROW_PATTERN.pattern() + " in \"" + + firstRowText + "\""); + } + final String number = matcher.group(1); + return Integer.parseInt(number); + } + + private void insertRows(final int offset, final int amount) { + final WebElement offsetInput = vaadinElementById(BasicEscalator.INSERT_ROWS_OFFSET); + offsetInput.sendKeys(String.valueOf(offset), Keys.RETURN); + + final WebElement amountInput = vaadinElementById(BasicEscalator.INSERT_ROWS_AMOUNT); + amountInput.sendKeys(String.valueOf(amount), Keys.RETURN); + + final WebElement button = vaadinElementById(BasicEscalator.INSERT_ROWS_BUTTON); + button.click(); + } + + private void removeRows(final int offset, final int amount) { + final WebElement offsetInput = vaadinElementById(BasicEscalator.REMOVE_ROWS_OFFSET); + offsetInput.sendKeys(String.valueOf(offset), Keys.RETURN); + + final WebElement amountInput = vaadinElementById(BasicEscalator.REMOVE_ROWS_AMOUNT); + amountInput.sendKeys(String.valueOf(amount), Keys.RETURN); + + final WebElement button = vaadinElementById(BasicEscalator.REMOVE_ROWS_BUTTON); + button.click(); + } + + private void setScrollTop(WebElement element, long px) { + executeScript("arguments[0].scrollTop = " + px, element); + } + + private List<WebElement> getBodyRows() { + return getDriver().findElements(By.xpath("//tbody/tr/td[1]")); + } + + private WebElement getVerticalScrollbar() { + return getDriver().findElement( + By.xpath("//div[" + + "contains(@class, 'v-escalator-scroller-vertical')" + + "]")); + } +} 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..fd3c8d5b2f --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/GridClientRenderers.java @@ -0,0 +1,260 @@ +/* + * 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.WebElement; +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.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); + } + } + } + + 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..be12c2bcb2 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/GridColspans.java @@ -0,0 +1,81 @@ +/* + * 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"); + + footer.setVisible(true); + } + + @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..bd8cad45c6 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/GridElement.java @@ -0,0 +1,279 @@ +/* + * 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"; + + public boolean isActive() { + return getAttribute("class").contains(ACTIVE_CLASS_NAME); + } + + public boolean isActiveHeader() { + return getAttribute("class").contains(ACTIVE_HEADER_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..142c370e13 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/IntArrayRenderer.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; + +import org.json.JSONArray; +import org.json.JSONException; + +import com.vaadin.ui.components.grid.AbstractRenderer; + +public class IntArrayRenderer extends AbstractRenderer<int[]> { + public IntArrayRenderer() { + super(int[].class); + } + + @Override + public Object encode(int[] value) { + try { + return new JSONArray(value); + } catch (JSONException e) { + throw new RuntimeException(e); + } + } +} 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..f55f5f064c --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/RowAwareRenderer.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; + +import org.json.JSONObject; + +import com.vaadin.tests.widgetset.client.grid.RowAwareRendererConnector.RowAwareRendererRpc; +import com.vaadin.ui.Label; +import com.vaadin.ui.components.grid.AbstractRenderer; + +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 Object encode(Void value) { + return JSONObject.NULL; + } + +} 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..d54b1838ea --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeatures.java @@ -0,0 +1,701 @@ +/* + * 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.ArrayList; +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(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); + + createGridActions(); + + createColumnActions(); + + createHeaderActions(); + + createFooterActions(); + + createRowActions(); + + 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 = (new ArrayList(grid + .getContainerDatasource() + .getContainerPropertyIds()) + .get((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)); + } + }, 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 = (new ArrayList(grid + .getContainerDatasource() + .getContainerPropertyIds()) + .get((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 = (new ArrayList(grid + .getContainerDatasource() + .getContainerPropertyIds()) + .get((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 = (new ArrayList(grid + .getContainerDatasource() + .getContainerPropertyIds()) + .get((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 = (new ArrayList(grid + .getContainerDatasource() + .getContainerPropertyIds()) + .get((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 = (new ArrayList(grid + .getContainerDatasource() + .getContainerPropertyIds()) + .get((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); + + createClickAction("Add first row", "Body rows", + 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++) { + item.getItemProperty(getColumnProperty(i)) + .setValue("newcell: " + i); + } + } + }, 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); + } + + @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..6ef0ab5006 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java @@ -0,0 +1,110 @@ +/* + * 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; + } + + 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()); + } + } + + private 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..ece9fdf7d7 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientColumnPropertiesTest.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.basicfeatures.client; + +import static org.junit.Assert.assertEquals; + +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); + } + +} 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..fe81380296 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridClientKeyEventsTest.java @@ -0,0 +1,108 @@ +/* + * 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.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()); + + } + } + +} 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/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/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..024be65e83 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridSortingTest.java @@ -0,0 +1,197 @@ +/* + * 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 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..19a68a87f4 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStaticSectionComponentTest.java @@ -0,0 +1,55 @@ +/* + * 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(); + + // Clicking also triggers sorting + assertEquals("2. Button clicked!", getLogRow(2)); + } + + @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..7c5607d4e6 --- /dev/null +++ b/uitest/src/com/vaadin/tests/components/grid/basicfeatures/server/GridStructureTest.java @@ -0,0 +1,229 @@ +/* + * 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.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()); + } + + 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/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..a7210236d4 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java @@ -0,0 +1,755 @@ +/* + * 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.List; +import java.util.Random; + +import com.google.gwt.core.client.Scheduler.ScheduledCommand; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.HTML; +import com.vaadin.client.ui.VLabel; +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.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.keyevents.BodyKeyDownHandler; +import com.vaadin.client.ui.grid.keyevents.BodyKeyPressHandler; +import com.vaadin.client.ui.grid.keyevents.BodyKeyUpHandler; +import com.vaadin.client.ui.grid.keyevents.FooterKeyDownHandler; +import com.vaadin.client.ui.grid.keyevents.FooterKeyPressHandler; +import com.vaadin.client.ui.grid.keyevents.FooterKeyUpHandler; +import com.vaadin.client.ui.grid.keyevents.GridKeyDownEvent; +import com.vaadin.client.ui.grid.keyevents.GridKeyPressEvent; +import com.vaadin.client.ui.grid.keyevents.GridKeyUpEvent; +import com.vaadin.client.ui.grid.keyevents.HeaderKeyDownHandler; +import com.vaadin.client.ui.grid.keyevents.HeaderKeyPressHandler; +import com.vaadin.client.ui.grid.keyevents.HeaderKeyUpHandler; +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.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 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); + + 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(); + + grid.getElement().getStyle().setZIndex(0); + addNorth(grid, 400); + + createKeyHandlers(); + } + + 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; + addMenuCommand("Visible", new ScheduledCommand() { + @Override + public void execute() { + grid.getColumn(index).setVisible( + !grid.getColumn(index).isVisible()); + } + }, "Component", "Columns", "Column " + i); + addMenuCommand("Sortable", new ScheduledCommand() { + @Override + public void execute() { + grid.getColumn(index).setSortable( + !grid.getColumn(index).isSortable()); + } + }, "Component", "Columns", "Column " + i); + + addMenuCommand("auto", new ScheduledCommand() { + @Override + public void execute() { + grid.getColumn(index).setWidth(-1); + } + }, "Component", "Columns", "Column " + i, "Width"); + addMenuCommand("50px", new ScheduledCommand() { + @Override + public void execute() { + grid.getColumn(index).setWidth(50); + } + }, "Component", "Columns", "Column " + i, "Width"); + addMenuCommand("200px", new ScheduledCommand() { + @Override + public void execute() { + grid.getColumn(index).setWidth(200); + } + }, "Component", "Columns", "Column " + i, "Width"); + + // Header types + addMenuCommand("Text Header", new ScheduledCommand() { + @Override + public void execute() { + grid.getHeader().getRow(0).getCell(index) + .setText("Text Header"); + } + }, "Component", "Columns", "Column " + i, "Header Type"); + addMenuCommand("HTML Header", new ScheduledCommand() { + @Override + public void execute() { + grid.getHeader().getRow(0).getCell(index) + .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(index).setWidget(button); + } + }, "Component", "Columns", "Column " + i, "Header Type"); + + // Footer types + addMenuCommand("Text Footer", new ScheduledCommand() { + @Override + public void execute() { + grid.getFooter().getRow(0).getCell(index) + .setText("Text Footer"); + } + }, "Component", "Columns", "Column " + i, "Footer Type"); + addMenuCommand("HTML Footer", new ScheduledCommand() { + @Override + public void execute() { + grid.getFooter().getRow(0).getCell(index) + .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(index).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(i).setText(caption); + } else if (i % 2 == 0) { + row.getCell(i).setHtml("<b>" + caption + "</b>"); + } else { + row.getCell(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(i).setText(caption); + } else if (i % 2 == 0) { + row.getCell(i).setHtml("<b>" + caption + "</b>"); + } else { + row.getCell(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(0), row.getCell(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 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(0), row.getCell(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.addKeyDownHandler(new BodyKeyDownHandler<List<Data>>() { + private final VLabel label = labels.get(0); + + @Override + public void onKeyDown(GridKeyDownEvent<List<Data>> event) { + updateLabel(label, event); + } + }); + + grid.addKeyDownHandler(new HeaderKeyDownHandler<List<Data>>() { + private final VLabel label = labels.get(1); + + @Override + public void onKeyDown(GridKeyDownEvent<List<Data>> event) { + updateLabel(label, event); + } + }); + + grid.addKeyDownHandler(new FooterKeyDownHandler<List<Data>>() { + private final VLabel label = labels.get(2); + + @Override + public void onKeyDown(GridKeyDownEvent<List<Data>> event) { + updateLabel(label, event); + } + }); + + // Key Up Events + grid.addKeyUpHandler(new BodyKeyUpHandler<List<Data>>() { + private final VLabel label = labels.get(3); + + @Override + public void onKeyUp(GridKeyUpEvent<List<Data>> event) { + updateLabel(label, event); + } + }); + + grid.addKeyUpHandler(new HeaderKeyUpHandler<List<Data>>() { + private final VLabel label = labels.get(4); + + @Override + public void onKeyUp(GridKeyUpEvent<List<Data>> event) { + updateLabel(label, event); + } + }); + + grid.addKeyUpHandler(new FooterKeyUpHandler<List<Data>>() { + private final VLabel label = labels.get(5); + + @Override + public void onKeyUp(GridKeyUpEvent<List<Data>> event) { + updateLabel(label, event); + } + }); + + // Key Press Events + grid.addKeyPressHandler(new BodyKeyPressHandler<List<Data>>() { + private final VLabel label = labels.get(6); + + @Override + public void onKeyPress(GridKeyPressEvent<List<Data>> event) { + updateLabel(label, event); + } + }); + + grid.addKeyPressHandler(new HeaderKeyPressHandler<List<Data>>() { + private final VLabel label = labels.get(7); + + @Override + public void onKeyPress(GridKeyPressEvent<List<Data>> event) { + updateLabel(label, event); + } + }); + + grid.addKeyPressHandler(new FooterKeyPressHandler<List<Data>>() { + private final VLabel label = labels.get(8); + + @Override + public void onKeyPress(GridKeyPressEvent<List<Data>> event) { + updateLabel(label, event); + } + }); + + } + + private void updateLabel(VLabel label, + AbstractGridKeyEvent<List<Data>, ?> 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..7a9f8a06f5 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/GridClientColumnRendererConnector.java @@ -0,0 +1,378 @@ +/* + * 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.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(0).setText("Column 1"); + + // Add another column with a custom complex renderer + c = createColumnWithRenderer(Renderers.CPLX_RENDERER); + grid.addColumn(c); + grid.getHeader().getDefaultRow().getCell(1).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()) { + int colIdx = getWidget().getColumns().indexOf( + order.getColumn()); + String columnHeader = getWidget().getHeader() + .getDefaultRow().getCell(colIdx).getText(); + text += columnHeader + ": " + + order.getDirection().toString(); + } + console.setInnerHTML(text); + } + }); + + // Handle RPC calls + registerRpc(GridClientColumnRendererRpc.class, + new GridClientColumnRendererRpc() { + + @Override + public void addColumn(Renderers renderer) { + + if (renderer == Renderers.NUMBER_RENDERER) { + GridColumn<Number, String> numberColumn = createNumberColumnWithRenderer(renderer); + getWidget().addColumn(numberColumn); + + } else if (renderer == Renderers.DATE_RENDERER) { + GridColumn<Date, String> dateColumn = createDateColumnWithRenderer(renderer); + getWidget().addColumn(dateColumn); + + } else { + GridColumn<String, String> column = createColumnWithRenderer(renderer); + getWidget().addColumn(column); + } + + int idx = getWidget().getColumnCount() - 1; + getWidget() + .getHeader() + .getDefaultRow() + .getCell(idx) + .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); + } + }; + + 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/client/grid/TestGridClientRpc.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/TestGridClientRpc.java new file mode 100644 index 0000000000..ae2799d228 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/TestGridClientRpc.java @@ -0,0 +1,48 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.widgetset.client.grid; + +import com.vaadin.shared.communication.ClientRpc; + +public interface TestGridClientRpc extends ClientRpc { + void insertRows(int offset, int amount); + + void removeRows(int offset, int amount); + + void insertColumns(int offset, int amount); + + void removeColumns(int offset, int amount); + + void scrollToRow(int index, String destination, int padding); + + void scrollToColumn(int index, String destination, int padding); + + void setFrozenColumns(int frozenColumns); + + void insertHeaders(int index, int amount); + + void removeHeaders(int index, int amount); + + void insertFooters(int index, int amount); + + void removeFooters(int index, int amount); + + void setColumnWidth(int index, int px); + + void calculateColumnWidths(); + + void randomRowHeight(); +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/TestGridConnector.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/TestGridConnector.java new file mode 100644 index 0000000000..6dbff5ca66 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/TestGridConnector.java @@ -0,0 +1,138 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.widgetset.client.grid; + +import com.google.gwt.user.client.Random; +import com.vaadin.client.ui.AbstractComponentConnector; +import com.vaadin.shared.ui.Connect; +import com.vaadin.shared.ui.grid.ScrollDestination; +import com.vaadin.tests.widgetset.server.grid.TestGrid; + +/** + * @since + * @author Vaadin Ltd + */ +@Connect(TestGrid.class) +public class TestGridConnector extends AbstractComponentConnector { + @Override + protected void init() { + super.init(); + registerRpc(TestGridClientRpc.class, new TestGridClientRpc() { + @Override + public void insertRows(int offset, int amount) { + getWidget().insertRows(offset, amount); + } + + @Override + public void removeRows(int offset, int amount) { + getWidget().removeRows(offset, amount); + } + + @Override + public void removeColumns(int offset, int amount) { + getWidget().removeColumns(offset, amount); + } + + @Override + public void insertColumns(int offset, int amount) { + getWidget().insertColumns(offset, amount); + } + + @Override + public void scrollToRow(int index, String destination, int padding) { + getWidget().scrollToRow(index, getDestination(destination), + padding); + } + + @Override + public void scrollToColumn(int index, String destination, + int padding) { + getWidget().scrollToColumn(index, getDestination(destination), + padding); + } + + private ScrollDestination getDestination(String destination) { + final ScrollDestination d; + if (destination.equals("start")) { + d = ScrollDestination.START; + } else if (destination.equals("middle")) { + d = ScrollDestination.MIDDLE; + } else if (destination.equals("end")) { + d = ScrollDestination.END; + } else { + d = ScrollDestination.ANY; + } + return d; + } + + @Override + public void setFrozenColumns(int frozenColumns) { + getWidget().getColumnConfiguration().setFrozenColumnCount( + frozenColumns); + } + + @Override + public void insertHeaders(int index, int amount) { + getWidget().getHeader().insertRows(index, amount); + } + + @Override + public void removeHeaders(int index, int amount) { + getWidget().getHeader().removeRows(index, amount); + } + + @Override + public void insertFooters(int index, int amount) { + getWidget().getFooter().insertRows(index, amount); + } + + @Override + public void removeFooters(int index, int amount) { + getWidget().getFooter().removeRows(index, amount); + } + + @Override + public void setColumnWidth(int index, int px) { + getWidget().getColumnConfiguration().setColumnWidth(index, px); + } + + @Override + public void calculateColumnWidths() { + getWidget().calculateColumnWidths(); + } + + @Override + public void randomRowHeight() { + getWidget().getHeader().setDefaultRowHeight( + Random.nextInt(20) + 20); + getWidget().getBody().setDefaultRowHeight( + Random.nextInt(20) + 20); + getWidget().getFooter().setDefaultRowHeight( + Random.nextInt(20) + 20); + } + }); + } + + @Override + public VTestGrid getWidget() { + return (VTestGrid) super.getWidget(); + } + + @Override + public TestGridState getState() { + return (TestGridState) super.getState(); + } +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/TestGridState.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/TestGridState.java new file mode 100644 index 0000000000..ecbc59552b --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/TestGridState.java @@ -0,0 +1,29 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.widgetset.client.grid; + +import com.vaadin.shared.AbstractComponentState; + +/** + * @since + * @author Vaadin Ltd + */ +public class TestGridState extends AbstractComponentState { + public static final String DEFAULT_HEIGHT = "400.0px"; + + /* TODO: this should be "100%" before setting final. */ + public static final String DEFAULT_WIDTH = "800.0px"; +} diff --git a/uitest/src/com/vaadin/tests/widgetset/client/grid/VTestGrid.java b/uitest/src/com/vaadin/tests/widgetset/client/grid/VTestGrid.java new file mode 100644 index 0000000000..fbce00fc11 --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/client/grid/VTestGrid.java @@ -0,0 +1,249 @@ +package com.vaadin.tests.widgetset.client.grid; + +import java.util.ArrayList; +import java.util.List; + +import com.google.gwt.user.client.Window.Location; +import com.google.gwt.user.client.ui.Composite; +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.FlyweightCell; +import com.vaadin.client.ui.grid.Row; +import com.vaadin.client.ui.grid.RowContainer; +import com.vaadin.shared.ui.grid.ScrollDestination; + +public class VTestGrid extends Composite { + + private static abstract class TestEscalatorUpdater implements + EscalatorUpdater { + + @Override + public void preAttach(Row row, Iterable<FlyweightCell> cellsToAttach) { + } + + @Override + public void postAttach(Row row, Iterable<FlyweightCell> attachedCells) { + } + + @Override + public void preDetach(Row row, Iterable<FlyweightCell> cellsToDetach) { + } + + @Override + public void postDetach(Row row, Iterable<FlyweightCell> detachedCells) { + } + } + + private static 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) { + if (cell.getColumn() % 3 == 0) { + cell.setColSpan(2); + } + + final Integer columnName = columns + .get(cell.getColumn()); + cell.getElement().setInnerText("Header " + columnName); + } + } + }; + } + + public EscalatorUpdater createFooterUpdater() { + return new TestEscalatorUpdater() { + @Override + public void update(final Row row, + final Iterable<FlyweightCell> cellsToUpdate) { + for (final FlyweightCell cell : cellsToUpdate) { + if (cell.getColumn() % 3 == 1) { + cell.setColSpan(2); + } + + final Integer columnName = columns + .get(cell.getColumn()); + cell.getElement().setInnerText("Footer " + columnName); + } + } + }; + } + + public EscalatorUpdater createBodyUpdater() { + return new TestEscalatorUpdater() { + private int i = 0; + + 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 (shouldRenderPretty()) { + cellInfo += " (" + i + ")"; + } + + if (cell.getColumn() > 0) { + cell.getElement().setInnerText("Cell: " + cellInfo); + } else { + cell.getElement().setInnerText( + "Row " + cell.getRow() + ": " + cellInfo); + } + + if (cell.getColumn() % 3 == cell.getRow() % 3) { + cell.setColSpan(3); + } + + if (shouldRenderPretty()) { + final double c = i * .1; + final int r = (int) ((Math.cos(c) + 1) * 128); + final int g = (int) ((Math.cos(c / Math.PI) + 1) * 128); + final int b = (int) ((Math.cos(c / (Math.PI * 2)) + 1) * 128); + cell.getElement() + .getStyle() + .setBackgroundColor( + "rgb(" + r + "," + g + "," + b + ")"); + if ((r * .8 + g * 1.3 + b * .9) / 3 < 127) { + cell.getElement().getStyle().setColor("white"); + } else { + cell.getElement().getStyle().clearColor(); + } + } + + i++; + } + + private boolean shouldRenderPretty() { + return Location.getQueryString().contains("pretty"); + } + + @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); + } + } + } + + private final Escalator escalator = new Escalator(); + private final Data data = new Data(); + + public VTestGrid() { + initWidget(escalator); + final RowContainer header = escalator.getHeader(); + header.setEscalatorUpdater(data.createHeaderUpdater()); + header.insertRows(0, 1); + + final RowContainer footer = escalator.getFooter(); + footer.setEscalatorUpdater(data.createFooterUpdater()); + footer.insertRows(0, 1); + + escalator.getBody().setEscalatorUpdater(data.createBodyUpdater()); + + insertRows(0, 100); + insertColumns(0, 10); + + setWidth(TestGridState.DEFAULT_WIDTH); + setHeight(TestGridState.DEFAULT_HEIGHT); + + } + + public void insertRows(final int offset, final int number) { + data.insertRows(offset, number); + escalator.getBody().insertRows(offset, number); + } + + public void insertColumns(final int offset, final int number) { + data.insertColumns(offset, number); + escalator.getColumnConfiguration().insertColumns(offset, number); + } + + public ColumnConfiguration getColumnConfiguration() { + return escalator.getColumnConfiguration(); + } + + public void scrollToRow(final int index, + final ScrollDestination destination, final int padding) { + escalator.scrollToRow(index, destination, padding); + } + + public void scrollToColumn(final int index, + final ScrollDestination destination, final int padding) { + escalator.scrollToColumn(index, destination, padding); + } + + public void removeRows(final int offset, final int amount) { + data.removeRows(offset, amount); + escalator.getBody().removeRows(offset, amount); + } + + public void removeColumns(final int offset, final int amount) { + data.removeColumns(offset, amount); + escalator.getColumnConfiguration().removeColumns(offset, amount); + } + + @Override + public void setWidth(String width) { + escalator.setWidth(width); + } + + @Override + public void setHeight(String height) { + escalator.setHeight(height); + } + + public RowContainer getHeader() { + return escalator.getHeader(); + } + + public RowContainer getBody() { + return escalator.getBody(); + } + + public RowContainer getFooter() { + return escalator.getFooter(); + } + + public void calculateColumnWidths() { + escalator.calculateColumnWidths(); + } +} 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); + } +} diff --git a/uitest/src/com/vaadin/tests/widgetset/server/grid/TestGrid.java b/uitest/src/com/vaadin/tests/widgetset/server/grid/TestGrid.java new file mode 100644 index 0000000000..0dbb60359d --- /dev/null +++ b/uitest/src/com/vaadin/tests/widgetset/server/grid/TestGrid.java @@ -0,0 +1,96 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.tests.widgetset.server.grid; + +import com.vaadin.tests.widgetset.client.grid.TestGridClientRpc; +import com.vaadin.tests.widgetset.client.grid.TestGridState; +import com.vaadin.ui.AbstractComponent; + +/** + * @since + * @author Vaadin Ltd + */ +public class TestGrid extends AbstractComponent { + public TestGrid() { + setWidth(TestGridState.DEFAULT_WIDTH); + setHeight(TestGridState.DEFAULT_HEIGHT); + } + + @Override + protected TestGridState getState() { + return (TestGridState) super.getState(); + } + + public void insertRows(int offset, int amount) { + rpc().insertRows(offset, amount); + } + + public void removeRows(int offset, int amount) { + rpc().removeRows(offset, amount); + } + + public void insertColumns(int offset, int amount) { + rpc().insertColumns(offset, amount); + } + + public void removeColumns(int offset, int amount) { + rpc().removeColumns(offset, amount); + } + + private TestGridClientRpc rpc() { + return getRpcProxy(TestGridClientRpc.class); + } + + public void scrollToRow(int index, String destination, int padding) { + rpc().scrollToRow(index, destination, padding); + } + + public void scrollToColumn(int index, String destination, int padding) { + rpc().scrollToColumn(index, destination, padding); + } + + public void setFrozenColumns(int frozenColumns) { + rpc().setFrozenColumns(frozenColumns); + } + + public void insertHeaders(int index, int amount) { + rpc().insertHeaders(index, amount); + } + + public void removeHeaders(int index, int amount) { + rpc().removeHeaders(index, amount); + } + + public void insertFooters(int index, int amount) { + rpc().insertFooters(index, amount); + } + + public void removeFooters(int index, int amount) { + rpc().removeFooters(index, amount); + } + + public void setColumnWidth(int index, int px) { + rpc().setColumnWidth(index, px); + } + + public void calculateColumnWidths() { + rpc().calculateColumnWidths(); + } + + public void randomizeDefaultRowHeight() { + rpc().randomRowHeight(); + } +} |