1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.sourceforge.jwebunit.webdriver;
20
21 import com.gargoylesoftware.htmlunit.WebClient;
22 import com.gargoylesoftware.htmlunit.WebResponse;
23 import net.sourceforge.jwebunit.api.HttpHeader;
24 import net.sourceforge.jwebunit.api.IElement;
25 import net.sourceforge.jwebunit.api.ITestingEngine;
26 import net.sourceforge.jwebunit.exception.ExpectedJavascriptAlertException;
27 import net.sourceforge.jwebunit.exception.ExpectedJavascriptConfirmException;
28 import net.sourceforge.jwebunit.exception.ExpectedJavascriptPromptException;
29 import net.sourceforge.jwebunit.exception.TestingEngineResponseException;
30 import net.sourceforge.jwebunit.html.Cell;
31 import net.sourceforge.jwebunit.html.Row;
32 import net.sourceforge.jwebunit.html.Table;
33 import net.sourceforge.jwebunit.javascript.JavascriptAlert;
34 import net.sourceforge.jwebunit.javascript.JavascriptConfirm;
35 import net.sourceforge.jwebunit.javascript.JavascriptPrompt;
36 import net.sourceforge.jwebunit.util.TestContext;
37 import org.apache.commons.lang.StringUtils;
38 import org.apache.http.Header;
39 import org.apache.http.HttpStatus;
40 import org.apache.regexp.RE;
41 import org.apache.regexp.RESyntaxException;
42 import org.browsermob.proxy.ProxyServer;
43 import org.browsermob.proxy.http.BrowserMobHttpRequest;
44 import org.browsermob.proxy.http.BrowserMobHttpResponse;
45 import org.browsermob.proxy.http.RequestInterceptor;
46 import org.browsermob.proxy.http.ResponseInterceptor;
47 import org.browsermob.proxy.jetty.util.MultiException;
48 import org.openqa.selenium.By;
49 import org.openqa.selenium.Cookie;
50 import org.openqa.selenium.JavascriptExecutor;
51 import org.openqa.selenium.NoSuchElementException;
52 import org.openqa.selenium.NoSuchWindowException;
53 import org.openqa.selenium.Proxy;
54 import org.openqa.selenium.WebDriver;
55 import org.openqa.selenium.WebElement;
56 import org.openqa.selenium.htmlunit.HtmlUnitDriver;
57 import org.openqa.selenium.remote.CapabilityType;
58 import org.openqa.selenium.remote.DesiredCapabilities;
59 import org.openqa.selenium.support.ui.Select;
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
62
63 import java.io.IOException;
64 import java.io.InputStream;
65 import java.net.MalformedURLException;
66 import java.net.URL;
67 import java.util.ArrayList;
68 import java.util.Calendar;
69 import java.util.Date;
70 import java.util.LinkedList;
71 import java.util.List;
72 import java.util.Map;
73 import java.util.Random;
74 import java.util.Set;
75
76
77
78
79
80
81
82 public class WebDriverTestingEngineImpl implements ITestingEngine {
83
84
85
86
87 private final Logger logger = LoggerFactory.getLogger(WebDriverTestingEngineImpl.class);
88 private ProxyServer proxyServer;
89 private WebDriver driver;
90 private TestContext testContext;
91 private static final int TRY_COUNT = 50;
92 private static final int DEFAULT_PORT = 8183;
93 private static final Random RANDOM = new Random();
94 private BrowserMobHttpResponse response;
95
96
97 private String formIdent;
98 private boolean throwExceptionOnScriptError = true;
99 private boolean ignoreFailingStatusCodes = false;
100
101
102
103 private boolean jsEnabled = true;
104
105 public WebDriverTestingEngineImpl() {
106 }
107
108 public void beginAt(URL aInitialURL, TestContext aTestContext) throws TestingEngineResponseException {
109 this.setTestContext(aTestContext);
110
111 Proxy proxy = startBrowserMobProxy();
112
113 DesiredCapabilities capabilities = new DesiredCapabilities();
114 capabilities.setCapability(CapabilityType.PROXY, proxy);
115 capabilities.setCapability(CapabilityType.SUPPORTS_JAVASCRIPT, jsEnabled);
116 capabilities.setBrowserName("htmlunit");
117 capabilities.setVersion("firefox");
118
119 driver = new HtmlUnitDriver(capabilities);
120
121
122 formIdent = null;
123
124
125 for (javax.servlet.http.Cookie c : aTestContext.getCookies()) {
126
127 String domain = c.getDomain();
128 if ("localhost".equals(domain)) {
129 domain = null;
130 }
131 if ("".equals(domain)) {
132 domain = null;
133 }
134 Date expiry = null;
135 if (c.getMaxAge() != -1) {
136 Calendar cal = Calendar.getInstance();
137 cal.add(Calendar.SECOND, c.getMaxAge());
138 expiry = cal.getTime();
139 }
140 driver.manage().addCookie(
141 new org.openqa.selenium.Cookie(c
142 .getName(), c.getValue(), domain, c.getPath() != null ? c
143 .getPath() : "", expiry, c.getSecure()));
144 }
145 gotoPage(aInitialURL);
146 }
147
148 private Proxy startBrowserMobProxy() {
149 for (int i = 1; i <= TRY_COUNT; i++) {
150 int port = getRandomPort();
151 proxyServer = new ProxyServer(port);
152 try {
153 proxyServer.start();
154 proxyServer.addResponseInterceptor(new ResponseInterceptor() {
155
156 @Override
157 public void process(BrowserMobHttpResponse response) {
158 WebDriverTestingEngineImpl.this.response = response;
159 }
160 });
161 if (testContext.getRequestHeaders() != null && !testContext.getRequestHeaders().isEmpty()) {
162 proxyServer.addRequestInterceptor(new RequestInterceptor() {
163
164 @Override
165 public void process(BrowserMobHttpRequest request) {
166 for (Map.Entry<String, String> requestHeader : testContext.getRequestHeaders().entrySet()) {
167 request.addRequestHeader(requestHeader.getKey(), requestHeader.getValue());
168 }
169 }
170 });
171 }
172 if (StringUtils.isNotBlank(testContext.getUserAgent())) {
173 proxyServer.addRequestInterceptor(new RequestInterceptor() {
174 @Override
175 public void process(BrowserMobHttpRequest request) {
176 request.getMethod().removeHeaders("User-Agent");
177 request.addRequestHeader("User-Agent", testContext.getUserAgent());
178 }
179 });
180 }
181 return proxyServer.seleniumProxy();
182 } catch (Exception e) {
183 if (i < TRY_COUNT) {
184 logger.error("Error while starting BrowserMob proxy on port " + port + ". Retry...: " + e.getMessage(), e);
185 if (e instanceof MultiException) {
186 Exception e1 = ((MultiException) e).getException(0);
187 logger.error("First exception: " + e1.getMessage(), e1);
188 }
189 continue;
190 }
191 }
192 }
193 throw new RuntimeException("Unable to start BrowserMob proxy after " + TRY_COUNT + " retries");
194 }
195
196 private static int getRandomPort() {
197 synchronized (RANDOM) {
198 return DEFAULT_PORT + RANDOM.nextInt(1000);
199 }
200 }
201
202 public void setTestContext(TestContext testContext) {
203 this.testContext = testContext;
204 }
205
206 public void closeBrowser() throws ExpectedJavascriptAlertException, ExpectedJavascriptConfirmException, ExpectedJavascriptPromptException {
207 formIdent = null;
208 if (driver != null) {
209 driver.quit();
210 driver = null;
211 }
212 if (proxyServer != null) {
213 try {
214 proxyServer.stop();
215 proxyServer = null;
216 } catch (Exception e) {
217 logger.error("Error while stopping proxy", e);
218 throw new RuntimeException("Error while stopping proxy", e);
219 }
220 }
221 }
222
223 public void gotoPage(URL url) throws TestingEngineResponseException {
224 formIdent = null;
225
226 String urlStr = url.toString().replace("http://localhost", "http://127.0.0.1");
227 driver.get(urlStr);
228 throwFailingHttpStatusCodeExceptionIfNecessary(
229 getServerResponseCode(), urlStr);
230 }
231
232
233
234
235
236
237 private void throwFailingHttpStatusCodeExceptionIfNecessary(int statusCode, String url) {
238 final boolean successful = (statusCode >= HttpStatus.SC_OK && statusCode < HttpStatus.SC_MULTIPLE_CHOICES)
239 || statusCode == HttpStatus.SC_USE_PROXY
240 || statusCode == HttpStatus.SC_NOT_MODIFIED;
241 if (!this.ignoreFailingStatusCodes && !successful) {
242 throw new TestingEngineResponseException(statusCode,
243 "unexpected status code [" + statusCode + "] at URL: [" + url + "]");
244 }
245 }
246
247 public void setScriptingEnabled(boolean value) {
248
249 jsEnabled = value;
250 if (driver != null && driver instanceof HtmlUnitDriver) {
251 ((HtmlUnitDriver) driver).setJavascriptEnabled(value);
252 }
253 }
254
255 public void setThrowExceptionOnScriptError(boolean value) {
256 this.throwExceptionOnScriptError = true;
257 }
258
259 public List<javax.servlet.http.Cookie> getCookies() {
260 List<javax.servlet.http.Cookie> result = new LinkedList<javax.servlet.http.Cookie>();
261 Set<Cookie> cookies = driver.manage().getCookies();
262 for (Cookie cookie : cookies) {
263 javax.servlet.http.Cookie c = new javax.servlet.http.Cookie(
264 cookie.getName(), cookie.getValue());
265 c.setDomain(cookie.getDomain());
266 Date expire = cookie.getExpiry();
267 if (expire == null) {
268 c.setMaxAge(-1);
269 } else {
270 Date now = Calendar.getInstance().getTime();
271
272 Long second = Long.valueOf((expire.getTime() - now.getTime()) / 1000);
273 c.setMaxAge(second.intValue());
274 }
275 c.setPath(cookie.getPath());
276 c.setSecure(cookie.isSecure());
277 result.add(c);
278 }
279 return result;
280 }
281
282 public boolean hasWindow(String windowName) {
283
284 String current = driver.getWindowHandle();
285 try {
286 driver.switchTo().window(windowName);
287 driver.switchTo().window(current);
288 return true;
289 } catch (NoSuchWindowException e) {
290 return false;
291 }
292 }
293
294 public boolean hasWindowByTitle(String windowTitle) {
295
296 String current = driver.getWindowHandle();
297 for (String handle : driver.getWindowHandles()) {
298 driver.switchTo().window(handle);
299 if (driver.getTitle().equals(windowTitle)) {
300 driver.switchTo().window(current);
301 return true;
302 }
303 }
304 driver.switchTo().window(current);
305 return false;
306 }
307
308 public void gotoWindow(String windowName) {
309 driver.switchTo().window(windowName);
310 }
311
312 public void gotoWindowByTitle(String title) {
313
314 String current = driver.getWindowHandle();
315 for (String handle : driver.getWindowHandles()) {
316 driver.switchTo().window(handle);
317 if (title.equals(driver.getTitle())) {
318 return;
319 }
320 }
321 driver.switchTo().window(current);
322 throw new RuntimeException("No window found with title [" + title + "]");
323 }
324
325 public void gotoWindow(int windowID) {
326 Set<String> handles = driver.getWindowHandles();
327 driver.switchTo().window(handles.toArray(new String[handles.size()])[windowID]);
328 }
329
330 public void gotoRootWindow() {
331 driver.switchTo().defaultContent();
332 }
333
334 public int getWindowCount() {
335 return driver.getWindowHandles().size();
336 }
337
338 public void closeWindow() {
339 formIdent = null;
340 driver.close();
341
342 if (getWindowCount() > 0) {
343 driver.switchTo().window(driver.getWindowHandles().iterator().next());
344 }
345 }
346
347 public boolean hasFrame(String frameNameOrId) {
348 List<WebElement> frameset = driver.findElements(By.tagName("frame"));
349 for (WebElement frame : frameset) {
350 if (frameNameOrId.equals(frame.getAttribute("name"))
351 || frameNameOrId.equals(frame.getAttribute("id"))) {
352 return true;
353 }
354 }
355 return false;
356 }
357
358 public void gotoFrame(String frameNameOrId) {
359 driver.switchTo().frame(frameNameOrId);
360 }
361
362 public void setWorkingForm(int index) {
363 formIdent = "position()=" + (index + 1);
364 }
365
366 public void setWorkingForm(String nameOrId, int index) {
367 if (nameOrId != null) {
368 formIdent = "(@name=" + escapeQuotes(nameOrId) + " or @id=" + escapeQuotes(nameOrId) + ")][position()="
369 + (index + 1);
370 } else {
371 formIdent = null;
372 }
373 }
374
375 protected String formSelector() {
376 if (formIdent == null) {
377 return "//form";
378 }
379 return "//form[" + formIdent + "]";
380 }
381
382 public boolean hasForm() {
383 return hasElementByXPath("//form");
384 }
385
386 public boolean hasForm(String nameOrID) {
387 return hasElementByXPath("//form[@name=" + escapeQuotes(nameOrID) + " or @id=" + escapeQuotes(nameOrID) + "]");
388 }
389
390 public boolean hasForm(String nameOrID, int index) {
391 return hasElementByXPath("//form[@name=" + escapeQuotes(nameOrID) + " or @id=" + escapeQuotes(nameOrID) + "][position()="
392 + (index + 1) + "]");
393 }
394
395 public boolean hasFormParameterNamed(String paramName) {
396 return getWebElementByXPath("//*[@name=" + escapeQuotes(paramName) + "]", false, true) != null;
397 }
398
399 private WebElement getWebElementByXPath(String xpathAfterForm, boolean searchOnlyInCurrentForm, boolean overrideWorkingForm) {
400
401 if (formIdent != null) {
402 try {
403 return driver.findElement(By.xpath("//form[" + formIdent + "]" + xpathAfterForm));
404 } catch (NoSuchElementException ex) {
405 if (searchOnlyInCurrentForm) {
406 return null;
407 }
408 }
409 }
410
411 List<WebElement> forms = driver.findElements(By.tagName("form"));
412 int index = 0;
413 for (WebElement f : forms) {
414 try {
415 WebElement e = driver.findElement(By.xpath("//form[position()=" + (index + 1) + "]" + xpathAfterForm));
416 if (overrideWorkingForm) {
417 setWorkingForm(index);
418 }
419 return e;
420 } catch (NoSuchElementException ex) {
421 index++;
422 }
423 }
424
425 try {
426 return driver.findElement(By.xpath("//body" + xpathAfterForm));
427 } catch (NoSuchElementException ex) {
428 return null;
429 }
430 }
431
432 private List<WebElement> getWebElementsByXPath(String xpathAfterForm) {
433 try {
434 return driver.findElements(By.xpath(formSelector() + xpathAfterForm));
435 } catch (NoSuchElementException e) {
436 return null;
437 }
438 }
439
440 public String getTextFieldValue(String paramName) {
441 WebElement e = getTextField(paramName);
442 return e.getAttribute("value");
443 }
444
445 public String getHiddenFieldValue(String paramName) {
446 WebElement e = getWebElementByXPath("//input[@type='hidden' and @name=" + escapeQuotes(paramName) + "]", false, true);
447 return e.getAttribute("value");
448 }
449
450 public void setTextField(String inputName, String text) {
451 WebElement e = getTextField(inputName);
452 e.clear();
453 e.sendKeys(text);
454 }
455
456
457
458
459 private WebElement getTextField(String paramName) {
460 WebElement e = getWebElementByXPath("//input[@type='text' and @name=" + escapeQuotes(paramName) + "]", false, true);
461 if (e == null) {
462 e = getWebElementByXPath("//textarea[@name=" + escapeQuotes(paramName) + "]", false, true);
463 }
464 if (e == null) {
465 e = getWebElementByXPath("//input[@type='file' and @name=" + escapeQuotes(paramName) + "]", false, true);
466 }
467 if (e == null) {
468 e = getWebElementByXPath("//input[@type='password' and @name=" + escapeQuotes(paramName) + "]", false, true);
469 }
470 return e;
471 }
472
473 public void setHiddenField(String inputName, String text) {
474 WebElement e = getWebElementByXPath("//input[@type='hidden' and @name=" + escapeQuotes(inputName) + "]", false, true);
475 ((JavascriptExecutor) driver).executeScript("arguments[0].value=" + escapeQuotes(text), e);
476 }
477
478 public String[] getSelectOptionValues(String selectName) {
479 return getSelectOptionValues(selectName, 0);
480 }
481
482 public String[] getSelectOptionValues(String selectName, int index) {
483 Select select = new Select(getWebElementByXPath("//select[@name=" + escapeQuotes(selectName) + "][" + (index + 1) + "]", true, true));
484 ArrayList<String> result = new ArrayList<String>();
485 for (WebElement opt : select.getOptions()) {
486 result.add(opt.getAttribute("value"));
487 }
488 return result.toArray(new String[result.size()]);
489 }
490
491 public String[] getSelectedOptions(String selectName) {
492 return getSelectedOptions(selectName, 0);
493 }
494
495 private String[] getSelectedOptions(Select select) {
496
497 String[] result = new String[select.getAllSelectedOptions().size()];
498 int i = 0;
499 for (WebElement opt : select.getAllSelectedOptions()) {
500 result[i++] = opt.getAttribute("value");
501 }
502 return result;
503 }
504
505 public String[] getSelectedOptions(String selectName, int index) {
506 Select select = new Select(getWebElementByXPath("//select[@name=" + escapeQuotes(selectName) + "][" + (index + 1) + "]", true, true));
507 return getSelectedOptions(select);
508 }
509
510 private String getSelectOptionValueForLabel(Select select, String label) {
511 for (WebElement opt : select.getOptions()) {
512 if (opt.getText().equals(label)) {
513 return opt.getAttribute("value");
514 }
515 }
516 throw new RuntimeException("Unable to find option " + label);
517 }
518
519 private String getSelectOptionLabelForValue(Select select, String value) {
520 for (WebElement opt : select.getOptions()) {
521 if (opt.getAttribute("value").equals(value)) {
522 return opt.getText();
523 }
524 }
525 throw new RuntimeException("Unable to find option " + value);
526 }
527
528 public String getSelectOptionLabelForValue(String selectName, String optionValue) {
529 Select select = new Select(getWebElementByXPath("//select[@name=" + escapeQuotes(selectName) + "]", true, true));
530 return getSelectOptionLabelForValue(select, optionValue);
531 }
532
533 public String getSelectOptionLabelForValue(String selectName, int index, String optionValue) {
534 Select select = new Select(getWebElementByXPath("//select[@name=" + escapeQuotes(selectName) + "][" + (index + 1) + "]", true, true));
535 return getSelectOptionLabelForValue(select, optionValue);
536 }
537
538 public String getSelectOptionValueForLabel(String selectName, String optionLabel) {
539 Select select = new Select(getWebElementByXPath("//select[@name=" + escapeQuotes(selectName) + "]", true, true));
540 return getSelectOptionValueForLabel(select, optionLabel);
541 }
542
543 public String getSelectOptionValueForLabel(String selectName, int index, String optionLabel) {
544 Select select = new Select(getWebElementByXPath("//select[@name=" + escapeQuotes(selectName) + "][" + (index + 1) + "]", true, true));
545 return getSelectOptionValueForLabel(select, optionLabel);
546 }
547
548 public void selectOptions(String selectName, String[] optionValues) {
549 selectOptions(selectName, 0, optionValues);
550 }
551
552 public void selectOptions(String selectName, int index, String[] optionValues) {
553 Select select = new Select(getWebElementByXPath("//select[@name=" + escapeQuotes(selectName) + "][" + (index + 1) + "]", true, true));
554 if (!select.isMultiple() && optionValues.length > 1)
555 throw new RuntimeException("Multiselect not enabled");
556 for (String option : optionValues) {
557 boolean found = false;
558 for (WebElement opt : select.getOptions()) {
559 if (opt.getAttribute("value").equals(option)) {
560 select.selectByValue(option);
561 found = true;
562 break;
563 }
564 }
565 if (!found) {
566 throw new RuntimeException("Option " + option
567 + " not found");
568 }
569 }
570 }
571
572 public void unselectOptions(String selectName, String[] optionValues) {
573 unselectOptions(selectName, 0, optionValues);
574 }
575
576 public void unselectOptions(String selectName, int index, String[] optionValues) {
577 Select select = new Select(getWebElementByXPath("//select[@name=" + escapeQuotes(selectName) + "][" + (index + 1) + "]", true, true));
578 if (!select.isMultiple() && optionValues.length > 1)
579 throw new RuntimeException("Multiselect not enabled");
580 for (String option : optionValues) {
581 boolean found = false;
582 for (WebElement opt : select.getOptions()) {
583 if (opt.getAttribute("value").equals(option)) {
584 select.deselectByValue(option);
585 found = true;
586 break;
587 }
588 }
589 if (!found) {
590 throw new RuntimeException("Option " + option
591 + " not found");
592 }
593 }
594 }
595
596 public boolean hasSelectOption(String selectName, String optionLabel) {
597 return hasSelectOption(selectName, 0, optionLabel);
598 }
599
600 public boolean hasSelectOptionValue(String selectName, String optionValue) {
601 return hasSelectOptionValue(selectName, 0, optionValue);
602 }
603
604 public boolean hasSelectOption(String selectName, int index, String optionLabel) {
605 Select select = new Select(getWebElementByXPath("//select[@name=" + escapeQuotes(selectName) + "][" + (index + 1) + "]", true, true));
606 for (WebElement opt : select.getOptions()) {
607 if (opt.getText().equals(optionLabel)) {
608 return true;
609 }
610 }
611 return false;
612 }
613
614 public boolean hasSelectOptionValue(String selectName, int index, String optionValue) {
615 Select select = new Select(getWebElementByXPath("//select[@name=" + escapeQuotes(selectName) + "][" + (index + 1) + "]", true, true));
616 for (WebElement opt : select.getOptions()) {
617 if (opt.getAttribute("value").equals(optionValue)) {
618 return true;
619 }
620 }
621 return false;
622 }
623
624 public boolean isCheckboxSelected(String checkBoxName) {
625 WebElement e = getWebElementByXPath("//input[@type='checkbox' and @name=" + escapeQuotes(checkBoxName) + "]", true, true);
626 return e.isSelected();
627 }
628
629 public boolean isCheckboxSelected(String checkBoxName, String checkBoxValue) {
630 WebElement e = getWebElementByXPath("//input[@type='checkbox' and @name=" + escapeQuotes(checkBoxName) + " and @value=" + escapeQuotes(checkBoxValue) + "]", true, true);
631 return e.isSelected();
632 }
633
634 public void checkCheckbox(String checkBoxName) {
635 WebElement e = getWebElementByXPath("//input[@type='checkbox' and @name=" + escapeQuotes(checkBoxName) + "]", true, true);
636 if (!e.isSelected()) {
637 e.click();
638 }
639 }
640
641 public void checkCheckbox(String checkBoxName, String checkBoxValue) {
642 WebElement e = getWebElementByXPath("//input[@type='checkbox' and @name=" + escapeQuotes(checkBoxName) + " and @value=" + escapeQuotes(checkBoxValue) + "]", true, true);
643 if (!e.isSelected()) {
644 e.click();
645 }
646 }
647
648 public void uncheckCheckbox(String checkBoxName) {
649 WebElement e = getWebElementByXPath("//input[@type='checkbox' and @name=" + escapeQuotes(checkBoxName) + "]", true, true);
650 if (e.isSelected()) {
651 e.click();
652 }
653 }
654
655 public void uncheckCheckbox(String checkBoxName, String value) {
656 WebElement e = getWebElementByXPath("//input[@type='checkbox' and @name=" + escapeQuotes(checkBoxName) + " and @value=" + escapeQuotes(value) + "]", true, true);
657 if (e.isSelected()) {
658 e.click();
659 }
660 }
661
662 public void clickRadioOption(String radioGroup, String radioOptionValue) {
663 WebElement e = getWebElementByXPath("//input[@type='radio' and @name=" + escapeQuotes(radioGroup) + " and @value=" + escapeQuotes(radioOptionValue) + "]", false, true);
664 e.click();
665 }
666
667 public boolean hasRadioOption(String radioGroup, String radioOptionValue) {
668 WebElement e = getWebElementByXPath("//input[@type='radio' and @name=" + escapeQuotes(radioGroup) + " and @value=" + escapeQuotes(radioOptionValue) + "]", false, true);
669 return e != null;
670 }
671
672 public String getSelectedRadio(String radioGroup) {
673 List<WebElement> radios = getWebElementsByXPath("/input[@type='radio' and @name=" + escapeQuotes(radioGroup) + "]");
674 for (WebElement r : radios) {
675 if (r.isSelected()) {
676 return r.getAttribute("value");
677 }
678 }
679 return null;
680 }
681
682 public boolean hasSubmitButton() {
683 return (getWebElementByXPath("//input[@type='submit' or @type='image']", true, true) != null) || (getWebElementByXPath("//button[@type='submit']", false, true) != null);
684 }
685
686 public boolean hasSubmitButton(String nameOrID) {
687 return (getWebElementByXPath("//input[(@type='submit' or @type='image') and (@name=" + escapeQuotes(nameOrID) + " or @id=" + nameOrID + ")]", true, true) != null)
688 || (getWebElementByXPath("//button[@type='submit' and (@name=" + escapeQuotes(nameOrID) + " or @id=" + escapeQuotes(nameOrID) + ")]", true, true) != null);
689 }
690
691 public boolean hasSubmitButton(String nameOrID, String value) {
692 return (getWebElementByXPath("//input[(@type='submit' or @type='image') and (@name=" + escapeQuotes(nameOrID) + " or @id=" + escapeQuotes(nameOrID) + ") and @value="
693 + escapeQuotes(value) + "]", true, true) != null)
694 || (getWebElementByXPath("//button[@type='submit' and (@name=" + escapeQuotes(nameOrID) + " or @id=" + escapeQuotes(nameOrID) + ") and @value=" + escapeQuotes(value) + "]",
695 true, true) != null);
696 }
697
698 public void submit() {
699 WebElement e = getWebElementByXPath("//input[@type='submit' or @type='image']", true, true);
700 if (e == null) {
701 e = getWebElementByXPath("//button[@type='submit']", true, true);
702 }
703 e.submit();
704 throwFailingHttpStatusCodeExceptionIfNecessary(
705 getServerResponseCode(), driver.getCurrentUrl());
706 }
707
708 public void submit(String nameOrID) {
709 WebElement e = getWebElementByXPath("//input[(@type='submit' or @type='image') and (@name=" + escapeQuotes(nameOrID) + " or @id=" + escapeQuotes(nameOrID) + ")]", true, true);
710 if (e == null) {
711 e = getWebElementByXPath("//button[@type='submit' and (@name=" + escapeQuotes(nameOrID) + " or @id=" + escapeQuotes(nameOrID) + ")]", true, true);
712 }
713 e.submit();
714 throwFailingHttpStatusCodeExceptionIfNecessary(
715 getServerResponseCode(), driver.getCurrentUrl());
716 }
717
718 public void submit(String buttonName, String buttonValue) {
719 WebElement e = getWebElementByXPath("//input[(@type='submit' or @type='image') and (@name=" + escapeQuotes(buttonName) + " or @id=" + escapeQuotes(buttonName)
720 + ") and @value=" + escapeQuotes(buttonValue) + "]", true, true);
721 if (e == null) {
722 e = getWebElementByXPath("//button[@type='submit' and (@name=" + escapeQuotes(buttonName) + " or @id=" + escapeQuotes(buttonName) + ") and @value="
723 + escapeQuotes(buttonValue) + "]", true, true);
724 }
725 e.submit();
726 throwFailingHttpStatusCodeExceptionIfNecessary(
727 getServerResponseCode(), driver.getCurrentUrl());
728 }
729
730 public boolean hasResetButton() {
731 return getWebElementByXPath("//input[@type='reset']", false, true) != null;
732 }
733
734 public boolean hasResetButton(String nameOrID) {
735 return getWebElementByXPath("//input[@type='reset' and (@name=" + escapeQuotes(nameOrID) + " or @id=" + escapeQuotes(nameOrID) + ")]", true, true) != null;
736 }
737
738 public void reset() {
739 getWebElementByXPath("//input[@type='reset']", true, true).click();
740 ;
741 }
742
743 private WebElement getButton(String nameOrID) {
744 WebElement e = getWebElementByXPath("//input[(@type='submit' or @type='image' or @type='reset' or @type='button') and (@name=" + escapeQuotes(nameOrID) + " or @id="
745 + escapeQuotes(nameOrID) + ")]", false, true);
746 if (e == null) {
747 e = getWebElementByXPath("//button[@name=" + escapeQuotes(nameOrID) + " or @id=" + escapeQuotes(nameOrID) + "]", false, true);
748 }
749 return e;
750 }
751
752 private WebElement getButtonWithText(String text) {
753 WebElement e = getWebElementByXPath("//input[(@type='submit' or @type='reset' or @type='button') and contains(@value," + escapeQuotes(text) + ")]", false, true);
754 if (e == null) {
755 e = getWebElementByXPath("//button[contains(.," + escapeQuotes(text) + ")]", false, true);
756 }
757 return e;
758 }
759
760 public boolean hasButtonWithText(String text) {
761 return getButtonWithText(text) != null;
762 }
763
764 public boolean hasButton(String buttonId) {
765 return getButton(buttonId) != null;
766 }
767
768 public void clickButton(String buttonId) {
769 getButton(buttonId).click();
770 }
771
772 public void clickButtonWithText(String buttonValueText) {
773 getButtonWithText(buttonValueText).click();
774 }
775
776 public URL getPageURL() {
777 try {
778 return new URL(driver.getCurrentUrl());
779 } catch (MalformedURLException ex) {
780 throw new RuntimeException(ex);
781 }
782 }
783
784 public String getPageText() {
785 try {
786 return driver.findElement(By.tagName("body")).getText();
787 } catch (Exception e) {
788
789 return driver.getPageSource();
790 }
791 }
792
793 public String getPageSource() {
794 return driver.getPageSource();
795
796
797
798
799
800
801
802
803
804
805
806
807 }
808
809 public String getPageTitle() {
810 return driver.getTitle();
811 }
812
813 public String getServerResponse() {
814 throw new UnsupportedOperationException("Not supported yet.");
815 }
816
817 public InputStream getInputStream() {
818 try {
819 return response.getRawResponse().getEntity().getContent();
820 } catch (Exception e) {
821 throw new TestingEngineResponseException(e);
822 }
823 }
824
825 public InputStream getInputStream(URL url) throws TestingEngineResponseException {
826 try {
827 return url.openStream();
828 } catch (IOException e) {
829 throw new TestingEngineResponseException(e);
830 }
831 }
832
833 public boolean hasTable(String tableSummaryNameOrId) {
834 return getHtmlTable(tableSummaryNameOrId) != null;
835 }
836
837 public Table getTable(String tableSummaryNameOrId) {
838 WebElement table = getHtmlTable(tableSummaryNameOrId);
839 Table result = new Table();
840 List<WebElement> trs = table.findElements(By.xpath("tr | tbody/tr"));
841 for (int i = 0; i < trs.size(); i++) {
842 Row newRow = new Row();
843 WebElement tr = trs.get(i);
844 List<WebElement> tds = tr.findElements(By.xpath("td | th"));
845 for (WebElement td : tds) {
846 int colspan;
847 try {
848 colspan = Integer.valueOf(td.getAttribute("colspan"));
849 } catch (NumberFormatException e) {
850 colspan = 1;
851 }
852 int rowspan;
853 try {
854 rowspan = Integer.valueOf(td.getAttribute("rowspan"));
855 } catch (NumberFormatException e) {
856 rowspan = 1;
857 }
858 newRow.appendCell(new Cell(td.getText(),
859 colspan,
860 rowspan));
861 }
862 result.appendRow(newRow);
863 }
864 return result;
865 }
866
867
868
869
870
871
872
873 private WebElement getHtmlTable(String tableSummaryOrId) {
874 try {
875 return driver.findElement(By.xpath("(//table[@id="
876 + escapeQuotes(tableSummaryOrId) + " or @summary=" + escapeQuotes(tableSummaryOrId) + "])"));
877 } catch (NoSuchElementException e) {
878 return null;
879 }
880 }
881
882 private WebElement getLinkWithImage(String filename, int index) {
883 try {
884 return driver.findElement(By.xpath("(//a[img[contains(@src,"
885 + escapeQuotes(filename) + ")]])[" + (index + 1) + "]"));
886 } catch (NoSuchElementException e) {
887 return null;
888 }
889 }
890
891 private WebElement getLinkWithText(String linkText, int index) {
892 List<WebElement> lnks = driver.findElements(By.xpath("//a"));
893 int count = 0;
894 for (WebElement lnk : lnks) {
895 if ((lnk.getText().indexOf(linkText) >= 0) && (count++ == index)) {
896 return lnk;
897 }
898 }
899 return null;
900 }
901
902 private WebElement getLinkWithExactText(String linkText, int index) {
903 List<WebElement> lnks = driver.findElements(By.xpath("//a"));
904 int count = 0;
905 for (WebElement lnk : lnks) {
906 if (lnk.getText().equals(linkText) && (count++ == index)) {
907 return lnk;
908 }
909 }
910 return null;
911 }
912
913 public boolean hasLinkWithText(String linkText, int index) {
914 return getLinkWithText(linkText, index) != null;
915 }
916
917 public boolean hasLinkWithExactText(String linkText, int index) {
918 return getLinkWithExactText(linkText, index) != null;
919 }
920
921 public boolean hasLinkWithImage(String imageFileName, int index) {
922 return getLinkWithImage(imageFileName, index) != null;
923 }
924
925 public boolean hasLink(String anId) {
926 try {
927 driver.findElement(By.xpath("//a[@id='" + anId + "']"));
928 return true;
929 } catch (NoSuchElementException e) {
930 return false;
931 }
932 }
933
934 public void clickLinkWithText(String linkText, int index) {
935 WebElement link = getLinkWithText(linkText, index);
936 if (link == null) {
937 throw new RuntimeException("No Link found for \"" + linkText
938 + "\" with index " + index);
939 }
940 link.click();
941 }
942
943 public void clickLinkWithExactText(String linkText, int index) {
944 WebElement link = getLinkWithExactText(linkText, index);
945 if (link == null) {
946 throw new RuntimeException("No Link found for \"" + linkText
947 + "\" with index " + index);
948 }
949 link.click();
950 }
951
952 public void clickLink(String anID) {
953 driver.findElement(By.xpath("//a[@id='" + anID + "']")).click();
954 }
955
956 public void clickLinkWithImage(String imageFileName, int index) {
957 WebElement link = getLinkWithImage(imageFileName, index);
958 if (link == null) {
959 throw new RuntimeException("No Link found with filename \""
960 + imageFileName + "\" and index " + index);
961 }
962 link.click();
963 }
964
965 public boolean hasElement(String anID) {
966 try {
967 driver.findElement(By.id(anID));
968 return true;
969 } catch (NoSuchElementException e) {
970 return false;
971 }
972 }
973
974 public boolean hasElementByXPath(String xpath) {
975 try {
976 driver.findElement(By.xpath(xpath));
977 return true;
978 } catch (NoSuchElementException e) {
979 return false;
980 }
981 }
982
983 public void clickElementByXPath(String xpath) {
984 driver.findElement(By.xpath(xpath)).click();
985 }
986
987 public String getElementAttributByXPath(String xpath, String attribut) {
988 return driver.findElement(By.xpath(xpath)).getAttribute(attribut);
989 }
990
991 public String getElementTextByXPath(String xpath) {
992 return driver.findElement(By.xpath(xpath)).getText();
993 }
994
995 public boolean isTextInElement(String elementID, String text) {
996 return isTextInElement(driver.findElement(By.id(elementID)), text);
997 }
998
999
1000
1001
1002
1003
1004
1005 private boolean isTextInElement(WebElement element, String text) {
1006 return element.getText().indexOf(text) >= 0;
1007 }
1008
1009 public boolean isMatchInElement(String elementID, String regexp) {
1010 return isMatchInElement(driver.findElement(By.id(elementID)), regexp);
1011 }
1012
1013
1014
1015
1016
1017
1018
1019 private boolean isMatchInElement(WebElement element, String regexp) {
1020 RE re = getRE(regexp);
1021 return re.match(element.getText());
1022 }
1023
1024 private RE getRE(String regexp) {
1025 try {
1026 return new RE(regexp, RE.MATCH_SINGLELINE);
1027 } catch (RESyntaxException e) {
1028 throw new RuntimeException(e);
1029 }
1030 }
1031
1032 public void setExpectedJavaScriptAlert(JavascriptAlert[] alerts) throws ExpectedJavascriptAlertException {
1033 throw new UnsupportedOperationException("Not supported yet.");
1034 }
1035
1036 public void setExpectedJavaScriptConfirm(JavascriptConfirm[] confirms) throws ExpectedJavascriptConfirmException {
1037 throw new UnsupportedOperationException("Not supported yet.");
1038 }
1039
1040 public void setExpectedJavaScriptPrompt(JavascriptPrompt[] prompts) throws ExpectedJavascriptPromptException {
1041 throw new UnsupportedOperationException("Not supported yet.");
1042 }
1043
1044 public IElement getElementByXPath(String xpath) {
1045 try {
1046 return new WebDriverElementImpl(driver, driver.findElement(By.xpath(xpath)));
1047 } catch (NoSuchElementException e) {
1048 return null;
1049 }
1050 }
1051
1052 public IElement getElementByID(String id) {
1053 try {
1054 return new WebDriverElementImpl(driver, driver.findElement(By.id(id)));
1055 } catch (NoSuchElementException e) {
1056 return null;
1057 }
1058 }
1059
1060 public List<IElement> getElementsByXPath(String xpath) {
1061 List<IElement> result = new ArrayList<IElement>();
1062 List<WebElement> elements = driver.findElements(By.xpath(xpath));
1063 for (WebElement child : elements) {
1064 result.add(new WebDriverElementImpl(driver, child));
1065 }
1066 return result;
1067 }
1068
1069 public int getServerResponseCode() {
1070 return response.getRawResponse().getStatusLine().getStatusCode();
1071 }
1072
1073 public String getHeader(String name) {
1074 return response.getHeader(name);
1075 }
1076
1077 public Map<String, String> getAllHeaders() {
1078 Map<String, String> map = new java.util.HashMap<String, String>();
1079 for (Header header : response.getRawResponse().getAllHeaders()) {
1080 map.put(header.getName(), header.getValue());
1081 }
1082 return map;
1083 }
1084
1085 public void setIgnoreFailingStatusCodes(boolean ignore) {
1086 this.ignoreFailingStatusCodes = ignore;
1087 }
1088
1089 public List<String> getComments() {
1090 throw new UnsupportedOperationException("Not supported yet.");
1091 }
1092
1093 public void setTimeout(int milliseconds) {
1094 throw new UnsupportedOperationException("Not supported yet.");
1095 }
1096
1097 public List<HttpHeader> getResponseHeaders() {
1098 List<HttpHeader> result = new LinkedList<HttpHeader>();
1099 for (Header header : response.getRawResponse().getAllHeaders()) {
1100 result.add(new HttpHeader(header.getName(), header.getValue()));
1101 }
1102 return result;
1103 }
1104
1105
1106
1107
1108
1109
1110 protected String escapeQuotes(String toEscape) {
1111
1112 if (toEscape.indexOf("\"") > -1 && toEscape.indexOf("'") > -1) {
1113 boolean quoteIsLast = false;
1114 if (toEscape.indexOf("\"") == toEscape.length() - 1) {
1115 quoteIsLast = true;
1116 }
1117 String[] substrings = toEscape.split("\"");
1118
1119 StringBuilder quoted = new StringBuilder("concat(");
1120 for (int i = 0; i < substrings.length; i++) {
1121 quoted.append("\"").append(substrings[i]).append("\"");
1122 quoted.append(((i == substrings.length - 1) ? (quoteIsLast ? ", '\"')" : ")") : ", '\"', "));
1123 }
1124 return quoted.toString();
1125 }
1126
1127
1128 if (toEscape.indexOf("\"") > -1) {
1129 return String.format("'%s'", toEscape);
1130 }
1131
1132
1133 return String.format("\"%s\"", toEscape);
1134 }
1135
1136 }