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