drnic-celerity 0.0.6.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (230) hide show
  1. data/History.txt +75 -0
  2. data/License.txt +621 -0
  3. data/Manifest.txt +229 -0
  4. data/README.rdoc +78 -0
  5. data/Rakefile +25 -0
  6. data/benchmark/bm_2000_spans.rb +48 -0
  7. data/benchmark/bm_digg.rb +26 -0
  8. data/benchmark/bm_google_images.rb +36 -0
  9. data/benchmark/bm_input_locator.rb +69 -0
  10. data/benchmark/bm_text_input.rb +19 -0
  11. data/benchmark/loader.rb +14 -0
  12. data/celerity.gemspec +40 -0
  13. data/lib/celerity.rb +77 -0
  14. data/lib/celerity/browser.rb +888 -0
  15. data/lib/celerity/clickable_element.rb +73 -0
  16. data/lib/celerity/collections.rb +156 -0
  17. data/lib/celerity/container.rb +779 -0
  18. data/lib/celerity/default_viewer.rb +14 -0
  19. data/lib/celerity/disabled_element.rb +40 -0
  20. data/lib/celerity/element.rb +314 -0
  21. data/lib/celerity/element_collection.rb +107 -0
  22. data/lib/celerity/element_locator.rb +177 -0
  23. data/lib/celerity/elements/button.rb +45 -0
  24. data/lib/celerity/elements/file_field.rb +29 -0
  25. data/lib/celerity/elements/form.rb +23 -0
  26. data/lib/celerity/elements/frame.rb +77 -0
  27. data/lib/celerity/elements/image.rb +76 -0
  28. data/lib/celerity/elements/label.rb +11 -0
  29. data/lib/celerity/elements/link.rb +30 -0
  30. data/lib/celerity/elements/meta.rb +7 -0
  31. data/lib/celerity/elements/non_control_elements.rb +106 -0
  32. data/lib/celerity/elements/option.rb +32 -0
  33. data/lib/celerity/elements/radio_check.rb +115 -0
  34. data/lib/celerity/elements/select_list.rb +142 -0
  35. data/lib/celerity/elements/table.rb +144 -0
  36. data/lib/celerity/elements/table_cell.rb +29 -0
  37. data/lib/celerity/elements/table_elements.rb +42 -0
  38. data/lib/celerity/elements/table_row.rb +48 -0
  39. data/lib/celerity/elements/text_field.rb +169 -0
  40. data/lib/celerity/exception.rb +83 -0
  41. data/lib/celerity/htmlunit.rb +65 -0
  42. data/lib/celerity/htmlunit/commons-codec-1.4.jar +0 -0
  43. data/lib/celerity/htmlunit/commons-collections-3.2.1.jar +0 -0
  44. data/lib/celerity/htmlunit/commons-httpclient-3.1.jar +0 -0
  45. data/lib/celerity/htmlunit/commons-io-1.4.jar +0 -0
  46. data/lib/celerity/htmlunit/commons-lang-2.4.jar +0 -0
  47. data/lib/celerity/htmlunit/commons-logging-1.1.1.jar +0 -0
  48. data/lib/celerity/htmlunit/cssparser-0.9.5.jar +0 -0
  49. data/lib/celerity/htmlunit/htmlunit-2.6-SNAPSHOT.jar +0 -0
  50. data/lib/celerity/htmlunit/htmlunit-core-js-2.6-SNAPSHOT.jar +0 -0
  51. data/lib/celerity/htmlunit/nekohtml-1.9.13-20090820.100833-15.jar +0 -0
  52. data/lib/celerity/htmlunit/sac-1.3.jar +0 -0
  53. data/lib/celerity/htmlunit/serializer-2.7.1.jar +0 -0
  54. data/lib/celerity/htmlunit/xalan-2.7.1.jar +0 -0
  55. data/lib/celerity/htmlunit/xercesImpl-2.9.1.jar +0 -0
  56. data/lib/celerity/htmlunit/xml-apis-1.3.04.jar +0 -0
  57. data/lib/celerity/identifier.rb +11 -0
  58. data/lib/celerity/ignoring_web_connection.rb +15 -0
  59. data/lib/celerity/input_element.rb +25 -0
  60. data/lib/celerity/listener.rb +141 -0
  61. data/lib/celerity/resources/no_viewer.png +0 -0
  62. data/lib/celerity/short_inspect.rb +20 -0
  63. data/lib/celerity/util.rb +91 -0
  64. data/lib/celerity/viewer_connection.rb +89 -0
  65. data/lib/celerity/watir_compatibility.rb +83 -0
  66. data/lib/celerity/xpath_support.rb +48 -0
  67. data/spec/browser_authentication_spec.rb +16 -0
  68. data/spec/browser_spec.rb +300 -0
  69. data/spec/clickable_element_spec.rb +39 -0
  70. data/spec/default_viewer_spec.rb +23 -0
  71. data/spec/element_spec.rb +51 -0
  72. data/spec/filefield_spec.rb +18 -0
  73. data/spec/htmlunit_spec.rb +56 -0
  74. data/spec/index_offset_spec.rb +24 -0
  75. data/spec/listener_spec.rb +142 -0
  76. data/spec/spec_helper.rb +8 -0
  77. data/tasks/benchmark.rake +4 -0
  78. data/tasks/deployment.rake +43 -0
  79. data/tasks/environment.rake +7 -0
  80. data/tasks/fix.rake +25 -0
  81. data/tasks/jar.rake +57 -0
  82. data/tasks/rdoc.rake +4 -0
  83. data/tasks/rspec.rake +43 -0
  84. data/tasks/simple_ci.rake +94 -0
  85. data/tasks/snapshot.rake +22 -0
  86. data/tasks/website.rake +17 -0
  87. data/tasks/yard.rake +9 -0
  88. data/website/benchmarks.html +237 -0
  89. data/website/css/color.css +153 -0
  90. data/website/css/hacks.css +3 -0
  91. data/website/css/layout.css +179 -0
  92. data/website/css/screen.css +5 -0
  93. data/website/css/textmate.css +226 -0
  94. data/website/css/typography.css +72 -0
  95. data/website/gfx/body_bg.gif +0 -0
  96. data/website/gfx/button_bg.jpg +0 -0
  97. data/website/gfx/header_bg.jpg +0 -0
  98. data/website/gfx/header_left.jpg +0 -0
  99. data/website/gfx/header_right.jpg +0 -0
  100. data/website/gfx/nav_bg.jpg +0 -0
  101. data/website/index.html +133 -0
  102. data/website/yard/Celerity.html +50 -0
  103. data/website/yard/Celerity/Area.html +212 -0
  104. data/website/yard/Celerity/Areas.html +103 -0
  105. data/website/yard/Celerity/Browser.html +5594 -0
  106. data/website/yard/Celerity/Button.html +312 -0
  107. data/website/yard/Celerity/Buttons.html +103 -0
  108. data/website/yard/Celerity/CheckBox.html +347 -0
  109. data/website/yard/Celerity/CheckBoxes.html +103 -0
  110. data/website/yard/Celerity/ClickableElement.html +448 -0
  111. data/website/yard/Celerity/Container.html +7676 -0
  112. data/website/yard/Celerity/Dd.html +198 -0
  113. data/website/yard/Celerity/Dds.html +103 -0
  114. data/website/yard/Celerity/DefaultViewer.html +101 -0
  115. data/website/yard/Celerity/DisabledElement.html +252 -0
  116. data/website/yard/Celerity/Div.html +198 -0
  117. data/website/yard/Celerity/Divs.html +103 -0
  118. data/website/yard/Celerity/Dl.html +198 -0
  119. data/website/yard/Celerity/Dls.html +103 -0
  120. data/website/yard/Celerity/Dt.html +198 -0
  121. data/website/yard/Celerity/Dts.html +103 -0
  122. data/website/yard/Celerity/Element.html +1703 -0
  123. data/website/yard/Celerity/ElementCollection.html +725 -0
  124. data/website/yard/Celerity/ElementLocator.html +589 -0
  125. data/website/yard/Celerity/Em.html +198 -0
  126. data/website/yard/Celerity/Ems.html +103 -0
  127. data/website/yard/Celerity/Exception.html +23 -0
  128. data/website/yard/Celerity/Exception/CelerityException.html +32 -0
  129. data/website/yard/Celerity/Exception/MissingWayOfFindingObjectException.html +32 -0
  130. data/website/yard/Celerity/Exception/NavigationException.html +33 -0
  131. data/website/yard/Celerity/Exception/NoValueFoundException.html +33 -0
  132. data/website/yard/Celerity/Exception/ObjectDisabledException.html +33 -0
  133. data/website/yard/Celerity/Exception/ObjectReadOnlyException.html +33 -0
  134. data/website/yard/Celerity/Exception/UnexpectedPageException.html +33 -0
  135. data/website/yard/Celerity/Exception/UnknownCellException.html +33 -0
  136. data/website/yard/Celerity/Exception/UnknownFormException.html +33 -0
  137. data/website/yard/Celerity/Exception/UnknownFrameException.html +33 -0
  138. data/website/yard/Celerity/Exception/UnknownObjectException.html +33 -0
  139. data/website/yard/Celerity/Exception/UnknownRowException.html +33 -0
  140. data/website/yard/Celerity/FileField.html +289 -0
  141. data/website/yard/Celerity/FileFields.html +103 -0
  142. data/website/yard/Celerity/Form.html +284 -0
  143. data/website/yard/Celerity/Forms.html +103 -0
  144. data/website/yard/Celerity/Frame.html +527 -0
  145. data/website/yard/Celerity/Frames.html +103 -0
  146. data/website/yard/Celerity/H1.html +198 -0
  147. data/website/yard/Celerity/H1s.html +103 -0
  148. data/website/yard/Celerity/H2.html +198 -0
  149. data/website/yard/Celerity/H2s.html +103 -0
  150. data/website/yard/Celerity/H3.html +198 -0
  151. data/website/yard/Celerity/H3s.html +103 -0
  152. data/website/yard/Celerity/H4.html +198 -0
  153. data/website/yard/Celerity/H4s.html +103 -0
  154. data/website/yard/Celerity/H5.html +198 -0
  155. data/website/yard/Celerity/H5s.html +103 -0
  156. data/website/yard/Celerity/H6.html +198 -0
  157. data/website/yard/Celerity/H6s.html +103 -0
  158. data/website/yard/Celerity/Hidden.html +285 -0
  159. data/website/yard/Celerity/Hiddens.html +103 -0
  160. data/website/yard/Celerity/Image.html +645 -0
  161. data/website/yard/Celerity/Images.html +103 -0
  162. data/website/yard/Celerity/InputElement.html +271 -0
  163. data/website/yard/Celerity/Label.html +210 -0
  164. data/website/yard/Celerity/Labels.html +103 -0
  165. data/website/yard/Celerity/Li.html +198 -0
  166. data/website/yard/Celerity/Link.html +295 -0
  167. data/website/yard/Celerity/Links.html +103 -0
  168. data/website/yard/Celerity/Lis.html +103 -0
  169. data/website/yard/Celerity/Listener.html +821 -0
  170. data/website/yard/Celerity/Map.html +198 -0
  171. data/website/yard/Celerity/Maps.html +103 -0
  172. data/website/yard/Celerity/Meta.html +196 -0
  173. data/website/yard/Celerity/Metas.html +103 -0
  174. data/website/yard/Celerity/MethodGenerator.html +195 -0
  175. data/website/yard/Celerity/NonControlElement.html +212 -0
  176. data/website/yard/Celerity/Ol.html +198 -0
  177. data/website/yard/Celerity/Ols.html +103 -0
  178. data/website/yard/Celerity/Option.html +348 -0
  179. data/website/yard/Celerity/Options.html +103 -0
  180. data/website/yard/Celerity/P.html +198 -0
  181. data/website/yard/Celerity/Pre.html +198 -0
  182. data/website/yard/Celerity/Pres.html +103 -0
  183. data/website/yard/Celerity/Ps.html +103 -0
  184. data/website/yard/Celerity/Radio.html +339 -0
  185. data/website/yard/Celerity/RadioCheckCommon.html +453 -0
  186. data/website/yard/Celerity/Radios.html +103 -0
  187. data/website/yard/Celerity/SelectList.html +1122 -0
  188. data/website/yard/Celerity/SelectLists.html +103 -0
  189. data/website/yard/Celerity/ShortInspect.html +108 -0
  190. data/website/yard/Celerity/Span.html +198 -0
  191. data/website/yard/Celerity/Spans.html +103 -0
  192. data/website/yard/Celerity/Strong.html +198 -0
  193. data/website/yard/Celerity/Strongs.html +103 -0
  194. data/website/yard/Celerity/Table.html +1287 -0
  195. data/website/yard/Celerity/TableBodies.html +103 -0
  196. data/website/yard/Celerity/TableBody.html +203 -0
  197. data/website/yard/Celerity/TableCell.html +279 -0
  198. data/website/yard/Celerity/TableCells.html +103 -0
  199. data/website/yard/Celerity/TableElement.html +437 -0
  200. data/website/yard/Celerity/TableFooter.html +203 -0
  201. data/website/yard/Celerity/TableFooters.html +103 -0
  202. data/website/yard/Celerity/TableHeader.html +203 -0
  203. data/website/yard/Celerity/TableHeaders.html +103 -0
  204. data/website/yard/Celerity/TableRow.html +478 -0
  205. data/website/yard/Celerity/TableRows.html +103 -0
  206. data/website/yard/Celerity/Tables.html +103 -0
  207. data/website/yard/Celerity/TextField.html +938 -0
  208. data/website/yard/Celerity/TextFields.html +103 -0
  209. data/website/yard/Celerity/Th.html +208 -0
  210. data/website/yard/Celerity/Ul.html +209 -0
  211. data/website/yard/Celerity/Uls.html +103 -0
  212. data/website/yard/Celerity/Util.html +264 -0
  213. data/website/yard/Celerity/VERSION.html +44 -0
  214. data/website/yard/HtmlUnit.html +23 -0
  215. data/website/yard/HtmlUnit/Html.html +23 -0
  216. data/website/yard/HtmlUnit/Util.html +23 -0
  217. data/website/yard/Java/ComGargoylesoftwareHtmlunitHtml/HtmlPage.html +90 -0
  218. data/website/yard/Java/JavaLang/Iterable.html +103 -0
  219. data/website/yard/Java/OrgW3cDom/NamedNodeMap.html +97 -0
  220. data/website/yard/README.txt.html +116 -0
  221. data/website/yard/String.html +103 -0
  222. data/website/yard/all-files.html +22 -0
  223. data/website/yard/all-methods.html +3276 -0
  224. data/website/yard/all-namespaces.html +258 -0
  225. data/website/yard/app.js +18 -0
  226. data/website/yard/index.html +19 -0
  227. data/website/yard/jquery.js +11 -0
  228. data/website/yard/style.css +68 -0
  229. data/website/yard/syntax_highlight.css +21 -0
  230. metadata +307 -0
@@ -0,0 +1,69 @@
1
+ require File.dirname(__FILE__) + "/loader"
2
+
3
+ browser = create_browser
4
+ browser.goto(HTML_DIR + "/forms_with_input_elements.html")
5
+
6
+ TESTS = 1000
7
+ res = Benchmark.bmbm do |results|
8
+ results.report("text input by id (String)") do
9
+ TESTS.times { browser.text_field(:id, "new_user_first_name").exists? }
10
+ end
11
+ results.report("text input by id (Regexp)") do
12
+ TESTS.times { browser.text_field(:id, /first_name/).exists? }
13
+ end
14
+ results.report("text input by name (String)") do
15
+ TESTS.times { browser.text_field(:name, "new_user_email").exists? }
16
+ end
17
+ results.report("text input by name (Regexp)") do
18
+ TESTS.times { browser.text_field(:name, /user_email/).exists? }
19
+ end
20
+
21
+ results.report("select list by id (String)") do
22
+ TESTS.times { browser.select_list(:id, 'new_user_country').exists? }
23
+ end
24
+ results.report("select list by id (Regexp)") do
25
+ TESTS.times { browser.select_list(:id, /user_country/).exists? }
26
+ end
27
+ results.report("select list by name (String)") do
28
+ TESTS.times { browser.select_list(:name, 'new_user_country').exists? }
29
+ end
30
+ results.report("select list by name (Regexp)") do
31
+ TESTS.times { browser.select_list(:name, /user_country/).exists? }
32
+ end
33
+
34
+ results.report("checkbox by id (String)") do
35
+ TESTS.times { browser.checkbox(:id, 'new_user_interests_books').exists? }
36
+ end
37
+ results.report("checkbox by id (Regexp)") do
38
+ TESTS.times { browser.checkbox(:id, /interests_books/).exists? }
39
+ end
40
+
41
+ results.report("checkbox by name (String)") do
42
+ TESTS.times { browser.checkbox(:name, 'new_user_interests').exists? }
43
+ end
44
+ results.report("checkbox by name (Regexp)") do
45
+ TESTS.times { browser.checkbox(:name, /user_interests/).exists? }
46
+ end
47
+
48
+ results.report("checkbox by id (String) and value (String)") do
49
+ TESTS.times { browser.checkbox(:id, 'new_user_interests_books', 'cars').exists? }
50
+ end
51
+ results.report("checkbox by id (Regexp) and value (Regexp)") do
52
+ TESTS.times { browser.checkbox(:id, /interests_books/, /car/).exists? }
53
+ end
54
+
55
+ results.report("checkbox by name (String) and value (String)") do
56
+ TESTS.times { browser.checkbox(:name, 'new_user_interests', 'dancing').exists? }
57
+ end
58
+ results.report("checkbox by name (Regexp) and value (Regexp)") do
59
+ TESTS.times { browser.checkbox(:name, /user_interests/, /danc/).exists? }
60
+ end
61
+
62
+
63
+
64
+ end
65
+
66
+ puts
67
+ total = res.inject(0.0) { |mem, bm| mem + bm.real }
68
+ puts "total : " + total.to_s
69
+ puts "average: " + (total/res.size.to_f).to_s
@@ -0,0 +1,19 @@
1
+ require File.dirname(__FILE__) + "/loader"
2
+
3
+ browser = create_browser
4
+ browser.goto(HTML_DIR + "/forms_with_input_elements.html")
5
+
6
+ TESTS = 10000
7
+ res = Benchmark.bmbm do |results|
8
+ results.report("TextField#set") do
9
+ TESTS.times { browser.text_field(:id, "new_user_first_name").set("1234567890") }
10
+ end
11
+ results.report("TextField#value=") do
12
+ TESTS.times { browser.text_field(:id, "new_user_first_name").value = "1234567890" }
13
+ end
14
+ end
15
+
16
+ puts
17
+ total = res.inject(0.0) { |mem, bm| mem + bm.real }
18
+ puts "total : " + total.to_s
19
+ puts "average: " + (total/res.size.to_f).to_s
@@ -0,0 +1,14 @@
1
+ require 'benchmark'
2
+ require File.dirname(__FILE__) + "/../spec/spec_helper"
3
+
4
+
5
+ def create_browser
6
+ if RUBY_PLATFORM =~ /java/
7
+ browser = Celerity::Browser.new(:log_level => :off)
8
+ else
9
+ require 'watir'
10
+ browser = Watir::IE.new
11
+ end
12
+
13
+ browser
14
+ end
data/celerity.gemspec ADDED
@@ -0,0 +1,40 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{celerity}
5
+ s.version = "0.0.6.17"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Jari Bakken", "T. Alexander Lystad", "Knut Johannes Dahle"]
9
+ s.date = %q{2009-09-04}
10
+ s.description = %q{Celerity is a JRuby library for easy and fast functional test automation for web applications.
11
+
12
+ It is a JRuby wrapper around HtmlUnit – a headless Java browser with
13
+ JavaScript support. It provides a simple API for programmatic navigation through
14
+ web applications. Celerity aims at being API compatible with Watir.}
15
+ s.email = ["jari.bakken@finn.no"]
16
+ s.extra_rdoc_files = ["History.txt", "License.txt", "Manifest.txt"]
17
+ s.files = ["History.txt", "License.txt", "Manifest.txt", "README.rdoc", "Rakefile", "benchmark/bm_2000_spans.rb", "benchmark/bm_digg.rb", "benchmark/bm_google_images.rb", "benchmark/bm_input_locator.rb", "benchmark/bm_text_input.rb", "benchmark/loader.rb", "celerity.gemspec", "lib/celerity.rb", "lib/celerity/browser.rb", "lib/celerity/clickable_element.rb", "lib/celerity/collections.rb", "lib/celerity/container.rb", "lib/celerity/default_viewer.rb", "lib/celerity/disabled_element.rb", "lib/celerity/element.rb", "lib/celerity/element_collection.rb", "lib/celerity/element_locator.rb", "lib/celerity/elements/button.rb", "lib/celerity/elements/file_field.rb", "lib/celerity/elements/form.rb", "lib/celerity/elements/frame.rb", "lib/celerity/elements/image.rb", "lib/celerity/elements/label.rb", "lib/celerity/elements/link.rb", "lib/celerity/elements/meta.rb", "lib/celerity/elements/non_control_elements.rb", "lib/celerity/elements/option.rb", "lib/celerity/elements/radio_check.rb", "lib/celerity/elements/select_list.rb", "lib/celerity/elements/table.rb", "lib/celerity/elements/table_cell.rb", "lib/celerity/elements/table_elements.rb", "lib/celerity/elements/table_row.rb", "lib/celerity/elements/text_field.rb", "lib/celerity/exception.rb", "lib/celerity/htmlunit.rb", "lib/celerity/htmlunit/commons-codec-1.4.jar", "lib/celerity/htmlunit/commons-collections-3.2.1.jar", "lib/celerity/htmlunit/commons-httpclient-3.1.jar", "lib/celerity/htmlunit/commons-io-1.4.jar", "lib/celerity/htmlunit/commons-lang-2.4.jar", "lib/celerity/htmlunit/commons-logging-1.1.1.jar", "lib/celerity/htmlunit/cssparser-0.9.5.jar", "lib/celerity/htmlunit/htmlunit-2.6-SNAPSHOT.jar", "lib/celerity/htmlunit/htmlunit-core-js-2.6-SNAPSHOT.jar", "lib/celerity/htmlunit/nekohtml-1.9.13-20090820.100833-15.jar", "lib/celerity/htmlunit/sac-1.3.jar", "lib/celerity/htmlunit/serializer-2.7.1.jar", "lib/celerity/htmlunit/xalan-2.7.1.jar", "lib/celerity/htmlunit/xercesImpl-2.9.1.jar", "lib/celerity/htmlunit/xml-apis-1.3.04.jar", "lib/celerity/identifier.rb", "lib/celerity/ignoring_web_connection.rb", "lib/celerity/input_element.rb", "lib/celerity/listener.rb", "lib/celerity/resources/no_viewer.png", "lib/celerity/short_inspect.rb", "lib/celerity/util.rb", "lib/celerity/viewer_connection.rb", "lib/celerity/watir_compatibility.rb", "lib/celerity/xpath_support.rb", "spec/browser_authentication_spec.rb", "spec/browser_spec.rb", "spec/clickable_element_spec.rb", "spec/default_viewer_spec.rb", "spec/element_spec.rb", "spec/filefield_spec.rb", "spec/htmlunit_spec.rb", "spec/index_offset_spec.rb", "spec/listener_spec.rb", "spec/spec_helper.rb", "tasks/benchmark.rake", "tasks/deployment.rake", "tasks/environment.rake", "tasks/fix.rake", "tasks/jar.rake", "tasks/rdoc.rake", "tasks/rspec.rake", "tasks/simple_ci.rake", "tasks/snapshot.rake", "tasks/website.rake", "tasks/yard.rake", "website/benchmarks.html", "website/css/color.css", "website/css/hacks.css", "website/css/layout.css", "website/css/screen.css", "website/css/textmate.css", "website/css/typography.css", "website/gfx/body_bg.gif", "website/gfx/button_bg.jpg", "website/gfx/header_bg.jpg", "website/gfx/header_left.jpg", "website/gfx/header_right.jpg", "website/gfx/nav_bg.jpg", "website/index.html", "website/yard/Celerity.html", "website/yard/Celerity/Area.html", "website/yard/Celerity/Areas.html", "website/yard/Celerity/Browser.html", "website/yard/Celerity/Button.html", "website/yard/Celerity/Buttons.html", "website/yard/Celerity/CheckBox.html", "website/yard/Celerity/CheckBoxes.html", "website/yard/Celerity/ClickableElement.html", "website/yard/Celerity/Container.html", "website/yard/Celerity/Dd.html", "website/yard/Celerity/Dds.html", "website/yard/Celerity/DefaultViewer.html", "website/yard/Celerity/DisabledElement.html", "website/yard/Celerity/Div.html", "website/yard/Celerity/Divs.html", "website/yard/Celerity/Dl.html", "website/yard/Celerity/Dls.html", "website/yard/Celerity/Dt.html", "website/yard/Celerity/Dts.html", "website/yard/Celerity/Element.html", "website/yard/Celerity/ElementCollection.html", "website/yard/Celerity/ElementLocator.html", "website/yard/Celerity/Em.html", "website/yard/Celerity/Ems.html", "website/yard/Celerity/Exception.html", "website/yard/Celerity/Exception/CelerityException.html", "website/yard/Celerity/Exception/MissingWayOfFindingObjectException.html", "website/yard/Celerity/Exception/NavigationException.html", "website/yard/Celerity/Exception/NoValueFoundException.html", "website/yard/Celerity/Exception/ObjectDisabledException.html", "website/yard/Celerity/Exception/ObjectReadOnlyException.html", "website/yard/Celerity/Exception/UnexpectedPageException.html", "website/yard/Celerity/Exception/UnknownCellException.html", "website/yard/Celerity/Exception/UnknownFormException.html", "website/yard/Celerity/Exception/UnknownFrameException.html", "website/yard/Celerity/Exception/UnknownObjectException.html", "website/yard/Celerity/Exception/UnknownRowException.html", "website/yard/Celerity/FileField.html", "website/yard/Celerity/FileFields.html", "website/yard/Celerity/Form.html", "website/yard/Celerity/Forms.html", "website/yard/Celerity/Frame.html", "website/yard/Celerity/Frames.html", "website/yard/Celerity/H1.html", "website/yard/Celerity/H1s.html", "website/yard/Celerity/H2.html", "website/yard/Celerity/H2s.html", "website/yard/Celerity/H3.html", "website/yard/Celerity/H3s.html", "website/yard/Celerity/H4.html", "website/yard/Celerity/H4s.html", "website/yard/Celerity/H5.html", "website/yard/Celerity/H5s.html", "website/yard/Celerity/H6.html", "website/yard/Celerity/H6s.html", "website/yard/Celerity/Hidden.html", "website/yard/Celerity/Hiddens.html", "website/yard/Celerity/Image.html", "website/yard/Celerity/Images.html", "website/yard/Celerity/InputElement.html", "website/yard/Celerity/Label.html", "website/yard/Celerity/Labels.html", "website/yard/Celerity/Li.html", "website/yard/Celerity/Link.html", "website/yard/Celerity/Links.html", "website/yard/Celerity/Lis.html", "website/yard/Celerity/Listener.html", "website/yard/Celerity/Map.html", "website/yard/Celerity/Maps.html", "website/yard/Celerity/Meta.html", "website/yard/Celerity/Metas.html", "website/yard/Celerity/MethodGenerator.html", "website/yard/Celerity/NonControlElement.html", "website/yard/Celerity/Ol.html", "website/yard/Celerity/Ols.html", "website/yard/Celerity/Option.html", "website/yard/Celerity/Options.html", "website/yard/Celerity/P.html", "website/yard/Celerity/Pre.html", "website/yard/Celerity/Pres.html", "website/yard/Celerity/Ps.html", "website/yard/Celerity/Radio.html", "website/yard/Celerity/RadioCheckCommon.html", "website/yard/Celerity/Radios.html", "website/yard/Celerity/SelectList.html", "website/yard/Celerity/SelectLists.html", "website/yard/Celerity/ShortInspect.html", "website/yard/Celerity/Span.html", "website/yard/Celerity/Spans.html", "website/yard/Celerity/Strong.html", "website/yard/Celerity/Strongs.html", "website/yard/Celerity/Table.html", "website/yard/Celerity/TableBodies.html", "website/yard/Celerity/TableBody.html", "website/yard/Celerity/TableCell.html", "website/yard/Celerity/TableCells.html", "website/yard/Celerity/TableElement.html", "website/yard/Celerity/TableFooter.html", "website/yard/Celerity/TableFooters.html", "website/yard/Celerity/TableHeader.html", "website/yard/Celerity/TableHeaders.html", "website/yard/Celerity/TableRow.html", "website/yard/Celerity/TableRows.html", "website/yard/Celerity/Tables.html", "website/yard/Celerity/TextField.html", "website/yard/Celerity/TextFields.html", "website/yard/Celerity/Th.html", "website/yard/Celerity/Ul.html", "website/yard/Celerity/Uls.html", "website/yard/Celerity/Util.html", "website/yard/Celerity/VERSION.html", "website/yard/HtmlUnit.html", "website/yard/HtmlUnit/Html.html", "website/yard/HtmlUnit/Util.html", "website/yard/Java/ComGargoylesoftwareHtmlunitHtml/HtmlPage.html", "website/yard/Java/JavaLang/Iterable.html", "website/yard/Java/OrgW3cDom/NamedNodeMap.html", "website/yard/README.txt.html", "website/yard/String.html", "website/yard/all-files.html", "website/yard/all-methods.html", "website/yard/all-namespaces.html", "website/yard/app.js", "website/yard/index.html", "website/yard/jquery.js", "website/yard/style.css", "website/yard/syntax_highlight.css"]
18
+ s.homepage = %q{http://celerity.rubyforge.org/}
19
+ s.rdoc_options = ["--main", "README.rdoc"]
20
+ s.require_paths = ["lib"]
21
+ s.rubyforge_project = %q{celerity}
22
+ s.rubygems_version = %q{1.3.3}
23
+ s.summary = %q{Celerity is a JRuby library for easy and fast functional test automation for web applications}
24
+
25
+ if s.respond_to? :specification_version then
26
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
27
+ s.specification_version = 3
28
+
29
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
30
+ s.add_development_dependency(%q<sinatra>, [">= 0.9.4"])
31
+ s.add_development_dependency(%q<hoe>, [">= 2.3.3"])
32
+ else
33
+ s.add_dependency(%q<sinatra>, [">= 0.9.4"])
34
+ s.add_dependency(%q<hoe>, [">= 2.3.3"])
35
+ end
36
+ else
37
+ s.add_dependency(%q<sinatra>, [">= 0.9.4"])
38
+ s.add_dependency(%q<hoe>, [">= 2.3.3"])
39
+ end
40
+ end
data/lib/celerity.rb ADDED
@@ -0,0 +1,77 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
2
+
3
+ raise "Celerity only works on JRuby at the moment." unless RUBY_PLATFORM =~ /java/
4
+
5
+ require "java"
6
+ require "logger"
7
+ require "uri"
8
+ require "pp"
9
+ require "timeout"
10
+ require "time"
11
+ require "socket"
12
+ require "fileutils"
13
+ require "thread"
14
+
15
+ module Celerity
16
+ VERSION = "0.0.6.17"
17
+
18
+ Log = Logger.new($DEBUG ? $stderr : nil)
19
+ Log.level = Logger::DEBUG
20
+
21
+ @index_offset = 1
22
+ class << self
23
+
24
+ #
25
+ # This index_offset attribute controls the indexing used when locating
26
+ # elements by :index or fetching from Celerity::ElementCollections.
27
+ #
28
+ # By default it is set to 1 for Watir compatibility, but users who use
29
+ # Celerity exlusively may want it set to 0 to make Celerity more consistent with Ruby.
30
+ #
31
+ attr_accessor :index_offset
32
+ end
33
+
34
+ DIR = File.expand_path(File.dirname(__FILE__) + "/celerity")
35
+ end
36
+
37
+ require "celerity/htmlunit"
38
+ require "celerity/exception"
39
+ require "celerity/clickable_element"
40
+ require "celerity/disabled_element"
41
+ require "celerity/element_collection"
42
+ require "celerity/collections"
43
+ require "celerity/element_locator"
44
+ require "celerity/identifier"
45
+ require "celerity/short_inspect"
46
+ require "celerity/container"
47
+ require "celerity/xpath_support"
48
+ require "celerity/element"
49
+ require "celerity/input_element"
50
+ require "celerity/elements/non_control_elements"
51
+ require "celerity/elements/button"
52
+ require "celerity/elements/file_field"
53
+ require "celerity/elements/form"
54
+ require "celerity/elements/frame"
55
+ require "celerity/elements/image"
56
+ require "celerity/elements/label"
57
+ require "celerity/elements/link"
58
+ require "celerity/elements/meta"
59
+ require "celerity/elements/option"
60
+ require "celerity/elements/radio_check"
61
+ require "celerity/elements/select_list"
62
+ require "celerity/elements/table"
63
+ require "celerity/elements/table_elements"
64
+ require "celerity/elements/table_cell"
65
+ require "celerity/elements/table_row"
66
+ require "celerity/elements/text_field"
67
+ require "celerity/util"
68
+ require "celerity/default_viewer"
69
+ require "celerity/listener"
70
+ require "celerity/ignoring_web_connection"
71
+ require "celerity/viewer_connection"
72
+ require "celerity/browser"
73
+ require "celerity/watir_compatibility"
74
+
75
+ # undefine deprecated methods to use them for Element attributes
76
+ Object.send :undef_method, :id if Object.method_defined? "id"
77
+ Object.send :undef_method, :type if Object.method_defined? "type"
@@ -0,0 +1,888 @@
1
+ module Celerity
2
+ class Browser
3
+ include Container
4
+ include XpathSupport
5
+
6
+ attr_accessor :page, :object, :charset
7
+ attr_reader :webclient, :viewer, :options
8
+
9
+ #
10
+ # Initialize a browser and go to the given URL
11
+ #
12
+ # @param [String] uri The URL to go to.
13
+ # @return [Celerity::Browser] instance.
14
+ #
15
+
16
+ def self.start(uri)
17
+ browser = new
18
+ browser.goto(uri)
19
+ browser
20
+ end
21
+
22
+ #
23
+ # Not implemented. Use ClickableElement#click_and_attach instead.
24
+ #
25
+
26
+ def self.attach(*args)
27
+ raise NotImplementedError, "use ClickableElement#click_and_attach instead"
28
+ end
29
+
30
+ #
31
+ # Creates a browser object.
32
+ #
33
+ # @see Celerity::Container for an introduction to the main API.
34
+ #
35
+ # @option opts :log_level [Symbol] (:warning) @see log_level=
36
+ # @option opts :browser [:internet_explorer, :firefox, :firefox3] (:firefox) Set the BrowserVersion used by HtmlUnit. Defaults to Firefox 2.
37
+ # @option opts :css [Boolean] (false) Enable CSS. Disabled by default.
38
+ # @option opts :secure_ssl [Boolean] (true) Enable/disable secure SSL. Enabled by default.
39
+ # @option opts :javascript_enabled [Boolean] (true) Enable/disable JavaScript evaluation. Enabled by default.
40
+ # @option opts :resynchronize [Boolean] (false) Use HtmlUnit::NicelyResynchronizingAjaxController to resynchronize Ajax calls.
41
+ # @option opts :javascript_exceptions [Boolean] (false) Raise exceptions on script errors. Disabled by default.
42
+ # @option opts :status_code_exceptions [Boolean] (false) Raise exceptions on failing status codes (404 etc.). Disabled by default.
43
+ # @option opts :charset [String] ("UTF-8") Specify the charset that webclient will use for requests, and those where texts are getting gibberished, like Browser#html.
44
+ # @option opts :proxy [String] (nil) Proxy server to use, in address:port format.
45
+ # @option opts :user_agent [String] Override the User-Agent set by the :browser option
46
+ # @option opts :ignore_pattern [Regexp] See Browser#ignore_pattern=
47
+ # @option opts :viewer [Boolean] (true) Connect to a CelerityViewer on port 6429 if available.
48
+ # @option opts :render [:html, :xml] (:html) What DOM representation to send to connected viewers.
49
+ # @option opts :refresh_handler [:immediat, :waiting, :threaded] (:immediate) Set HtmlUnit's refresh handler.
50
+ #
51
+ # @return [Celerity::Browser] An instance of the browser.
52
+ #
53
+ # @api public
54
+ #
55
+
56
+ def initialize(opts = {})
57
+ unless opts.is_a?(Hash)
58
+ raise TypeError, "wrong argument type #{opts.class}, expected Hash"
59
+ end
60
+
61
+ unless (render_types = [:html, :xml, nil, 'html', 'xml']).include?(opts[:render])
62
+ raise ArgumentError, "expected one of #{render_types.inspect} for key :render"
63
+ end
64
+
65
+ opts = opts.dup # we'll delete from opts, so dup to avoid side effects
66
+ @options = opts.dup # keep the unmodified version around as well
67
+
68
+ @render_type = opts.delete(:render) || :html
69
+ @charset = opts.delete(:charset) || "UTF-8"
70
+ self.log_level = opts.delete(:log_level) || :warning
71
+
72
+ @page = nil
73
+ @error_checkers = []
74
+ @browser = self # for Container#browser
75
+
76
+ setup_webclient opts
77
+ setup_viewer opts.delete(:viewer)
78
+
79
+ raise ArgumentError, "unknown option #{opts.inspect}" unless opts.empty?
80
+ end
81
+
82
+ def inspect
83
+ short_inspect :exclude => %w[@webclient @browser @object @options @listener @event_listener]
84
+ end
85
+
86
+ #
87
+ # Goto the given URL
88
+ #
89
+ # @param [String] uri The url.
90
+ # @return [String] The url.
91
+ #
92
+
93
+ def goto(uri)
94
+ uri = "http://#{uri}" unless uri =~ %r{://}
95
+
96
+ request = HtmlUnit::WebRequestSettings.new(::Java::JavaNet::URL.new(uri))
97
+ request.setCharset(@charset)
98
+
99
+ rescue_status_code_exception do
100
+ self.page = @webclient.getPage(request)
101
+ end
102
+
103
+ url()
104
+ end
105
+
106
+ #
107
+ # Set the credentials used for basic HTTP authentication. (Celerity only)
108
+ #
109
+ # Example:
110
+ # browser.credentials = "username:password"
111
+ #
112
+ # @param [String] A string with username / password, separated by a colon
113
+ #
114
+
115
+ def credentials=(string)
116
+ user, pass = string.split(":")
117
+ dcp = HtmlUnit::DefaultCredentialsProvider.new
118
+ dcp.addCredentials(user, pass)
119
+ @webclient.setCredentialsProvider(dcp)
120
+ end
121
+
122
+ #
123
+ # Unsets the current page / closes all windows
124
+ #
125
+
126
+ def close
127
+ @page = nil
128
+ @webclient.closeAllWindows
129
+ @viewer.close
130
+ end
131
+
132
+ #
133
+ # @return [String] the URL of the current page
134
+ #
135
+
136
+ def url
137
+ assert_exists
138
+ @page.getWebResponse.getRequestUrl.toString
139
+ end
140
+
141
+ #
142
+ # @return [String] the title of the current page
143
+ #
144
+
145
+ def title
146
+ @page ? @page.getTitleText : ''
147
+ end
148
+
149
+ #
150
+ # @return [String] the value of window.status
151
+ #
152
+
153
+ def status
154
+ execute_script "window.status" # avoid the listener overhead
155
+ end
156
+
157
+ #
158
+ # @return [String] the HTML content of the current page
159
+ #
160
+
161
+ def html
162
+ @page ? @page.getWebResponse.getContentAsString(@charset) : ''
163
+ end
164
+
165
+ #
166
+ # @return [String] the XML representation of the DOM
167
+ #
168
+
169
+ def xml
170
+ return '' unless @page
171
+ return @page.asXml if @page.respond_to?(:asXml)
172
+ return text # fallback to text (for exampel for "plain/text" pages)
173
+ end
174
+
175
+ #
176
+ # @return [String] a text representation of the current page
177
+ #
178
+
179
+ def text
180
+ return '' unless @page
181
+
182
+ if @page.respond_to?("getContent")
183
+ string = @page.getContent.strip
184
+ elsif @page.documentElement
185
+ string = @page.documentElement.asText.strip
186
+ else
187
+ string = ''
188
+ end
189
+
190
+ # Celerity::Util.normalize_text(string)
191
+ string
192
+ end
193
+
194
+ #
195
+ # @return [Hash] response headers as a hash
196
+ #
197
+
198
+ def response_headers
199
+ return {} unless @page
200
+
201
+ Hash[*@page.getWebResponse.getResponseHeaders.map { |obj| [obj.name, obj.value] }.flatten]
202
+ end
203
+
204
+ #
205
+ # @return [Fixnum] status code of the last request
206
+ #
207
+
208
+ def status_code
209
+ @page.getWebResponse.getStatusCode
210
+ end
211
+
212
+ #
213
+ # @return [String] content-type as in 'text/html'
214
+ #
215
+
216
+ def content_type
217
+ return '' unless @page
218
+
219
+ @page.getWebResponse.getContentType
220
+ end
221
+
222
+ #
223
+ # @return [IO, nil] page contents as an IO, returns nil if no page is loaded.
224
+ #
225
+
226
+ def io
227
+ return nil unless @page
228
+
229
+ @page.getWebResponse.getContentAsStream.to_io
230
+ end
231
+
232
+ #
233
+ # Check if the current page contains the given text.
234
+ #
235
+ # @param [String, Regexp] expected_text The text to look for.
236
+ # @return [Numeric, nil] The index of the matched text, or nil if it isn't found.
237
+ # @raise [TypeError]
238
+ #
239
+
240
+ def contains_text(expected_text)
241
+ return nil unless exist?
242
+ super
243
+ end
244
+
245
+ #
246
+ # @return [HtmlUnit::HtmlHtml] the underlying HtmlUnit document.
247
+ #
248
+
249
+ def document
250
+ @object
251
+ end
252
+
253
+ #
254
+ # Goto back one history item
255
+ # @return [String] The url of the resulting page.
256
+ #
257
+
258
+ def back
259
+ @webclient.getCurrentWindow.getHistory.back
260
+ refresh_page_from_window
261
+
262
+ url
263
+ end
264
+
265
+ #
266
+ # Go forward one history item
267
+ # @return [String] The url of the resulting page.
268
+ #
269
+
270
+ def forward
271
+ @webclient.getCurrentWindow.getHistory.forward
272
+ refresh_page_from_window
273
+
274
+ url
275
+ end
276
+
277
+ #
278
+ # Wait for javascript jobs to finish
279
+ #
280
+
281
+ def wait
282
+ assert_exists
283
+ @webclient.waitForBackgroundJavaScript(10000);
284
+ end
285
+
286
+ #
287
+ # Refresh the current page
288
+ #
289
+
290
+ def refresh
291
+ assert_exists
292
+ @page.refresh
293
+ end
294
+
295
+ #
296
+ # Clears all cookies. (Celerity only)
297
+ #
298
+
299
+ def clear_cookies
300
+ @webclient.getCookieManager.clearCookies
301
+ end
302
+
303
+ #
304
+ # Clears the cache of "compiled JavaScript files and parsed CSS snippets"
305
+ #
306
+
307
+ def clear_cache
308
+ @webclient.cache.clear
309
+ end
310
+
311
+ #
312
+ # Get the cookies for this session. (Celerity only)
313
+ #
314
+ # @return [Hash<domain, Hash<name, value>>]
315
+ #
316
+
317
+ def cookies
318
+ result = Hash.new { |hash, key| hash[key] = {} }
319
+
320
+ cookies = @webclient.getCookieManager.getCookies
321
+ cookies.each do |cookie|
322
+ result[cookie.getDomain][cookie.getName] = cookie.getValue
323
+ end
324
+
325
+ result
326
+ end
327
+
328
+ #
329
+ # Add a cookie with the given parameters (Celerity only)
330
+ #
331
+ # @param [String] domain
332
+ # @param [String] name
333
+ # @param [String] value
334
+ #
335
+ # @option opts :path [String] ("/") A path
336
+ # @option opts :max_age [Fixnum] (??) A max age
337
+ # @option opts :secure [Boolean] (false)
338
+ #
339
+
340
+ def add_cookie(domain, name, value, opts = {})
341
+ path = opts.delete(:path) || "/"
342
+ max_age = opts.delete(:max_age) || (Time.now + 60*60*24) # not sure if this is correct
343
+ secure = opts.delete(:secure) || false
344
+
345
+ raise(ArgumentError, "unknown option: #{opts.inspect}") unless opts.empty?
346
+
347
+ cookie = Cookie.new(domain, name, value, path, max_age, secure)
348
+ @webclient.getCookieManager.addCookie(cookie)
349
+ end
350
+
351
+ #
352
+ # Remove the cookie with the given domain and name (Celerity only)
353
+ #
354
+ # @param [String] domain
355
+ # @param [String] name
356
+ #
357
+ # @raise [CookieNotFoundError] if the cookie doesn't exist
358
+ #
359
+
360
+ def remove_cookie(domain, name)
361
+ cm = @webclient.getCookieManager
362
+ cookie = cm.getCookies.find { |c| c.getDomain == domain && c.getName == name }
363
+
364
+ if cookie.nil?
365
+ raise CookieNotFoundError, "no cookie with domain #{domain.inspect} and name #{name.inspect}"
366
+ end
367
+
368
+ cm.removeCookie(cookie)
369
+ end
370
+
371
+ #
372
+ # Execute the given JavaScript on the current page.
373
+ # @return [Object] The resulting Object
374
+ #
375
+
376
+ def execute_script(source)
377
+ assert_exists
378
+ @page.executeJavaScript(source.to_s).getJavaScriptResult
379
+ end
380
+
381
+ # experimental - should be removed?
382
+ def send_keys(keys)
383
+ keys = keys.gsub(/\s*/, '').scan(/((?:\{[A-Z]+?\})|.)/u).flatten
384
+ keys.each do |key|
385
+ element = @page.getFocusedElement
386
+ case key
387
+ when "{TAB}"
388
+ @page.tabToNextElement
389
+ when /\w/
390
+ element.type(key)
391
+ else
392
+ raise NotImplementedError
393
+ end
394
+ end
395
+ end
396
+
397
+ #
398
+ # Wait until the given block evaluates to true (Celerity only)
399
+ #
400
+ # @param [Fixnum] timeout Number of seconds to wait before timing out (default: 30).
401
+ # @yieldparam [Celerity::Browser] browser The browser instance.
402
+ # @see Celerity::Browser#resynchronized
403
+ #
404
+
405
+ def wait_until(timeout = 30, &block)
406
+ returned = nil
407
+
408
+ Timeout.timeout(timeout) do
409
+ until returned = yield(self)
410
+ refresh_page_from_window
411
+ sleep 0.1
412
+ end
413
+ end
414
+
415
+ returned
416
+ end
417
+
418
+ #
419
+ # Wait while the given block evaluates to true (Celerity only)
420
+ #
421
+ # @param [Fixnum] timeout Number of seconds to wait before timing out (default: 30).
422
+ # @yieldparam [Celerity::Browser] browser The browser instance.
423
+ # @see Celerity::Browser#resynchronized
424
+ #
425
+
426
+ def wait_while(timeout = 30, &block)
427
+ returned = nil
428
+
429
+ Timeout.timeout(timeout) do
430
+ while returned = yield(self)
431
+ refresh_page_from_window
432
+ sleep 0.1
433
+ end
434
+ end
435
+
436
+ returned
437
+ end
438
+
439
+ #
440
+ # Allows you to temporarily switch to HtmlUnit's NicelyResynchronizingAjaxController
441
+ # to resynchronize ajax calls.
442
+ #
443
+ # @browser.resynchronized do |b|
444
+ # b.link(:id, 'trigger_ajax_call').click
445
+ # end
446
+ #
447
+ # @yieldparam [Celerity::Browser] browser The current browser object.
448
+ # @see Celerity::Browser#new for how to configure the browser to always use this.
449
+ #
450
+
451
+ def resynchronized(&block)
452
+ old_controller = @webclient.ajaxController
453
+ @webclient.setAjaxController(::HtmlUnit::NicelyResynchronizingAjaxController.new)
454
+ yield self
455
+ @webclient.setAjaxController(old_controller)
456
+ end
457
+
458
+ #
459
+ # Allows you to temporarliy switch to HtmlUnit's default AjaxController, so
460
+ # ajax calls are performed asynchronously. This is useful if you have created
461
+ # the Browser with :resynchronize => true, but want to switch it off temporarily.
462
+ #
463
+ # @yieldparam [Celerity::Browser] browser The current browser object.
464
+ # @see Celerity::Browser#new
465
+ #
466
+
467
+ def asynchronized(&block)
468
+ old_controller = @webclient.ajaxController
469
+ @webclient.setAjaxController(::HtmlUnit::AjaxController.new)
470
+ yield self
471
+ @webclient.setAjaxController(old_controller)
472
+ end
473
+
474
+ #
475
+ # Start or stop HtmlUnit's DebuggingWebConnection. (Celerity only)
476
+ # The output will go to /tmp/«name»
477
+ #
478
+ # @param [String] name directory name
479
+ # @param [block] blk block to execute
480
+ #
481
+
482
+ def debug_web_connection(name, &blk)
483
+ old_wc = @webclient.getWebConnection
484
+
485
+ @webclient.setWebConnection HtmlUnit::Util::DebuggingWebConnection.new(old_wc, name)
486
+ res = yield
487
+ @webclient.setWebConnection old_wc
488
+
489
+ res
490
+ end
491
+
492
+ #
493
+ # Add a listener block for one of the available types. (Celerity only)
494
+ # Types map to HtmlUnit interfaces like this:
495
+ #
496
+ # :status => StatusHandler
497
+ # :alert => AlertHandler ( window.alert() )
498
+ # :web_window_event => WebWindowListener
499
+ # :html_parser => HTMLParserListener
500
+ # :incorrectness => IncorrectnessListener
501
+ # :confirm => ConfirmHandler ( window.confirm() )
502
+ # :prompt => PromptHandler ( window.prompt() )
503
+ #
504
+ # Examples:
505
+ #
506
+ # browser.add_listener(:status) { |page, message| ... }
507
+ # browser.add_listener(:alert) { |page, message| ... }
508
+ # browser.add_listener(:web_window_event) { |web_window_event| ... }
509
+ # browser.add_listener(:html_parser) { |message, url, line, column, key| ... }
510
+ # browser.add_listener(:incorrectness) { |message, origin| ... }
511
+ # browser.add_listener(:confirm) { |page, message| ...; true }
512
+ # browser.add_listener(:prompt) { |page, message| ... }
513
+ #
514
+ #
515
+ # @param [Symbol] type One of the above symbols.
516
+ # @param [Proc] block A block to be executed for events of this type.
517
+ #
518
+
519
+ def add_listener(type, &block)
520
+ listener.add_listener(type, &block)
521
+ end
522
+
523
+ def remove_listener(type, &block)
524
+ listener.remove_listener(type, &block)
525
+ end
526
+
527
+ #
528
+ # Specify a boolean value to click either 'OK' or 'Cancel' in any confirm
529
+ # dialogs that might show up during the duration of the given block.
530
+ #
531
+ # (Celerity only)
532
+ #
533
+ # @param [Boolean] bool true to click 'OK', false to click 'cancel'
534
+ # @param [Proc] block A block that will trigger the confirm() call(s).
535
+ #
536
+
537
+ def confirm(bool, &block)
538
+ blk = lambda { bool }
539
+
540
+ listener.add_listener(:confirm, &blk)
541
+ yield
542
+ listener.remove_listener(:confirm, blk)
543
+ end
544
+
545
+ #
546
+ # Add a 'checker' proc that will be run on every page load
547
+ #
548
+ # @param [Proc] checker The proc to be run (can also be given as a block)
549
+ # @yieldparam [Celerity::Browser] browser The current browser object.
550
+ # @raise [ArgumentError] if no Proc or block was given.
551
+ #
552
+
553
+ def add_checker(checker = nil, &block)
554
+ if block_given?
555
+ @error_checkers << block
556
+ elsif Proc === checker
557
+ @error_checkers << checker
558
+ else
559
+ raise ArgumentError, "argument must be a Proc or block"
560
+ end
561
+ end
562
+
563
+ #
564
+ # Remove the given checker from the list of checkers
565
+ # @param [Proc] checker The Proc to disable.
566
+ #
567
+
568
+ def disable_checker(checker)
569
+ @error_checkers.delete(checker)
570
+ end
571
+
572
+ #
573
+ # :finest, :finer, :fine, :config, :info, :warning, :severe, or :off, :all
574
+ #
575
+ # @return [Symbol] the current log level
576
+ #
577
+
578
+ def log_level
579
+ Celerity::Util.logger_for('com.gargoylesoftware.htmlunit').level.to_s.downcase.to_sym
580
+ end
581
+
582
+ #
583
+ # Set Java log level (default is :warning, can be any of :all, :finest, :finer, :fine, :config, :info, :warning, :severe, :off)
584
+ #
585
+ # @param [Symbol] level The new log level.
586
+ #
587
+
588
+ def log_level=(level)
589
+ log_level = java.util.logging.Level.const_get(level.to_s.upcase)
590
+
591
+ [ 'com.gargoylesoftware.htmlunit',
592
+ 'com.gargoylesoftware.htmlunit.html',
593
+ 'com.gargoylesoftware.htmlunit.javascript',
594
+ 'org.apache.commons.httpclient'
595
+ ].each { |package| Celerity::Util.logger_for(package).level = log_level }
596
+
597
+ level
598
+ end
599
+
600
+ #
601
+ # If a request is made to an URL that matches the pattern set here, Celerity
602
+ # will ignore the request and return an empty page with content type "text/html" instead.
603
+ #
604
+ # This is useful to block unwanted requests (like ads/banners).
605
+ #
606
+
607
+ def ignore_pattern=(regexp)
608
+ unless regexp.kind_of?(Regexp)
609
+ raise TypeError, "expected Regexp, got #{regexp.inspect}:#{regexp.class}"
610
+ end
611
+
612
+ Celerity::IgnoringWebConnection.new(@webclient, regexp)
613
+ end
614
+
615
+ #
616
+ # Checks if we have a page currently loaded.
617
+ # @return [true, false]
618
+ #
619
+
620
+ def exist?
621
+ !!@page
622
+ end
623
+ alias_method :exists?, :exist?
624
+
625
+ #
626
+ # Turn on/off javascript exceptions
627
+ #
628
+ # @param [Bool]
629
+ #
630
+
631
+ def javascript_exceptions=(bool)
632
+ @webclient.throwExceptionOnScriptError = bool
633
+ end
634
+
635
+ def javascript_exceptions
636
+ @webclient.throwExceptionOnScriptError
637
+ end
638
+
639
+ #
640
+ # Turn on/off status code exceptions
641
+ #
642
+ # @param [Bool]
643
+ #
644
+
645
+ def status_code_exceptions=(bool)
646
+ @webclient.throwExceptionOnFailingStatusCode = bool
647
+ end
648
+
649
+ def status_code_exceptions
650
+ @webclient.throwExceptionOnFailingStatusCode
651
+ end
652
+
653
+ #
654
+ # Turn on/off CSS loading
655
+ #
656
+ # @param [Bool]
657
+ #
658
+
659
+ def css=(bool)
660
+ @webclient.cssEnabled = bool
661
+ end
662
+
663
+ def css
664
+ @webclient.cssEnabled
665
+ end
666
+
667
+ def refresh_handler=(symbol)
668
+ handler = case symbol
669
+ when :waiting
670
+ HtmlUnit::WaitingRefreshHandler.new
671
+ when :threaded
672
+ HtmlUnit::ThreadedRefreshHandler.new
673
+ when :immediate
674
+ HtmlUnit::ImmediateRefreshHandler.new
675
+ else
676
+ raise ArgumentError, "expected :waiting, :threaded or :immediate"
677
+ end
678
+
679
+ @webclient.setRefreshHandler handler
680
+ end
681
+
682
+ #
683
+ # Turn on/off secure SSL
684
+ #
685
+ # @param [Bool]
686
+ #
687
+
688
+ def secure_ssl=(bool)
689
+ @webclient.useInsecureSSL = !bool
690
+ end
691
+
692
+ def secure_ssl
693
+ !@webclient.useInsecureSSL
694
+ end
695
+
696
+ #
697
+ # Turn on/off JavaScript execution
698
+ #
699
+ # @param [Bool]
700
+ #
701
+
702
+ def javascript_enabled=(bool)
703
+ @webclient.setJavaScriptEnabled(bool)
704
+ end
705
+
706
+ def javascript_enabled
707
+ @webclient.isJavaScriptEnabled
708
+ end
709
+
710
+ #
711
+ # Sets the current page object for the browser
712
+ #
713
+ # @param [HtmlUnit::HtmlPage] value The page to set.
714
+ # @api private
715
+ #
716
+
717
+ def page=(value)
718
+ return if @page == value
719
+ @page = value
720
+
721
+ if @page.respond_to?("getDocumentElement")
722
+ @object = @page.getDocumentElement || @object
723
+ elsif @page.is_a? HtmlUnit::UnexpectedPage
724
+ raise UnexpectedPageException, @page.getWebResponse.getContentType
725
+ end
726
+
727
+ render unless @viewer == DefaultViewer
728
+ run_error_checks
729
+
730
+ value
731
+ end
732
+
733
+ #
734
+ # Check that we have a @page object.
735
+ #
736
+ # @raise [UnknownObjectException] if no page is loaded.
737
+ # @api private
738
+ #
739
+
740
+ def assert_exists
741
+ raise UnknownObjectException, "no page loaded" unless exist?
742
+ end
743
+
744
+ #
745
+ # Returns the element that currently has the focus (Celerity only)
746
+ #
747
+
748
+ def focused_element
749
+ element_from_dom_node(page.getFocusedElement())
750
+ end
751
+
752
+ #
753
+ # Enable Celerity's internal WebWindowEventListener
754
+ #
755
+ # @api private
756
+ #
757
+
758
+ def enable_event_listener
759
+ @event_listener ||= lambda do |event|
760
+ self.page = @page ? @page.getEnclosingWindow.getEnclosedPage : event.getNewPage
761
+ end
762
+
763
+ listener.add_listener(:web_window_event, &@event_listener)
764
+ end
765
+
766
+ #
767
+ # Disable Celerity's internal WebWindowEventListener
768
+ #
769
+ # @api private
770
+ #
771
+
772
+ def disable_event_listener
773
+ listener.remove_listener(:web_window_event, @event_listener)
774
+
775
+ if block_given?
776
+ result = yield
777
+ enable_event_listener
778
+
779
+ result
780
+ end
781
+ end
782
+
783
+ private
784
+
785
+ #
786
+ # Runs the all the checker procs added by +add_checker+
787
+ #
788
+ # @see add_checker
789
+ # @api private
790
+ #
791
+
792
+ def run_error_checks
793
+ @error_checkers.each { |e| e[self] }
794
+ end
795
+
796
+ #
797
+ # Configure the webclient according to the options given to #new.
798
+ # @see initialize
799
+ #
800
+
801
+ def setup_webclient(opts)
802
+ browser = (opts.delete(:browser) || :firefox).to_sym
803
+
804
+ browser_version = case browser
805
+ when :firefox, :ff, :ff2
806
+ ::HtmlUnit::BrowserVersion::FIREFOX_2
807
+ when :firefox3, :ff3
808
+ ::HtmlUnit::BrowserVersion::FIREFOX_3
809
+ when :internet_explorer, :ie
810
+ ::HtmlUnit::BrowserVersion::INTERNET_EXPLORER_7
811
+ else
812
+ raise ArgumentError, "unknown browser: #{browser.inspect}"
813
+ end
814
+
815
+ if ua = opts.delete(:user_agent)
816
+ browser_version.setUserAgent(ua)
817
+ end
818
+
819
+ @webclient = if proxy = opts.delete(:proxy)
820
+ phost, pport = proxy.split(":")
821
+ ::HtmlUnit::WebClient.new(browser_version, phost, pport.to_i)
822
+ else
823
+ ::HtmlUnit::WebClient.new(browser_version)
824
+ end
825
+
826
+ self.javascript_exceptions = false unless opts.delete(:javascript_exceptions)
827
+ self.status_code_exceptions = false unless opts.delete(:status_code_exceptions)
828
+ self.css = false unless opts.delete(:css)
829
+ self.javascript_enabled = opts.delete(:javascript_enabled) != false
830
+ self.secure_ssl = opts.delete(:secure_ssl) == false
831
+ self.ignore_pattern = opts.delete(:ignore_pattern) if opts[:ignore_pattern]
832
+ self.refresh_handler = opts.delete(:refresh_handler) if opts[:refresh_handler]
833
+
834
+ if opts.delete(:resynchronize)
835
+ controller = ::HtmlUnit::NicelyResynchronizingAjaxController.new
836
+ @webclient.setAjaxController controller
837
+ end
838
+
839
+ enable_event_listener
840
+ end
841
+
842
+ def setup_viewer(option)
843
+ @viewer = DefaultViewer
844
+ return if option == false
845
+
846
+ host_string = option.kind_of?(String) ? option : "127.0.0.1:6429"
847
+ host, port = host_string.split(":")
848
+
849
+ if viewer = ViewerConnection.create(host, port.to_i)
850
+ @viewer = viewer
851
+ end
852
+ rescue Errno::ECONNREFUSED => e
853
+ nil
854
+ end
855
+
856
+ #
857
+ # This *should* be unneccessary, but sometimes the page we get from the
858
+ # window is different (ie. a different object) from our current @page
859
+ # (Used by #wait_while and #wait_until)
860
+ #
861
+
862
+ def refresh_page_from_window
863
+ new_page = @page.getEnclosingWindow.getEnclosedPage
864
+
865
+ if new_page && (new_page != @page)
866
+ self.page = new_page
867
+ else
868
+ Log.debug "unneccessary refresh"
869
+ end
870
+ end
871
+
872
+ #
873
+ # Render the current page on the connected viewer.
874
+ # @api private
875
+ #
876
+
877
+ def render
878
+ @viewer.render_html(self.send(@render_type), url)
879
+ rescue Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::EPIPE
880
+ @viewer = DefaultViewer
881
+ end
882
+
883
+ def listener
884
+ @listener ||= Celerity::Listener.new(@webclient)
885
+ end
886
+
887
+ end # Browser
888
+ end # Celerity