1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.extension.test.po

File ExtensionPane.java

 

Coverage histogram

../../../../../img/srcFileCovDistChart9.png
38% of files have more coverage

Code metrics

22
65
32
1
395
187
43
0.66
2.03
32
1.34

Classes

Class Line # Actions
ExtensionPane 36 65 0% 43 16
0.865546286.6%
 

Contributing tests

This file is covered by 15 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.extension.test.po;
21   
22    import java.util.List;
23   
24    import org.apache.commons.lang3.StringUtils;
25    import org.openqa.selenium.By;
26    import org.openqa.selenium.WebElement;
27    import org.xwiki.extension.ExtensionId;
28    import org.xwiki.test.ui.po.BaseElement;
29   
30    /**
31    * Displays an extension.
32    *
33    * @version $Id: 6f9fca51a67d9a2cf3a95d9d14a548ff0949e62d $
34    * @since 4.2M1
35    */
 
36    public class ExtensionPane extends BaseElement
37    {
38    /**
39    * The XPath used to locate an extension action button.
40    */
41    private static final String ACTION_BUTTON_XPATH =
42    ".//button[@name = 'extensionAction' and @value='%s' and normalize-space(text())='%s']";
43   
44    /**
45    * The name of the "class" attribute of HTML elements.
46    */
47    private static final String CLASS_ATTRIBUTE = "class";
48   
49    /**
50    * The element that wraps the extension display.
51    */
52    private final WebElement container;
53   
54    /**
55    * Creates a new instance.
56    *
57    * @param container the element that wraps the extension display
58    */
 
59  61 toggle public ExtensionPane(WebElement container)
60    {
61  61 this.container = container;
62    }
63   
64    /**
65    * @return the extension status (loading, core, installed, remote, remote-installed, remote-core,
66    * remote-installed-incompatible, remote-core-incompatible)
67    */
 
68  16 toggle public String getStatus()
69    {
70  16 String[] classNames = container.getAttribute(CLASS_ATTRIBUTE).split("\\s+");
71  16 if (classNames.length < 2) {
72  0 return null;
73    }
74  16 return classNames[1].substring("extension-item-".length());
75    }
76   
77    /**
78    * @return the extension status message
79    */
 
80  9 toggle public String getStatusMessage()
81    {
82  9 By xpath = By.xpath("*[@class = 'extension-header']//*[@class = 'extension-status']");
83  9 List<WebElement> found = getDriver().findElementsWithoutWaiting(container, xpath);
84  9 return found.size() > 0 ? found.get(0).getText() : null;
85    }
86   
87    /**
88    * @return the extension identifier
89    */
 
90  3 toggle public ExtensionId getId()
91    {
92  3 return new ExtensionId(getName(), getVersion());
93    }
94   
95    /**
96    * @return the extension name
97    */
 
98  12 toggle public String getName()
99    {
100  12 By xpath = By.xpath("*[@class = 'extension-header']//*[@class = 'extension-name']");
101  12 return getDriver().findElementWithoutWaiting(container, xpath).getText();
102    }
103   
104    /**
105    * @return the extension version
106    */
 
107  7 toggle public String getVersion()
108    {
109  7 By xpath = By.xpath("*[@class = 'extension-header']//*[@class = 'extension-version']");
110  7 return getDriver().findElementWithoutWaiting(container, xpath).getText();
111    }
112   
113    /**
114    * @return the extension authors
115    */
 
116  1 toggle public List<WebElement> getAuthors()
117    {
118  1 return getDriver().findElementsWithoutWaiting(container, By.className("extension-author"));
119    }
120   
121    /**
122    * @return the extension summary
123    */
 
124  2 toggle public String getSummary()
125    {
126  2 List<WebElement> found = getDriver().findElementsWithoutWaiting(container, By.className("extension-summary"));
127  2 return found.size() > 0 ? found.get(0).getText() : null;
128    }
129   
130    /**
131    * Clicks on the show details button.
132    *
133    * @return the extension pane showing the extension details
134    */
 
135  2 toggle public ExtensionPane showDetails()
136    {
137  2 WebElement showDetailsButton = getShowDetailsButton();
138  2 if (showDetailsButton.getAttribute(CLASS_ATTRIBUTE).contains("visibilityAction")) {
139    // Just toggle show/hide details.
140  0 showDetailsButton.click();
141  0 return this;
142    } else {
143    // Retrieve the details. Wait until the extension body is not loading.
144  2 return clickAndWaitUntilElementIsVisible(showDetailsButton, "/*[@class = 'extension-body']");
145    }
146    }
147   
148    /**
149    * @return the button used to show the extension details
150    */
 
151  2 toggle public WebElement getShowDetailsButton()
152    {
153  2 return maybeFindElement(By.xpath(String.format(ACTION_BUTTON_XPATH, "showDetails", "Show details")));
154    }
155   
156    /**
157    * Clicks on the given button and waits for the specified element to be visible.
158    *
159    * @param button the button to be clicked
160    * @param xpathSuffix the XPath suffix inside the 'extension-item' element
161    * @return the new extension pane, after the specified element became visible
162    */
 
163  27 toggle private ExtensionPane clickAndWaitUntilElementIsVisible(WebElement button, String xpathSuffix)
164    {
165  27 String xpath = getXPath();
166  27 button.click();
167  27 getDriver().waitUntilElementIsVisible(By.xpath(xpath + xpathSuffix));
168    // We have to create a new extension pane because the DOM has changed.
169  27 return new ExtensionPane(getDriver().findElementWithoutWaiting(By.xpath(xpath)));
170    }
171   
172    /**
173    * @return the XPath used to locate this extension
174    */
 
175  27 toggle private String getXPath()
176    {
177  27 String nameAndVersion =
178    getDriver().findElementWithoutWaiting(container, By.className("extension-title")).getText();
179  27 return String.format("//form[contains(@class, 'extension-item') and descendant::*["
180    + "contains(@class, 'extension-title') and normalize-space(.) = '%s']]", nameAndVersion);
181    }
182   
183    /**
184    * Clicks on the hide details button.
185    *
186    * @return the extension pane that doesn't show the extension details
187    */
 
188  0 toggle public ExtensionPane hideDetails()
189    {
190  0 getHideDetailsButton().click();
191  0 return this;
192    }
193   
194    /**
195    * @return the button used to hide the extension details
196    */
 
197  0 toggle public WebElement getHideDetailsButton()
198    {
199  0 return maybeFindElement(By.xpath(String.format(ACTION_BUTTON_XPATH, "hideDetails", "Hide details")));
200    }
201   
202    /**
203    * Clicks on the given button and waits for a confirmation or for the job/action to be done.
204    *
205    * @param button the button to be clicked
206    * @return the extension pane showing the confirmation or the job log
207    */
 
208  25 toggle private ExtensionPane clickAndWaitForConfirmationOrJobDone(WebElement button)
209    {
210    // Wait until the the continue button is present or the extension is not loading and both the extension body and
211    // the progress section are present and not loading.
212  25 return clickAndWaitUntilElementIsVisible(button,
213    "[descendant::button[@name = 'extensionAction' and @value = 'continue' and not(@disabled)] or ("
214    + "not(contains(@class, 'loading')) and descendant::*[@class = 'extension-body']"
215    + "/*[@class = 'extension-body-progress extension-body-section'])]");
216    }
217   
218    /**
219    * Clicks on the install button and waits for the install plan to be computed.
220    *
221    * @return the extension pane displaying the install plan
222    */
 
223  5 toggle public ExtensionPane install()
224    {
225  5 return maybeOpenActionDropDownMenu().clickAndWaitForConfirmationOrJobDone(getInstallButton());
226    }
227   
228    /**
229    * @return the install button, if present
230    */
 
231  6 toggle public WebElement getInstallButton()
232    {
233  6 return maybeFindElement(By.xpath(String.format(ACTION_BUTTON_XPATH, "install", "Install")));
234    }
235   
236    /**
237    * @param locator specifies the element to look for
238    * @return the specified element, if found, {@code null} otherwise
239    */
 
240  33 toggle private WebElement maybeFindElement(By locator)
241    {
242  33 List<WebElement> found = getDriver().findElementsWithoutWaiting(container, locator);
243  33 return found.size() > 0 ? found.get(0) : null;
244    }
245   
246    /**
247    * Clicks on the drop-down toggle, if present, to expand the group of extension action buttons.
248    *
249    * @return this
250    */
 
251  11 toggle private ExtensionPane maybeOpenActionDropDownMenu()
252    {
253  11 String xpath = ".//*[@class = 'extension-actions']//*[@class = 'dropdown-toggle']";
254  11 List<WebElement> found = getDriver().findElementsWithoutWaiting(container, By.xpath(xpath));
255  11 if (found.size() > 0) {
256  7 found.get(0).click();
257    }
258  11 return this;
259    }
260   
261    /**
262    * Clicks on the uninstall button and waits for the uninstall plan to be computed.
263    *
264    * @return the extension pane displaying the uninstall plan
265    */
 
266  3 toggle public ExtensionPane uninstall()
267    {
268  3 return maybeOpenActionDropDownMenu().clickAndWaitForConfirmationOrJobDone(getUninstallButton());
269    }
270   
271    /**
272    * @return the uninstall button, if present
273    */
 
274  6 toggle public WebElement getUninstallButton()
275    {
276  6 return maybeFindElement(By.xpath(String.format(ACTION_BUTTON_XPATH, "uninstall", "Uninstall")));
277    }
278   
279    /**
280    * Clicks on the upgrade button and waits for the upgrade plan to be computed.
281    *
282    * @return the extension pane displaying the upgrade plan
283    */
 
284  2 toggle public ExtensionPane upgrade()
285    {
286  2 return maybeOpenActionDropDownMenu().clickAndWaitForConfirmationOrJobDone(getUpgradeButton());
287    }
288   
289    /**
290    * @return the upgrade button, if present
291    */
 
292  3 toggle public WebElement getUpgradeButton()
293    {
294  3 return maybeFindElement(By.xpath(String.format(ACTION_BUTTON_XPATH, "install", "Upgrade")));
295    }
296   
297    /**
298    * Clicks on the downgrade button and waits for the downgrade plan to be computed.
299    *
300    * @return the extension pane displaying the downgrade plan
301    */
 
302  1 toggle public ExtensionPane downgrade()
303    {
304  1 return maybeOpenActionDropDownMenu().clickAndWaitForConfirmationOrJobDone(getDowngradeButton());
305    }
306   
307    /**
308    * @return the downgrade button, if present
309    */
 
310  2 toggle public WebElement getDowngradeButton()
311    {
312  2 return maybeFindElement(By.xpath(String.format(ACTION_BUTTON_XPATH, "install", "Downgrade")));
313    }
314   
315    /**
316    * Confirms the current action and wait for it to be performed.
317    *
318    * @return the extension pane displaying the extension after the current action has been performed
319    */
 
320  14 toggle public ExtensionPane confirm()
321    {
322  14 return clickAndWaitForConfirmationOrJobDone(getContinueButton());
323    }
324   
325    /**
326    * @return the button used to continue the current job or to execute a previously computed job plan
327    */
 
328  14 toggle public WebElement getContinueButton()
329    {
330  14 return maybeFindElement(By.xpath(String.format(ACTION_BUTTON_XPATH, "continue", "Continue")));
331    }
332   
333    /**
334    * Clicks on the specified tab and returns the corresponding section if it's available.
335    *
336    * @param label the tab label
337    * @return the element that wraps the section corresponding to the specified tab
338    */
 
339  20 toggle private WebElement clickTab(String label)
340    {
341  20 By tabXPath = By.xpath(".//*[@class = 'innerMenu']//a[normalize-space(.) = '" + label + "']");
342  20 List<WebElement> found = getDriver().findElementsWithoutWaiting(container, tabXPath);
343  20 if (found.size() == 0) {
344  0 return null;
345    }
346  20 String sectionAnchor = StringUtils.substringAfterLast(found.get(0).getAttribute("href"), "#");
347  20 found.get(0).click();
348  20 By sectionXPath =
349    By.xpath(".//*[contains(@class, 'extension-body-section') and preceding-sibling::*[1][@id = '"
350    + sectionAnchor + "']]");
351  20 return getDriver().findElementWithoutWaiting(container, sectionXPath);
352    }
353   
354    /**
355    * Selects the extension description tab.
356    *
357    * @return the extension description section
358    */
 
359  2 toggle public ExtensionDescriptionPane openDescriptionSection()
360    {
361  2 WebElement section = clickTab("Description");
362  2 return section != null ? new ExtensionDescriptionPane(section) : null;
363    }
364   
365    /**
366    * Selects the extension dependencies tab.
367    *
368    * @return the extension dependencies section
369    */
 
370  3 toggle public ExtensionDependenciesPane openDependenciesSection()
371    {
372  3 WebElement section = clickTab("Dependencies");
373  3 return section != null ? new ExtensionDependenciesPane(section) : null;
374    }
375   
376    /**
377    * Selects the extension progress tab.
378    *
379    * @return the extension progress section
380    */
 
381  15 toggle public ExtensionProgressPane openProgressSection()
382    {
383  15 WebElement section = clickTab("Progress");
384  15 return section != null ? new ExtensionProgressPane(section) : null;
385    }
386   
387    /**
388    * @return the progress bar pane
389    */
 
390  2 toggle public ProgressBarPane getProgressBar()
391    {
392  2 List<WebElement> found = getDriver().findElementsWithoutWaiting(container, By.className("ui-progress"));
393  2 return found.size() != 1 ? null : new ProgressBarPane(found.get(0));
394    }
395    }