]> source.dussan.org Git - vaadin-framework.git/commitdiff
Merge branch 'master' into HEAD
authorHenrik Paul <henrik@vaadin.com>
Wed, 4 Mar 2015 08:01:31 +0000 (10:01 +0200)
committerHenrik Paul <henrik@vaadin.com>
Wed, 4 Mar 2015 14:07:29 +0000 (16:07 +0200)
Change-Id: Id48abba25a16fe7f8e679e5ce2ab3ab536951676

1  2 
client/src/com/vaadin/client/widgets/Escalator.java
client/src/com/vaadin/client/widgets/Grid.java
uitest/src/com/vaadin/testbench/elements/GridElement.java
uitest/src/com/vaadin/tests/components/grid/basicfeatures/EscalatorBasicClientFeaturesTest.java
uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicClientFeaturesTest.java
uitest/src/com/vaadin/tests/components/grid/basicfeatures/GridBasicFeaturesTest.java
uitest/src/com/vaadin/tests/components/grid/basicfeatures/client/GridDetailsClientTest.java
uitest/src/com/vaadin/tests/components/grid/basicfeatures/element/CustomGridElement.java
uitest/src/com/vaadin/tests/components/grid/basicfeatures/escalator/EscalatorBasicsTest.java
uitest/src/com/vaadin/tests/widgetset/client/grid/GridBasicClientFeaturesWidget.java

index c0936bccec090ac0eda94b80fd261cf28cefc477,3c2d070fa0febed781d38356833311a17e1a74ba..0edcaa9c917c18b0523b6515685f192f9b8d4396
@@@ -6308,46 -6297,16 +6325,59 @@@ public class Grid<T> extends ResizeComp
          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();
+     }
  }
diff --cc uitest/src/com/vaadin/testbench/elements/GridElement.java
index ff7343a3d6ec75b19288f5d0d6a6b86a0edb4ae5,68ddfc878ee8c96be2fd3f7b516575df1f263016..0000000000000000000000000000000000000000
deleted file mode 100644,100644
+++ /dev/null
@@@ -1,377 -1,367 +1,0 @@@
--/*
-- * Copyright 2000-2014 Vaadin Ltd.
-- * 
-- * Licensed under the Apache License, Version 2.0 (the "License"); you may not
-- * use this file except in compliance with the License. You may obtain a copy of
-- * the License at
-- * 
-- * http://www.apache.org/licenses/LICENSE-2.0
-- * 
-- * Unless required by applicable law or agreed to in writing, software
-- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-- * License for the specific language governing permissions and limitations under
-- * the License.
-- */
--package com.vaadin.testbench.elements;
--
--import java.util.ArrayList;
--import java.util.List;
--
--import org.openqa.selenium.NoSuchElementException;
--import org.openqa.selenium.WebElement;
--
--import com.vaadin.testbench.By;
--import com.vaadin.testbench.TestBenchElement;
 -import com.vaadin.testbench.elementsbase.AbstractElement;
 -import com.vaadin.testbench.elementsbase.ServerClass;
--
--/**
-  * TestBench Element API for Grid.
 - * 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 + "]");
--    }
--}
index 853489746f7285888f14381a6a7db4e94a4e1dd2,e03d50415c8faa3fe83882fc133a12a95d2698ea..61c75b61629db7aaef3b03358f6add1867fc84f7
@@@ -258,15 -244,11 +259,15 @@@ public abstract class EscalatorBasicCli
      }
  
      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"));
      }
index d0e076fd3bdc413c3cc663fb3475878e67db5c74,ad3e1fe5ebc8ee17cbd4890c19b89b5d8381c726..44dacb4886dde51004ed335602e685dd24dfb158
@@@ -21,10 -21,10 +21,10 @@@ import org.openqa.selenium.interactions
  
  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
@@@ -79,12 -79,11 +79,12 @@@ public abstract class GridBasicClientFe
      }
  
      @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();
          }
index 0e339ec0ae06bc3200747cb43c971d4f17099d9a,e22fcc422b0d72bfac54e11e856283728e164c37..ad415e416564154eb9528ee8e23c25d72fa176ec
@@@ -23,11 -23,10 +23,10 @@@ import org.openqa.selenium.JavascriptEx
  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")
@@@ -64,9 -59,9 +59,9 @@@ public abstract class GridBasicFeatures
          }
      }
  
--    protected GridElement getGridElement() {
++    protected CustomGridElement getGridElement() {
          return ((TestBenchElement) findElement(By.id("testComponent")))
--                .wrap(GridElement.class);
++                .wrap(CustomGridElement.class);
      }
  
      protected void scrollGridVerticallyTo(double px) {
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..d32b731cf1f00c160246dba76839ee1c5cb5f958
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,184 @@@
++/*
++ * 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);
++    }
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..dc9b8722f2e4c71ccb61506bbce36c3e5bbf63a3
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,40 @@@
++/*
++ * 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));
++    }
++}
index 95ed6ab3ff8ecea0232e4b264dc6ea395f2a7dc7,4742236ac681b09336f34b63359ad9f3849c5f13..1d26477d343346a594264a5695fe63d3cdcc11c7
@@@ -57,6 -56,25 +56,23 @@@ public class EscalatorBasicsTest extend
          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());