org.xwiki.test.ui.po.LiveTableElement.java Source code

Java tutorial

Introduction

Here is the source code for org.xwiki.test.ui.po.LiveTableElement.java

Source

/*
 * See the NOTICE file distributed with this work for additional
 * information regarding copyright ownership.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.xwiki.test.ui.po;

import java.util.List;

import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.TimeoutException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.Select;

/**
 * Represents the actions possible on a livetable.
 * 
 * @version $Id: 9e3225e5ec475ac27b74426efcfe0530cc1a311d $
 * @since 3.2M3
 */
public class LiveTableElement extends BaseElement {
    private String livetableId;

    public LiveTableElement(String livetableId) {
        this.livetableId = livetableId;
    }

    /**
     * @return if the livetable has finished displaying and is ready for service
     */
    public boolean isReady() {
        Object result = executeJavascript(
                "return Element.hasClassName('" + livetableId + "-ajax-loader','hidden')");
        return result instanceof Boolean ? (Boolean) result : false;
    }

    /**
     * Wait till the livetable has finished displaying all its rows (so that we can then assert the livetable content
     * without running the risk that the rows have not been updated yet).
     */
    public void waitUntilReady() {
        long t1 = System.currentTimeMillis();
        while ((System.currentTimeMillis() - t1 < getUtil().getTimeout() * 1000L)) {
            if (isReady()) {
                return;
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                // Do nothing just break out
                break;
            }
        }
        throw new TimeoutException("Livetable isn't ready after the timeout has expired.");
    }

    public boolean hasColumn(String columnTitle) {
        List<WebElement> elements = getUtil().findElementsWithoutWaiting(getDriver(),
                By.xpath("//th[contains(@class, 'xwiki-livetable-display-header-text') and normalize-space(.) = '"
                        + columnTitle + "']"));
        return elements.size() > 0;
    }

    public void filterColumn(String inputId, String filterValue) {
        // Make extra sure Selenium can't go quicker than the live table status by forcing it before filtering.
        executeJavascript("return $('" + livetableId + "-ajax-loader').removeClassName('hidden')");

        WebElement element = getDriver().findElement(By.id(inputId));
        if ("select".equals(element.getTagName())) {
            new Select(element).selectByVisibleText(filterValue);
        } else {
            element.clear();
            element.sendKeys(filterValue);
        }
        waitUntilReady();
    }

    /**
     * @param inputId the filter input identifier
     * @return the value of the filter input for the specified column
     * @see #filterColumn(String, String)
     */
    public String getFilterValue(String inputId) {
        return getDriver().findElement(By.id(inputId)).getAttribute("value");
    }

    /**
     * @param columnTitle the title of live table column
     * @return the 0-based index of the specified column
     */
    public int getColumnIndex(String columnTitle) {
        WebElement liveTable = getDriver().findElement(By.id(livetableId));

        String escapedColumnTitle = columnTitle.replace("\\", "\\\\").replace("'", "\\'");
        String columnXPath = "//thead[@class = 'xwiki-livetable-display-header']//th[normalize-space(.) = '%s']";
        WebElement column = liveTable.findElement(By.xpath(String.format(columnXPath, escapedColumnTitle)));

        return ((Long) ((JavascriptExecutor) getDriver()).executeScript("return arguments[0].cellIndex;", column))
                .intValue();
    }

    /**
     * Checks if there is a row that has the given value for the specified column.
     * 
     * @param columnTitle the title of live table column
     * @param columnValue the value to match rows against
     * @return {@code true} if there is a row that matches the given value for the specified column, {@code false}
     *         otherwise
     */
    public boolean hasRow(String columnTitle, String columnValue) {
        String escapedColumnValue = columnValue.replace("'", "\\'");
        String cellXPath = "//tr/td[position() = %s and . = '%s']";

        WebElement liveTableBody = getDriver().findElement(By.id(livetableId + "-display"));
        return liveTableBody
                .findElements(
                        By.xpath(String.format(cellXPath, getColumnIndex(columnTitle) + 1, escapedColumnValue)))
                .size() > 0;
    }

    /**
     * @return the number of rows in the live table
     */
    public int getRowCount() {
        WebElement liveTableBody = getUtil().findElementWithoutWaiting(getDriver(),
                By.id(livetableId + "-display"));
        // We use XPath because we're interested only in the direct children.
        return getUtil().findElementsWithoutWaiting(getDriver(), liveTableBody, By.xpath("tr")).size();
    }

    /**
     * @since 5.3RC1
     */
    public WebElement getRow(int rowNumber) {
        WebElement liveTableBody = getUtil().findElementWithoutWaiting(getDriver(),
                By.id(livetableId + "-display"));
        return getUtil().findElementWithoutWaiting(getDriver(), liveTableBody, By.xpath("tr[" + rowNumber + "]"));
    }

    /**
     * @since 5.3RC1
     */
    public WebElement getCell(WebElement rowElement, int columnNumber) {
        return getUtil().findElementWithoutWaiting(getDriver(), rowElement, By.xpath("td[" + columnNumber + "]"));
    }

    /**
     * @since 5.3RC1
     */
    public ViewPage clickCell(int rowNumber, int columnNumber) {
        WebElement tdElement = getCell(getRow(rowNumber), columnNumber);
        // First scroll the element into view, if needed, by moving the mouse to the top left corner of the element.
        new Actions(getDriver()).moveToElement(tdElement, 0, 0).perform();
        // Find the first A element and click it!
        tdElement.findElement(By.tagName("a")).click();
        return new ViewPage();
    }

    /**
     * @since 3.2M3
     */
    public void waitUntilRowCountGreaterThan(final int minimalExpectedRowCount) {
        final By by = By.xpath("//tbody[@id = '" + this.livetableId + "-display']//tr");
        getUtil().waitUntilCondition(new ExpectedCondition<Boolean>() {
            @Override
            public Boolean apply(WebDriver driver) {
                return driver.findElements(by).size() >= minimalExpectedRowCount;
            }
        });
    }
}