1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package net.sourceforge.jwebunit.htmlunit;
20
21 import com.gargoylesoftware.htmlunit.AlertHandler;
22 import com.gargoylesoftware.htmlunit.BrowserVersion;
23 import com.gargoylesoftware.htmlunit.ConfirmHandler;
24 import com.gargoylesoftware.htmlunit.DefaultCredentialsProvider;
25 import com.gargoylesoftware.htmlunit.ElementNotFoundException;
26 import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
27 import com.gargoylesoftware.htmlunit.ImmediateRefreshHandler;
28 import com.gargoylesoftware.htmlunit.JavaScriptPage;
29 import com.gargoylesoftware.htmlunit.Page;
30 import com.gargoylesoftware.htmlunit.PromptHandler;
31 import com.gargoylesoftware.htmlunit.RefreshHandler;
32 import com.gargoylesoftware.htmlunit.TextPage;
33 import com.gargoylesoftware.htmlunit.TopLevelWindow;
34 import com.gargoylesoftware.htmlunit.UnexpectedPage;
35 import com.gargoylesoftware.htmlunit.WebClient;
36 import com.gargoylesoftware.htmlunit.WebResponse;
37 import com.gargoylesoftware.htmlunit.WebWindow;
38 import com.gargoylesoftware.htmlunit.WebWindowEvent;
39 import com.gargoylesoftware.htmlunit.WebWindowListener;
40 import com.gargoylesoftware.htmlunit.WebWindowNotFoundException;
41 import com.gargoylesoftware.htmlunit.html.DomComment;
42 import com.gargoylesoftware.htmlunit.html.DomNode;
43 import com.gargoylesoftware.htmlunit.html.FrameWindow;
44 import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
45 import com.gargoylesoftware.htmlunit.html.HtmlButton;
46 import com.gargoylesoftware.htmlunit.html.HtmlButtonInput;
47 import com.gargoylesoftware.htmlunit.html.HtmlCheckBoxInput;
48 import com.gargoylesoftware.htmlunit.html.HtmlElement;
49 import com.gargoylesoftware.htmlunit.html.HtmlForm;
50 import com.gargoylesoftware.htmlunit.html.HtmlHiddenInput;
51 import com.gargoylesoftware.htmlunit.html.HtmlImageInput;
52 import com.gargoylesoftware.htmlunit.html.HtmlInput;
53 import com.gargoylesoftware.htmlunit.html.HtmlOption;
54 import com.gargoylesoftware.htmlunit.html.HtmlPage;
55 import com.gargoylesoftware.htmlunit.html.HtmlRadioButtonInput;
56 import com.gargoylesoftware.htmlunit.html.HtmlResetInput;
57 import com.gargoylesoftware.htmlunit.html.HtmlSelect;
58 import com.gargoylesoftware.htmlunit.html.HtmlSubmitInput;
59 import com.gargoylesoftware.htmlunit.html.HtmlTable;
60 import com.gargoylesoftware.htmlunit.html.HtmlTableCell;
61 import com.gargoylesoftware.htmlunit.html.HtmlTableRow;
62 import com.gargoylesoftware.htmlunit.html.HtmlTableRow.CellIterator;
63 import com.gargoylesoftware.htmlunit.html.HtmlTextArea;
64 import com.gargoylesoftware.htmlunit.util.Cookie;
65 import com.gargoylesoftware.htmlunit.util.NameValuePair;
66 import com.gargoylesoftware.htmlunit.xml.XmlPage;
67 import net.sourceforge.jwebunit.api.HttpHeader;
68 import net.sourceforge.jwebunit.api.IElement;
69 import net.sourceforge.jwebunit.api.ITestingEngine;
70 import net.sourceforge.jwebunit.exception.ExpectedJavascriptAlertException;
71 import net.sourceforge.jwebunit.exception.ExpectedJavascriptConfirmException;
72 import net.sourceforge.jwebunit.exception.ExpectedJavascriptPromptException;
73 import net.sourceforge.jwebunit.exception.TestingEngineResponseException;
74 import net.sourceforge.jwebunit.exception.UnableToSetFormException;
75 import net.sourceforge.jwebunit.exception.UnexpectedJavascriptAlertException;
76 import net.sourceforge.jwebunit.exception.UnexpectedJavascriptConfirmException;
77 import net.sourceforge.jwebunit.exception.UnexpectedJavascriptPromptException;
78 import net.sourceforge.jwebunit.html.Cell;
79 import net.sourceforge.jwebunit.html.Row;
80 import net.sourceforge.jwebunit.html.Table;
81 import net.sourceforge.jwebunit.javascript.JavascriptAlert;
82 import net.sourceforge.jwebunit.javascript.JavascriptConfirm;
83 import net.sourceforge.jwebunit.javascript.JavascriptPrompt;
84 import net.sourceforge.jwebunit.util.TestContext;
85 import org.apache.http.auth.AuthScope;
86 import org.apache.regexp.RE;
87 import org.apache.regexp.RESyntaxException;
88 import org.slf4j.Logger;
89 import org.slf4j.LoggerFactory;
90 import org.w3c.dom.Node;
91 import org.w3c.dom.NodeList;
92
93 import java.io.IOException;
94 import java.io.InputStream;
95 import java.net.InetAddress;
96 import java.net.URL;
97 import java.net.UnknownHostException;
98 import java.util.ArrayList;
99 import java.util.Arrays;
100 import java.util.Calendar;
101 import java.util.Date;
102 import java.util.LinkedList;
103 import java.util.List;
104 import java.util.Map;
105 import java.util.Set;
106
107
108
109
110
111
112
113
114 public class HtmlUnitTestingEngineImpl implements ITestingEngine {
115
116
117
118 private final Logger logger = LoggerFactory.getLogger(HtmlUnitTestingEngineImpl.class);
119
120
121
122
123 private RefreshHandler refreshHandler;
124
125
126
127 private WebClient wc;
128
129
130
131
132 private WebWindow win;
133
134
135
136
137 private TestContext testContext;
138
139
140
141
142 private HtmlForm form;
143
144
145
146
147 private boolean jsEnabled = true;
148
149
150
151
152 private boolean throwExceptionOnScriptError = true;
153
154
155
156
157 private List<JavascriptAlert> expectedJavascriptAlerts = new LinkedList<JavascriptAlert>();
158
159
160
161
162 private List<JavascriptConfirm> expectedJavascriptConfirms = new LinkedList<JavascriptConfirm>();
163
164
165
166
167 private List<JavascriptPrompt> expectedJavascriptPrompts = new LinkedList<JavascriptPrompt>();
168
169
170
171
172 private BrowserVersion defaultBrowserVersion = BrowserVersion.FIREFOX_38;
173
174
175
176
177 private boolean ignoreFailingStatusCodes = false;
178
179
180
181
182 private int timeout = 0;
183
184
185
186
187
188
189 public HtmlUnitTestingEngineImpl() {
190 }
191
192
193
194
195
196
197 HtmlUnitTestingEngineImpl(WebClient client) {
198 this.wc = client;
199 }
200
201
202
203
204
205
206
207
208 @Override
209 public void beginAt(URL initialURL, TestContext context)
210 throws TestingEngineResponseException {
211 this.setTestContext(context);
212 initWebClient();
213 gotoPage(initialURL);
214 }
215
216
217
218
219
220 @Override
221 public void closeBrowser() throws ExpectedJavascriptAlertException,
222 ExpectedJavascriptConfirmException,
223 ExpectedJavascriptPromptException {
224 if (wc != null) {
225 wc.close();
226 wc = null;
227 }
228 form = null;
229 if (this.expectedJavascriptAlerts.size() > 0) {
230 throw new ExpectedJavascriptAlertException(
231 (expectedJavascriptAlerts.get(0))
232 .getMessage());
233 }
234 if (this.expectedJavascriptConfirms.size() > 0) {
235 throw new ExpectedJavascriptConfirmException(
236 (expectedJavascriptConfirms.get(0))
237 .getMessage());
238 }
239 if (this.expectedJavascriptPrompts.size() > 0) {
240 throw new ExpectedJavascriptPromptException(
241 (expectedJavascriptPrompts.get(0))
242 .getMessage());
243 }
244
245 }
246
247
248
249
250
251
252
253 @Override
254 public void gotoPage(URL initialURL) throws TestingEngineResponseException {
255 try {
256 wc.getPage(initialURL);
257 win = wc.getCurrentWindow();
258 form = null;
259 } catch (FailingHttpStatusCodeException ex) {
260 throw new TestingEngineResponseException(ex.getStatusCode(),
261 "unexpected status code [" + ex.getStatusCode() + "] at URL: [" + initialURL + "]", ex);
262 } catch (IOException ex) {
263 throw new RuntimeException(ex);
264 }
265 }
266
267
268
269
270 @Override
271 public void setScriptingEnabled(boolean value) {
272
273 jsEnabled = value;
274 if (wc != null) {
275 wc.getOptions().setJavaScriptEnabled(value);
276 }
277 }
278
279 @Override
280 public void setThrowExceptionOnScriptError(boolean value) {
281 throwExceptionOnScriptError = value;
282 if (wc != null) {
283 wc.getOptions().setThrowExceptionOnScriptError(value);
284 }
285 }
286
287 @Override
288 public List<javax.servlet.http.Cookie> getCookies() {
289 List<javax.servlet.http.Cookie> result = new LinkedList<javax.servlet.http.Cookie>();
290 Set<Cookie> cookies = wc.getCookieManager().getCookies();
291 for (Cookie cookie : cookies) {
292 javax.servlet.http.Cookie c = new javax.servlet.http.Cookie(
293 cookie.getName(), cookie.getValue());
294 c.setComment(cookie.toHttpClient().getComment());
295 c.setDomain(cookie.getDomain());
296 Date expire = cookie.toHttpClient().getExpiryDate();
297 if (expire == null) {
298 c.setMaxAge(-1);
299 } else {
300 Date now = Calendar.getInstance().getTime();
301
302 Long second = Long.valueOf((expire.getTime() - now.getTime()) / 1000);
303 c.setMaxAge(second.intValue());
304 }
305 c.setPath(cookie.getPath());
306 c.setSecure(cookie.toHttpClient().isSecure());
307 c.setVersion(cookie.toHttpClient().getVersion());
308 result.add(c);
309 }
310 return result;
311 }
312
313 @Override
314 public boolean hasWindow(String windowName) {
315 try {
316 getWindow(windowName);
317 } catch (WebWindowNotFoundException e) {
318 return false;
319 }
320 return true;
321 }
322
323 @Override
324 public boolean hasWindowByTitle(String title) {
325 return getWindowByTitle(title) != null;
326 }
327
328
329
330
331
332
333 @Override
334 public void gotoWindow(String windowName) {
335 setMainWindow(getWindow(windowName));
336 }
337
338 @Override
339 public void gotoWindow(int windowID) {
340 setMainWindow(wc.getWebWindows().get(windowID));
341 }
342
343 @Override
344 public int getWindowCount() {
345 return wc.getWebWindows().size();
346 }
347
348
349
350
351
352
353 @Override
354 public void gotoWindowByTitle(String title) {
355 WebWindow window = getWindowByTitle(title);
356 if (window != null) {
357 setMainWindow(window);
358 }
359 else {
360 throw new RuntimeException("No window found with title [" + title + "]");
361 }
362 }
363
364
365
366
367 @Override
368 public void closeWindow() {
369 if (win != null) {
370 ((TopLevelWindow) win.getTopWindow()).close();
371 win = wc.getCurrentWindow();
372 form = null;
373 }
374
375 }
376
377
378
379
380 @Override
381 public boolean hasFrame(String frameNameOrId) {
382 return getFrame(frameNameOrId) != null;
383 }
384
385
386
387
388 @Override
389 public void gotoFrame(String frameNameOrId) {
390 WebWindow frame = getFrame(frameNameOrId);
391 if (frame == null) {
392 throw new RuntimeException("No frame found in current page with name or id [" + frameNameOrId + "]");
393 }
394 win = frame;
395 }
396
397
398
399
400 @Override
401 public void setWorkingForm(int index) {
402 HtmlForm newForm = getForm(index);
403 if (newForm == null) {
404 throw new UnableToSetFormException("No form found in current page with index " + index);
405 }
406 setWorkingForm(newForm);
407 }
408
409
410
411
412 @Override
413 public void setWorkingForm(String nameOrId, int index) {
414 HtmlForm newForm = getForm(nameOrId, index);
415 if (newForm == null) {
416 throw new UnableToSetFormException("No form found in current page with name or id [" + nameOrId + "] and index " + index);
417 }
418 setWorkingForm(newForm);
419 }
420
421
422
423
424 @Override
425 public boolean hasForm() {
426 return ((HtmlPage) win.getEnclosedPage()).getForms().size() > 0;
427 }
428
429
430
431
432
433
434 @Override
435 public boolean hasForm(String nameOrID) {
436 return getForm(nameOrID) != null;
437 }
438
439 @Override
440 public boolean hasForm(String nameOrID, int index) {
441 return getForm(nameOrID, index) != null;
442 }
443
444 @Override
445 public boolean hasFormParameterNamed(String paramName) {
446 for (HtmlElement e : getCurrentPage().getHtmlElementDescendants()) {
447 if (e.getAttribute("name").equals(paramName)) {
448
449 if (e.getEnclosingForm() != null && getWorkingForm() == null) {
450 setWorkingForm(e.getEnclosingForm());
451 }
452 return true;
453 }
454 }
455 return false;
456 }
457
458
459
460
461
462
463
464 @Override
465 public String getTextFieldValue(String paramName) {
466
467 if (form != null) {
468 for (HtmlElement e : form.getHtmlElementDescendants()) {
469 if (e instanceof HtmlInput && e.getAttribute("name").equals(paramName)) {
470
471 return ((HtmlInput) e).getValueAttribute();
472 }
473 if (e instanceof HtmlTextArea && e.getAttribute("name").equals(paramName)) {
474
475 return ((HtmlTextArea) e).getText();
476 }
477 }
478 }
479
480
481 HtmlElement outside_element = getHtmlElementWithAttribute("name", paramName);
482 if (outside_element != null) {
483 if (outside_element instanceof HtmlInput) {
484
485 if (outside_element.getEnclosingForm() != null) {
486 form = outside_element.getEnclosingForm();
487 }
488 return ((HtmlInput) outside_element).getValueAttribute();
489 }
490 if (outside_element instanceof HtmlTextArea) {
491
492 if (outside_element.getEnclosingForm() != null) {
493 form = outside_element.getEnclosingForm();
494 }
495 return ((HtmlTextArea) outside_element).getText();
496 }
497 }
498
499
500 throw new RuntimeException(
501 "getTextFieldParameterValue failed, text field with name ["
502 + paramName + "] does not exist.");
503 }
504
505
506
507
508
509
510
511 @Override
512 public String getHiddenFieldValue(String paramName) {
513
514 if (form != null) {
515 for (HtmlElement e : form.getHtmlElementDescendants()) {
516 if (e instanceof HtmlHiddenInput && e.getAttribute("name").equals(paramName)) {
517
518 return ((HtmlInput) e).getValueAttribute();
519 }
520 }
521 }
522
523
524 HtmlElement outside_element = getHtmlElementWithAttribute("name", paramName);
525 if (outside_element != null) {
526 if (outside_element instanceof HtmlHiddenInput) {
527
528 if (outside_element.getEnclosingForm() != null) {
529 form = outside_element.getEnclosingForm();
530 }
531 return ((HtmlHiddenInput) outside_element).getValueAttribute();
532 }
533 }
534
535
536 throw new RuntimeException("No hidden field with name [" + paramName
537 + "] was found.");
538 }
539
540
541
542
543
544
545
546 @Override
547 public void setTextField(String paramName, String text) {
548
549 if (form != null) {
550 for (HtmlElement e : form.getHtmlElementDescendants()) {
551 if (e instanceof HtmlInput && e.getAttribute("name").equals(paramName)) {
552
553 ((HtmlInput) e).setValueAttribute(text);
554 return;
555 }
556 if (e instanceof HtmlTextArea && e.getAttribute("name").equals(paramName)) {
557
558 ((HtmlTextArea) e).setText(text);
559 return;
560 }
561 }
562 }
563
564
565 HtmlElement outside_element = getHtmlElementWithAttribute("name", paramName);
566 if (outside_element != null) {
567 if (outside_element instanceof HtmlInput) {
568 ((HtmlInput) outside_element).setValueAttribute(text);
569
570 if (outside_element.getEnclosingForm() != null) {
571 form = outside_element.getEnclosingForm();
572 }
573 return;
574 }
575 if (outside_element instanceof HtmlTextArea) {
576 ((HtmlTextArea) outside_element).setText(text);
577
578 if (outside_element.getEnclosingForm() != null) {
579 form = outside_element.getEnclosingForm();
580 }
581 return;
582 }
583 }
584
585
586 throw new RuntimeException("No text field with name [" + paramName
587 + "] was found.");
588 }
589
590
591
592
593
594
595
596 @Override
597 public void setHiddenField(String fieldName, String text) {
598
599 if (form != null) {
600 for (HtmlElement e : form.getHtmlElementDescendants()) {
601 if (e instanceof HtmlHiddenInput && e.getAttribute("name").equals(fieldName)) {
602
603 ((HtmlHiddenInput) e).setValueAttribute(text);
604 return;
605 }
606 }
607 }
608
609
610 HtmlElement outside_element = getHtmlElementWithAttribute("name", fieldName);
611 if (outside_element != null) {
612 if (outside_element instanceof HtmlHiddenInput) {
613 ((HtmlHiddenInput) outside_element).setValueAttribute(text);
614
615 if (outside_element.getEnclosingForm() != null) {
616 form = outside_element.getEnclosingForm();
617 }
618 return;
619 }
620 }
621
622
623 throw new RuntimeException("No hidden field with name [" + fieldName
624 + "] was found.");
625 }
626
627
628
629
630
631
632 @Override
633 public String[] getSelectOptionValues(String selectName) {
634 HtmlSelect sel = getForm().getSelectByName(selectName);
635 ArrayList<String> result = new ArrayList<String>();
636 for (HtmlOption opt : sel.getOptions()) {
637 result.add(opt.getValueAttribute());
638 }
639 return result.toArray(new String[result.size()]);
640 }
641
642
643
644
645
646
647
648
649 @Override
650 public String[] getSelectOptionValues(String selectName, int index) {
651 List<HtmlSelect> sels = getForm().getSelectsByName(selectName);
652 if (sels == null || sels.size() < index + 1) {
653 throw new RuntimeException("Did not find select with name [" + selectName
654 + "] at index " + index);
655 }
656 HtmlSelect sel = sels.get(index);
657 ArrayList<String> result = new ArrayList<String>();
658 for (HtmlOption opt : sel.getOptions()) {
659 result.add(opt.getValueAttribute());
660 }
661 return result.toArray(new String[result.size()]);
662 }
663
664 private String[] getSelectedOptions(HtmlSelect sel) {
665 String[] result = new String[sel.getSelectedOptions().size()];
666 int i = 0;
667 for (HtmlOption opt : sel.getSelectedOptions()) {
668 result[i++] = opt.getValueAttribute();
669 }
670 return result;
671 }
672
673 @Override
674 public String[] getSelectedOptions(String selectName) {
675 HtmlSelect sel = getForm().getSelectByName(selectName);
676 return getSelectedOptions(sel);
677 }
678
679 @Override
680 public String[] getSelectedOptions(String selectName, int index) {
681 List<HtmlSelect> sels = getForm().getSelectsByName(selectName);
682 if (sels == null || sels.size() < index + 1) {
683 throw new RuntimeException("Did not find select with name [" + selectName
684 + "] at index " + index);
685 }
686 HtmlSelect sel = sels.get(index);
687 return getSelectedOptions(sel);
688 }
689
690 private String getSelectOptionValueForLabel(HtmlSelect sel, String label) {
691 for (HtmlOption opt : sel.getOptions()) {
692 if (opt.asText().equals(label)) {
693 return opt.getValueAttribute();
694 }
695 }
696 throw new RuntimeException("Unable to find option " + label + " for "
697 + sel.getNameAttribute());
698 }
699
700 @Override
701 public String getSelectOptionValueForLabel(String selectName, String label) {
702 HtmlSelect sel = getForm().getSelectByName(selectName);
703 return getSelectOptionValueForLabel(sel, label);
704 }
705
706 @Override
707 public String getSelectOptionValueForLabel(String selectName, int index, String label) {
708 List<HtmlSelect> sels = getForm().getSelectsByName(selectName);
709 if (sels == null || sels.size() < index + 1) {
710 throw new RuntimeException("Did not find select with name [" + selectName
711 + "] at index " + index);
712 }
713 HtmlSelect sel = sels.get(index);
714 return getSelectOptionValueForLabel(sel, label);
715 }
716
717 private String getSelectOptionLabelForValue(HtmlSelect sel, String value) {
718 for (HtmlOption opt : sel.getOptions()) {
719 if (opt.getValueAttribute().equals(value)) {
720 return opt.asText();
721 }
722 }
723 throw new RuntimeException("Unable to find option " + value + " for "
724 + sel.getNameAttribute());
725 }
726
727 @Override
728 public String getSelectOptionLabelForValue(String selectName, String value) {
729 HtmlSelect sel = getForm().getSelectByName(selectName);
730 return getSelectOptionLabelForValue(sel, value);
731 }
732
733 @Override
734 public String getSelectOptionLabelForValue(String selectName, int index, String value) {
735 List<HtmlSelect> sels = getForm().getSelectsByName(selectName);
736 if (sels == null || sels.size() < index + 1) {
737 throw new RuntimeException("Did not find select with name [" + selectName
738 + "] at index " + index);
739 }
740 HtmlSelect sel = sels.get(index);
741 return getSelectOptionLabelForValue(sel, value);
742 }
743
744 @Override
745 public URL getPageURL() {
746 return win.getEnclosedPage().getWebResponse().getWebRequest().getUrl();
747 }
748
749 @Override
750 public String getPageSource() {
751 return win.getEnclosedPage().getWebResponse()
752 .getContentAsString();
753 }
754
755 @Override
756 public String getPageTitle() {
757 return getCurrentPageTitle();
758 }
759
760 @Override
761 public String getPageText() {
762 Page page = win.getEnclosedPage();
763 if (page instanceof HtmlPage) {
764 return ((HtmlPage) page).getBody().asText();
765 }
766 if (page instanceof TextPage) {
767 return ((TextPage) page).getContent();
768 }
769 if (page instanceof JavaScriptPage) {
770 return ((JavaScriptPage) page).getContent();
771 }
772 if (page instanceof XmlPage) {
773 return ((XmlPage) page).getContent();
774 }
775 if (page instanceof UnexpectedPage) {
776 return ((UnexpectedPage) page).getWebResponse()
777 .getContentAsString();
778 }
779 throw new RuntimeException(
780 "Unexpected error in getPageText(). This method need to be updated.");
781 }
782
783 @Override
784 public String getServerResponse() {
785 StringBuffer result = new StringBuffer();
786 WebResponse wr = wc.getCurrentWindow().getEnclosedPage()
787 .getWebResponse();
788 result.append(wr.getStatusCode()).append(" ").append(
789 wr.getStatusMessage()).append("\n");
790 result.append("Location: ").append(wr.getWebRequest().getUrl()).append("\n");
791 for (NameValuePair h : wr.getResponseHeaders()) {
792 result.append(h.getName()).append(": ").append(h.getValue())
793 .append("\n");
794 }
795 result.append("\n");
796 result.append(wr.getContentAsString());
797 return result.toString();
798 }
799
800 @Override
801 public InputStream getInputStream() {
802 try {
803 return wc.getCurrentWindow().getEnclosedPage().getWebResponse()
804 .getContentAsStream();
805 } catch (IOException e) {
806 throw new RuntimeException(e);
807 }
808 }
809
810 @Override
811 public InputStream getInputStream(URL resourceUrl)
812 throws TestingEngineResponseException {
813 WebWindow imageWindow = null;
814 try {
815
816
817 imageWindow = wc.openWindow(resourceUrl, "for_stream");
818 Page page = imageWindow.getEnclosedPage();
819 return page.getWebResponse().getContentAsStream();
820 } catch (FailingHttpStatusCodeException aException) {
821 throw new TestingEngineResponseException(
822 aException.getStatusCode(), aException);
823 } catch (IOException e) {
824 throw new RuntimeException(e);
825 } finally {
826 if (imageWindow != null) {
827 wc.deregisterWebWindow(imageWindow);
828 }
829 }
830 }
831
832
833
834
835
836
837
838
839
840
841
842 protected WebClient createWebClient() {
843
844
845
846
847
848
849
850 BrowserVersion bv;
851 if (testContext.getUserAgent() != null) {
852 bv = BrowserVersion.FIREFOX_38.clone();
853 bv.setUserAgent(testContext.getUserAgent());
854 } else {
855 bv = defaultBrowserVersion;
856 }
857
858 if (getTestContext().getProxyHost() != null && getTestContext().getProxyPort() > 0) {
859
860 return new WebClient(bv, getTestContext().getProxyHost(), getTestContext().getProxyPort());
861 } else {
862 return new WebClient(bv);
863 }
864 }
865
866
867
868
869 private void initWebClient() {
870
871 wc = createWebClient();
872
873 wc.getOptions().setJavaScriptEnabled(jsEnabled);
874 wc.getOptions().setThrowExceptionOnFailingStatusCode(!ignoreFailingStatusCodes);
875 wc.getOptions().setThrowExceptionOnScriptError(throwExceptionOnScriptError);
876 wc.getOptions().setRedirectEnabled(true);
877 wc.getOptions().setUseInsecureSSL(true);
878 if (refreshHandler == null) {
879 wc.setRefreshHandler(new ImmediateRefreshHandler());
880 } else {
881 wc.setRefreshHandler(refreshHandler);
882 }
883 wc.getOptions().setTimeout(timeout);
884 DefaultCredentialsProvider creds = new DefaultCredentialsProvider();
885 if (getTestContext().hasAuthorization()) {
886 creds.addCredentials(getTestContext().getUser(), getTestContext()
887 .getPassword());
888 }
889 if (getTestContext().hasNTLMAuthorization()) {
890 InetAddress netAddress;
891 String address;
892 try {
893 netAddress = InetAddress.getLocalHost();
894 address = netAddress.getHostName();
895 } catch (UnknownHostException e) {
896 address = "";
897 }
898 creds.addNTLMCredentials(getTestContext().getUser(),
899 getTestContext().getPassword(), "", -1, address,
900 getTestContext().getDomain());
901 }
902 if (getTestContext().hasProxyAuthorization()) {
903 creds.addCredentials(getTestContext().getProxyUser(),
904 getTestContext().getProxyPasswd(), getTestContext()
905 .getProxyHost(), getTestContext().getProxyPort(), AuthScope.ANY_REALM);
906 }
907 wc.setCredentialsProvider(creds);
908 wc.addWebWindowListener(new WebWindowListener() {
909 @Override
910 public void webWindowClosed(WebWindowEvent event) {
911 if (win == null || event.getOldPage().equals(win.getEnclosedPage())) {
912 win = wc.getCurrentWindow();
913 form = null;
914 }
915 String win = event.getWebWindow().getName();
916 Page oldPage = event.getOldPage();
917 String oldPageTitle = "no_html";
918 if (oldPage instanceof HtmlPage) {
919 oldPageTitle = ((HtmlPage) oldPage).getTitleText();
920 }
921 logger.debug("Window {} closed : {}", win, oldPageTitle);
922 }
923
924 @Override
925 public void webWindowContentChanged(WebWindowEvent event) {
926 form = null;
927 String winName = event.getWebWindow().getName();
928 Page oldPage = event.getOldPage();
929 Page newPage = event.getNewPage();
930 String oldPageTitle = "no_html";
931 if (oldPage instanceof HtmlPage) {
932 oldPageTitle = ((HtmlPage) oldPage).getTitleText();
933 }
934 String newPageTitle = "no_html";
935 if (newPage instanceof HtmlPage) {
936 newPageTitle = ((HtmlPage) newPage).getTitleText();
937 }
938 logger.debug("Window \"{}\" changed : \"{}\" became \"{}", new Object[] {winName, oldPageTitle, newPageTitle});
939 }
940
941 @Override
942 public void webWindowOpened(WebWindowEvent event) {
943 String win = event.getWebWindow().getName();
944 Page newPage = event.getNewPage();
945 if (newPage instanceof HtmlPage) {
946 logger.debug("Window {} opened : {}", win, ((HtmlPage) newPage).getTitleText());
947 } else {
948 logger.info("Window {} opened", win);
949 }
950 }
951 });
952
953 wc.setAlertHandler(new AlertHandler() {
954 @Override
955 public void handleAlert(Page page, String msg) {
956 if (expectedJavascriptAlerts.size() < 1) {
957 throw new UnexpectedJavascriptAlertException(msg);
958 } else {
959 JavascriptAlert expected = expectedJavascriptAlerts
960 .remove(0);
961 if (!msg.equals(expected.getMessage())) {
962 throw new UnexpectedJavascriptAlertException(msg);
963 }
964 }
965 }
966 });
967
968 wc.setConfirmHandler(new ConfirmHandler() {
969 @Override
970 public boolean handleConfirm(Page page, String msg) {
971 if (expectedJavascriptConfirms.size() < 1) {
972 throw new UnexpectedJavascriptConfirmException(msg);
973 } else {
974 JavascriptConfirm expected = expectedJavascriptConfirms
975 .remove(0);
976 if (!msg.equals(expected.getMessage())) {
977 throw new UnexpectedJavascriptConfirmException(msg);
978 } else {
979 return expected.getAction();
980 }
981 }
982 }
983 });
984
985 wc.setPromptHandler(new PromptHandler() {
986 @Override
987 public String handlePrompt(Page page, String msg) {
988 if (expectedJavascriptPrompts.size() < 1) {
989 throw new UnexpectedJavascriptPromptException(msg);
990 } else {
991 JavascriptPrompt expected = expectedJavascriptPrompts
992 .remove(0);
993 if (!msg.equals(expected.getMessage())) {
994 throw new UnexpectedJavascriptPromptException(msg);
995 } else {
996 return expected.getInput();
997 }
998 }
999 }
1000 });
1001
1002 for (javax.servlet.http.Cookie c : getTestContext().getCookies()) {
1003
1004 wc.getCookieManager().addCookie(
1005 new Cookie(c.getDomain() != null ? c.getDomain() : "", c
1006 .getName(), c.getValue(), c.getPath() != null ? c
1007 .getPath() : "", c.getMaxAge(), c.getSecure()));
1008 }
1009
1010 Map<String, String> requestHeaders = getTestContext().getRequestHeaders();
1011
1012 for (Map.Entry<String, String> requestHeader : requestHeaders.entrySet()) {
1013 wc.addRequestHeader(requestHeader.getKey(), requestHeader.getValue());
1014 }
1015 }
1016
1017
1018
1019
1020
1021
1022
1023 public WebWindow getWindow(String windowName) {
1024 return wc.getWebWindowByName(windowName);
1025 }
1026
1027
1028
1029
1030
1031
1032 public WebWindow getCurrentWindow() {
1033 return win;
1034 }
1035
1036
1037
1038
1039
1040
1041 public WebClient getWebClient() {
1042 return wc;
1043 }
1044
1045 private HtmlElement getHtmlElement(String anID) {
1046 try {
1047 return ((HtmlPage) win.getEnclosedPage()).getHtmlElementById(anID);
1048 } catch (ElementNotFoundException e) {
1049 return null;
1050 }
1051 }
1052
1053 private HtmlElement getHtmlElementByXPath(String xpath) {
1054 return getHtmlElementByXPath(getCurrentPage(), xpath);
1055 }
1056
1057 private HtmlElement getHtmlElementByXPath(DomNode parent, String xpath) {
1058 return (HtmlElement) parent.getFirstByXPath(xpath);
1059 }
1060
1061
1062
1063
1064 @Override
1065 public List<String> getComments() {
1066 List<String> comments = new ArrayList<String>();
1067 getComments(comments, ((HtmlPage) win.getEnclosedPage()));
1068
1069 return comments;
1070 }
1071
1072
1073
1074
1075
1076
1077
1078 private void getComments(List<String> comments, Node node) {
1079 NodeList nodes = node.getChildNodes();
1080 for (int i = 0; i < nodes.getLength(); i++) {
1081 Node n = nodes.item(i);
1082 if (n instanceof DomComment) {
1083 comments.add(((DomComment) n).getData().trim());
1084 }
1085
1086 getComments(comments, n);
1087 }
1088 }
1089
1090
1091
1092
1093 private WebWindow getWindowByTitle(String title) {
1094 for (WebWindow window : wc.getWebWindows()) {
1095 if (window.getEnclosedPage() instanceof HtmlPage
1096 && ((HtmlPage) window.getEnclosedPage()).getTitleText()
1097 .equals(title)) {
1098 return window;
1099 }
1100 }
1101 return null;
1102 }
1103
1104
1105
1106
1107
1108 public String getCurrentPageTitle() {
1109 if (win.getEnclosedPage() instanceof HtmlPage) {
1110 return ((HtmlPage) win.getEnclosedPage()).getTitleText();
1111 }
1112 return "";
1113 }
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131 protected HtmlForm getForm() {
1132 if (form == null) {
1133 if (hasForm()) {
1134 setWorkingForm(getForm(0));
1135 return getForm(0);
1136 } else {
1137 throw new RuntimeException("No form in current page");
1138 }
1139 } else {
1140 return form;
1141 }
1142 }
1143
1144 private HtmlForm getForm(int formIndex) {
1145 return ((HtmlPage) win.getEnclosedPage()).getForms().get(
1146 formIndex);
1147 }
1148
1149 private HtmlForm getForm(String nameOrID) {
1150 try {
1151 return (HtmlForm) ((HtmlPage) win.getEnclosedPage())
1152 .getHtmlElementById(nameOrID);
1153 } catch (ElementNotFoundException e) {
1154
1155 }
1156 try {
1157 return ((HtmlPage) win.getEnclosedPage()).getFormByName(nameOrID);
1158 } catch (ElementNotFoundException e) {
1159
1160 }
1161 return null;
1162 }
1163
1164 private HtmlForm getForm(String nameOrID, int index) {
1165 List<HtmlForm> forms = new ArrayList<HtmlForm>();
1166 for (HtmlForm form : getCurrentPage().getForms()) {
1167 if (nameOrID.equals(form.getId())
1168 || nameOrID.equals(form.getNameAttribute())) {
1169 forms.add(form);
1170 }
1171 }
1172 if (forms.size() > index) {
1173 return forms.get(index);
1174 }
1175 else {
1176 return null;
1177 }
1178 }
1179
1180 private List<HtmlForm> getForms() {
1181 HtmlPage page = (HtmlPage) win.getEnclosedPage();
1182 return page.getForms();
1183 }
1184
1185 protected HtmlPage getCurrentPage() {
1186 Page page = win.getEnclosedPage();
1187 if (page instanceof HtmlPage) {
1188 return (HtmlPage) page;
1189 }
1190 throw new RuntimeException("Non HTML content");
1191 }
1192
1193 private void setWorkingForm(HtmlForm newForm) {
1194 form = newForm;
1195 }
1196
1197 private HtmlForm getWorkingForm() {
1198 return form;
1199 }
1200
1201
1202
1203
1204
1205
1206
1207
1208 private boolean hasHtmlElementWithAttribute(String attributeName, String value) {
1209 return getHtmlElementWithAttribute(attributeName, value) != null;
1210 }
1211
1212
1213
1214
1215
1216
1217
1218
1219 private HtmlElement getHtmlElementWithAttribute(String attributeName, String value) {
1220 for (HtmlElement e : getCurrentPage().getHtmlElementDescendants()) {
1221 if (e.getAttribute(attributeName).equals(value)) {
1222 return e;
1223 }
1224 }
1225 return null;
1226 }
1227
1228
1229
1230
1231
1232
1233 public boolean hasFormSelectNamed(String selectName) {
1234 return hasHtmlElementWithAttribute("name", selectName);
1235 }
1236
1237
1238
1239
1240
1241
1242
1243 public HtmlElement getSubmitButton(String buttonName) {
1244 List<HtmlElement> btns = new LinkedList<HtmlElement>();
1245 if (form != null) {
1246 btns.addAll(getForm().getInputsByName(buttonName));
1247 btns.addAll(getForm().getButtonsByName(buttonName));
1248 } else {
1249 for (HtmlForm f : getCurrentPage().getForms()) {
1250 btns.addAll(f.getInputsByName(buttonName));
1251 btns.addAll(f.getButtonsByName(buttonName));
1252 }
1253 }
1254 for (HtmlElement o : btns) {
1255 if (o instanceof HtmlSubmitInput) {
1256 HtmlSubmitInput btn = (HtmlSubmitInput) o;
1257 if (form == null) {
1258 form = btn.getEnclosingFormOrDie();
1259 }
1260 return btn;
1261 }
1262 if (o instanceof HtmlImageInput) {
1263 HtmlImageInput btn = (HtmlImageInput) o;
1264 if (form == null) {
1265 form = btn.getEnclosingFormOrDie();
1266 }
1267 return btn;
1268 }
1269 if (o instanceof HtmlButton) {
1270 HtmlButton btn = (HtmlButton) o;
1271 if (btn.getTypeAttribute().equals("submit")) {
1272 if (form == null) {
1273 form = btn.getEnclosingFormOrDie();
1274 }
1275 return btn;
1276 }
1277 }
1278 }
1279 return null;
1280 }
1281
1282 public HtmlElement getResetButton(String buttonName) {
1283 List<HtmlElement> btns = new LinkedList<HtmlElement>();
1284 if (form != null) {
1285 btns.addAll(getForm().getInputsByName(buttonName));
1286 btns.addAll(getForm().getButtonsByName(buttonName));
1287 } else {
1288 for (HtmlForm f : getCurrentPage().getForms()) {
1289 btns.addAll(f.getInputsByName(buttonName));
1290 btns.addAll(f.getButtonsByName(buttonName));
1291 }
1292 }
1293 for (HtmlElement o : btns) {
1294 if (o instanceof HtmlResetInput) {
1295 HtmlResetInput btn = (HtmlResetInput) o;
1296 if (form == null) {
1297 form = btn.getEnclosingFormOrDie();
1298 }
1299 return btn;
1300 }
1301 if (o instanceof HtmlButton) {
1302 HtmlButton btn = (HtmlButton) o;
1303 if (btn.getTypeAttribute().equals("reset")) {
1304 if (form == null) {
1305 form = btn.getEnclosingFormOrDie();
1306 }
1307 return btn;
1308 }
1309 }
1310 }
1311 return null;
1312 }
1313
1314
1315
1316
1317
1318
1319
1320
1321 public HtmlElement getSubmitButton(String buttonName,
1322 String buttonValue) {
1323 List<HtmlElement> btns = new LinkedList<HtmlElement>();
1324 if (form != null) {
1325 btns.addAll(getForm().getInputsByName(buttonName));
1326 btns.addAll(getForm().getButtonsByName(buttonName));
1327 } else {
1328 for (HtmlForm f : getCurrentPage().getForms()) {
1329 btns.addAll(f.getInputsByName(buttonName));
1330 btns.addAll(f.getButtonsByName(buttonName));
1331 }
1332 }
1333 for (HtmlElement o : btns) {
1334 if (o instanceof HtmlSubmitInput) {
1335 HtmlSubmitInput btn = (HtmlSubmitInput) o;
1336 if (btn.getValueAttribute().equals(buttonValue)) {
1337 if (form == null) {
1338 form = btn.getEnclosingFormOrDie();
1339 }
1340 return btn;
1341 }
1342 }
1343 if (o instanceof HtmlImageInput) {
1344 HtmlImageInput btn = (HtmlImageInput) o;
1345 if (btn.getValueAttribute().equals(buttonValue)) {
1346 if (form == null) {
1347 form = btn.getEnclosingFormOrDie();
1348 }
1349 return btn;
1350 }
1351 }
1352 if (o instanceof HtmlButton) {
1353 HtmlButton btn = (HtmlButton) o;
1354 if (btn.getValueAttribute().equals(buttonValue)
1355 && btn.getTypeAttribute().equals("submit")) {
1356 if (form == null) {
1357 form = btn.getEnclosingFormOrDie();
1358 }
1359 return btn;
1360 }
1361 }
1362 }
1363 return null;
1364 }
1365
1366 private HtmlElement getSubmitButton() {
1367 List<HtmlElement> btns = new LinkedList<HtmlElement>();
1368 if (form != null) {
1369 btns.addAll(getForm().getElementsByAttribute("input", "type", "submit"));
1370 btns.addAll(getForm().getElementsByAttribute("input", "type", "image"));
1371 btns.addAll(getForm().getElementsByAttribute("button", "type", "submit"));
1372 } else {
1373 for (HtmlForm f : getCurrentPage().getForms()) {
1374 btns.addAll(f.getElementsByAttribute("input", "type", "submit"));
1375 btns.addAll(f.getElementsByAttribute("input", "type", "image"));
1376 btns.addAll(f.getElementsByAttribute("button", "type", "submit"));
1377 }
1378 }
1379 for (HtmlElement o : btns) {
1380 if (o instanceof HtmlSubmitInput) {
1381 HtmlSubmitInput btn = (HtmlSubmitInput) o;
1382 if (form == null) {
1383 form = btn.getEnclosingFormOrDie();
1384 }
1385 return btn;
1386 }
1387 if (o instanceof HtmlImageInput) {
1388 HtmlImageInput btn = (HtmlImageInput) o;
1389 if (form == null) {
1390 form = btn.getEnclosingFormOrDie();
1391 }
1392 return btn;
1393 }
1394 if (o instanceof HtmlButton) {
1395 HtmlButton btn = (HtmlButton) o;
1396 if (btn.getTypeAttribute().equals("submit")) {
1397 if (form == null) {
1398 form = btn.getEnclosingFormOrDie();
1399 }
1400 return btn;
1401 }
1402 }
1403 }
1404 return null;
1405 }
1406
1407
1408
1409
1410 @Override
1411 public boolean hasSubmitButton() {
1412 return getSubmitButton() != null;
1413 }
1414
1415
1416
1417
1418 @Override
1419 public boolean hasSubmitButton(String buttonName) {
1420 return getSubmitButton(buttonName) != null;
1421 }
1422
1423
1424
1425
1426 @Override
1427 public boolean hasSubmitButton(String buttonName, String buttonValue) {
1428 try {
1429 return getSubmitButton(buttonName, buttonValue) != null;
1430 } catch (UnableToSetFormException e) {
1431 return false;
1432 }
1433
1434 }
1435
1436 @Override
1437 public boolean hasResetButton() {
1438 HtmlForm form = getForm();
1439 List<?> l = form.getByXPath("//input[@type='reset']");
1440 List<?> l2 = form.getByXPath("//button[@type='reset']");
1441 return (l.size() > 0 || l2.size() > 0);
1442 }
1443
1444 @Override
1445 public boolean hasResetButton(String buttonName) {
1446 return getResetButton(buttonName) != null;
1447 }
1448
1449
1450
1451
1452
1453
1454 private HtmlElement getButton(String buttonId) {
1455 HtmlElement btn = null;
1456 try {
1457 btn = getCurrentPage().getHtmlElementById(buttonId);
1458 if (btn instanceof HtmlButton || btn instanceof HtmlButtonInput
1459 || btn instanceof HtmlSubmitInput
1460 || btn instanceof HtmlResetInput) {
1461 return btn;
1462 }
1463 } catch (ElementNotFoundException e) {
1464 return null;
1465 }
1466 return null;
1467 }
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482 @Override
1483 public boolean hasButtonWithText(String text) {
1484 return getButtonWithText(text) != null ? true : false;
1485 }
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501 public HtmlElement getButtonWithText(String buttonValueText) {
1502 if (buttonValueText == null) {
1503 throw new NullPointerException("Cannot search for button with null text");
1504 }
1505
1506 List<? extends HtmlElement> l = ((HtmlPage) win.getEnclosedPage()).getDocumentElement()
1507 .getHtmlElementsByTagNames(
1508 Arrays.asList(new String[] {"button", "input"}));
1509 for (HtmlElement e : l) {
1510 if (e instanceof HtmlButton) {
1511
1512
1513
1514 if (buttonValueText.equals(((HtmlButton) e).getTextContent())) {
1515 return e;
1516 }
1517 }
1518 else if (e instanceof HtmlButtonInput ||
1519 e instanceof HtmlSubmitInput ||
1520 e instanceof HtmlResetInput) {
1521 if (buttonValueText.equals(e.getAttribute("value"))) {
1522 return e;
1523 }
1524 }
1525 }
1526 return null;
1527 }
1528
1529
1530
1531
1532
1533
1534
1535 @Override
1536 public boolean hasButton(String buttonId) {
1537 try {
1538 return getButton(buttonId) != null;
1539 } catch (UnableToSetFormException e) {
1540 return false;
1541 }
1542 }
1543
1544 @Override
1545 public boolean isCheckboxSelected(String checkBoxName) {
1546 HtmlCheckBoxInput cb = getCheckbox(checkBoxName);
1547 return cb.isChecked();
1548 }
1549
1550 @Override
1551 public boolean isCheckboxSelected(String checkBoxName, String checkBoxValue) {
1552 HtmlCheckBoxInput cb = getCheckbox(checkBoxName, checkBoxValue);
1553 return cb.isChecked();
1554 }
1555
1556
1557
1558
1559
1560
1561
1562 public boolean isTextInTable(String tableSummaryOrId, String text) {
1563 HtmlTable table = getHtmlTable(tableSummaryOrId);
1564 if (table == null) {
1565 throw new RuntimeException("No table with summary or id ["
1566 + tableSummaryOrId + "] found in response.");
1567 }
1568 for (int row = 0; row < table.getRowCount(); row++) {
1569 for (int col = 0; table.getCellAt(row, col) != null; col++) {
1570 HtmlTableCell cell = table.getCellAt(row, col);
1571 if (cell != null) {
1572 String cellHtml = cell.asText();
1573 if (cellHtml.indexOf(text) != -1) {
1574 return true;
1575 }
1576 }
1577 }
1578 }
1579 return false;
1580 }
1581
1582 @Override
1583 public Table getTable(String tableSummaryNameOrId) {
1584 HtmlTable table = getHtmlTable(tableSummaryNameOrId);
1585 Table result = new Table();
1586 for (int i = 0; i < table.getRowCount(); i++) {
1587 Row newRow = new Row();
1588 HtmlTableRow htmlRow = table.getRow(i);
1589 CellIterator cellIt = htmlRow.getCellIterator();
1590 while (cellIt.hasNext()) {
1591 HtmlTableCell htmlCell = cellIt.nextCell();
1592 newRow.appendCell(new Cell(htmlCell.asText(), htmlCell
1593 .getColumnSpan(), htmlCell.getRowSpan()));
1594 }
1595 result.appendRow(newRow);
1596 }
1597 return result;
1598 }
1599
1600
1601
1602
1603
1604
1605
1606 private HtmlTable getHtmlTable(String tableSummaryNameOrId) {
1607 try {
1608 return (HtmlTable) ((HtmlPage) win.getEnclosedPage())
1609 .getHtmlElementById(tableSummaryNameOrId);
1610 } catch (ElementNotFoundException e) {
1611
1612 }
1613 try {
1614 return (HtmlTable) ((HtmlPage) win.getEnclosedPage())
1615 .getDocumentElement().getOneHtmlElementByAttribute("table",
1616 "summary", tableSummaryNameOrId);
1617 } catch (ElementNotFoundException e) {
1618
1619 }
1620 try {
1621 return (HtmlTable) ((HtmlPage) win.getEnclosedPage())
1622 .getDocumentElement().getOneHtmlElementByAttribute("table",
1623 "name", tableSummaryNameOrId);
1624 } catch (ElementNotFoundException e) {
1625
1626 }
1627 return null;
1628 }
1629
1630 @Override
1631 public boolean hasTable(String tableSummaryNameOrId) {
1632 return getHtmlTable(tableSummaryNameOrId) != null;
1633 }
1634
1635
1636
1637
1638
1639 @Override
1640 public void submit() {
1641 HtmlElement btn = getSubmitButton();
1642 if (btn == null) {
1643 throw new RuntimeException("No submit button found in current form.");
1644 }
1645 try {
1646 btn.click();
1647 } catch (FailingHttpStatusCodeException e) {
1648 throw new TestingEngineResponseException(
1649 e.getStatusCode(), e);
1650 } catch (IOException e) {
1651 throw new RuntimeException(
1652 "HtmlUnit Error submitting form using default submit button, "
1653 + "check that form has single submit button, otherwise use submit(name): \n", e);
1654 }
1655 }
1656
1657
1658
1659
1660
1661
1662
1663 @Override
1664 public void submit(String buttonName) {
1665 HtmlElement btn = getSubmitButton(buttonName);
1666 if (btn == null) {
1667 throw new RuntimeException("No submit button found in current form.");
1668 }
1669 try {
1670 btn.click();
1671 } catch (FailingHttpStatusCodeException e) {
1672 throw new TestingEngineResponseException(
1673 e.getStatusCode(), e);
1674 } catch (IOException e) {
1675 throw new RuntimeException(
1676 "HtmlUnit Error submitting form using default submit button", e);
1677 }
1678 }
1679
1680
1681
1682
1683
1684
1685
1686
1687 @Override
1688 public void submit(String buttonName, String buttonValue) {
1689 List<HtmlElement> l = new LinkedList<HtmlElement>();
1690 l.addAll(getForm().getInputsByName(buttonName));
1691 l.addAll(getForm().getButtonsByName(buttonName));
1692 try {
1693 for (int i = 0; i < l.size(); i++) {
1694 Object o = l.get(i);
1695 if (o instanceof HtmlSubmitInput) {
1696 HtmlSubmitInput inpt = (HtmlSubmitInput) o;
1697 if (inpt.getValueAttribute().equals(buttonValue)) {
1698 inpt.click();
1699 return;
1700 }
1701 }
1702 if (o instanceof HtmlImageInput) {
1703 HtmlImageInput inpt = (HtmlImageInput) o;
1704 if (inpt.getValueAttribute().equals(buttonValue)) {
1705 inpt.click();
1706 return;
1707 }
1708 }
1709 if (o instanceof HtmlButton) {
1710 HtmlButton inpt = (HtmlButton) o;
1711 if (inpt.getTypeAttribute().equals("submit")
1712 && inpt.getValueAttribute().equals(buttonValue)) {
1713 inpt.click();
1714 return;
1715 }
1716 }
1717 }
1718 } catch (FailingHttpStatusCodeException e) {
1719
1720 throw new TestingEngineResponseException(
1721 e.getStatusCode(), e);
1722 } catch (IOException e) {
1723 throw new RuntimeException(
1724 "HtmlUnit Error submitting form using submit button with name ["
1725 + buttonName + "] and value [" + buttonValue
1726 + "]", e);
1727 }
1728 throw new RuntimeException(
1729 "No submit button found in current form with name ["
1730 + buttonName + "] and value [" + buttonValue + "].");
1731 }
1732
1733
1734
1735
1736 @Override
1737 public void reset() {
1738 getForm().reset();
1739 }
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749 @Override
1750 public boolean hasLinkWithText(String linkText, int index) {
1751 return getLinkWithText(linkText, index) != null;
1752 }
1753
1754 @Override
1755 public boolean hasLinkWithExactText(String linkText, int index) {
1756 return getLinkWithExactText(linkText, index) != null;
1757 }
1758
1759 @Override
1760 public boolean hasLinkWithImage(String imageFileName, int index) {
1761 return getLinkWithImage(imageFileName, index) != null;
1762 }
1763
1764
1765
1766
1767
1768
1769 @Override
1770 public boolean hasLink(String anId) {
1771 try {
1772 ((HtmlPage) win.getEnclosedPage()).getHtmlElementById(anId);
1773 } catch (ElementNotFoundException e) {
1774 return false;
1775 }
1776 return true;
1777 }
1778
1779 @Override
1780 public void clickLinkWithText(String linkText, int index) {
1781 HtmlAnchor link = getLinkWithText(linkText, index);
1782 if (link == null) {
1783 throw new RuntimeException("No Link found for \"" + linkText
1784 + "\" with index " + index);
1785 }
1786 try {
1787 link.click();
1788 } catch (IOException e) {
1789 throw new RuntimeException("Click failed", e);
1790 }
1791 }
1792
1793 @Override
1794 public void clickLinkWithExactText(String linkText, int index) {
1795 HtmlAnchor link = getLinkWithExactText(linkText, index);
1796 if (link == null) {
1797 throw new RuntimeException("No Link found for \"" + linkText
1798 + "\" with index " + index);
1799 }
1800 try {
1801 link.click();
1802 } catch (IOException e) {
1803 throw new RuntimeException("Click failed", e);
1804 }
1805 }
1806
1807 private HtmlCheckBoxInput getCheckbox(String checkBoxName) {
1808 Object[] l = getForm().getInputsByName(checkBoxName).toArray();
1809 for (int i = 0; i < l.length; i++) {
1810 if (l[i] instanceof HtmlCheckBoxInput) {
1811 return (HtmlCheckBoxInput) l[i];
1812 }
1813 }
1814 throw new RuntimeException("No checkbox with name [" + checkBoxName
1815 + "] was found in current form.");
1816 }
1817
1818 private HtmlCheckBoxInput getCheckbox(String checkBoxName, String value) {
1819 Object[] l = getForm().getInputsByName(checkBoxName).toArray();
1820 for (int i = 0; i < l.length; i++) {
1821 if ((l[i] instanceof HtmlCheckBoxInput) &&
1822 ((HtmlCheckBoxInput) l[i]).getValueAttribute()
1823 .equals(value)) {
1824 return (HtmlCheckBoxInput) l[i];
1825 }
1826 }
1827 throw new RuntimeException("No checkbox with name [" + checkBoxName
1828 + "] and value [" + value + "] was found in current form.");
1829 }
1830
1831
1832
1833
1834
1835
1836 @Override
1837 public void checkCheckbox(String checkBoxName) {
1838 HtmlCheckBoxInput cb = getCheckbox(checkBoxName);
1839 if (!cb.isChecked()) {
1840 try {
1841 cb.click();
1842 } catch (IOException e) {
1843 throw new RuntimeException("checkCheckbox failed", e);
1844 }
1845 }
1846 }
1847
1848 @Override
1849 public void checkCheckbox(String checkBoxName, String value) {
1850 HtmlCheckBoxInput cb = getCheckbox(checkBoxName, value);
1851 if (!cb.isChecked()) {
1852 try {
1853 cb.click();
1854 } catch (IOException e) {
1855 e.printStackTrace();
1856 throw new RuntimeException("checkCheckbox failed", e);
1857 }
1858 }
1859 }
1860
1861
1862
1863
1864
1865
1866 @Override
1867 public void uncheckCheckbox(String checkBoxName) {
1868 HtmlCheckBoxInput cb = getCheckbox(checkBoxName);
1869 if (cb.isChecked()) {
1870 try {
1871 cb.click();
1872 } catch (IOException e) {
1873 e.printStackTrace();
1874 throw new RuntimeException("checkCheckbox failed", e);
1875 }
1876 }
1877 }
1878
1879 @Override
1880 public void uncheckCheckbox(String checkBoxName, String value) {
1881 HtmlCheckBoxInput cb = getCheckbox(checkBoxName, value);
1882 if (cb.isChecked()) {
1883 try {
1884 cb.click();
1885 } catch (IOException e) {
1886 e.printStackTrace();
1887 throw new RuntimeException("uncheckCheckbox failed", e);
1888 }
1889 }
1890 }
1891
1892 private HtmlRadioButtonInput getRadioOption(String radioGroup, String radioOption) {
1893 for (HtmlForm form : getForms()) {
1894 List<HtmlRadioButtonInput> buttons = form.getRadioButtonsByName(radioGroup);
1895 for (HtmlRadioButtonInput button : buttons) {
1896 if (button.getValueAttribute().equals(radioOption)) {
1897 return button;
1898 }
1899 }
1900 }
1901 return null;
1902 }
1903
1904
1905
1906
1907
1908
1909
1910 @Override
1911 public void clickRadioOption(String radioGroup, String radioOption) {
1912 HtmlRadioButtonInput rb = getRadioOption(radioGroup, radioOption);
1913 if (!rb.isChecked()) {
1914 try {
1915 rb.click();
1916 } catch (IOException e) {
1917 e.printStackTrace();
1918 throw new RuntimeException("checkCheckbox failed", e);
1919 }
1920 }
1921 }
1922
1923
1924
1925
1926
1927
1928
1929 @Override
1930 public void clickLink(String anID) {
1931 clickElementByXPath("//a[@id=\"" + anID + "\"]");
1932 }
1933
1934 private HtmlAnchor getLinkWithImage(String filename, int index) {
1935 return (HtmlAnchor) getHtmlElementByXPath("(//a[img[contains(@src,\""
1936 + filename + "\")]])[" + (index + 1) + "]");
1937 }
1938
1939 private HtmlAnchor getLinkWithText(String linkText, int index) {
1940 List<HtmlAnchor> lnks = ((HtmlPage) win.getEnclosedPage()).getAnchors();
1941 int count = 0;
1942 for (HtmlAnchor lnk : lnks) {
1943 if ((lnk.asText().indexOf(linkText) >= 0) && (count++ == index)) {
1944 return lnk;
1945 }
1946 }
1947 return null;
1948 }
1949
1950 private HtmlAnchor getLinkWithExactText(String linkText, int index) {
1951 List<HtmlAnchor> lnks = ((HtmlPage) win.getEnclosedPage()).getAnchors();
1952 int count = 0;
1953 for (HtmlAnchor lnk : lnks) {
1954 if ((lnk.asText().equals(linkText)) && (count++ == index)) {
1955 return lnk;
1956 }
1957 }
1958 return null;
1959 }
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969 @Override
1970 public void clickLinkWithImage(String imageFileName, int index) {
1971 HtmlAnchor link = getLinkWithImage(imageFileName, index);
1972 if (link == null) {
1973 throw new RuntimeException("No Link found with filename \""
1974 + imageFileName + "\" and index " + index);
1975 }
1976 try {
1977 link.click();
1978 } catch (IOException e) {
1979 throw new RuntimeException("Click failed", e);
1980 }
1981 }
1982
1983 @Override
1984 public boolean hasElement(String anID) {
1985 return getHtmlElement(anID) != null;
1986 }
1987
1988 @Override
1989 public boolean hasElementByXPath(String xpath) {
1990 return getHtmlElementByXPath(xpath) != null;
1991 }
1992
1993 @Override
1994 public void clickElementByXPath(String xpath) {
1995 HtmlElement e = getHtmlElementByXPath(xpath);
1996 if (e == null) {
1997 throw new RuntimeException("No element found with xpath \"" + xpath
1998 + "\"");
1999 }
2000 try {
2001 e.click();
2002 } catch (IOException exp) {
2003 throw new RuntimeException("Click failed", exp);
2004 }
2005 }
2006
2007 @Override
2008 public String getElementAttributByXPath(String xpath, String attribut) {
2009 HtmlElement e = getHtmlElementByXPath(xpath);
2010 if (e == null) {
2011 return null;
2012 }
2013 return e.getAttribute(attribut);
2014 }
2015
2016 @Override
2017 public String getElementTextByXPath(String xpath) {
2018 HtmlElement e = getHtmlElementByXPath(xpath);
2019 if (e == null) {
2020 return null;
2021 }
2022 return e.asText();
2023 }
2024
2025
2026
2027
2028
2029
2030 @Override
2031 public void clickButton(String buttonId) {
2032 HtmlElement btn = getButton(buttonId);
2033 try {
2034 btn.click();
2035 } catch (Exception e) {
2036 throw new RuntimeException(e);
2037 }
2038 }
2039
2040
2041
2042
2043
2044
2045
2046 @Override
2047 public void clickButtonWithText(String buttonValueText) {
2048 HtmlElement b = getButtonWithText(buttonValueText);
2049 if (b != null) {
2050 try {
2051 b.click();
2052 } catch (Exception e) {
2053 throw new RuntimeException(e);
2054 }
2055 }
2056 else {
2057 throw new RuntimeException("No button found with text: " + buttonValueText);
2058 }
2059 }
2060
2061
2062
2063
2064
2065
2066
2067 @Override
2068 public boolean hasRadioOption(String radioGroup, String radioOption) {
2069 return getRadioOption(radioGroup, radioOption) != null;
2070 }
2071
2072 @Override
2073 public String getSelectedRadio(String radioGroup) {
2074 List<HtmlRadioButtonInput> radios = getForm().getRadioButtonsByName(radioGroup);
2075 for (HtmlRadioButtonInput radio : radios) {
2076 if (radio.isChecked()) {
2077 return radio.getValueAttribute();
2078 }
2079 }
2080 throw new RuntimeException("Unexpected state: no radio button was selected in radio group [" + radioGroup + "]. Is it possible in a real browser?");
2081 }
2082
2083
2084
2085
2086
2087
2088
2089 @Override
2090 public boolean hasSelectOption(String selectName, String optionLabel) {
2091 String[] opts = getSelectOptionValues(selectName);
2092 for (int i = 0; i < opts.length; i++) {
2093 String label = getSelectOptionLabelForValue(selectName, opts[i]);
2094 if (label.equals(optionLabel)) {
2095 return true;
2096 }
2097 }
2098 return false;
2099 }
2100
2101
2102
2103
2104
2105
2106
2107 @Override
2108 public boolean hasSelectOptionValue(String selectName, String optionValue) {
2109 String[] opts = getSelectOptionValues(selectName);
2110 for (int i = 0; i < opts.length; i++) {
2111 if (opts[i].equals(optionValue)) {
2112 return true;
2113 }
2114 }
2115 return false;
2116 }
2117
2118
2119
2120
2121
2122
2123
2124 @Override
2125 public void selectOptions(String selectName, String[] options) {
2126 HtmlSelect sel = getForm().getSelectByName(selectName);
2127 if (!sel.isMultipleSelectEnabled() && options.length > 1) {
2128 throw new RuntimeException("Multiselect not enabled");
2129 }
2130 for (String option : options) {
2131 boolean found = false;
2132 for (HtmlOption opt : sel.getOptions()) {
2133 if (opt.getValueAttribute().equals(option)) {
2134 sel.setSelectedAttribute(opt, true);
2135 found = true;
2136 break;
2137 }
2138 }
2139 if (!found) {
2140 throw new RuntimeException("Option " + option
2141 + " not found");
2142 }
2143 }
2144 }
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154 @Override
2155 public boolean hasSelectOption(String selectName, int index, String optionLabel) {
2156 String[] opts = getSelectOptionValues(selectName, index);
2157 for (int i = 0; i < opts.length; i++) {
2158 String label = getSelectOptionLabelForValue(selectName, index, opts[i]);
2159 if (label.equals(optionLabel)) {
2160 return true;
2161 }
2162 }
2163 return false;
2164 }
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174 @Override
2175 public boolean hasSelectOptionValue(String selectName, int index, String optionValue) {
2176 String[] opts = getSelectOptionValues(selectName, index);
2177 for (int i = 0; i < opts.length; i++) {
2178 if (opts[i].equals(optionValue)) {
2179 return true;
2180 }
2181 }
2182 return false;
2183 }
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193 @Override
2194 public void selectOptions(String selectName, int index, String[] options) {
2195 List<HtmlSelect> sels = getForm().getSelectsByName(selectName);
2196 if (sels == null || sels.size() < index + 1) {
2197 throw new RuntimeException("Did not find select with name [" + selectName
2198 + "] at index " + index);
2199 }
2200 HtmlSelect sel = sels.get(index);
2201 if (!sel.isMultipleSelectEnabled() && options.length > 1) {
2202 throw new RuntimeException("Multiselect not enabled");
2203 }
2204 for (String option : options) {
2205 boolean found = false;
2206 for (HtmlOption opt : sel.getOptions()) {
2207 if (opt.getValueAttribute().equals(option)) {
2208 sel.setSelectedAttribute(opt, true);
2209 found = true;
2210 break;
2211 }
2212 }
2213 if (!found) {
2214 throw new RuntimeException("Option " + option
2215 + " not found");
2216 }
2217 }
2218 }
2219
2220 @Override
2221 public void unselectOptions(String selectName, String[] options) {
2222 HtmlSelect sel = getForm().getSelectByName(selectName);
2223 if (!sel.isMultipleSelectEnabled() && options.length > 1) {
2224 throw new RuntimeException("Multiselect not enabled");
2225 }
2226 for (String option : options) {
2227 boolean found = false;
2228 for (HtmlOption opt : sel.getOptions()) {
2229 if (opt.asText().equals(option)) {
2230 sel.setSelectedAttribute(opt, false);
2231 found = true;
2232 break;
2233 }
2234 }
2235 if (!found) {
2236 throw new RuntimeException("Option " + option
2237 + " not found");
2238 }
2239 }
2240 }
2241
2242 @Override
2243 public void unselectOptions(String selectName, int index, String[] options) {
2244 List<HtmlSelect> sels = getForm().getSelectsByName(selectName);
2245 if (sels == null || sels.size() < index + 1) {
2246 throw new RuntimeException("Did not find select with name [" + selectName
2247 + "] at index " + index);
2248 }
2249 HtmlSelect sel = sels.get(index);
2250 if (!sel.isMultipleSelectEnabled() && options.length > 1) {
2251 throw new RuntimeException("Multiselect not enabled");
2252 }
2253 for (String option : options) {
2254 boolean found = false;
2255 for (HtmlOption opt : sel.getOptions()) {
2256 if (opt.asText().equals(option)) {
2257 sel.setSelectedAttribute(opt, false);
2258 found = true;
2259 break;
2260 }
2261 }
2262 if (!found) {
2263 throw new RuntimeException("Option " + option
2264 + " not found");
2265 }
2266 }
2267 }
2268
2269 @Override
2270 public boolean isTextInElement(String elementID, String text) {
2271 return isTextInElement(getHtmlElement(elementID), text);
2272 }
2273
2274
2275
2276
2277
2278
2279
2280 private boolean isTextInElement(HtmlElement element, String text) {
2281 return element.asText().indexOf(text) >= 0;
2282 }
2283
2284 @Override
2285 public boolean isMatchInElement(String elementID, String regexp) {
2286 return isMatchInElement(getHtmlElement(elementID), regexp);
2287 }
2288
2289
2290
2291
2292
2293
2294
2295 private boolean isMatchInElement(HtmlElement element, String regexp) {
2296 RE re = getRE(regexp);
2297 return re.match(element.asText());
2298 }
2299
2300 private RE getRE(String regexp) {
2301 try {
2302 return new RE(regexp, RE.MATCH_SINGLELINE);
2303 } catch (RESyntaxException e) {
2304 throw new RuntimeException(e);
2305 }
2306 }
2307
2308
2309
2310
2311 @Override
2312 public void gotoRootWindow() {
2313 win = win.getTopWindow();
2314 }
2315
2316 private void setMainWindow(WebWindow win) {
2317 wc.setCurrentWindow(win);
2318 this.win = win;
2319 }
2320
2321
2322
2323
2324
2325
2326
2327 private WebWindow getFrame(String frameNameOrId) {
2328
2329 for (FrameWindow frame : getCurrentPage().getFrames()) {
2330 if (frameNameOrId.equals(frame.getFrameElement().getId())) {
2331 return frame;
2332 }
2333 }
2334
2335 for (FrameWindow frame : getCurrentPage().getFrames()) {
2336 if (frameNameOrId.equals(frame.getName())) {
2337 return frame;
2338 }
2339 }
2340
2341 return null;
2342 }
2343
2344
2345
2346
2347 private void setTestContext(TestContext testContext) {
2348 this.testContext = testContext;
2349 }
2350
2351
2352
2353
2354 protected TestContext getTestContext() {
2355 return testContext;
2356 }
2357
2358 @Override
2359 public void setExpectedJavaScriptAlert(JavascriptAlert[] alerts)
2360 throws ExpectedJavascriptAlertException {
2361 if (this.expectedJavascriptAlerts.size() > 0) {
2362 throw new ExpectedJavascriptAlertException(
2363 (expectedJavascriptAlerts.get(0))
2364 .getMessage());
2365 }
2366 for (int i = 0; i < alerts.length; i++) {
2367 expectedJavascriptAlerts.add(alerts[i]);
2368 }
2369 }
2370
2371 @Override
2372 public void setExpectedJavaScriptConfirm(JavascriptConfirm[] confirms)
2373 throws ExpectedJavascriptConfirmException {
2374 if (this.expectedJavascriptConfirms.size() > 0) {
2375 throw new ExpectedJavascriptConfirmException(
2376 (expectedJavascriptConfirms.get(0))
2377 .getMessage());
2378 }
2379 for (int i = confirms.length - 1; i >= 0; i--) {
2380 expectedJavascriptConfirms.add(confirms[i]);
2381 }
2382 }
2383
2384 @Override
2385 public void setExpectedJavaScriptPrompt(JavascriptPrompt[] prompts)
2386 throws ExpectedJavascriptPromptException {
2387 if (this.expectedJavascriptPrompts.size() > 0) {
2388 throw new ExpectedJavascriptPromptException(
2389 (expectedJavascriptPrompts.get(0))
2390 .getMessage());
2391 }
2392 for (int i = prompts.length - 1; i >= 0; i--) {
2393 expectedJavascriptPrompts.add(prompts[i]);
2394 }
2395 }
2396
2397
2398
2399
2400
2401
2402 @Override
2403 public IElement getElementByXPath(String xpath) {
2404 HtmlElement element = this.getHtmlElementByXPath(xpath);
2405 if (element != null) {
2406 return new HtmlUnitElementImpl(element);
2407 }
2408 return null;
2409 }
2410
2411
2412
2413
2414
2415
2416 @Override
2417 public IElement getElementByID(String id) {
2418 HtmlElement element = this.getHtmlElement(id);
2419 if (element != null) {
2420 return new HtmlUnitElementImpl(element);
2421 }
2422 return null;
2423 }
2424
2425
2426
2427
2428
2429
2430 @Override
2431 public List<IElement> getElementsByXPath(String xpath) {
2432 List<IElement> children = new ArrayList<IElement>();
2433 for (Object child : getCurrentPage().getByXPath(xpath)) {
2434 if (child instanceof HtmlElement) {
2435 children.add(new HtmlUnitElementImpl((HtmlElement) child));
2436 }
2437 }
2438 return children;
2439 }
2440
2441
2442
2443
2444
2445
2446 @Override
2447 public int getServerResponseCode() {
2448 return getWebResponse().getStatusCode();
2449 }
2450
2451
2452
2453
2454 public WebResponse getWebResponse() {
2455 return wc.getCurrentWindow().getEnclosedPage().getWebResponse();
2456 }
2457
2458
2459
2460
2461 @Override
2462 public void setIgnoreFailingStatusCodes(boolean ignore) {
2463 ignoreFailingStatusCodes = ignore;
2464 if (wc != null) {
2465 wc.getOptions().setThrowExceptionOnFailingStatusCode(!ignore);
2466 }
2467 }
2468
2469
2470
2471
2472
2473
2474 @Override
2475 public String getHeader(String name) {
2476 return getWebResponse().getResponseHeaderValue(name);
2477 }
2478
2479
2480
2481
2482
2483
2484 @Override
2485 @Deprecated
2486 public Map<String, String> getAllHeaders() {
2487 Map<String, String> map = new java.util.HashMap<String, String>();
2488 for (NameValuePair header : getWebResponse().getResponseHeaders()) {
2489 map.put(header.getName(), header.getValue());
2490 }
2491 return map;
2492 }
2493
2494 @Override
2495 public List<HttpHeader> getResponseHeaders() {
2496 List<HttpHeader> result = new LinkedList<HttpHeader>();
2497 for (NameValuePair header : getWebResponse().getResponseHeaders()) {
2498 result.add(new HttpHeader(header.getName(), header.getValue()));
2499 }
2500 return result;
2501 }
2502
2503
2504
2505
2506
2507
2508
2509
2510 public BrowserVersion getDefaultBrowserVersion() {
2511 return defaultBrowserVersion;
2512 }
2513
2514
2515
2516
2517
2518
2519
2520
2521 public void setDefaultBrowserVersion(BrowserVersion defaultBrowserVersion) {
2522 this.defaultBrowserVersion = defaultBrowserVersion;
2523 }
2524
2525 @Override
2526 public void setTimeout(int milliseconds) {
2527 if (wc != null && wc.getWebConnection() != null) {
2528 throw new IllegalArgumentException("Cannot set the timeout when the WebConnection has already been created.");
2529 }
2530 timeout = milliseconds;
2531 }
2532
2533 public void setRefreshHandler(RefreshHandler handler) {
2534 this.refreshHandler = handler;
2535
2536 if (wc != null) {
2537 wc.setRefreshHandler(refreshHandler);
2538 }
2539 }
2540
2541 }