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
31
32
33
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
101
102
103 public WebDriverElement(By locator)
104 {
105 this(locator, TimeoutType.DEFAULT);
106 }
107
108
109
110
111
112
113
114 public WebDriverElement(By locator, TimeoutType timeoutType)
115 {
116 this(locator, WebDriverLocators.root(), timeoutType);
117 }
118
119
120
121
122
123
124
125 public WebDriverElement(By locator, WebDriverLocatable parent)
126 {
127 this(locator, parent, TimeoutType.DEFAULT);
128 }
129
130
131
132
133
134
135
136
137 public WebDriverElement(By locator, WebDriverLocatable parent, TimeoutType timeoutType)
138 {
139 this(WebDriverLocators.nested(locator, parent), timeoutType);
140 }
141
142
143
144
145
146
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
376
377
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 }