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,14 @@
1
+ module Celerity
2
+ class DefaultViewer
3
+ IMAGE = "#{Celerity::DIR}/resources/no_viewer.png"
4
+
5
+ class << self
6
+ def save(path = nil)
7
+ return unless path
8
+ FileUtils.copy(IMAGE, path)
9
+ end
10
+
11
+ def close; end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,40 @@
1
+ module Celerity
2
+
3
+ #
4
+ # Mixed in to all elements that can have the 'disabled' attribute.
5
+ #
6
+
7
+ module DisabledElement
8
+ include Celerity::Exception
9
+
10
+ #
11
+ # Returns false if the element is disabled.
12
+ #
13
+
14
+ def enabled?
15
+ !disabled?
16
+ end
17
+
18
+ #
19
+ # Returns true if the element is disabled.
20
+ #
21
+
22
+ def disabled?
23
+ assert_exists unless defined?(@object) && @object
24
+ @object.isDisabled
25
+ end
26
+ alias_method :disabled, :disabled?
27
+
28
+ #
29
+ # Used internally.
30
+ # @api private
31
+ #
32
+
33
+ def assert_enabled
34
+ if disabled?
35
+ raise ObjectDisabledException, "Object #{identifier_string} is disabled"
36
+ end
37
+ end
38
+
39
+ end
40
+ end
@@ -0,0 +1,314 @@
1
+ module Celerity
2
+
3
+ #
4
+ # Superclass for all HTML elements.
5
+ #
6
+
7
+ class Element
8
+ include Exception
9
+ include Container
10
+
11
+ attr_reader :container
12
+
13
+ # number of spaces that separate the property from the value in the create_string method
14
+ TO_S_SIZE = 14
15
+
16
+ # HTML 4.01 Transitional DTD
17
+ HTML_401_TRANSITIONAL = {
18
+ :core => [:class, :id, :style, :title],
19
+ :cell_halign => [:align, :char, :charoff],
20
+ :cell_valign => [:valign],
21
+ :i18n => [:dir, :lang],
22
+ :event => [:onclick, :ondblclick, :onmousedown, :onmouseup, :onmouseover,
23
+ :onmousemove, :onmouseout, :onkeypress, :onkeydown, :onkeyup],
24
+ :sloppy => [:name, :value]
25
+ }
26
+
27
+ CELLHALIGN_ATTRIBUTES = HTML_401_TRANSITIONAL[:cell_halign]
28
+ CELLVALIGN_ATTRIBUTES = HTML_401_TRANSITIONAL[:cell_valign]
29
+ BASE_ATTRIBUTES = HTML_401_TRANSITIONAL.values_at(:core, :i18n, :event, :sloppy).flatten
30
+ ATTRIBUTES = BASE_ATTRIBUTES
31
+ TAGS = []
32
+
33
+ DEFAULT_HOW = nil
34
+
35
+ # @api private
36
+ def initialize(container, *args)
37
+ self.container = container
38
+
39
+ case args.size
40
+ when 2
41
+ @conditions = { args[0] => args[1] }
42
+ when 1
43
+ if args.first.is_a? Hash
44
+ @conditions = args.first
45
+ elsif (how = self.class::DEFAULT_HOW)
46
+ @conditions = { how => args.first }
47
+ else
48
+ raise ArgumentError, "wrong number of arguments (1 for 2)"
49
+ end
50
+ else
51
+ raise ArgumentError, "wrong number of arguments (#{args.size} for 2)"
52
+ end
53
+
54
+ @conditions.freeze
55
+ @object = nil
56
+ end
57
+
58
+ #
59
+ # Get the parent element
60
+ # @return [Celerity::Element, nil] subclass of Celerity::Element, or nil if no parent was found
61
+ #
62
+
63
+ def parent
64
+ assert_exists
65
+
66
+ obj = @object.parentNode
67
+ until element_class = Celerity::Util.htmlunit2celerity(obj.class)
68
+ return nil if obj.nil?
69
+ obj = obj.parentNode
70
+ end
71
+
72
+ element_class.new(@container, :object, obj)
73
+ end
74
+
75
+ #
76
+ # Sets the focus to this element.
77
+ #
78
+
79
+ def focus
80
+ assert_exists
81
+ @object.focus
82
+ end
83
+
84
+ #
85
+ # Fires the given event for this element
86
+ #
87
+
88
+ def fire_event(event_name)
89
+ assert_exists
90
+ @object.fireEvent(event_name.sub(/^on/, ''))
91
+ end
92
+
93
+ #
94
+ # Used internally. Find the element on the page.
95
+ # @api private
96
+ #
97
+
98
+ def locate
99
+ @object = ElementLocator.new(@container, self.class).find_by_conditions(@conditions)
100
+ end
101
+
102
+ #
103
+ # Returns the HtmlUnit object backing this element
104
+ #
105
+
106
+ def object
107
+ @object || locate
108
+ end
109
+
110
+ #
111
+ # Returns a JavaScript object representing the receiver
112
+ #
113
+ # @api internal - subject to change
114
+ #
115
+
116
+ def javascript_object
117
+ assert_exists
118
+ @object.getScriptObject
119
+ end
120
+
121
+ #
122
+ # @return [String] A string representation of the element.
123
+ #
124
+
125
+ def to_s
126
+ assert_exists
127
+ create_string(@object)
128
+ end
129
+
130
+ #
131
+ # @param [String, #to_s] The attribute.
132
+ # @return [String] The value of the given attribute.
133
+ #
134
+
135
+ def attribute_value(attribute)
136
+ assert_exists
137
+ @object.getAttribute(attribute.to_s)
138
+ end
139
+
140
+ #
141
+ # Check if the element is visible to the user or not.
142
+ # Note that this only takes the _style attribute_ of the element (and
143
+ # its parents) into account - styles from applied CSS is not considered.
144
+ #
145
+ # @return [boolean]
146
+ #
147
+
148
+ def visible?
149
+ assert_exists
150
+ @object.isDisplayed
151
+ end
152
+
153
+ #
154
+ # Used internally to ensure the element actually exists.
155
+ #
156
+ # @raise [Celerity::Exception::UnknownObjectException] if the element can't be found.
157
+ # @api private
158
+ #
159
+
160
+ def assert_exists
161
+ locate unless @object
162
+ unless @object
163
+ raise UnknownObjectException, "Unable to locate #{self.class.name[/::(.*)$/, 1]}, using #{identifier_string}"
164
+ end
165
+ end
166
+
167
+ #
168
+ # Checks if the element exists.
169
+ # @return [true, false]
170
+ #
171
+
172
+ def exists?
173
+ assert_exists
174
+ true
175
+ rescue UnknownObjectException, UnknownFrameException
176
+ false
177
+ end
178
+ alias_method :exist?, :exists?
179
+
180
+ #
181
+ # Return a text representation of the element as it would appear in a browser.
182
+ #
183
+ # @see inner_text
184
+ # @return [String]
185
+ #
186
+
187
+ def text
188
+ assert_exists
189
+ @object.asText.strip # this must behave like ElementLocator
190
+ end
191
+
192
+ #
193
+ # Return the text content of this DOM node, disregarding its visibility.
194
+ #
195
+ # (Celerity-specific?)
196
+ #
197
+ # @see text
198
+ # @return [String]
199
+ #
200
+
201
+ def inner_text
202
+ assert_exists
203
+ Celerity::Util.normalize_text @object.getTextContent
204
+ end
205
+
206
+ #
207
+ # @return [String] The normative XML representation of the element (including children).
208
+ #
209
+
210
+ def to_xml
211
+ assert_exists
212
+ @object.asXml
213
+ end
214
+ alias_method :asXml, :to_xml
215
+ alias_method :as_xml, :to_xml
216
+ alias_method :html, :to_xml
217
+
218
+ #
219
+ # @return [String] A string representation of the element's attributes.
220
+ #
221
+
222
+ def attribute_string
223
+ assert_exists
224
+
225
+ result = ''
226
+ @object.getAttributes.each do |attribute|
227
+ result << %Q{#{attribute.getName}="#{attribute.getValue}"}
228
+ end
229
+
230
+ result
231
+ end
232
+
233
+ #
234
+ # return the canonical xpath for this element (Celerity-specific)
235
+ #
236
+
237
+ def xpath
238
+ assert_exists
239
+ @object.getCanonicalXPath
240
+ end
241
+
242
+ #
243
+ # Dynamically get element attributes.
244
+ #
245
+ # @see ATTRIBUTES constant for a list of valid methods for a given element.
246
+ #
247
+ # @return [String] The resulting attribute.
248
+ # @raise [NoMethodError] if the element doesn't support this attribute.
249
+ #
250
+
251
+ def method_missing(meth, *args, &blk)
252
+ assert_exists
253
+
254
+ meth = selector_to_attribute(meth)
255
+
256
+ if self.class::ATTRIBUTES.include?(meth) || (self.class == Element && @object.hasAttribute(meth.to_s))
257
+ return @object.getAttribute(meth.to_s)
258
+ end
259
+ Log.warn "Element\#method_missing calling super with #{meth.inspect}"
260
+ super
261
+ end
262
+
263
+ def methods(*args)
264
+ ms = super
265
+ ms += self.class::ATTRIBUTES.map { |e| e.to_s }
266
+ ms.sort
267
+ end
268
+
269
+ def respond_to?(meth, include_private = false)
270
+ meth = selector_to_attribute(meth)
271
+ return true if self.class::ATTRIBUTES.include?(meth)
272
+ super
273
+ end
274
+
275
+ private
276
+
277
+ def create_string(element)
278
+ ret = []
279
+
280
+ unless (tag = element.getTagName).empty?
281
+ ret << "tag:".ljust(TO_S_SIZE) + tag
282
+ end
283
+
284
+ element.getAttributes.each do |attribute|
285
+ ret << " #{attribute.getName}:".ljust(TO_S_SIZE+2) + attribute.getValue.to_s
286
+ end
287
+
288
+ unless (text = element.asText).empty?
289
+ ret << " text:".ljust(TO_S_SIZE+2) + element.asText
290
+ end
291
+
292
+ ret.join("\n")
293
+ end
294
+
295
+ def identifier_string
296
+ if @conditions.size == 1
297
+ how, what = @conditions.to_a.first
298
+ "#{how.inspect} and #{what.inspect}"
299
+ else
300
+ @conditions.inspect
301
+ end
302
+ end
303
+
304
+ def selector_to_attribute(meth)
305
+ case meth
306
+ when :class_name then :class
307
+ when :caption then :value
308
+ when :url then :href
309
+ else meth
310
+ end
311
+ end
312
+
313
+ end # Element
314
+ end # Celerity
@@ -0,0 +1,107 @@
1
+ module Celerity
2
+
3
+ #
4
+ # This class is the superclass for the iterator classes (Buttons, Links, Spans etc.)
5
+ # It would normally only be accessed by the iterator methods (Browser#spans, Browser#links, ...).
6
+ #
7
+
8
+ class ElementCollection
9
+ include Enumerable
10
+
11
+ #
12
+ # @api private
13
+ #
14
+
15
+ def initialize(container, how = nil, what = nil)
16
+ @container = container
17
+ @object = (how == :object ? what : nil)
18
+ @length = length
19
+ end
20
+
21
+ #
22
+ # @return [Fixnum] The number of elements in this collection.
23
+ #
24
+
25
+ def length
26
+ if @object
27
+ @object.length
28
+ else
29
+ @elements ||= ElementLocator.new(@container, element_class).elements_by_idents
30
+ @elements.size
31
+ end
32
+ end
33
+ alias_method :size, :length
34
+
35
+ #
36
+ # @yieldparam [Celerity::Element] element Iterate through the elements in this collection.
37
+ #
38
+
39
+ def each
40
+ if @elements
41
+ @elements.each { |e| yield(element_class.new(@container, :object, e)) }
42
+ else
43
+ 0.upto(@length - 1) { |i| yield iterator_object(i) }
44
+ end
45
+
46
+ @length
47
+ end
48
+
49
+ #
50
+ # Get the element at the given index.
51
+ # By default, this is 1-indexed to keep compatibility with Watir.
52
+ #
53
+ # Also note that because of Watir's lazy loading, this will return an Element
54
+ # instance even if the index is out of bounds.
55
+ #
56
+ # @param [Fixnum] n Index of wanted element, 1-indexed unless Celerity.index_offset is changed.
57
+ # @return [Celerity::Element] Returns a subclass of Celerity::Element
58
+ #
59
+
60
+ def [](n)
61
+ if @elements && @elements[n - Celerity.index_offset]
62
+ element_class.new(@container, :object, @elements[n - Celerity.index_offset])
63
+ else
64
+ iterator_object(n - Celerity.index_offset)
65
+ end
66
+ end
67
+
68
+ #
69
+ # Get the first element in this collection. (Celerity-specific)
70
+ #
71
+ # @return [Celerity::Element] Returns a subclass of Celerity::Element
72
+ #
73
+
74
+ def first
75
+ self[Celerity.index_offset]
76
+ end
77
+
78
+ #
79
+ # Get the last element in this collection. (Celerity-specific)
80
+ #
81
+ # @return [Celerity::Element] Returns a subclass of Celerity::Element
82
+ #
83
+
84
+ def last
85
+ self[Celerity.index_offset - 1]
86
+ end
87
+
88
+ #
89
+ # Note: This can be quite useful in irb:
90
+ #
91
+ # puts browser.text_fields
92
+ #
93
+ # @return [String] A string representation of all elements in this collection.
94
+ #
95
+
96
+ def to_s
97
+ map { |e| e.to_s }.join("\n")
98
+ end
99
+
100
+ private
101
+
102
+ def iterator_object(i)
103
+ element_class.new(@container, :index, i+1)
104
+ end
105
+
106
+ end # ElementCollection
107
+ end # Celerity