001/*
002 * (C) Copyright 2011 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 *     Sun Seng David TAN
018 *     Florent Guillaume
019 *     Antoine Taillefer
020 */
021package org.nuxeo.functionaltests.pages.tabs;
022
023import static org.junit.Assert.assertEquals;
024import static org.junit.Assert.assertNotNull;
025
026import java.util.ArrayList;
027import java.util.Arrays;
028import java.util.List;
029
030import org.nuxeo.functionaltests.AjaxRequestManager;
031import org.nuxeo.functionaltests.Locator;
032import org.nuxeo.functionaltests.Required;
033import org.nuxeo.functionaltests.pages.DocumentBasePage;
034import org.openqa.selenium.Alert;
035import org.openqa.selenium.By;
036import org.openqa.selenium.NoSuchElementException;
037import org.openqa.selenium.WebDriver;
038import org.openqa.selenium.WebElement;
039import org.openqa.selenium.support.FindBy;
040
041import com.google.common.base.Function;
042
043/**
044 * The content tab sub page. Most of the time available for folderish documents and displaying the current document's
045 * children.
046 */
047public class ContentTabSubPage extends DocumentBasePage {
048
049    private static final String COPY_BUTTON_XPATH = "//input[@value=\"Copy\"]";
050
051    private static final String PASTE_BUTTON_XPATH = "//input[@value=\"Paste\"]";
052
053    private static final String DELETE_BUTTON_XPATH = "//input[@value=\"Delete\"]";
054
055    private static final String ADD_TO_WORKLIST_BUTTON_XPATH = "//input[@value=\"Add to Worklist\"]";
056
057    private static final String SELECT_ALL_BUTTON_XPATH = "//input[@type=\"checkbox\" and @title=\"Select all / deselect all\"]";
058
059    private static final String CHECK_BOX_XPATH = "td/input[@type=\"checkbox\"]";
060
061    private static final String DOCUMENT_TITLE_XPATH = "td//span[@id[starts-with(.,'title_')]]";
062
063    @Required
064    @FindBy(id = "document_content")
065    WebElement documentContentForm;
066
067    @FindBy(linkText = "New")
068    WebElement newButton;
069
070    @FindBy(id = "cv_document_content_0_quickFilterForm:nxl_document_content_filter:nxw_search_title")
071    WebElement filterInput;
072
073    @FindBy(id = "cv_document_content_0_quickFilterForm:submitFilter")
074    WebElement filterButton;
075
076    @FindBy(id = "cv_document_content_0_resetFilterForm:resetFilter")
077    WebElement clearFilterButton;
078
079    @FindBy(xpath = "//form[@id=\"document_content\"]//tbody//tr")
080    List<WebElement> childDocumentRows;
081
082    public List<WebElement> getChildDocumentRows() {
083        return childDocumentRows;
084    }
085
086    public ContentTabSubPage(WebDriver driver) {
087        super(driver);
088    }
089
090    /**
091     * Clicking on one of the child with the title.
092     *
093     * @param documentTitle
094     */
095    public DocumentBasePage goToDocument(String documentTitle) {
096        documentContentForm.findElement(By.linkText(documentTitle)).click();
097        return asPage(DocumentBasePage.class);
098    }
099
100    /**
101     * Clicks on the new button and select the type of document to create
102     *
103     * @param docType the document type to create
104     * @param pageClassToProxy The page object type to return
105     * @return The create form page object
106     */
107    public <T> T getDocumentCreatePage(String docType, Class<T> pageClassToProxy) {
108        newButton.click();
109        WebElement fancyBox = getFancyBoxContent();
110        // find the link to doc type that needs to be created
111        WebElement link = fancyBox.findElement(By.linkText(docType));
112        assertNotNull(link);
113        link.click();
114        return asPage(pageClassToProxy);
115    }
116
117    public DocumentBasePage removeDocument(String documentTitle) {
118        // get all table item and if the link has the documents title, click
119        // (enable) checkbox
120
121        List<WebElement> trelements = documentContentForm.findElement(By.tagName("tbody")).findElements(
122                By.tagName("tr"));
123        for (WebElement trItem : trelements) {
124            try {
125                trItem.findElement(By.linkText(documentTitle));
126                WebElement checkBox = trItem.findElement(By.xpath("td/input[@type=\"checkbox\"]"));
127                checkBox.click();
128                break;
129            } catch (NoSuchElementException e) {
130                // next
131            }
132        }
133        deleteSelectedDocuments();
134
135        return asPage(DocumentBasePage.class);
136    }
137
138    protected void deleteSelectedDocuments() {
139        findElementWaitUntilEnabledAndClick(By.xpath(DELETE_BUTTON_XPATH));
140        Alert alert = driver.switchTo().alert();
141        assertEquals("Delete selected document(s)?", alert.getText());
142        alert.accept();
143    }
144
145    public DocumentBasePage addToWorkList(String documentTitle) {
146        // get all table item and if the link has the documents title, click
147        // (enable) checkbox
148
149        selectByTitle(documentTitle);
150        findElementWaitUntilEnabledAndClick(By.xpath(ADD_TO_WORKLIST_BUTTON_XPATH));
151
152        return asPage(DocumentBasePage.class);
153    }
154
155    /**
156     * Removes all documents visible on current page.
157     */
158    public ContentTabSubPage removeAllDocuments() {
159        ContentTabSubPage page = asPage(ContentTabSubPage.class);
160        By locator = By.xpath(SELECT_ALL_BUTTON_XPATH);
161        if (!hasElement(locator)) {
162            // no document to remove
163            return page;
164        }
165        AjaxRequestManager arm = new AjaxRequestManager(driver);
166        arm.begin();
167        findElementWaitUntilEnabledAndClick(By.xpath(SELECT_ALL_BUTTON_XPATH));
168        arm.end();
169        deleteSelectedDocuments();
170
171        return asPage(ContentTabSubPage.class);
172    }
173
174    /**
175     * Perform filter on the given string.
176     *
177     * @param filter the string to filter
178     * @param expectedDisplayedElt
179     * @param timeout
180     * @since 5.7.2
181     */
182    public ContentTabSubPage filterDocument(final String filter, final int expectedNbOfDisplayedResult,
183            final int timeout) {
184        filterInput.clear();
185        filterInput.sendKeys(filter);
186        filterButton.click();
187        Locator.waitUntilGivenFunction(new Function<WebDriver, Boolean>() {
188            @Override
189            public Boolean apply(WebDriver driver) {
190                try {
191                    return getChildDocumentRows().size() == expectedNbOfDisplayedResult;
192                } catch (NoSuchElementException e) {
193                    return false;
194                }
195            }
196        });
197        return asPage(ContentTabSubPage.class);
198    }
199
200    /**
201     * Reset the filter.
202     *
203     * @param expectedNbOfDisplayedResult
204     * @param timeout
205     * @since 5.7.2
206     */
207    public ContentTabSubPage clearFilter(final int expectedNbOfDisplayedResult, final int timeout) {
208        clearFilterButton.click();
209        Locator.waitUntilGivenFunction(new Function<WebDriver, Boolean>() {
210            @Override
211            public Boolean apply(WebDriver driver) {
212                try {
213                    return getChildDocumentRows().size() == expectedNbOfDisplayedResult;
214                } catch (NoSuchElementException e) {
215                    return false;
216                }
217            }
218        });
219        return asPage(ContentTabSubPage.class);
220    }
221
222    /**
223     * Selects documents by their index in the content view.
224     *
225     * @since 5.7.8
226     * @deprecated since 8.1, use {@link #selectByIndex(int...)} instead.
227     */
228    @Deprecated
229    public ContentTabSubPage selectDocumentByIndex(int... indexes) {
230        return selectByIndex(indexes);
231    }
232
233    /**
234     * Selects documents by their index in the content view.
235     *
236     * @since 8.1
237     */
238    public ContentTabSubPage selectByIndex(int... indexes) {
239        AjaxRequestManager a = new AjaxRequestManager(driver);
240        for (int i : indexes) {
241            a.watchAjaxRequests();
242            getChildDocumentRows().get(i).findElement(By.xpath(CHECK_BOX_XPATH)).click();
243            a.waitForAjaxRequests();
244        }
245        return asPage(ContentTabSubPage.class);
246    }
247
248    /**
249     * Selects documents by their title in the content view.
250     *
251     * @since 5.7.8
252     * @deprecated since 8.1 use {@link #selectByTitle(String...)}
253     */
254    @Deprecated
255    public ContentTabSubPage selectDocumentByTitles(String... titles) {
256        return selectByTitle(titles);
257    }
258
259    /**
260     * Selects documents by title in the content view.
261     *
262     * @since 8.1
263     */
264    public ContentTabSubPage selectByTitle(String... titles) {
265        return selectByIndex(convertToIndexes(titles));
266    }
267
268    protected int[] convertToIndexes(String... titles) {
269        List<String> titleList = Arrays.asList(titles);
270        List<Integer> temp = new ArrayList<Integer>();
271        int index = 0;
272        for (WebElement row : childDocumentRows) {
273            String docTitle = row.findElement(By.xpath(DOCUMENT_TITLE_XPATH)).getText();
274            if (docTitle != null && titleList.contains(docTitle)) {
275                temp.add(index);
276            }
277            index++;
278        }
279        int[] result = new int[temp.size()];
280        for (int i = 0; i < temp.size(); i++) {
281            result[i] = temp.get(i);
282        }
283        return result;
284    }
285
286    /**
287     * Selects documents by their index in the content view and copy them in the clipboard.
288     *
289     * @param indexes
290     * @since 5.7.8
291     */
292    public ContentTabSubPage copyByIndex(int... indexes) {
293        selectByIndex(indexes);
294        findElementWaitUntilEnabledAndClick(By.xpath(COPY_BUTTON_XPATH));
295        return asPage(ContentTabSubPage.class);
296    }
297
298    /**
299     * Selects documents by their title in the content view and copy them in the clipboard.
300     *
301     * @param indexes
302     * @since 5.7.8
303     */
304    public ContentTabSubPage copyByTitle(String... titles) {
305        return copyByIndex(convertToIndexes(titles));
306    }
307
308    /**
309     * Pastes the content of the clip board.
310     *
311     * @since 5.7.8
312     */
313    public ContentTabSubPage paste() {
314        findElementWaitUntilEnabledAndClick(By.xpath(PASTE_BUTTON_XPATH));
315        return asPage(ContentTabSubPage.class);
316    }
317
318    /**
319     * @since 5.9.3
320     */
321    public DocumentBasePage goToDocument(final int index) {
322        getChildDocumentRows().get(index).findElement(By.xpath("td[3]/div/a[1]")).click();
323        return asPage(DocumentBasePage.class);
324    }
325}