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