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