/* * 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.ArrayList; import java.util.List; import org.openqa.selenium.By; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebDriverException; import org.openqa.selenium.WebElement; import org.openqa.selenium.support.FindBy; import org.openqa.selenium.support.pagefactory.ByChained; import org.openqa.selenium.support.ui.ExpectedCondition; import org.xwiki.test.ui.po.editor.EditPage; /** * Represents the actions possible on the Create Page template page. * * @version $Id: 7ca54039d0ef9c57717711ea12cc4c5eaf2e1446 $ * @since 3.2M3 */ public class CreatePagePage extends ViewPage { /** * The element that contains the document picker used to select the target document. */ @FindBy(className = "location-picker") private WebElement documentPickerElement; private DocumentPicker documentPicker; @FindBy(id = "terminal") private WebElement isTerminalCheckbox; public static CreatePagePage gotoPage() { getUtil().gotoPage("Main", "WebHome", "create"); return new CreatePagePage(); } /** * @return the document picker used to select the target document */ public DocumentPicker getDocumentPicker() { if (this.documentPicker == null) { this.documentPicker = new DocumentPicker(this.documentPickerElement); } return this.documentPicker; } private List<WebElement> getAvailableTemplateInputs() { return getDriver().findElementsWithoutWaiting(By.xpath("//input[@name = 'type' and @data-type = 'template']")); } private List<WebElement> getAvailableTypeInputs() { return getDriver().findElementsWithoutWaiting(By.xpath("//input[@name = 'type']")); } /** * @since 3.2M3 */ public int getAvailableTemplateSize() { return getAvailableTemplateInputs().size(); } public List<String> getAvailableTemplates() { List<String> availableTemplates = new ArrayList<String>(); List<WebElement> templateInputs = getAvailableTemplateInputs(); for (WebElement input : templateInputs) { if (input.getAttribute("value").length() > 0) { availableTemplates.add(input.getAttribute("value")); } } return availableTemplates; } public void setTemplate(String template) { List<WebElement> templates = getAvailableTemplateInputs(); for (WebElement templateInput : templates) { if (templateInput.getAttribute("value").equals(template)) { // Get the label corresponding to the input so we can click on it WebElement label = getDriver().findElementWithoutWaiting( By.xpath("//label[@for = '" + templateInput.getAttribute("id") + "']")); label.click(); return; } } throw new RuntimeException("Failed to find template [" + template + "]"); } public void setType(String type) { List<WebElement> types = getAvailableTypeInputs(); for (WebElement typeInput : types) { if (typeInput.getAttribute("value").equals(type)) { // Get the label corresponding to the input so we can click on it WebElement label = getDriver().findElementWithoutWaiting( By.xpath("//label[@for = '" + typeInput.getAttribute("id") + "']")); label.click(); return; } } throw new RuntimeException("Failed to find type [" + type + "]"); } public void clickCreate() { // Submit the create form. Don`t use the DocumentPicker element since it might not always be there. getDriver().findElementWithoutWaiting(By.id("create")).submit(); } public EditPage createPage(String spaceValue, String pageValue) { return createPage(spaceValue, pageValue, false); } public EditPage createPage(String spaceValue, String pageValue, boolean isTerminalPage) { return createPage(null, spaceValue, pageValue, isTerminalPage); } /** * @since 7.2M3 */ public EditPage createPage(String title, String spaceValue, String pageValue, boolean isTerminalPage) { fillForm(title, spaceValue, pageValue, isTerminalPage); clickCreate(); return new EditPage(); } public EditPage createPageFromTemplate(String spaceValue, String pageValue, String templateValue) { return createPageFromTemplate(null, spaceValue, pageValue, templateValue); } public EditPage createPageFromTemplate(String title, String spaceValue, String pageValue, String templateValue) { return createPageFromTemplate(title, spaceValue, pageValue, templateValue, false); } /** * @since 7.2M1 */ public EditPage createPageFromTemplate(String spaceValue, String pageValue, String templateValue, boolean isTerminalPage) { return createPageFromTemplate(null, spaceValue, pageValue, templateValue, isTerminalPage); } /** * @since 7.2M3 */ public EditPage createPageFromTemplate(String title, String spaceValue, String pageValue, String templateValue, boolean isTerminalPage) { fillForm(title, spaceValue, pageValue, isTerminalPage); setTemplate(templateValue); clickCreate(); return new EditPage(); } /** * @param title document title, ignored if {@code null} * @param spaceReference document's space reference (parent nested document), ignored if {@code null} * @param pageName document's name (space name or page name, depending if terminal or not), ignored if {@code null} * @param isTerminalPage true if the new document is terminal, false for non-terminal * @since public since 7.4M2 */ public void fillForm(String title, String spaceReference, String pageName, boolean isTerminalPage) { if (title != null) { getDocumentPicker().setTitle(title); } if (spaceReference != null) { getDocumentPicker().setParent(spaceReference); } if (pageName != null) { getDocumentPicker().setName(pageName); } // Since the default is to not create terminal pages, only set this if the user is asking to create a terminal // page. This allows this API to work when using isTerminalPage = false even for simpler users which don't get // to see the Terminal option. if (isTerminalPage) { setTerminalPage(isTerminalPage); } } /** * Waits for a global error message in the page. * * @since 3.2M3 */ public void waitForErrorMessage() { getDriver().waitUntilElementIsVisible(By.className("errormessage")); } /** * Waits for a validation error in a field. * * @since 3.2M3 */ public void waitForFieldErrorMessage() { getDriver().waitUntilElementIsVisible(new ByChained(By.className("LV_invalid"))); } /** * @return true if the page to create should be a terminal page, false otherwise * @since 7.2M1 */ public boolean isTerminalPage() { return this.isTerminalCheckbox.isSelected(); } /** * @param isTerminalPage true if the page to create is terminal, false otherwise * @since 7.2M1 */ public void setTerminalPage(boolean isTerminalPage) { if (isTerminalPage != this.isTerminalCheckbox.isSelected()) { this.isTerminalCheckbox.click(); } } /** * @return true if the choice between terminal or non-terminal document is displayed, false otherwise. * @since 7.2M3 */ public boolean isTerminalOptionDisplayed() { List<WebElement> elements = getDriver().findElementsWithoutWaiting(By.id("terminal")); return elements.size() > 0 && elements.get(0).isDisplayed(); } /** * Wait for the location preview to display the passed path string and throw an exception if the timeout is reached. * Note that we need to wait since the Breadcrumb is udated live and asserting its content without waiting would * lead to false positives. * <p> * Note: This method can not be implemented inside {@link BreadcrumbElement} because a change of parent replaces * completely the {@link BreadcrumbElement}'s container and thus it becomes stale. To avoid that, at each wait * iteration, we lookup the current breadcrumb element and not a cached one. * <p> * TODO: Reuse {@link DocumentPicker} inside this PO instead of duplicating this method. * * @param expectedPathString the path string to wait for * @since 7.2RC1 */ public void waitForLocationPreviewContent(final String expectedPathString) { // TODO: Ugly hack. Would need to find a better solution final StringBuilder currentValue = new StringBuilder(); try { getDriver().waitUntilCondition(new ExpectedCondition<Boolean>() { @Override public Boolean apply(WebDriver driver) { try { String value = getDocumentPicker().getLocation().getPathAsString(); currentValue.setLength(0); currentValue.append(value); return expectedPathString.equals(value); } catch (Exception e) { return false; } } }); } catch (WebDriverException e) { // Display a nicer error message than would be displayed otherwise throw new WebDriverException(String.format("Found [%s], was expecting [%s]", currentValue.toString(), expectedPathString), e); } } }