drnic-celerity 0.0.6.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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