/* * Copyright 2000-2016 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.table; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import java.util.List; import org.junit.Test; import org.openqa.selenium.By; import org.openqa.selenium.Keys; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.interactions.Actions; import org.openqa.selenium.remote.DesiredCapabilities; import org.openqa.selenium.support.ui.ExpectedCondition; import com.vaadin.testbench.elements.TableElement; import com.vaadin.testbench.parallel.Browser; import com.vaadin.tests.tb3.MultiBrowserTest; /** * Tests that navigation with PageDown/PageUp/Home/End in Table works * * @author Vaadin Ltd */ public class TableNavigationPageDownTest extends MultiBrowserTest { private static final int ROW_NUMBER = 50; private int lowerWrapperY = -1; private int pageHeight = -1; private int rowHeight = -1; private WebElement wrapper; @Override public List<DesiredCapabilities> getBrowsersToTest() { // Sending PageDown has no effect on PhantomJS. On IE focus // in Table is often lost, so default scrolling happens on PageDown. return getBrowserCapabilities(Browser.FIREFOX, Browser.CHROME); } @Override public void setup() throws Exception { super.setup(); openTestURL(); TableElement table = $(TableElement.class).first(); rowHeight = table.getCell(1, 0).getLocation().getY() - table.getCell(0, 0).getLocation().getY(); wrapper = findElement(By.className("v-table-body-wrapper")); pageHeight = wrapper.getSize().getHeight(); lowerWrapperY = wrapper.getLocation().getY() + pageHeight; } private void sendKeyUntilEndIsReached(Keys key) { while (true) { int lastVisibleRowNumber = getLastVisibleRowNumber(); sendKey(key); if (!waitUntilLastRowHasChanged(lastVisibleRowNumber)) { break; } } } private void sendKey(Keys key) { new Actions(driver).sendKeys(key).build().perform(); } private boolean waitUntilLastRowHasChanged(final int row) { try { waitUntil(new ExpectedCondition<Boolean>() { @Override public Boolean apply(WebDriver input) { return row != getLastVisibleRowNumber(); } }, 1); return true; } catch (Exception e) { return false; } } private int getLastVisibleRowNumber() { return getRowNumber(getLastVisibleRow()); } private void sendPageDownUntilBottomIsReached() { sendKeyUntilEndIsReached(Keys.PAGE_DOWN); } private void sendPageUpUntilTopIsReached() { sendKeyUntilEndIsReached(Keys.PAGE_UP); } @Test public void navigatePageDown() { // Scroll to a point where you can reach the bottom with a couple of // page downs. // Can't use v-table-body height because lower rows haven't been // fetched yet. testBenchElement(wrapper) .scroll(ROW_NUMBER * rowHeight - (int) (2.8 * pageHeight)); waitForScrollToFinish(); getLastVisibleRow().click(); sendPageDownUntilBottomIsReached(); assertEquals("Last table row should be visible", ROW_NUMBER - 1, getLastVisibleRowNumber()); } @Test public void navigatePageUp() { // Scroll to a point where you can reach the top with a couple of page // ups. testBenchElement(wrapper).scroll((int) (2.8 * pageHeight)); waitForScrollToFinish(); getFirstVisibleRow().click(); sendPageUpUntilTopIsReached(); assertEquals("First table row should be visible", 0, getRowNumber(getFirstVisibleRow())); } @Test public void navigateEndAndHome() { getLastVisibleRow().click(); new Actions(driver).sendKeys(Keys.END).build().perform(); waitForScrollToFinish(); assertEquals("Last table row should be visible", ROW_NUMBER - 1, getRowNumber(getLastVisibleRow())); new Actions(driver).sendKeys(Keys.HOME).build().perform(); waitForScrollToFinish(); assertEquals("First table row should be visible", 0, getRowNumber(getFirstVisibleRow())); } /** * Waits until the scroll position indicator goes away, signifying that all * the required rows have been fetched. */ private void waitForScrollToFinish() { waitUntil(new ExpectedCondition<Boolean>() { @Override public Boolean apply(WebDriver input) { List<WebElement> elements = findElements( By.className("v-table-scrollposition")); return elements.isEmpty() || !elements.get(0).isDisplayed(); } @Override public String toString() { // Timed out after 10 seconds waiting for ... return "scroll position indicator to vanish"; } }); } /** * Returns row number from its first cell */ private int getRowNumber(WebElement row) { return Integer.valueOf(row .findElement(By.className("v-table-cell-wrapper")).getText()); } /** * Returns the first fully visible row */ private WebElement getFirstVisibleRow() { List<WebElement> allFetchedRows = wrapper .findElements(By.tagName("tr")); int wrapperY = wrapper.getLocation().getY(); for (WebElement row : allFetchedRows) { int rowY = row.getLocation().getY(); if ((rowY >= wrapperY) && (rowY - rowHeight <= wrapperY)) { return row; } } fail("Could not find first visible row"); return null; } /** * Returns the last fully visible row */ private WebElement getLastVisibleRow() { List<WebElement> allFetchedRows = wrapper .findElements(By.tagName("tr")); for (WebElement row : allFetchedRows) { int lowerY = row.getLocation().getY() + rowHeight; if ((lowerY <= lowerWrapperY) && (lowerY + rowHeight >= lowerWrapperY)) { return row; } } fail("Could not find last visible row"); return null; } }