View Javadoc

1   package com.atlassian.pageobjects.elements;
2   
3   import com.atlassian.annotations.Internal;
4   import com.atlassian.pageobjects.PageBinder;
5   import com.atlassian.pageobjects.elements.search.DefaultQuery;
6   import com.atlassian.pageobjects.elements.timeout.TimeoutType;
7   import com.atlassian.pageobjects.elements.timeout.Timeouts;
8   import com.atlassian.pageobjects.internal.elements.search.DefaultWebDriverQuery;
9   import com.atlassian.webdriver.Elements;
10  import com.atlassian.webdriver.utils.Check;
11  import com.google.common.base.Function;
12  import com.google.common.collect.Lists;
13  import org.openqa.selenium.By;
14  import org.openqa.selenium.Dimension;
15  import org.openqa.selenium.Point;
16  import org.openqa.selenium.WebDriver;
17  import org.openqa.selenium.WebElement;
18  
19  import javax.annotation.Nonnull;
20  import javax.annotation.Nullable;
21  import javax.inject.Inject;
22  import java.util.List;
23  import java.util.Set;
24  
25  import static com.atlassian.webdriver.Elements.ATTRIBUTE_CLASS;
26  import static com.atlassian.webdriver.Elements.ATTRIBUTE_ID;
27  import static com.google.common.base.Preconditions.checkNotNull;
28  
29  /**
30   * Implementation of {@link PageElement} that waits for element to be
31   * present before executing each actions.
32   *
33   * @since 2.0
34   */
35  @Internal
36  public class WebDriverElement implements PageElement
37  {
38      public static Function<PageElement, WebDriverLocatable> TO_LOCATABLE = new Function<PageElement, WebDriverLocatable>()
39      {
40          @Override
41          public WebDriverLocatable apply(PageElement element)
42          {
43              return toLocatable(element);
44          }
45      };
46  
47      @Inject
48      protected WebDriver driver;
49  
50      @Inject
51      protected PageBinder pageBinder;
52  
53      @Inject
54      protected Timeouts timeouts;
55  
56      protected final WebDriverLocatable locatable;
57      protected final TimeoutType defaultTimeout;
58  
59      @Nonnull
60      public static <P extends PageElement> Function<WebDriverLocatable, P> bind(@Nonnull final PageBinder pageBinder,
61                                                                                 @Nonnull final Class<P> elementType,
62                                                                                 @Nonnull final TimeoutType timeoutType)
63      {
64          checkNotNull(pageBinder, "pageBinder");
65          checkNotNull(elementType, "elementType");
66          checkNotNull(timeoutType, "timeoutType");
67  
68          return new Function<WebDriverLocatable, P>()
69          {
70              @Override
71              public P apply(WebDriverLocatable locatable)
72              {
73                  return pageBinder.bind(WebDriverElementMappings.findMapping(elementType), locatable, timeoutType);
74              }
75          };
76      }
77  
78      @Nonnull
79      public static WebDriverLocatable toLocatable(@Nonnull PageElement pageElement)
80      {
81          return cast(pageElement).locatable;
82      }
83  
84      static WebElement getWebElement(PageElement element)
85      {
86          return cast(element).asWebElement();
87      }
88  
89      private static WebDriverElement cast(PageElement element)
90      {
91          if (!WebDriverElement.class.isInstance(element))
92          {
93              throw new IllegalStateException("Unknown implementation of PageElement, cannot use to retrieve WebElement");
94          }
95          return WebDriverElement.class.cast(element);
96      }
97  
98  
99      /**
100      * Creates a WebDriverElement within the driver's search context and default timeout
101      * @param locator The locator mechanism to use.
102      */
103     public WebDriverElement(By locator)
104     {
105         this(locator, TimeoutType.DEFAULT);
106     }
107 
108     /**
109      * Creates a WebDriverElement within the driver's search context and given timeout type.
110      * 
111      * @param locator The locator mechanism to use.
112      * @param timeoutType default timeout of this element
113      */
114     public WebDriverElement(By locator, TimeoutType timeoutType)
115     {
116         this(locator, WebDriverLocators.root(), timeoutType);
117     }
118 
119     /**
120      * Creates a WebDriverElement within a given parent and default timeout.
121      *
122      * @param locator The locator mechanism to use.
123      * @param parent The locatable parent of this element.
124      */
125     public WebDriverElement(By locator, WebDriverLocatable parent)
126     {
127         this(locator, parent, TimeoutType.DEFAULT);
128     }
129 
130     /**
131      * Creates a WebDriverElement within a given parent and given timeout type.
132      *
133      * @param locator The locator mechanism to use.
134      * @param parent The locatable parent of this element.
135      * @param timeoutType default timeout of this element
136      */
137     public WebDriverElement(By locator, WebDriverLocatable parent, TimeoutType timeoutType)
138     {
139         this(WebDriverLocators.nested(locator, parent), timeoutType);
140     }
141 
142     /**
143      * Creates a WebDriverElement with the given locatable and timeout type.
144      *
145      * @param locatable WebDriverLocatable that that locate this element
146      * @param timeoutType default timeout of this element
147      */
148     public WebDriverElement(WebDriverLocatable locatable, TimeoutType timeoutType)
149     {
150         this.locatable = checkNotNull(locatable, "locatable");
151         this.defaultTimeout = checkNotNull(timeoutType, "timeoutType");
152     }
153 
154     protected long timeout()
155     {
156         return timeouts.timeoutFor(defaultTimeout);
157     }
158 
159     protected WebDriverLocatable.LocateTimeout createTimout()
160     {
161         return new WebDriverLocatable.LocateTimeout.Builder()
162                 .timeout(timeout())
163                 .pollInterval(timeouts.timeoutFor(TimeoutType.EVALUATION_INTERVAL))
164                 .build();
165     }
166 
167     public boolean isPresent()
168     {
169         return locatable.isPresent(driver, createTimout());
170     }
171 
172     public boolean isVisible()
173     {
174         WebElement element = waitForWebElement();
175         return element.isDisplayed();
176     }
177 
178     public boolean isEnabled()
179     {
180         return waitForWebElement().isEnabled();
181     }
182 
183     public boolean isSelected()
184     {
185         return waitForWebElement().isSelected();
186     }
187 
188     @Nullable
189     @Override
190     public String getId()
191     {
192         return getAttribute(ATTRIBUTE_ID);
193     }
194 
195     @Nonnull
196     @Override
197     public Set<String> getCssClasses()
198     {
199         return Elements.getCssClasses(getAttribute(ATTRIBUTE_CLASS));
200     }
201 
202     public boolean hasClass(@Nonnull final String className)
203     {
204         checkNotNull(className, "className");
205         return Check.hasClass(className, waitForWebElement());
206     }
207 
208     public String getAttribute(@Nonnull final String name)
209     {
210         return waitForWebElement().getAttribute(name);
211     }
212 
213     public boolean hasAttribute(@Nonnull final String name, final String value)
214     {
215         return value.equals(getAttribute(name));
216     }
217 
218     public String getText()
219     {
220         return waitForWebElement().getText();
221     }
222 
223     @Nonnull
224     public String getTagName()
225     {
226         return waitForWebElement().getTagName();
227     }
228 
229     public String getValue()
230     {
231         return waitForWebElement().getAttribute("value");
232     }
233 
234     @Nonnull
235     @Override
236     public Point getLocation()
237     {
238         return waitForWebElement().getLocation();
239     }
240 
241     @Nonnull
242     @Override
243     public Dimension getSize()
244     {
245         return waitForWebElement().getSize();
246     }
247 
248     @Nonnull
249     public PageElement click()
250     {
251         waitForWebElement().click();
252         return this;
253     }
254 
255     @Nonnull
256     public PageElement type(final CharSequence... keysToSend)
257     {
258         waitForWebElement().sendKeys(keysToSend);
259         return this;
260     }
261 
262     @Nonnull
263     public PageElement select()
264     {
265         WebElement el = waitForWebElement();
266         if (!el.isSelected()) {
267             el.click();
268         }
269         return this;
270     }
271 
272     @Nonnull
273     public PageElement toggle()
274     {
275         WebElement el = waitForWebElement();
276         el.click();
277         return this;
278     }
279 
280     @Nonnull
281     public PageElement clear()
282     {
283         waitForWebElement().clear();
284         return this;
285     }
286 
287     @Nonnull
288     public TimedElement timed()
289     {
290        return pageBinder.bind(WebDriverTimedElement.class, locatable, defaultTimeout);
291     }
292 
293     @Nonnull
294     public PageElementJavascript javascript()
295     {
296         return new WebDriverElementJavascript(this);
297     }
298 
299     @Nonnull
300     public PageElement find(@Nonnull By locator)
301     {
302         return pageBinder.bind(WebDriverElement.class, locator, locatable);
303     }
304 
305     @Nonnull
306     public PageElement find(@Nonnull By locator, @Nonnull TimeoutType timeoutType)
307     {
308         return pageBinder.bind(WebDriverElement.class, locator, locatable, timeoutType);
309     }
310 
311     @Nonnull
312     public <T extends PageElement> T find(@Nonnull By locator, @Nonnull Class<T> elementClass)
313     {
314         return pageBinder.bind(WebDriverElementMappings.findMapping(elementClass), locator, locatable);
315     }
316 
317     @Nonnull
318     public <T extends PageElement> T find(@Nonnull By locator, @Nonnull Class<T> elementClass, @Nonnull TimeoutType timeoutType)
319     {
320         return pageBinder.bind(WebDriverElementMappings.findMapping(elementClass), locator, locatable, timeoutType);
321     }
322 
323     @Nonnull
324     public List<PageElement> findAll(@Nonnull final By locator)
325     {
326         return findAll(locator, defaultTimeout);
327     }
328 
329     @Nonnull
330     public List<PageElement> findAll(@Nonnull By locator, @Nonnull TimeoutType timeoutType)
331     {
332         return findAll(locator, PageElement.class, timeoutType);
333     }
334 
335     @Nonnull
336     public <T extends PageElement> List<T> findAll(@Nonnull By locator, @Nonnull Class<T> elementClass)
337     {
338         return findAll(locator, elementClass, defaultTimeout);
339     }
340 
341     @Nonnull
342     public <T extends PageElement> List<T> findAll(@Nonnull By locator, @Nonnull Class<T> elementClass,
343                                                    @Nonnull TimeoutType timeoutType)
344     {
345         List<T> elements = Lists.newLinkedList();
346         List<WebElement> webElements = waitForWebElement().findElements(locator);
347 
348         for(int i = 0; i < webElements.size(); i++)
349         {
350             elements.add(pageBinder.bind(WebDriverElementMappings.findMapping(elementClass),
351                     WebDriverLocators.list(webElements.get(i), locator, i, locatable), timeoutType));
352         }
353         return elements;
354     }
355 
356     @Nonnull
357     @Override
358     public PageElement withTimeout(@Nonnull TimeoutType timeoutType)
359     {
360         if (this.defaultTimeout == timeoutType)
361         {
362             return this;
363         }
364         return pageBinder.bind(WebDriverElement.class, locatable, checkNotNull(timeoutType));
365     }
366 
367     @Nonnull
368     @Override
369     public DefaultQuery search()
370     {
371         return pageBinder.bind(DefaultWebDriverQuery.class, this);
372     }
373 
374     /**
375      * This allows retrieving the web element from the page element.
376      *
377      * @return the web element that represents the page element.
378      */
379     @Nonnull
380     public WebElement asWebElement()
381     {
382         return waitForWebElement();
383     }
384 
385     @Nonnull
386     public TimeoutType getDefaultTimeout()
387     {
388         return defaultTimeout;
389     }
390 
391     @Override
392     public String toString()
393     {
394         return "WebDriverElement[locatable=" + locatable + ",defaultTimeout=" + defaultTimeout + "]";
395     }
396 
397     protected WebElement waitForWebElement()
398     {
399         return waitForWebElement(createTimout());
400     }
401 
402     protected WebElement waitForWebElement(WebDriverLocatable.LocateTimeout timeout)
403     {
404         return (WebElement) locatable.waitUntilLocated(driver, timeout);
405     }
406 }