org.xwiki.test.wysiwyg.framework.XWikiExplorer.java Source code

Java tutorial

Introduction

Here is the source code for org.xwiki.test.wysiwyg.framework.XWikiExplorer.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.wysiwyg.framework;

import java.util.List;

import org.apache.commons.lang3.StringUtils;
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.support.ui.ExpectedCondition;
import org.xwiki.test.ui.XWikiWebDriver;

/**
 * Utility class used to write integration tests involving the XWiki Explorer tree.
 * 
 * @version $Id: 08d6ba557079b82af53b36e7f16c3c0482b8d86d $
 */
public class XWikiExplorer {
    private static final String FINDER_LOCATOR = "//input[@class = 'xtree-finder' and following-sibling::div[contains(@class, 'xExplorer')]]";

    private static final By SELECTED_NODE = By
            .xpath("//div[contains(@class, 'xExplorer')]//li[@role = 'treeitem' and @aria-selected = 'true']");

    private final XWikiWebDriver driver;

    /**
     * Creates a new XWikiExplorer that uses the passed web driver.
     * 
     * @param driver the web driver
     */
    public XWikiExplorer(XWikiWebDriver driver) {
        this.driver = driver;
    }

    /**
     * Open the node that corresponds to the specified space.
     * 
     * @param spaceName the space name
     * @return this
     */
    public XWikiExplorer openSpace(String spaceName) {
        return open(getSpaceNodeId(spaceName));
    }

    /**
     * Open the node that corresponds to the specified page.
     * 
     * @param spaceName the space name
     * @param pageName the page name
     * @return this
     */
    public XWikiExplorer openPage(String spaceName, String pageName) {
        return open(getDocumentNodeId(spaceName, pageName));
    }

    /**
     * Open the node that corresponds to the 'Attachments' meta node of the specified page.
     * 
     * @param spaceName the space name
     * @param pageName the page name
     * @return this
     */
    public XWikiExplorer openAttachments(String spaceName, String pageName) {
        return open(getAttachmentsNodeId(spaceName, pageName));
    }

    private XWikiExplorer open(String nodeId) {
        // Select the node first in order to scroll it into view. Clicking on the toggle to expand the node has no
        // effect otherwise (Selenium doesn't manage to scroll the node into view when the toggle is clicked).
        select(nodeId);

        String toggleLocatorFormat = "//div[contains(@class, 'xExplorer')]//li[@id = '%s'"
                + " and @aria-expanded = '%s']/i[contains(@class, 'jstree-ocl')]";
        this.driver.findElementByXPath(String.format(toggleLocatorFormat, nodeId, false)).click();
        this.driver.waitUntilElementIsVisible(By.xpath(String.format(toggleLocatorFormat, nodeId, true)));

        return this;
    }

    /**
     * Select the node that corresponds to the specified space.
     * 
     * @param spaceName the space name
     * @return this
     */
    public XWikiExplorer selectSpace(String spaceName) {
        return select(getSpaceNodeId(spaceName));
    }

    /**
     * Select the node that corresponds to the 'New page...' meta node of the specified space.
     * 
     * @param spaceName the space name
     * @return this
     */
    public XWikiExplorer selectNewPage(String spaceName) {
        return select(getNewDocumentNodeId(spaceName));
    }

    /**
     * Select the node that corresponds to the specified page.
     * 
     * @param spaceName the space name
     * @param pageName the page name
     * @return this
     */
    public XWikiExplorer selectPage(String spaceName, String pageName) {
        return select(getDocumentNodeId(spaceName, pageName));
    }

    /**
     * Toggles the selection of the specified page by clicking the label of the corresponding node while holding the
     * Control key down.
     * 
     * @param spaceName the space name
     * @param pageName the page name
     * @return
     */
    public XWikiExplorer togglePageSelection(String spaceName, String pageName) {
        return toggleSelection(getDocumentNodeId(spaceName, pageName));
    }

    /**
     * Select the node that corresponds to the 'Upload file...' meta node of the specified page.
     * 
     * @param spaceName the space name
     * @param pageName the page name
     * @return this
     */
    public XWikiExplorer selectNewAttachment(String spaceName, String pageName) {
        return select(String.format("addAttachment:xwiki:%s.%s", spaceName, pageName));
    }

    /**
     * Select the node that corresponds to the specified attachment.
     * 
     * @param spaceName the space name
     * @param pageName the page name
     * @param fileName the file name
     * @return this
     */
    public XWikiExplorer selectAttachment(String spaceName, String pageName, String fileName) {
        return select(getAttachmentNodeId(spaceName, pageName, fileName));
    }

    private XWikiExplorer select(String nodeId) {
        this.driver.findElementByXPath(getNodeLocator(nodeId) + "/a[@class = 'jstree-anchor']").click();
        return this;
    }

    private XWikiExplorer toggleSelection(String nodeId) {
        WebElement node = this.driver
                .findElementByXPath(getNodeLocator(nodeId) + "/a[contains(@class, 'jstree-anchor')]");
        new Actions(this.driver).keyDown(Keys.CONTROL).click(node).keyUp(Keys.CONTROL).perform();
        return this;
    }

    /**
     * @param spaceName the space name
     * @return {@code true} if the node corresponding to the specified space is present in the tree
     */
    public boolean hasSpace(String spaceName) {
        return hasNode(getSpaceNodeId(spaceName));
    }

    /**
     * @param spaceName the space name
     * @param pageName the page name
     * @return {@code true} if the node corresponding to the specified page is present in the tree
     */
    public boolean hasPage(String spaceName, String pageName) {
        return hasNode(getDocumentNodeId(spaceName, pageName));
    }

    /**
     * @param spaceName the space name
     * @param pageName the page name
     * @param fileName the file name
     * @return {@code true} if the node corresponding to the specified attachment is present in the tree
     */
    public boolean hasAttachment(String spaceName, String pageName, String fileName) {
        return hasNode(getAttachmentNodeId(spaceName, pageName, fileName));
    }

    private boolean hasNode(String nodeId) {
        return this.driver.hasElementWithoutWaiting(By.xpath(getNodeLocator(nodeId)));
    }

    /**
     * Types the given space name into the finder and selects the first suggestions that matches the space name.
     * 
     * @param spaceName the space name
     * @return this
     */
    public XWikiExplorer findAndSelectSpace(String spaceName) {
        find(spaceName).selectSpace(spaceName);
        return waitForNodeSelected();
    }

    /**
     * Types the given page title into the finder and selects the first suggestions that matches the page title.
     * 
     * @param pageTitle the page title
     * @return this
     */
    public XWikiExplorer findAndSelectPage(String pageTitle) {
        find(pageTitle).selectPage(pageTitle);
        return waitForNodeSelected();
    }

    /**
     * Types the given file name into the finder and selects the first suggestions that matches the file name.
     * 
     * @param fileName the file name
     * @return this
     */
    public XWikiExplorer findAndSelectAttachment(String fileName) {
        find(fileName).selectAttachment(fileName);
        return waitForNodeSelected();
    }

    /**
     * Type the given text into the finder and wait for suggestions.
     * 
     * @param text the text to find
     * @return the suggestions page
     */
    public TreeSuggestionsPane find(String text) {
        WebElement finder = this.driver.findElementByXPath(FINDER_LOCATOR);
        finder.clear();
        finder.sendKeys(text);
        // Wait for the list of suggestions.
        this.driver.waitUntilElementIsVisible(By
                .xpath("//div[contains(@class, 'xtree-finder-suggestions')]//ul[contains(@class, 'suggestList')]"));
        return new TreeSuggestionsPane(this.driver);
    }

    /**
     * Wait for the tree to load.
     * 
     * @return this
     */
    public XWikiExplorer waitForIt() {
        // The editor attempts to open the tree to a specified node. If the node is found then it is selected. Otherwise
        // the value of the finder is set to the node id. Thus we wait for a node to be selected or for the finder to
        // have a non-empty value.
        this.driver.waitUntilCondition(new ExpectedCondition<Boolean>() {
            @Override
            public Boolean apply(WebDriver input) {
                List<WebElement> finders = XWikiExplorer.this.driver
                        .findElementsWithoutWaiting(By.xpath(FINDER_LOCATOR));
                return (!finders.isEmpty() && !StringUtils.isEmpty(finders.get(0).getAttribute("value")))
                        || XWikiExplorer.this.driver.hasElementWithoutWaiting(SELECTED_NODE);
            }
        });
        return this;
    }

    /**
     * Waits for the specified page to be selected.
     * 
     * @param spaceName the name of the space containing the page
     * @param pageName the name of the page to wait for
     * @return this
     */
    public XWikiExplorer waitForPageSelected(String spaceName, String pageName) {
        return waitForNodeSelected(getDocumentNodeId(spaceName, pageName));
    }

    /**
     * Waits for the "New page.." node under the specified space to be selected.
     * 
     * @param spaceName the name of the space where the new page would be created
     * @return this
     */
    public XWikiExplorer waitForNewPageSelected(String spaceName) {
        return waitForNodeSelected(getNewDocumentNodeId(spaceName));
    }

    /**
     * Waits for the specified attachment to be selected.
     * 
     * @param spaceName the name of the space containing the page
     * @param pageName the name of the page who has the attachment
     * @param fileName the attachment file name
     * @return this
     */
    public XWikiExplorer waitForAttachmentSelected(String spaceName, String pageName, String fileName) {
        return waitForNodeSelected(getAttachmentNodeId(spaceName, pageName, fileName));
    }

    /**
     * Waits for the attachments node of the specified page to be selected. The attachments node is the parent node for
     * all the attachments of a page.
     * 
     * @param spaceName the space containing the page
     * @param pageName the name of the page whose attachments node is selected
     * @return this
     */
    public XWikiExplorer waitForAttachmentsSelected(String spaceName, String pageName) {
        return waitForNodeSelected(getAttachmentsNodeId(spaceName, pageName));
    }

    private XWikiExplorer waitForNodeSelected() {
        this.driver.waitUntilElementIsVisible(SELECTED_NODE);
        return this;
    }

    private XWikiExplorer waitForNodeSelected(String nodeId) {
        this.driver.waitUntilElementIsVisible(By.xpath(String.format(
                "//div[contains(@class, 'xExplorer')]//li[@id = '%s' and @aria-selected = 'true']", nodeId)));
        return this;
    }

    public XWikiExplorer waitForFinderValue(final String value) {
        this.driver.waitUntilElementHasAttributeValue(By.xpath(FINDER_LOCATOR), "value", value);
        return this;
    }

    private String getDocumentNodeId(String spaceName, String pageName) {
        return String.format("document:xwiki:%s.%s", spaceName, pageName);
    }

    private String getNewDocumentNodeId(String spaceName) {
        return String.format("addDocument:xwiki:%s.WebHome", spaceName);
    }

    private String getSpaceNodeId(String spaceName) {
        return "space:xwiki:" + spaceName;
    }

    private String getAttachmentNodeId(String spaceName, String pageName, String fileName) {
        return String.format("attachment:xwiki:%s.%s@%s", spaceName, pageName, fileName);
    }

    private String getAttachmentsNodeId(String spaceName, String pageName) {
        return String.format("attachments:xwiki:%s.%s", spaceName, pageName);
    }

    private String getNodeLocator(String nodeId) {
        return String.format("//div[contains(@class, 'xExplorer')]//li[@id = '%s']", nodeId);
    }
}