001/*
002 * (C) Copyright 2016 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Antoine Taillefer
018 *     Yannis JULIENNE
019 */
020package org.nuxeo.functionaltests.pages.tabs;
021
022import java.util.ArrayList;
023import java.util.List;
024
025import org.apache.commons.logging.Log;
026import org.apache.commons.logging.LogFactory;
027import org.nuxeo.functionaltests.AbstractTest;
028import org.nuxeo.functionaltests.Locator;
029import org.nuxeo.functionaltests.Required;
030import org.nuxeo.functionaltests.pages.DocumentBasePage;
031import org.openqa.selenium.Alert;
032import org.openqa.selenium.By;
033import org.openqa.selenium.NoSuchElementException;
034import org.openqa.selenium.NotFoundException;
035import org.openqa.selenium.WebDriver;
036import org.openqa.selenium.WebDriverException;
037import org.openqa.selenium.WebElement;
038import org.openqa.selenium.support.FindBy;
039import org.openqa.selenium.support.ui.Clock;
040import org.openqa.selenium.support.ui.SystemClock;
041
042import static org.junit.Assert.assertEquals;
043import static org.junit.Assert.fail;
044
045/**
046 * Representation of a Archived versions sub tab page.
047 */
048public class ArchivedVersionsSubPage extends DocumentBasePage {
049
050    private static final Log log = LogFactory.getLog(ArchivedVersionsSubPage.class);
051
052    private static final String DELETE_ACTION_ID = "CURRENT_VERSION_SELECTION_DELETE";
053
054    private static final String VIEW_VERSION_ACTION_ID = "VIEW_VERSION";
055
056    private static final String RESTORE_VERSION_ACTION_ID = "RESTORE_VERSION";
057
058    @Required
059    @FindBy(id = "document_versions")
060    WebElement documentVersions;
061
062    @FindBy(id = "document_versions_form")
063    WebElement documentVersionsForm;
064
065    public ArchivedVersionsSubPage(WebDriver driver) {
066        super(driver);
067    }
068
069    /**
070     * Gets the version labels.
071     *
072     * @return the version labels
073     */
074    public List<String> getVersionLabels() {
075        List<String> versionLabels = new ArrayList<String>();
076        List<WebElement> trElements;
077        try {
078            trElements = documentVersionsForm.findElement(By.tagName("tbody")).findElements(By.tagName("tr"));
079        } catch (NoSuchElementException nsee) {
080            return versionLabels;
081        }
082        for (WebElement trItem : trElements) {
083            try {
084                WebElement versionLabel = trItem.findElement(By.xpath("td[2]"));
085                versionLabels.add(versionLabel.getText());
086            } catch (NoSuchElementException e) {
087                // Go to next line
088            }
089        }
090        return versionLabels;
091    }
092
093    /**
094     * Selects a version given its label.
095     *
096     * @param versionLabel the version label
097     * @return the archived versions sub page
098     */
099    public ArchivedVersionsSubPage selectVersion(String versionLabel) {
100
101        List<WebElement> trElements = documentVersionsForm.findElement(By.tagName("tbody"))
102                                                          .findElements(By.tagName("tr"));
103        for (WebElement trItem : trElements) {
104            try {
105                trItem.findElement(By.xpath("td[text()=\"" + versionLabel + "\"]"));
106                WebElement checkBox = trItem.findElement(By.xpath("td/input[@type=\"checkbox\"]"));
107                Locator.waitUntilEnabledAndClick(checkBox);
108                break;
109            } catch (NoSuchElementException e) {
110                // Go to next line
111            }
112        }
113        return asPage(ArchivedVersionsSubPage.class);
114    }
115
116    /**
117     * Checks the ability to remove selected versions.
118     *
119     * @param canRemove true to check if can remove selected versions
120     */
121    public void checkCanRemoveSelectedVersions(boolean canRemove) {
122        checkCanExecuteActionOnSelectedVersions(DELETE_ACTION_ID, canRemove);
123    }
124
125    /**
126     * Checks the ability to execute the action identified by {@code actionId} on selected versions.
127     *
128     * @param actionId the action id
129     * @param canExecute true to check if can execute action identified by {@code actionId} on selected versions
130     */
131    public void checkCanExecuteActionOnSelectedVersions(String actionId, boolean canExecute) {
132        try {
133            findElementAndWaitUntilEnabled(By.xpath("//span[@id=\"" + actionId + "\"]/input"),
134                    AbstractTest.LOAD_TIMEOUT_SECONDS * 1000, AbstractTest.AJAX_SHORT_TIMEOUT_SECONDS * 1000);
135            if (!canExecute) {
136                fail(actionId + " action should not be enabled because there is no version selected.");
137            }
138        } catch (NotFoundException nfe) {
139            if (canExecute) {
140                log.error(nfe, nfe);
141                fail(actionId + " action should be enabled because there is at least one version selected.");
142            }
143        }
144    }
145
146    /**
147     * Removes the selected versions.
148     *
149     * @return the archived versions sub page
150     */
151    public ArchivedVersionsSubPage removeSelectedVersions() {
152
153        ArchivedVersionsSubPage archivedVersionsPage = null;
154        // As accepting the Delete confirm alert randomly fails to reload the
155        // page, we need to repeat the Delete action until it is really taken
156        // into account, ie. the "Delete" button is not displayed any more nor
157        // enabled.
158        Clock clock = new SystemClock();
159        long end = clock.laterBy(AbstractTest.LOAD_TIMEOUT_SECONDS * 1000);
160        while (clock.isNowBefore(end)) {
161            try {
162                archivedVersionsPage = executeActionOnSelectedVersions(DELETE_ACTION_ID, true,
163                        ArchivedVersionsSubPage.class, AbstractTest.LOAD_SHORT_TIMEOUT_SECONDS * 1000,
164                        AbstractTest.AJAX_TIMEOUT_SECONDS * 1000);
165            } catch (NotFoundException nfe) {
166                if (archivedVersionsPage == null) {
167                    break;
168                }
169                return archivedVersionsPage;
170            }
171            try {
172                Thread.sleep(100);
173            } catch (InterruptedException e) {
174                Thread.currentThread().interrupt();
175                throw new RuntimeException(e);
176            }
177        }
178        throw new WebDriverException("Couldn't remove selected versions");
179    }
180
181    /**
182     * Executes the action identified by {@code actionId} on selected versions.
183     *
184     * @param <T> the generic type of the page to return
185     * @param actionId the action id
186     * @param isConfirm true if the action needs a javascript confirm
187     * @param pageClass the class of the page to return
188     * @param findElementTimeout the find element timeout in milliseconds
189     * @param waitUntilEnabledTimeout the wait until enabled timeout in milliseconds
190     * @return the page displayed after the action execution
191     */
192    public <T> T executeActionOnSelectedVersions(String actionId, boolean isConfirm, Class<T> pageClass,
193            int findElementTimeout, int waitUntilEnabledTimeout) {
194        Locator.findElementWaitUntilEnabledAndClick(null, By.xpath("//span[@id=\"" + actionId + "\"]/input"),
195                findElementTimeout, waitUntilEnabledTimeout);
196        if (isConfirm) {
197            Alert alert = driver.switchTo().alert();
198            assertEquals("Delete selected document(s)?", alert.getText());
199            alert.accept();
200        }
201        return asPage(pageClass);
202    }
203
204    /**
205     * Views the version with label {@code versionLabel}.
206     *
207     * @param versionLabel the version label
208     * @return the version page
209     */
210    public DocumentBasePage viewVersion(String versionLabel) {
211        return executeActionOnVersion(versionLabel, VIEW_VERSION_ACTION_ID);
212    }
213
214    /**
215     * Restores the version with label {@code versionLabel}.
216     *
217     * @param versionLabel the version label
218     * @return the restored version page
219     */
220    public DocumentBasePage restoreVersion(String versionLabel) {
221        return executeActionOnVersion(versionLabel, RESTORE_VERSION_ACTION_ID);
222    }
223
224    /**
225     * Executes the action identified by {@code actionId} on the version with label {@code versionLabel}.
226     *
227     * @param versionLabel the version label
228     * @param actionId the action id
229     * @return the page displayed after the action execution
230     */
231    public DocumentBasePage executeActionOnVersion(String versionLabel, String actionId) {
232
233        List<WebElement> trElements = documentVersionsForm.findElement(By.tagName("tbody"))
234                                                          .findElements(By.tagName("tr"));
235        for (WebElement trItem : trElements) {
236            try {
237                trItem.findElement(By.xpath("td[text()=\"" + versionLabel + "\"]"));
238                WebElement actionButton = trItem.findElement(By.xpath("td/span[@id=\"" + actionId + "\"]/input"));
239                Locator.waitUntilEnabledAndClick(actionButton);
240                break;
241            } catch (NoSuchElementException e) {
242                // Go to next line
243            }
244        }
245        return asPage(DocumentBasePage.class);
246    }
247
248    /**
249     * @since 8.3
250     */
251    public String getDocumentVersionsText() {
252        return documentVersions.getText();
253    }
254}