org.xwiki.test.ui.po.editor.UserPicker.java Source code

Java tutorial

Introduction

Here is the source code for org.xwiki.test.ui.po.editor.UserPicker.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.editor;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.openqa.selenium.By;
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.xwiki.test.ui.po.BaseElement;

/**
 * Represents the actions possible on the user picker.
 * 
 * @version $Id: eeb76af855f2179802d9cbe0c581d0464f5ce7ba $
 * @since 4.5
 */
public class UserPicker extends BaseElement {
    public static class UserElement extends BaseElement {
        /**
         * The element that wraps the user display.
         */
        private WebElement container;

        /**
         * Creates a new user element that wraps the given {@link WebElement}.
         * 
         * @param container the element that wraps the user display
         */
        public UserElement(WebElement container) {
            this.container = container;
        }

        /**
         * @return the avatar image
         */
        public WebElement getAvatar() {
            return getUtil().findElementWithoutWaiting(getDriver(), container, By.className("icon"));
        }

        /**
         * @return the full user name
         */
        public String getName() {
            String name = getUtil().findElementWithoutWaiting(getDriver(), container, By.className("user-name"))
                    .getText();
            // Remove the "x" coming from the delete icon.
            List<WebElement> delete = getUtil().findElementsWithoutWaiting(getDriver(), container,
                    By.className("delete-tool"));
            if (delete.size() > 0) {
                name = StringUtils.removeEnd(name, delete.get(0).getText());
            }
            return name;
        }

        /**
         * @return the user alias
         */
        public String getAlias() {
            return getUtil().findElementWithoutWaiting(getDriver(), container, By.className("user-alias"))
                    .getText();
        }

        /**
         * @return the text displayed by this element; this is useful when this element is not actually an user but a
         *         message like "User not found"
         */
        public String getText() {
            return container.getText();
        }

        /**
         * Remove this user from the current selection.
         */
        public void delete() {
            new Actions(getDriver()).moveToElement(container)
                    .click(getUtil().findElementWithoutWaiting(getDriver(), container, By.className("delete-tool")))
                    .perform();
        }

        /**
         * Moves the mouse over this element.
         */
        public void moveMouseOver() {
            new Actions(getDriver()).moveToElement(container).perform();
        }

        /**
         * Moves this user before the given user using drag and drop.
         * 
         * @param user the reference user
         */
        public void moveBefore(UserElement user) {
            new Actions(getDriver()).clickAndHold(container).moveToElement(user.container, 0, 0).release()
                    .perform();
        }
    }

    /**
     * The text input that is enhanced with a user picker.
     */
    private final WebElement textInput;

    /**
     * Exposes the user picker bound to the given text input;
     * 
     * @param textInput the text input that is enhanced with a user picker
     */
    public UserPicker(WebElement textInput) {
        this.textInput = textInput;
    }

    /**
     * Types into the text input.
     * 
     * @param keysToSend the keys to type into the text input
     * @return this
     */
    public UserPicker sendKeys(CharSequence... keysToSend) {
        textInput.sendKeys(keysToSend);
        return this;
    }

    /**
     * Clears the content of the text input.
     * 
     * @return this
     */
    public UserPicker clear() {
        textInput.clear();
        return this;
    }

    /**
     * @return the value of the text input
     */
    public String getValue() {
        return textInput.getAttribute("value");
    }

    /**
     * @return the link element used to clear the list of selected users
     */
    public WebElement getClearSelectionLink() {
        String xpath = "preceding-sibling::a[@class = 'clear-tool' and position() = last()]";
        return getUtil().findElementWithoutWaiting(getDriver(), textInput, By.xpath(xpath));
    }

    /**
     * Waits until the suggestions for the current value of the text input are retrieved.
     * 
     * @return this
     */
    public UserPicker waitForSuggestions() {
        getUtil().waitUntilCondition(new ExpectedCondition<Boolean>() {
            public Boolean apply(WebDriver driver) {
                return !textInput.getAttribute("class").contains("loading") && isSuggestListDisplayed(driver);
            }

            private boolean isSuggestListDisplayed(WebDriver driver) {
                WebElement suggestItems = driver.findElement(By.className("suggestItems"));
                // div.suggestItems is added to the document before the suggestions are retrieved. We need to wait for
                // the actual list of suggestions (ul.suggestList).
                WebElement suggestList = suggestItems.findElement(By.className("suggestList"));
                // div.suggestItems fades when closing.
                return suggestList.isDisplayed() && Double.parseDouble(suggestItems.getCssValue("opacity")) == 1;
            }
        });
        return this;
    }

    /**
     * Waits until the list of suggestions disappears.
     * 
     * @param timeout how long to wait, in seconds
     * @return this
     */
    private UserPicker waitForSuggestionsToDisappear(int timeout) {
        int previousTimeout = getUtil().getTimeout();
        getUtil().setTimeout(timeout);
        try {
            getUtil().waitUntilCondition(new ExpectedCondition<Boolean>() {
                public Boolean apply(WebDriver driver) {
                    return driver.findElements(By.className("suggestItems")).size() == 0;
                }
            });
        } finally {
            getUtil().setTimeout(previousTimeout);
        }
        return this;
    }

    /**
     * Waits for the list of suggestions to fade out.
     * 
     * @return this
     */
    public UserPicker waitForSuggestionsToFadeOut() {
        return waitForSuggestionsToDisappear(2);
    }

    /**
     * Waits for the list of suggestions to disappear.
     * 
     * @return this
     */
    public UserPicker waitForSuggestionsToDisappear() {
        return waitForSuggestionsToDisappear(35);
    }

    /**
     * Clicks on the suggestion that contains the given text.
     * 
     * @param userNameOrAlias user name or alias
     * @return this
     */
    public UserPicker select(String userNameOrAlias) {
        getUtil()
                .findElementWithoutWaiting(getDriver(),
                        By.xpath("//ul[@class = 'xlist suggestList']/li[contains(., '" + userNameOrAlias + "')]"))
                .click();
        return this;
    }

    /**
     * @return the list of suggested users based on the value of the text input
     */
    public List<UserElement> getSuggestions() {
        List<UserElement> suggestions = new ArrayList<UserElement>();
        for (WebElement item : getUtil().findElementsWithoutWaiting(getDriver(),
                By.xpath("//ul[@class = 'xlist suggestList']/li"))) {
            suggestions.add(new UserElement(item));
        }
        return suggestions;
    }

    /**
     * @return the list of selected users
     */
    public List<UserElement> getAcceptedSuggestions() {
        List<UserElement> acceptedSuggestions = new ArrayList<UserElement>();
        for (WebElement item : getUtil().findElementsWithoutWaiting(getDriver(), textInput, By.xpath(
                "preceding-sibling::ul[contains(@class, 'accepted-suggestions') and position() = last()]/li"))) {
            acceptedSuggestions.add(new UserElement(item));
        }
        return acceptedSuggestions;
    }

    /**
     * Moves the mouse over the text input.
     * 
     * @return this
     */
    public UserPicker moveMouseOver() {
        new Actions(getDriver()).moveToElement(textInput).perform();
        return this;
    }

    /**
     * Waits for the user picker to load. You need to call this when the initial selection is not empty (because the
     * user picker makes separate requests to retrieve information about the selected users).
     * 
     * @return this
     */
    public UserPicker waitToLoad() {
        getUtil().waitUntilCondition(new ExpectedCondition<Boolean>() {
            public Boolean apply(WebDriver driver) {
                String classNames = textInput.getAttribute("class");
                return classNames.contains("initialized") && !classNames.contains("loading");
            }
        });
        return this;
    }
}