getEscalator().resetSizesFromDom();
}
+ /**
+ * Sets a new details generator for row details.
+ * <p>
+ * The currently opened row details will be re-rendered.
+ *
+ * @since
+ * @param detailsGenerator
+ * the details generator to set
+ */
+ public void setDetailsGenerator(DetailsGenerator detailsGenerator)
+ throws IllegalArgumentException {
+
+ this.detailsGenerator = detailsGenerator;
+
+ // this will refresh all visible spacers
+ escalator.getBody().setSpacerUpdater(gridSpacerUpdater);
+ }
+
+ /**
+ * Gets the current details generator for row details.
+ *
+ * @since
+ * @return the detailsGenerator the current details generator
+ */
+ public DetailsGenerator getDetailsGenerator() {
+ return detailsGenerator;
+ }
+
+ /**
+ * Shows or hides the details for a specific row.
+ *
+ * @since
+ * @param row
+ * the index of the affected row
+ * @param visible
+ * <code>true</code> to show the details, or <code>false</code>
+ * to hide them
+ */
+ public void setDetailsVisible(int rowIndex, boolean visible) {
+ double height = visible ? DETAILS_ROW_INITIAL_HEIGHT : -1;
+ escalator.getBody().setSpacer(rowIndex, height);
+ }
++
+ /**
+ * Requests that the column widths should be recalculated.
+ * <p>
+ * The actual recalculation is not necessarily done immediately so you
+ * cannot rely on the columns being the correct width after the call
+ * returns.
+ *
+ * @since
+ */
+ public void recalculateColumnWidths() {
+ autoColumnWidthsRecalculator.schedule();
+ }
}
+++ /dev/null
--/*
-- * Copyright 2000-2014 Vaadin Ltd.
-- *
-- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
-- * use this file except in compliance with the License. You may obtain a copy of
-- * the License at
-- *
-- * http://www.apache.org/licenses/LICENSE-2.0
-- *
-- * Unless required by applicable law or agreed to in writing, software
-- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-- * License for the specific language governing permissions and limitations under
-- * the License.
-- */
--package com.vaadin.testbench.elements;
--
--import java.util.ArrayList;
--import java.util.List;
--
--import org.openqa.selenium.NoSuchElementException;
--import org.openqa.selenium.WebElement;
--
--import com.vaadin.testbench.By;
--import com.vaadin.testbench.TestBenchElement;
-import com.vaadin.testbench.elementsbase.AbstractElement;
-import com.vaadin.testbench.elementsbase.ServerClass;
--
--/**
- * TestBench Element API for Grid.
- * TestBench Element API for Grid
-- *
-- * @since
-- * @author Vaadin Ltd
-- */
--@ServerClass("com.vaadin.ui.Grid")
--public class GridElement extends AbstractComponentElement {
--
-- public static class GridCellElement extends AbstractElement {
--
-- private static final String FOCUSED_CELL_CLASS_NAME = "-cell-focused";
-- private static final String FROZEN_CLASS_NAME = "frozen";
--
-- public boolean isFocused() {
-- return getAttribute("class").contains(FOCUSED_CELL_CLASS_NAME);
-- }
--
-- public boolean isFrozen() {
-- return getAttribute("class").contains(FROZEN_CLASS_NAME);
-- }
-- }
--
-- public static class GridRowElement extends AbstractElement {
--
-- private static final String FOCUSED_CLASS_NAME = "-row-focused";
-- private static final String SELECTED_CLASS_NAME = "-row-selected";
--
-- public boolean isFocused() {
-- return getAttribute("class").contains(FOCUSED_CLASS_NAME);
-- }
--
-- @Override
-- public boolean isSelected() {
-- return getAttribute("class").contains(SELECTED_CLASS_NAME);
-- }
-- }
--
-- public static class GridEditorElement extends AbstractElement {
--
-- private GridElement grid;
--
-- private GridEditorElement setGrid(GridElement grid) {
-- this.grid = grid;
-- return this;
-- }
--
-- /**
-- * Gets the editor field for column in given index.
-- *
-- * @param colIndex
-- * the column index
-- * @return the editor field for given location
-- *
-- * @throws NoSuchElementException
-- * if {@code isEditable(colIndex) == false}
-- */
-- public TestBenchElement getField(int colIndex) {
-- return grid.getSubPart("#editor[" + colIndex + "]");
-- }
--
-- /**
-- * Gets whether the column with the given index is editable, that is,
-- * has an associated editor field.
-- *
-- * @param colIndex
-- * the column index
-- * @return {@code true} if the column has an editor field, {@code false}
-- * otherwise
-- */
-- public boolean isEditable(int colIndex) {
-- return grid
-- .isElementPresent(By.vaadin("#editor[" + colIndex + "]"));
-- }
--
-- /**
-- * Checks whether a field is marked with an error.
-- *
-- * @param colIndex
-- * column index
-- * @return <code>true</code> iff the field is marked with an error
-- */
-- public boolean isFieldErrorMarked(int colIndex) {
-- return getField(colIndex).getAttribute("class").contains("error");
-- }
--
-- /**
-- * Saves the fields of this editor.
-- * <p>
-- * <em>Note:</em> that this closes the editor making this element
-- * useless.
-- */
-- public void save() {
-- findElement(By.className("v-grid-editor-save")).click();
-- }
--
-- /**
-- * Cancels this editor.
-- * <p>
-- * <em>Note:</em> that this closes the editor making this element
-- * useless.
-- */
-- public void cancel() {
-- findElement(By.className("v-grid-editor-cancel")).click();
-- }
--
-- /**
-- * Gets the error message text, or <code>null</code> if no message is
-- * present.
-- */
-- public String getErrorMessage() {
-- WebElement messageWrapper = findElement(By
-- .className("v-grid-editor-message"));
-- List<WebElement> divs = messageWrapper.findElements(By
-- .tagName("div"));
-- if (divs.isEmpty()) {
-- return null;
-- } else {
-- return divs.get(0).getText();
-- }
-- }
-- }
--
-- /**
- * Scrolls Grid element so that wanted row is displayed.
- * 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.
- * Get header row count
-- *
-- * @return Header row count
-- */
-- public int getHeaderCount() {
-- return getSubPart("#header").findElements(By.xpath("./tr")).size();
-- }
--
-- /**
- * Get footer row count.
- * 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.
- * Get a header row by index
-- *
-- * @param rowIndex
-- * Row index
-- * @return The th element of the row
-- */
-- public TestBenchElement getHeaderRow(int rowIndex) {
-- return getSubPart("#header[" + rowIndex + "]");
-- }
--
-- /**
- * Get a footer row by index.
- * Get a footer row by index
-- *
-- * @param rowIndex
-- * Row index
-- * @return The tr element of the row
-- */
-- public TestBenchElement getFooterRow(int rowIndex) {
-- return getSubPart("#footer[" + rowIndex + "]");
-- }
--
-- /**
- * Get the vertical scroll element.
- * Get the vertical scroll element
-- *
-- * @return The element representing the vertical scrollbar
-- */
-- public TestBenchElement getVerticalScroller() {
-- List<WebElement> rootElements = findElements(By.xpath("./div"));
-- return (TestBenchElement) rootElements.get(0);
-- }
--
-- /**
- * Get the horizontal scroll element.
- * Get the horizontal scroll element
-- *
-- * @return The element representing the horizontal scrollbar
-- */
-- public TestBenchElement getHorizontalScroller() {
-- List<WebElement> rootElements = findElements(By.xpath("./div"));
-- return (TestBenchElement) rootElements.get(1);
-- }
--
-- /**
- * Get the header element.
- * Get the header element
-- *
-- * @return The thead element
-- */
-- public TestBenchElement getHeader() {
-- return getSubPart("#header");
-- }
--
-- /**
- * Get the body element.
- * Get the body element
-- *
-- * @return the tbody element
-- */
-- public TestBenchElement getBody() {
-- return getSubPart("#cell");
-- }
--
-- /**
- * Get the footer element.
- * Get the footer element
-- *
-- * @return the tfoot element
-- */
-- public TestBenchElement getFooter() {
-- return getSubPart("#footer");
-- }
--
-- /**
- * Get the element wrapping the table element.
- * Get the element wrapping the table element
-- *
-- * @return The element that wraps the table element
-- */
-- public TestBenchElement getTableWrapper() {
-- List<WebElement> rootElements = findElements(By.xpath("./div"));
-- return (TestBenchElement) rootElements.get(2);
-- }
--
-- public GridEditorElement getEditor() {
-- return getSubPart("#editor").wrap(GridEditorElement.class)
-- .setGrid(this);
-- }
--
-- /**
- * Helper function to get Grid subparts wrapped correctly.
- * 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));
- }
-
- /**
- * Gets the element that contains the details of a row.
- *
- * @since
- * @param rowIndex
- * the index of the row for the details
- * @return the element that contains the details of a row
- */
- public TestBenchElement getDetails(int rowIndex) {
- return getSubPart("#details[" + rowIndex + "]");
-- }
--}
}
protected void scrollHorizontallyTo(int px) {
- executeScript("arguments[0].scrollLeft = " + px,
- getHorizontalScrollbar());
+ getHorizontalScrollbar().scrollLeft(px);
+ }
+
- private long getScrollLeft() {
++ protected long getScrollLeft() {
+ return ((Long) executeScript("return arguments[0].scrollLeft;",
+ getHorizontalScrollbar())).longValue();
}
- private TestBenchElement getHorizontalScrollbar() {
+ protected TestBenchElement getHorizontalScrollbar() {
return (TestBenchElement) getEscalator().findElement(
By.className("v-escalator-scroller-horizontal"));
}
import com.vaadin.testbench.By;
import com.vaadin.testbench.TestBenchElement;
--import com.vaadin.testbench.elements.GridElement;
++import com.vaadin.tests.components.grid.basicfeatures.element.CustomGridElement;
/**
- * Variant of GridBasicFeaturesTest to be used with GridBasicClientFeatures.
+ * GridBasicClientFeatures.
*
* @since
* @author Vaadin Ltd
}
@Override
-- protected GridElement getGridElement() {
++ protected CustomGridElement getGridElement() {
if (composite) {
// Composite requires the basic client features widget for subparts
return ((TestBenchElement) findElement(By
- .vaadin("//TestWidgetComponent"))).wrap(GridElement.class);
+ .vaadin("//TestWidgetComponent")))
- .wrap(GridElement.class);
++ .wrap(CustomGridElement.class);
} else {
return super.getGridElement();
}
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.testbench.elements.GridElement;
- import com.vaadin.tests.annotations.TestCategory;
+ import com.vaadin.testbench.parallel.TestCategory;
++import com.vaadin.tests.components.grid.basicfeatures.element.CustomGridElement;
import com.vaadin.tests.tb3.MultiBrowserTest;
@TestCategory("grid")
}
}
-- protected GridElement getGridElement() {
++ protected CustomGridElement getGridElement() {
return ((TestBenchElement) findElement(By.id("testComponent")))
-- .wrap(GridElement.class);
++ .wrap(CustomGridElement.class);
}
protected void scrollGridVerticallyTo(double px) {
--- /dev/null
--- /dev/null
++/*
++ * Copyright 2000-2014 Vaadin Ltd.
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
++ * use this file except in compliance with the License. You may obtain a copy of
++ * the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
++ * License for the specific language governing permissions and limitations under
++ * the License.
++ */
++package com.vaadin.tests.components.grid.basicfeatures.client;
++
++import static org.junit.Assert.assertEquals;
++import static org.junit.Assert.assertFalse;
++import static org.junit.Assert.assertNotEquals;
++import static org.junit.Assert.assertNotNull;
++import static org.junit.Assert.assertNull;
++import static org.junit.Assert.assertTrue;
++import static org.junit.Assert.fail;
++
++import org.junit.Before;
++import org.junit.Test;
++import org.openqa.selenium.NoSuchElementException;
++import org.openqa.selenium.WebElement;
++
++import com.vaadin.testbench.By;
++import com.vaadin.testbench.ElementQuery;
++import com.vaadin.testbench.TestBenchElement;
++import com.vaadin.testbench.elements.NotificationElement;
++import com.vaadin.tests.components.grid.basicfeatures.GridBasicClientFeaturesTest;
++
++public class GridDetailsClientTest extends GridBasicClientFeaturesTest {
++
++ private static final String[] SET_GENERATOR = new String[] { "Component",
++ "Row details", "Set generator" };
++ private static final String[] SET_FAULTY_GENERATOR = new String[] {
++ "Component", "Row details", "Set faulty generator" };
++ private static final String[] SET_EMPTY_GENERATOR = new String[] {
++ "Component", "Row details", "Set empty generator" };
++ private static final String[] TOGGLE_DETAILS_FOR_ROW_1 = new String[] {
++ "Component", "Row details", "Toggle details for row 1" };
++ private static final String[] TOGGLE_DETAILS_FOR_ROW_100 = new String[] {
++ "Component", "Row details", "Toggle details for row 100" };
++
++ @Before
++ public void setUp() {
++ setDebug(true);
++ openTestURL();
++ }
++
++ @Test(expected = NoSuchElementException.class)
++ public void noDetailsByDefault() {
++ assertNull("details for row 1 should not exist at the start",
++ getGridElement().getDetails(1));
++ }
++
++ @Test
++ public void nullRendererShowsDetailsPlaceholder() {
++ selectMenuPath(TOGGLE_DETAILS_FOR_ROW_1);
++ TestBenchElement details = getGridElement().getDetails(1);
++ assertNotNull("details for row 1 should not exist at the start",
++ details);
++ assertTrue("details should've been empty for null renderer", details
++ .getText().isEmpty());
++ }
++
++ @Test
++ public void applyRendererThenOpenDetails() {
++ selectMenuPath(SET_GENERATOR);
++ selectMenuPath(TOGGLE_DETAILS_FOR_ROW_1);
++
++ TestBenchElement details = getGridElement().getDetails(1);
++ assertTrue("Unexpected details content",
++ details.getText().startsWith("Row: 1."));
++ }
++
++ @Test
++ public void openDetailsThenAppyRenderer() {
++ selectMenuPath(TOGGLE_DETAILS_FOR_ROW_1);
++ selectMenuPath(SET_GENERATOR);
++
++ TestBenchElement details = getGridElement().getDetails(1);
++ assertTrue("Unexpected details content",
++ details.getText().startsWith("Row: 1."));
++ }
++
++ @Test
++ public void openHiddenDetailsThenScrollToIt() {
++ try {
++ getGridElement().getDetails(100);
++ fail("details row for 100 was apparently found, while it shouldn't have been.");
++ } catch (NoSuchElementException e) {
++ // expected
++ }
++
++ selectMenuPath(SET_GENERATOR);
++ selectMenuPath(TOGGLE_DETAILS_FOR_ROW_100);
++
++ // scroll a bit beyond so we see below.
++ getGridElement().scrollToRow(101);
++
++ TestBenchElement details = getGridElement().getDetails(100);
++ assertTrue("Unexpected details content",
++ details.getText().startsWith("Row: 100."));
++ }
++
++ @Test
++ public void errorUpdaterShowsErrorNotification() {
++ assertFalse("No notifications should've been at the start",
++ $(NotificationElement.class).exists());
++
++ selectMenuPath(TOGGLE_DETAILS_FOR_ROW_1);
++ selectMenuPath(SET_FAULTY_GENERATOR);
++
++ ElementQuery<NotificationElement> notification = $(NotificationElement.class);
++ assertTrue("Was expecting an error notification here",
++ notification.exists());
++ notification.first().close();
++
++ assertEquals("The error details element should be empty", "",
++ getGridElement().getDetails(1).getText());
++ }
++
++ @Test
++ public void updaterStillWorksAfterError() {
++ selectMenuPath(TOGGLE_DETAILS_FOR_ROW_1);
++
++ selectMenuPath(SET_FAULTY_GENERATOR);
++ $(NotificationElement.class).first().close();
++ selectMenuPath(SET_GENERATOR);
++
++ assertNotEquals(
++ "New details should've been generated even after error", "",
++ getGridElement().getDetails(1).getText());
++ }
++
++ @Test
++ public void updaterRendersExpectedWidgets() {
++ selectMenuPath(SET_GENERATOR);
++ selectMenuPath(TOGGLE_DETAILS_FOR_ROW_1);
++
++ TestBenchElement detailsElement = getGridElement().getDetails(1);
++ assertNotNull(detailsElement.findElement(By.className("gwt-Label")));
++ assertNotNull(detailsElement.findElement(By.className("gwt-Button")));
++ }
++
++ @Test
++ public void widgetsInUpdaterWorkAsExpected() {
++ selectMenuPath(SET_GENERATOR);
++ selectMenuPath(TOGGLE_DETAILS_FOR_ROW_1);
++
++ TestBenchElement detailsElement = getGridElement().getDetails(1);
++ WebElement button = detailsElement.findElement(By
++ .className("gwt-Button"));
++ button.click();
++
++ WebElement label = detailsElement
++ .findElement(By.className("gwt-Label"));
++ assertEquals("clicked", label.getText());
++ }
++
++ @Test
++ public void emptyGenerator() {
++ selectMenuPath(SET_EMPTY_GENERATOR);
++ selectMenuPath(TOGGLE_DETAILS_FOR_ROW_1);
++
++ assertEquals("empty generator did not produce an empty details row",
++ "", getGridElement().getDetails(1).getText());
++ }
++
++ @Test(expected = NoSuchElementException.class)
++ public void removeDetailsRow() {
++ selectMenuPath(SET_GENERATOR);
++ selectMenuPath(TOGGLE_DETAILS_FOR_ROW_1);
++ selectMenuPath(TOGGLE_DETAILS_FOR_ROW_1);
++
++ getGridElement().getDetails(1);
++ }
++}
--- /dev/null
--- /dev/null
++/*
++ * Copyright 2000-2014 Vaadin Ltd.
++ *
++ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
++ * use this file except in compliance with the License. You may obtain a copy of
++ * the License at
++ *
++ * http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
++ * License for the specific language governing permissions and limitations under
++ * the License.
++ */
++package com.vaadin.tests.components.grid.basicfeatures.element;
++
++import com.vaadin.testbench.By;
++import com.vaadin.testbench.TestBenchElement;
++import com.vaadin.testbench.elements.GridElement;
++import com.vaadin.testbench.elementsbase.ServerClass;
++
++@ServerClass("com.vaadin.ui.Grid")
++public class CustomGridElement extends GridElement {
++ /**
++ * Gets the element that contains the details of a row.
++ *
++ * @since
++ * @param rowIndex
++ * the index of the row for the details
++ * @return the element that contains the details of a row
++ */
++ public TestBenchElement getDetails(int rowIndex) {
++ return getSubPart("#details[" + rowIndex + "]");
++ }
++
++ private TestBenchElement getSubPart(String subPartSelector) {
++ return (TestBenchElement) findElement(By.vaadin(subPartSelector));
++ }
++}
assertEscalatorIsRemovedCorrectly();
}
- assertEquals("Vertical scroll position", "50", getVerticalScrollbar()
- .getAttribute("scrollTop"));
- assertEquals("Horizontal scroll position", "50",
- getHorizontalScrollbar().getAttribute("scrollLeft"));
+ @Test
+ public void testDetachingAndReattachingAnEscalator() {
+ selectMenuPath(GENERAL, POPULATE_COLUMN_ROW);
+
+ scrollVerticallyTo(50);
+ scrollHorizontallyTo(50);
+
+ selectMenuPath(GENERAL, DETACH_ESCALATOR);
+ selectMenuPath(GENERAL, ATTACH_ESCALATOR);
+
++ assertEquals("Vertical scroll position", 50, getScrollTop());
++ assertEquals("Horizontal scroll position", 50, getScrollLeft());
+
+ assertEquals("First cell of first visible row", "Row 2: 0,2",
+ getBodyCell(0, 0).getText());
+ }
+
private void assertEscalatorIsRemovedCorrectly() {
assertFalse($(NotificationElement.class).exists());
assertNull(getEscalator());