celerity_thingista 0.9.2

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 (118) hide show
  1. data/.document +5 -0
  2. data/.gitignore +9 -0
  3. data/.gitmodules +3 -0
  4. data/.travis.yml +4 -0
  5. data/Gemfile +3 -0
  6. data/LICENSE +278 -0
  7. data/README.rdoc +84 -0
  8. data/Rakefile +15 -0
  9. data/benchmark/bm_2000_spans.rb +48 -0
  10. data/benchmark/bm_digg.rb +26 -0
  11. data/benchmark/bm_google_images.rb +36 -0
  12. data/benchmark/bm_input_locator.rb +69 -0
  13. data/benchmark/bm_text_input.rb +19 -0
  14. data/benchmark/loader.rb +14 -0
  15. data/celerity.gemspec +26 -0
  16. data/lib/celerity.rb +75 -0
  17. data/lib/celerity/browser.rb +924 -0
  18. data/lib/celerity/clickable_element.rb +73 -0
  19. data/lib/celerity/collections.rb +164 -0
  20. data/lib/celerity/container.rb +802 -0
  21. data/lib/celerity/default_viewer.rb +14 -0
  22. data/lib/celerity/disabled_element.rb +40 -0
  23. data/lib/celerity/element.rb +314 -0
  24. data/lib/celerity/element_collection.rb +115 -0
  25. data/lib/celerity/element_locator.rb +164 -0
  26. data/lib/celerity/elements/button.rb +54 -0
  27. data/lib/celerity/elements/file_field.rb +29 -0
  28. data/lib/celerity/elements/form.rb +22 -0
  29. data/lib/celerity/elements/frame.rb +86 -0
  30. data/lib/celerity/elements/image.rb +89 -0
  31. data/lib/celerity/elements/label.rb +16 -0
  32. data/lib/celerity/elements/link.rb +43 -0
  33. data/lib/celerity/elements/meta.rb +14 -0
  34. data/lib/celerity/elements/non_control_elements.rb +124 -0
  35. data/lib/celerity/elements/option.rb +38 -0
  36. data/lib/celerity/elements/radio_check.rb +114 -0
  37. data/lib/celerity/elements/select_list.rb +146 -0
  38. data/lib/celerity/elements/table.rb +154 -0
  39. data/lib/celerity/elements/table_cell.rb +36 -0
  40. data/lib/celerity/elements/table_elements.rb +42 -0
  41. data/lib/celerity/elements/table_row.rb +54 -0
  42. data/lib/celerity/elements/text_field.rb +168 -0
  43. data/lib/celerity/exception.rb +83 -0
  44. data/lib/celerity/htmlunit.rb +64 -0
  45. data/lib/celerity/htmlunit/commons-codec-1.7.jar +0 -0
  46. data/lib/celerity/htmlunit/commons-collections-3.2.1.jar +0 -0
  47. data/lib/celerity/htmlunit/commons-io-2.4.jar +0 -0
  48. data/lib/celerity/htmlunit/commons-lang3-3.1.jar +0 -0
  49. data/lib/celerity/htmlunit/commons-logging-1.1.1.jar +0 -0
  50. data/lib/celerity/htmlunit/cssparser-0.9.9.jar +0 -0
  51. data/lib/celerity/htmlunit/htmlunit-2.12.jar +0 -0
  52. data/lib/celerity/htmlunit/htmlunit-core-js-2.12.jar +0 -0
  53. data/lib/celerity/htmlunit/httpclient-4.2.3.jar +0 -0
  54. data/lib/celerity/htmlunit/httpcore-4.2.2.jar +0 -0
  55. data/lib/celerity/htmlunit/httpmime-4.2.3.jar +0 -0
  56. data/lib/celerity/htmlunit/jetty-http-8.1.9.v20130131.jar +0 -0
  57. data/lib/celerity/htmlunit/jetty-io-8.1.9.v20130131.jar +0 -0
  58. data/lib/celerity/htmlunit/jetty-util-8.1.9.v20130131.jar +0 -0
  59. data/lib/celerity/htmlunit/jetty-websocket-8.1.9.v20130131.jar +0 -0
  60. data/lib/celerity/htmlunit/nekohtml-1.9.18.jar +0 -0
  61. data/lib/celerity/htmlunit/sac-1.3.jar +0 -0
  62. data/lib/celerity/htmlunit/serializer-2.7.1.jar +0 -0
  63. data/lib/celerity/htmlunit/xalan-2.7.1.jar +0 -0
  64. data/lib/celerity/htmlunit/xercesImpl-2.10.0.jar +0 -0
  65. data/lib/celerity/htmlunit/xml-apis-1.4.01.jar +0 -0
  66. data/lib/celerity/identifier.rb +28 -0
  67. data/lib/celerity/ignoring_web_connection.rb +15 -0
  68. data/lib/celerity/input_element.rb +25 -0
  69. data/lib/celerity/javascript_debugger.rb +32 -0
  70. data/lib/celerity/listener.rb +143 -0
  71. data/lib/celerity/resources/no_viewer.png +0 -0
  72. data/lib/celerity/short_inspect.rb +29 -0
  73. data/lib/celerity/util.rb +129 -0
  74. data/lib/celerity/version.rb +3 -0
  75. data/lib/celerity/viewer_connection.rb +89 -0
  76. data/lib/celerity/watir_compatibility.rb +70 -0
  77. data/lib/celerity/xpath_support.rb +50 -0
  78. data/spec/browser_authentication_spec.rb +16 -0
  79. data/spec/browser_spec.rb +439 -0
  80. data/spec/button_spec.rb +24 -0
  81. data/spec/clickable_element_spec.rb +39 -0
  82. data/spec/default_viewer_spec.rb +23 -0
  83. data/spec/element_spec.rb +77 -0
  84. data/spec/filefield_spec.rb +18 -0
  85. data/spec/htmlunit_spec.rb +63 -0
  86. data/spec/implementation.rb +7 -0
  87. data/spec/index_offset_spec.rb +24 -0
  88. data/spec/link_spec.rb +16 -0
  89. data/spec/listener_spec.rb +142 -0
  90. data/spec/spec_helper.rb +6 -0
  91. data/spec/table_spec.rb +41 -0
  92. data/spec/watir_compatibility_spec.rb +32 -0
  93. data/tasks/benchmark.rake +4 -0
  94. data/tasks/check.rake +24 -0
  95. data/tasks/clean.rake +3 -0
  96. data/tasks/fix.rake +25 -0
  97. data/tasks/jar.rake +55 -0
  98. data/tasks/rdoc.rake +4 -0
  99. data/tasks/snapshot.rake +25 -0
  100. data/tasks/spec.rake +27 -0
  101. data/tasks/website.rake +10 -0
  102. data/tasks/yard.rake +16 -0
  103. data/website/benchmarks.html +237 -0
  104. data/website/css/color.css +153 -0
  105. data/website/css/hacks.css +3 -0
  106. data/website/css/layout.css +179 -0
  107. data/website/css/screen.css +5 -0
  108. data/website/css/textmate.css +226 -0
  109. data/website/css/typography.css +72 -0
  110. data/website/gfx/body_bg.gif +0 -0
  111. data/website/gfx/button_bg.jpg +0 -0
  112. data/website/gfx/header_bg.jpg +0 -0
  113. data/website/gfx/header_left.jpg +0 -0
  114. data/website/gfx/header_right.jpg +0 -0
  115. data/website/gfx/nav_bg.jpg +0 -0
  116. data/website/index.html +125 -0
  117. data/website/yard/index.html +1 -0
  118. metadata +246 -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
+ attr_writer :identifier_string
13
+
14
+ # HTML 4.01 Transitional DTD
15
+ HTML_401_TRANSITIONAL = {
16
+ :core => [:class, :id, :style, :title],
17
+ :cell_halign => [:align, :char, :charoff],
18
+ :cell_valign => [:valign],
19
+ :i18n => [:dir, :lang],
20
+ :event => [:onclick, :ondblclick, :onmousedown, :onmouseup, :onmouseover,
21
+ :onmousemove, :onmouseout, :onkeypress, :onkeydown, :onkeyup],
22
+ :sloppy => [:name, :value]
23
+ }
24
+
25
+ CELLHALIGN_ATTRIBUTES = HTML_401_TRANSITIONAL[:cell_halign]
26
+ CELLVALIGN_ATTRIBUTES = HTML_401_TRANSITIONAL[:cell_valign]
27
+ BASE_ATTRIBUTES = HTML_401_TRANSITIONAL.values_at(:core, :i18n, :event, :sloppy).flatten
28
+ ATTRIBUTES = BASE_ATTRIBUTES
29
+ TAGS = []
30
+
31
+ DEFAULT_HOW = nil
32
+
33
+ # @api private
34
+ def initialize(container, *args)
35
+ self.container = container
36
+
37
+ case args.size
38
+ when 2
39
+ @conditions = { args[0] => args[1] }
40
+ when 1
41
+ if args.first.is_a? Hash
42
+ @conditions = args.first
43
+ elsif (how = self.class::DEFAULT_HOW)
44
+ @conditions = { how => args.first }
45
+ else
46
+ raise ArgumentError, "wrong number of arguments (1 for 2)"
47
+ end
48
+ when 0
49
+ @conditions = { :index => Celerity.index_offset }
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
+ def ==(other)
59
+ return false unless other.kind_of? Element
60
+ xpath == other.xpath
61
+ end
62
+
63
+ #
64
+ # Get the parent element
65
+ # @return [Celerity::Element, nil] subclass of Celerity::Element, or nil if no parent was found
66
+ #
67
+
68
+ def parent
69
+ assert_exists
70
+
71
+ obj = @object.parentNode
72
+ until element_class = Celerity::Util.htmlunit2celerity(obj.class)
73
+ return nil if obj.nil?
74
+ obj = obj.parentNode
75
+ end
76
+
77
+ element_class.new(@container, :object, obj)
78
+ end
79
+
80
+ #
81
+ # Sets the focus to this element.
82
+ #
83
+
84
+ def focus
85
+ assert_exists
86
+ @object.focus
87
+ end
88
+
89
+ #
90
+ # Returns true if this element is the currently focused element
91
+ #
92
+ # Celerity-specific.
93
+ #
94
+
95
+ def focused?
96
+ assert_exists
97
+ @object == browser.page.getFocusedElement
98
+ end
99
+
100
+ #
101
+ # Fires the given event for this element
102
+ #
103
+
104
+ def fire_event(event_name)
105
+ assert_exists
106
+ @object.fireEvent(event_name.sub(/^on/, ''))
107
+ end
108
+
109
+ #
110
+ # Used internally. Find the element on the page.
111
+ # @api private
112
+ #
113
+
114
+ def locate
115
+ @object = ElementLocator.new(@container, self.class).find_by_conditions(@conditions)
116
+ end
117
+
118
+ #
119
+ # Returns the HtmlUnit object backing this element
120
+ #
121
+
122
+ def object
123
+ @object || locate
124
+ end
125
+
126
+ #
127
+ # Returns a JavaScript object representing the receiver
128
+ #
129
+ # @api internal - subject to change
130
+ #
131
+
132
+ def javascript_object
133
+ assert_exists
134
+ @object.getScriptObject
135
+ end
136
+
137
+ #
138
+ # @return [String] A string representation of the element.
139
+ #
140
+
141
+ def to_s
142
+ assert_exists
143
+ Celerity::Util.create_string @object
144
+ end
145
+
146
+ #
147
+ # @param [String, #to_s] The attribute.
148
+ # @return [String] The value of the given attribute.
149
+ #
150
+
151
+ def attribute_value(attribute)
152
+ assert_exists
153
+ @object.getAttribute attribute.to_s
154
+ end
155
+
156
+ #
157
+ # Check if the element is visible to the user or not.
158
+ # Note that this only takes the _style attribute_ of the element (and
159
+ # its parents) into account - styles from applied CSS is not considered.
160
+ #
161
+ # @return [boolean]
162
+ #
163
+
164
+ def visible?
165
+ assert_exists
166
+ @object.isDisplayed
167
+ end
168
+
169
+ #
170
+ # Used internally to ensure the element actually exists.
171
+ #
172
+ # @raise [Celerity::Exception::UnknownObjectException] if the element can't be found.
173
+ # @api private
174
+ #
175
+
176
+ def assert_exists
177
+ locate unless @object
178
+ unless @object
179
+ raise UnknownObjectException, "Unable to locate #{self.class.name[/::(.*)$/, 1]}, using #{identifier_string}"
180
+ end
181
+ end
182
+
183
+ #
184
+ # Checks if the element exists.
185
+ # @return [true, false]
186
+ #
187
+
188
+ def exists?
189
+ assert_exists
190
+ true
191
+ rescue UnknownObjectException, UnknownFrameException
192
+ false
193
+ end
194
+ alias_method :exist?, :exists?
195
+
196
+ #
197
+ # Return a text representation of the element as it would appear in a browser.
198
+ #
199
+ # @see inner_text
200
+ # @return [String]
201
+ #
202
+
203
+ def text
204
+ assert_exists
205
+ @object.asText.strip # this must behave like ElementLocator
206
+ end
207
+
208
+ #
209
+ # Return the text content of this DOM node, disregarding its visibility.
210
+ #
211
+ # (Celerity-specific?)
212
+ #
213
+ # @see text
214
+ # @return [String]
215
+ #
216
+
217
+ def inner_text
218
+ assert_exists
219
+ Celerity::Util.normalize_text @object.getTextContent
220
+ end
221
+
222
+ #
223
+ # @return [String] The normative XML representation of the element (including children).
224
+ #
225
+
226
+ def to_xml
227
+ assert_exists
228
+ @object.asXml
229
+ end
230
+ alias_method :asXml, :to_xml
231
+ alias_method :as_xml, :to_xml
232
+ alias_method :html, :to_xml
233
+
234
+ #
235
+ # @return [String] A string representation of the element's attributes.
236
+ #
237
+
238
+ def attribute_string
239
+ assert_exists
240
+
241
+ result = ''
242
+ @object.getAttributes.each do |attribute|
243
+ result << %Q{#{attribute.getName}="#{attribute.getValue}"}
244
+ end
245
+
246
+ result
247
+ end
248
+
249
+ #
250
+ # return the canonical xpath for this element (Celerity-specific)
251
+ #
252
+
253
+ def xpath
254
+ assert_exists
255
+ @object.getCanonicalXPath
256
+ end
257
+
258
+ #
259
+ # Dynamically get element attributes.
260
+ #
261
+ # @see ATTRIBUTES constant for a list of valid methods for a given element.
262
+ #
263
+ # @return [String] The resulting attribute.
264
+ # @raise [NoMethodError] if the element doesn't support this attribute.
265
+ #
266
+
267
+ def method_missing(meth, *args, &blk)
268
+ assert_exists
269
+
270
+ meth = selector_to_attribute(meth)
271
+
272
+ if self.class::ATTRIBUTES.include?(meth) || (self.class == Element && @object.hasAttribute(meth.to_s))
273
+ return @object.getAttribute(meth.to_s)
274
+ end
275
+ Log.warn "Element\#method_missing calling super with #{meth.inspect}"
276
+ super
277
+ end
278
+
279
+ def methods(*args)
280
+ ms = super
281
+ ms += self.class::ATTRIBUTES.map { |e| e.to_s }
282
+ ms.sort
283
+ end
284
+
285
+ def respond_to?(meth, include_private = false)
286
+ meth = selector_to_attribute(meth)
287
+ return true if self.class::ATTRIBUTES.include?(meth)
288
+ super
289
+ end
290
+
291
+ private
292
+
293
+ def identifier_string
294
+ @identifier_string ||= (
295
+ if @conditions.size == 1
296
+ how, what = @conditions.to_a.first
297
+ "#{how.inspect} and #{what.inspect}"
298
+ else
299
+ @conditions.inspect
300
+ end
301
+ )
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,115 @@
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
+ # Returns true if the collection is empty.
37
+ #
38
+
39
+ def empty?
40
+ length == 0
41
+ end
42
+
43
+ #
44
+ # @yieldparam [Celerity::Element] element Iterate through the elements in this collection.
45
+ #
46
+
47
+ def each
48
+ if @elements
49
+ @elements.each { |e| yield(element_class.new(@container, :object, e)) }
50
+ else
51
+ 0.upto(@length - 1) { |i| yield iterator_object(i) }
52
+ end
53
+
54
+ @length
55
+ end
56
+
57
+ #
58
+ # Get the element at the given index.
59
+ # By default, this is 1-indexed to keep compatibility with Watir.
60
+ #
61
+ # Also note that because of Watir's lazy loading, this will return an Element
62
+ # instance even if the index is out of bounds.
63
+ #
64
+ # @param [Fixnum] n Index of wanted element, 1-indexed unless Celerity.index_offset is changed.
65
+ # @return [Celerity::Element] Returns a subclass of Celerity::Element
66
+ #
67
+
68
+ def [](n)
69
+ if @elements && @elements[n - Celerity.index_offset]
70
+ element_class.new(@container, :object, @elements[n - Celerity.index_offset])
71
+ else
72
+ iterator_object(n - Celerity.index_offset)
73
+ end
74
+ end
75
+
76
+ #
77
+ # Get the first element in this collection. (Celerity-specific)
78
+ #
79
+ # @return [Celerity::Element] Returns a subclass of Celerity::Element
80
+ #
81
+
82
+ def first
83
+ self[Celerity.index_offset]
84
+ end
85
+
86
+ #
87
+ # Get the last element in this collection. (Celerity-specific)
88
+ #
89
+ # @return [Celerity::Element] Returns a subclass of Celerity::Element
90
+ #
91
+
92
+ def last
93
+ self[Celerity.index_offset - 1]
94
+ end
95
+
96
+ #
97
+ # Note: This can be quite useful in irb:
98
+ #
99
+ # puts browser.text_fields
100
+ #
101
+ # @return [String] A string representation of all elements in this collection.
102
+ #
103
+
104
+ def to_s
105
+ map { |e| e.to_s }.join("\n")
106
+ end
107
+
108
+ private
109
+
110
+ def iterator_object(i)
111
+ element_class.new(@container, :index, i + Celerity.index_offset)
112
+ end
113
+
114
+ end # ElementCollection
115
+ end # Celerity