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,30 @@
1
+ module Celerity
2
+ class Link < Element
3
+ include ClickableElement
4
+
5
+ TAGS = [ Identifier.new('a') ]
6
+ ATTRIBUTES = BASE_ATTRIBUTES | [:charset, :type, :name, :href, :hreflang,
7
+ :target, :rel, :rev, :accesskey, :shape,
8
+ :coords, :tabindex, :onfocus, :onblur]
9
+ DEFAULT_HOW = :href
10
+
11
+ #
12
+ # Returns the absolute URL for this link (Celerity-specific)
13
+ #
14
+ # (Watir/IE does this for href(), but we don't want that.)
15
+ #
16
+
17
+ def absolute_url
18
+ assert_exists
19
+ href = @object.getAttribute('href')
20
+
21
+ unless href.empty? || URI.parse(href).absolute?
22
+ href = URI.join(browser.url, href).to_s
23
+ end
24
+
25
+ href
26
+ end
27
+
28
+
29
+ end # Link
30
+ end # Celerity
@@ -0,0 +1,7 @@
1
+ module Celerity
2
+ class Meta < Element
3
+ ATTRIBUTES = [:name, :id, :'http-equiv', :content, :scheme] | HTML_401_TRANSITIONAL[:i18n]
4
+ DEFAULT_HOW = :id
5
+ TAGS = [ Identifier.new('meta') ]
6
+ end
7
+ end
@@ -0,0 +1,106 @@
1
+ module Celerity
2
+
3
+ #
4
+ # Superclass for for Span, Pre, Div, H1, ...
5
+ #
6
+
7
+ class NonControlElement < Element
8
+ include Exception
9
+ include ClickableElement
10
+
11
+ ATTRIBUTES = BASE_ATTRIBUTES
12
+ DEFAULT_HOW = :id
13
+ end
14
+
15
+ #
16
+ #--
17
+ # classes ordered alphabetically
18
+ #++
19
+ #
20
+
21
+ class Area < NonControlElement
22
+ ATTRIBUTES = ATTRIBUTES | [:shape, :coords, :href, :nohref, :alt, :tabindex, :accesskey, :onfocus, :onblur]
23
+ TAGS = [ Identifier.new('area') ]
24
+ end
25
+
26
+ class Dd < NonControlElement
27
+ TAGS = [ Identifier.new('dd')]
28
+ end
29
+
30
+ class Div < NonControlElement
31
+ TAGS = [ Identifier.new('div')]
32
+ end
33
+
34
+ class Dl < NonControlElement
35
+ TAGS = [ Identifier.new('dl')]
36
+ end
37
+
38
+ class Dt < NonControlElement
39
+ TAGS = [ Identifier.new('dt')]
40
+ end
41
+
42
+ class Em < NonControlElement
43
+ TAGS = [ Identifier.new('em')]
44
+ end
45
+
46
+ class H1 < NonControlElement
47
+ TAGS = [ Identifier.new('h1') ]
48
+ end
49
+
50
+ class H2 < NonControlElement
51
+ TAGS = [ Identifier.new('h2') ]
52
+ end
53
+
54
+ class H3 < NonControlElement
55
+ TAGS = [ Identifier.new('h3') ]
56
+ end
57
+
58
+ class H4 < NonControlElement
59
+ TAGS = [ Identifier.new('h4') ]
60
+ end
61
+
62
+ class H5 < NonControlElement
63
+ TAGS = [ Identifier.new('h5') ]
64
+ end
65
+
66
+ class H6 < NonControlElement
67
+ TAGS = [ Identifier.new('h6') ]
68
+ end
69
+
70
+ class Li < NonControlElement
71
+ TAGS = [ Identifier.new('li') ]
72
+ end
73
+
74
+ class Map < NonControlElement
75
+ TAGS = [ Identifier.new('map') ]
76
+ end
77
+
78
+ class Ol < NonControlElement
79
+ TAGS = [ Identifier.new('ol') ]
80
+ end
81
+
82
+ class P < NonControlElement
83
+ TAGS = [ Identifier.new('p') ]
84
+ end
85
+
86
+ class Pre < NonControlElement
87
+ TAGS = [ Identifier.new('pre')]
88
+ end
89
+
90
+ class Span < NonControlElement
91
+ TAGS = [ Identifier.new('span') ]
92
+ end
93
+
94
+ class Strong < NonControlElement
95
+ TAGS = [ Identifier.new('strong') ]
96
+ end
97
+
98
+ # class Title < NonControlElement
99
+ # TAGS = [ Identifier.new('title') ]
100
+ # end
101
+
102
+ class Ul < NonControlElement
103
+ TAGS = [ Identifier.new('ul') ]
104
+ end
105
+
106
+ end
@@ -0,0 +1,32 @@
1
+ module Celerity
2
+
3
+ #
4
+ # Represents an option in a select list.
5
+ #
6
+
7
+ class Option < Element
8
+ include ClickableElement
9
+ include DisabledElement
10
+
11
+ TAGS = [ Identifier.new('option') ]
12
+ ATTRIBUTES = BASE_ATTRIBUTES | [:selected, :disabled, :label, :value]
13
+ DEFAULT_HOW = :text
14
+
15
+ alias_method :select, :click
16
+
17
+ #
18
+ # Is this option selected?
19
+ #
20
+
21
+ def selected?
22
+ assert_exists
23
+ @object.isSelected
24
+ end
25
+
26
+ def label
27
+ # overrides Container#label
28
+ assert_exists
29
+ @object.getLabelAttribute
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,115 @@
1
+ module Celerity
2
+
3
+ #
4
+ # Common superclass for radios and check boxes.
5
+ #
6
+
7
+ class RadioCheckCommon < InputElement
8
+ DEFAULT_HOW = :name
9
+
10
+ #
11
+ # Can optionally take a value parameter as a third arg, so we override initialize
12
+ #
13
+
14
+ def initialize(container, type, *args)
15
+ @type = type
16
+ case args.size
17
+ when 2
18
+ super(container, args[0] => args[1])
19
+ when 3
20
+ super(container, args[0] => args[1], :value => args[2])
21
+ else
22
+ super(container, *args)
23
+ end
24
+ end
25
+
26
+ #
27
+ # returns true if the element is checked
28
+ # @return [true, false]
29
+ #
30
+
31
+ def set?
32
+ assert_exists
33
+ @object.isChecked
34
+ end
35
+ alias_method :checked?, :set?
36
+
37
+ #
38
+ # Unset this element.
39
+ #
40
+
41
+ def clear
42
+ set(false)
43
+ end
44
+ end
45
+
46
+ #
47
+ # This class is the representation of a radio button.
48
+ #
49
+
50
+ class Radio < RadioCheckCommon
51
+ TAGS = [Identifier.new('input', :type => %w[radio])]
52
+
53
+ #
54
+ # @api private
55
+ #
56
+
57
+ def initialize(container, *args)
58
+ super(container, %w[radio], *args)
59
+ end
60
+
61
+ #
62
+ # Set the radio button to the given value.
63
+ #
64
+ # radio.set? #=> false
65
+ # radio.set
66
+ # radio.set? #=> true
67
+ # radio.set(false)
68
+ # radio.set? #=> false
69
+ #
70
+
71
+ def set(value = true)
72
+ assert_exists
73
+ assert_enabled
74
+ value ? @object.click : @object.setChecked(value)
75
+ end
76
+
77
+ end
78
+
79
+ #
80
+ # This class is the representation of a check box.
81
+ #
82
+
83
+ class CheckBox < RadioCheckCommon
84
+ TAGS = [Identifier.new('input', :type => %w[checkbox])]
85
+
86
+ #
87
+ # @api private
88
+ #
89
+
90
+ def initialize(container, *args)
91
+ super(container, %w[checkbox], *args)
92
+ end
93
+
94
+ #
95
+ # Set the checkbox to the given value.
96
+ #
97
+ # checkbox.set? #=> false
98
+ # checkbox.set
99
+ # checkbox.set? #=> true
100
+ # checkbox.set(false)
101
+ # checkbox.set? #=> false
102
+ #
103
+
104
+ def set(value = true)
105
+ assert_exists
106
+ assert_enabled
107
+
108
+ if (value && !set?) || (!value && set?)
109
+ Log.debug(@object.inspect)
110
+ @object.click
111
+ end
112
+ end
113
+ end
114
+
115
+ end
@@ -0,0 +1,142 @@
1
+ module Celerity
2
+ class SelectList < InputElement
3
+ TAGS = [ Identifier.new('select') ]
4
+ DEFAULT_HOW = :name
5
+
6
+ #
7
+ # @return [Array<String>] An array of strings representing the text value of the select list's options.
8
+ #
9
+
10
+ def options
11
+ assert_exists
12
+ @object.getOptions.map do |e|
13
+ e.asText.empty? ? e.getLabelAttribute : e.asText
14
+ end
15
+ end
16
+
17
+ #
18
+ # @return [Array<String>] An array of strings representing the text value of the currently selected options.
19
+ #
20
+
21
+ def selected_options
22
+ assert_exists
23
+ @object.getSelectedOptions.map { |e| e.asText.empty? ? e.getLabelAttribute : e.asText }
24
+ end
25
+
26
+ #
27
+ # Clear all selected options
28
+ #
29
+
30
+ def clear
31
+ # assert_exists called by SelectList#type here
32
+ # TODO: should update page for each option changed?
33
+ @object.getSelectedOptions.each { |e| e.setSelected(false) } unless type() == 'select-one'
34
+ end
35
+
36
+ #
37
+ # Select the option(s) whose text or label matches the given string.
38
+ # If several options match the value given, all will be selected.
39
+ #
40
+ # @param [String, Regexp] value A value.
41
+ # @raise [Celerity::Exception::NoValueFoundException] if the value does not exist.
42
+ # @return [String] The option selected. If multiple options match, returns the first match
43
+ #
44
+ #
45
+
46
+ def select(value)
47
+ assert_exists
48
+
49
+ selected = nil
50
+ @object.getOptions.select do |option|
51
+ next unless matches_option?(option, value)
52
+
53
+ selected ||= option.asText
54
+ option.click
55
+ end
56
+
57
+ unless selected
58
+ raise NoValueFoundException, "unknown option with value #{value.inspect} for select_list #{@conditions.inspect}"
59
+ end
60
+
61
+ selected
62
+ end
63
+ alias_method :set, :select
64
+
65
+ #
66
+ # Selects the option(s) whose value attribute matches the given string.
67
+ # @param [String, Regexp] value A value.
68
+ # @raise [Celerity::Exception::NoValueFoundException] if the value does not exist.
69
+ # @return [String] The option selected. If multiple options match, returns the first match
70
+ #
71
+
72
+ def select_value(value)
73
+ assert_exists
74
+ selected = @object.getOptions.map { |e| e.click if matches?(e.getValueAttribute, value) }.compact.first
75
+
76
+ unless selected
77
+ raise NoValueFoundException, "unknown option with value #{value.inspect} for select_list #{@conditions.inspect}"
78
+ end
79
+
80
+ selected.asText
81
+ end
82
+
83
+ #
84
+ # Returns true if the select list has one or more options matching the given value.
85
+ #
86
+ # @param [String, Regexp] value A value.
87
+ # @return [true, false]
88
+ #
89
+
90
+ def include?(value)
91
+ assert_exists
92
+ !!@object.getOptions.find { |e| matches_option?(e, value) }
93
+ end
94
+
95
+ #
96
+ # Returns true if any of the selected options match the given value.
97
+ #
98
+ # @param [String, Regexp] value A value.
99
+ # @raise [Celerity::Exception::UnknownObjectException] if the value does not exist.
100
+ # @return [true, false]
101
+ #
102
+
103
+ def selected?(value)
104
+ assert_exists
105
+ raise UnknownObjectException, "unknown option with value #{value.inspect} for select_list #{@conditions.inspect}" unless include?(value)
106
+ !!@object.getOptions.find { |e| matches_option?(e, value) && e.isSelected }
107
+ end
108
+
109
+ #
110
+ # Returns 'select-multiple' if the select list has the 'multiple' attribute,
111
+ # defined, otherwise 'select-one'.
112
+ #
113
+ # @return [String]
114
+ #
115
+
116
+ def type
117
+ assert_exists
118
+ 'select-' + (@object.hasAttribute('multiple') ? 'multiple' : 'one')
119
+ end
120
+
121
+ #
122
+ # Returns the value of the first selected option in the select list.
123
+ # Returns nil if no option is selected.
124
+ #
125
+ # @return [String, nil]
126
+ #
127
+
128
+ def value
129
+ assert_exists
130
+ if (option = @object.getSelectedOptions.to_a.first)
131
+ option.getValueAttribute
132
+ end
133
+ end
134
+
135
+ private
136
+
137
+ def matches_option?(option, value)
138
+ matches?(option.asText, value) || (option.hasAttribute("label") && matches?(option.getLabelAttribute, value))
139
+ end
140
+
141
+ end # SelectList
142
+ end # Celerity
@@ -0,0 +1,144 @@
1
+ module Celerity
2
+
3
+ class Table < Element
4
+ include ClickableElement
5
+ include Enumerable
6
+ include Container
7
+
8
+ TAGS = [ Identifier.new('table') ]
9
+ ATTRIBUTES = BASE_ATTRIBUTES | [:summary, :width, :border, :frame, :rules,
10
+ :cellspacing, :cellpadding, :align, :bgcolor]
11
+ DEFAULT_HOW = :id
12
+
13
+ def locate
14
+ super
15
+ if @object # cant call assert_exists here, as an exists? method call will fail
16
+ @rows = @object.getRows
17
+ @cells = []
18
+ @rows.each do |row|
19
+ row.getCells.each do |c|
20
+ @cells << c
21
+ end
22
+ end
23
+ end
24
+
25
+ @object
26
+ end
27
+
28
+ #
29
+ # @return [Celerity::TableRows]
30
+ #
31
+
32
+ def rows
33
+ assert_exists
34
+ TableRows.new(self, :object, @rows)
35
+ end
36
+
37
+ #
38
+ # @return [Celerity::TableCells]
39
+ #
40
+
41
+ def cells
42
+ assert_exists
43
+ TableCells.new(self, :object, @cells)
44
+ end
45
+
46
+ #
47
+ # Iterates through each row in the table.
48
+ # @yieldparam [Celerity::TableRow] row A row.
49
+ #
50
+
51
+ def each
52
+ assert_exists
53
+ @rows.each { |row| yield TableRow.new(self, :object, row) }
54
+ end
55
+
56
+ #
57
+ # Returns the TableRow at the given index (1-indexed).
58
+ #
59
+ # browser.table(:foo, 'bar')[1] # => #<TableRow...>
60
+ # browser.table(:foo, 'bar').child_row[1] # => #<TableRow...>
61
+ #
62
+ # @param [Fixnum] index The index of the wanted row, 1-indexed.
63
+ # @raise [Celerity::Exception::UnknownRowException]
64
+ # @return [Celerity::TableRow]
65
+ #
66
+
67
+ def child_row(index)
68
+ assert_exists
69
+
70
+ if (index - Celerity.index_offset) >= @rows.length
71
+ raise UnknownRowException, "Unable to locate a row at index #{index}"
72
+ end
73
+
74
+ TableRow.new(self, :object, @rows[index - Celerity.index_offset])
75
+ end
76
+ alias_method :[], :child_row
77
+
78
+ #
79
+ # Returns the TableCell at the given index (1-indexed).
80
+ #
81
+ # In a 10-column row, table.child_cell[11] will return the first cell on the second row.
82
+ #
83
+ # @param [Fixnum] index The index of the wanted cell, 1-indexed.
84
+ # @raise [Celerity::Exception::UnknownCellException]
85
+ # @return [Celerity::TableCell]
86
+ #
87
+
88
+ def child_cell(index)
89
+ assert_exists
90
+
91
+ if (index - Celerity.index_offset) >= @cells.length
92
+ raise UnknownCellException, "Unable to locate a cell at index #{index}"
93
+ end
94
+
95
+ TableCell.new(self, :object, @cells[index - Celerity.index_offset])
96
+ end
97
+
98
+ #
99
+ # The number of rows in the table
100
+ # @return [Fixnum]
101
+ #
102
+
103
+ def row_count
104
+ assert_exists
105
+ @object.getRowCount
106
+ end
107
+
108
+ #
109
+ # Returns the number of columns on the row at the given index. (1-indexed)
110
+ # Default is the number of columns on the first row
111
+ # @param [Fixnum] index An index, 1-indexed (optional).
112
+ # @return [Fixnum]
113
+ #
114
+
115
+ def column_count(index = Celerity.index_offset)
116
+ assert_exists
117
+ @object.getRow(index - Celerity.index_offset).getCells.length
118
+ end
119
+
120
+ #
121
+ # Returns the text of each cell in the the table as a two-dimensional array.
122
+ # @return [Array<Array<String>>]
123
+ #
124
+
125
+ def to_a
126
+ assert_exists
127
+ # @object.getRows.map do |table_row|
128
+ # table_row.getCells.map { |td| td.asText.strip }
129
+ # end
130
+ rows.map do |table_row|
131
+ table_row.map { |td| td.text }
132
+ end
133
+ end
134
+
135
+ def column_values(column_number)
136
+ (1..row_count).map { |index| self[index][column_number].text }
137
+ end
138
+
139
+ def row_values(row_number)
140
+ (1..column_count(row_number)).map { |index| self[row_number][index].text }
141
+ end
142
+
143
+ end # Table
144
+ end # Celerity