operawatir 0.4.1.pre5-jruby → 0.4.1.pre6-jruby

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/AUTHORS +1 -0
  2. data/CHANGES +170 -3
  3. data/README.md +30 -27
  4. data/VERSION +1 -1
  5. data/bin/desktopwatir +19 -16
  6. data/bin/operawatir +4 -4
  7. data/lib/operadriver/client-combined-nodeps.jar +0 -0
  8. data/lib/operadriver/webdriver-opera.jar +0 -0
  9. data/lib/operawatir/browser.rb +1 -2
  10. data/lib/operawatir/collection.rb +1 -1
  11. data/lib/operawatir/compat/collection.rb +13 -0
  12. data/lib/operawatir/compat/element.rb +57 -15
  13. data/lib/operawatir/compat/window.rb +41 -0
  14. data/lib/operawatir/desktop_browser.rb +26 -9
  15. data/lib/operawatir/desktop_container.rb +82 -29
  16. data/lib/operawatir/element.rb +48 -24
  17. data/lib/operawatir/keys.rb +18 -25
  18. data/lib/operawatir/preferences.rb +223 -6
  19. data/lib/operawatir/quickwidgets/quick_button.rb +8 -2
  20. data/lib/operawatir/quickwidgets/quick_checkbox.rb +4 -4
  21. data/lib/operawatir/quickwidgets/quick_editfield.rb +1 -1
  22. data/lib/operawatir/quickwidgets/quick_find.rb +11 -0
  23. data/lib/operawatir/quickwidgets/quick_griditem.rb +11 -0
  24. data/lib/operawatir/quickwidgets/quick_gridlayout.rb +11 -0
  25. data/lib/operawatir/quickwidgets/quick_searchfield.rb +5 -1
  26. data/lib/operawatir/quickwidgets/quick_tab.rb +0 -1
  27. data/lib/operawatir/quickwidgets/quick_treeitem.rb +22 -1
  28. data/lib/operawatir/quickwidgets/quick_widget.rb +61 -22
  29. data/lib/operawatir/quickwidgets/quick_window.rb +26 -0
  30. data/lib/operawatir/quickwidgets.rb +2 -1
  31. data/lib/operawatir/window.rb +36 -25
  32. data/lib/operawatir.rb +1 -1
  33. data/operawatir.gemspec +38 -5
  34. data/spec/operawatir/core/element_spec.rb +5 -0
  35. data/spec/operawatir/core/window_spec.rb +42 -0
  36. data/spec/operawatir/desktop/desktopbrowser_spec.rb +16 -0
  37. data/spec/operawatir/desktop/quickaddressfield_spec.rb +15 -3
  38. data/spec/operawatir/desktop/quickbutton_spec.rb +234 -20
  39. data/spec/operawatir/desktop/quickcheckbox_spec.rb +36 -0
  40. data/spec/operawatir/desktop/quickdialogtab_spec.rb +30 -0
  41. data/spec/operawatir/desktop/quickdropdown_spec.rb +39 -0
  42. data/spec/operawatir/desktop/quickeditfield_spec.rb +51 -0
  43. data/spec/operawatir/desktop/quickfind_spec.rb +30 -0
  44. data/spec/operawatir/desktop/quickgriditem_spec.rb +16 -0
  45. data/spec/operawatir/desktop/quickgridlayout_spec.rb +15 -0
  46. data/spec/operawatir/desktop/quicklabel_spec.rb +28 -0
  47. data/spec/operawatir/desktop/quickradiobutton_spec.rb +24 -0
  48. data/spec/operawatir/desktop/quicksearchfield_spec.rb +26 -0
  49. data/spec/operawatir/desktop/quicktab_spec.rb +86 -0
  50. data/spec/operawatir/desktop/quickthumbnail_spec.rb +37 -0
  51. data/spec/operawatir/desktop/quicktreeitem_spec.rb +135 -0
  52. data/spec/operawatir/desktop/quicktreeview_spec.rb +30 -0
  53. data/spec/operawatir/desktop/quickwidget_spec.rb +52 -11
  54. data/spec/operawatir/desktop/quickwindow_spec.rb +11 -0
  55. data/spec/operawatir/desktop/shared/shared.rb +100 -10
  56. data/spec/operawatir/fixtures/browsers.svg +367 -0
  57. data/spec/operawatir/fixtures/frames.html +13 -0
  58. data/spec/watir2/select_list_spec.rb +84 -71
  59. metadata +37 -4
  60. data/lib/operadriver/selenium-common.jar +0 -0
@@ -35,9 +35,9 @@ class OperaWatir::Element
35
35
  !attr(name).nil?
36
36
  end
37
37
 
38
- def method_missing(name, *args, &blk)
39
- if !(block_given? || !args.empty?) && has_attribute?(name)
40
- attr(name)
38
+ def method_missing(method, *args, &blk)
39
+ if !(block_given? || !args.empty?) && has_attribute?(method)
40
+ attr(method)
41
41
  else
42
42
  super
43
43
  end
@@ -59,6 +59,8 @@ class OperaWatir::Element
59
59
  def_delegator :node, :isEnabled, :enabled?
60
60
  def_delegator :node, :isSelected, :checked?
61
61
 
62
+ def_delegator :node, :setSelected, :select
63
+
62
64
  def_delegator :node, :isSelected, :selected?
63
65
 
64
66
  def_delegator :node, :toggle, :toggle_check!
@@ -66,8 +68,6 @@ class OperaWatir::Element
66
68
  def_delegator :node, :getText, :text
67
69
  def_delegator :node, :getHTML, :html
68
70
 
69
- alias_method :to_s, :text
70
-
71
71
  def_delegator :node, :getElementName, :tag_name
72
72
  def_delegator :node, :clear, :clear
73
73
 
@@ -77,32 +77,54 @@ class OperaWatir::Element
77
77
  #
78
78
  # @return [String] Value of the element.
79
79
  def value
80
+ =begin
80
81
  if tag_name =~ /input|textarea|select/i
81
- node.getValue
82
+ node.getValue #
83
+ elsif tag_name =~ /button/i
84
+ text # getVisibleContents
82
85
  else
83
- attr :value
86
+ attr :value # attribute @value
84
87
  end
88
+ =end
89
+
90
+ node.getValue
91
+ end
92
+
93
+ #
94
+ # Does the element exist in the DOM?
95
+ #
96
+ # @return [Boolean] True if element exists, false otherwise.
97
+ #
98
+
99
+ def exist?
100
+ !!!tag_name.empty?
85
101
  end
86
102
 
103
+ alias_method :exists?, :exist? # LOL Ruby
104
+
87
105
  def disabled?
88
106
  !enabled?
89
107
  end
90
108
 
91
109
  def check!
92
- if not selected?
93
- node.toggle
94
- end
110
+ node.toggle if not selected?
95
111
  end
96
112
 
97
113
  def uncheck!
98
- if selected?
99
- node.toggle
100
- end
114
+ node.toggle if selected?
101
115
  end
102
116
 
103
117
 
104
118
  # Events
105
119
 
120
+ #
121
+ # Clicks on the top left of the element, or the given x,y offset
122
+ # relative to the element.
123
+ #
124
+ # @param [Integer] x The offset from the top left of the element.
125
+ # @param [Integer] y The offset from the top of the element.
126
+ #
127
+
106
128
  def click(x=0, y=0)
107
129
  node.click(x.to_i, y.to_i)
108
130
  end
@@ -138,9 +160,13 @@ class OperaWatir::Element
138
160
  def_delegator :node, :submit, :submit!
139
161
 
140
162
  def text=(input)
141
- # Focus before typing
142
- clear unless value.empty?
143
- node.sendKeys(input.to_s.split('').to_java(:string))
163
+ if attr(:type) =~ /checkbox/i
164
+ toggle_check! unless checked?
165
+ else
166
+ # Focus before typing
167
+ clear unless value.empty?
168
+ node.sendKeys(input.to_s.split('').to_java(:string))
169
+ end
144
170
  end
145
171
 
146
172
  alias_method :set, :text=
@@ -150,6 +176,8 @@ class OperaWatir::Element
150
176
  raise Exceptions::NotImplementedException
151
177
  end
152
178
 
179
+ # FIXME: This should be migrated to using browserbot.js, as watir-webdriver
180
+ # is using.
153
181
  def fire_event(event, x = 0, y = 0)
154
182
  loc = location
155
183
  x += loc[:x]
@@ -162,19 +190,15 @@ class OperaWatir::Element
162
190
  event = $1 if $1
163
191
  event = event.downcase.to_sym
164
192
 
165
- # TODO Should this be moved to OperaDriver instead?
166
193
  case event
167
- when :abort, :blur, :change, :error, :focus, :load, :reset,
168
- :resize, :scroll, :submit, :unload
194
+ when :abort, :blur, :change, :error, :focus, :load, :reset, :resize, :scroll, :submit, :unload
169
195
  type = 'HTMLEvents';
170
196
  init = "initEvent(\"#{event.to_s}\", true, true)"
171
- when :click, :dblclick, :mousedown, :mousemove, :mouseout,
172
- :mouseover, :mouseup
197
+ when :click, :dblclick, :mousedown, :mousemove, :mouseout, :mouseover, :mouseup
173
198
  type = 'MouseEvents'
174
199
  init = "initMouseEvent(\"#{event.to_s}\", true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null)"
175
200
  else
176
- raise Exceptions::NotImplementedException,
177
- "Event on#{event} is not a valid ECMAscript event for OperaWatir."
201
+ raise Exceptions::NotImplementedException, "Event on#{event} is not a valid ECMAscript event for OperaWatir."
178
202
  end
179
203
 
180
204
  script = "var event = document.createEvent(\"#{type}\"); " +
@@ -185,7 +209,7 @@ class OperaWatir::Element
185
209
  end
186
210
 
187
211
  def visible?
188
- node.isVisible()
212
+ node.isVisible
189
213
  end
190
214
 
191
215
  # UI
@@ -7,42 +7,27 @@ class OperaWatir::Keys
7
7
  self.browser = browser
8
8
  end
9
9
 
10
- # Holds down supplied arbitrary list of keys indefinitely.
11
10
  #
12
- # @param [Symbol, String] *args Arbitrary list of symbols
13
- # (modification keys) or strings (regular keys) to be pressed
14
- # down.
11
+ # Holds down supplied arbitrary list of keys indefinitely.
15
12
  #
13
+ # @param [Symbol, String] *args Arbitrary list of symbols (modification)
14
+ # keys or strings (regular keys) to be
15
+ # pressed down.
16
+ #
16
17
  # @example
18
+ #
17
19
  # browser.keys.down 'a'
18
20
  # browser.keys.down 'a', :right
19
- #
21
+ #
20
22
  # @seealso up
21
23
  # @seealso send
24
+ #
22
25
 
23
-
24
-
25
- =begin
26
-
27
- Holds down supplied arbitrary list of keys indefinitely.
28
-
29
- @param [Symbol, String] *args Arbitrary list of symbols (modification)
30
- keys or strings (regular keys) to be
31
- pressed down.
32
-
33
- @example
34
-
35
- browser.keys.down 'a'
36
- browser.keys.down 'a', :right
37
-
38
- @seealso up
39
- @seealso send
40
-
41
- =end
42
26
  def down(*args)
43
27
  args.each { |key| driver.keyDown(key) }
44
28
  end
45
29
 
30
+ #
46
31
  # Depresses supplied arbitrary list of keys.
47
32
  #
48
33
  # @param [Symbol, String] *args Arbitrary list of symbols
@@ -52,19 +37,25 @@ class OperaWatir::Keys
52
37
  # browser.keys.up 'a', :right
53
38
  #
54
39
  # @seealso release
40
+ #
41
+
55
42
  def up(*args)
56
43
  args.each { |key| driver.keyUp(key) }
57
44
  end
58
45
 
46
+ #
59
47
  # Releases all pressed down keys.
60
48
  #
61
49
  # @example
62
50
  # browser.keys.down :control, :shift, 'a'
63
51
  # browser.keys.release
52
+ #
53
+
64
54
  def release
65
55
  driver.releaseKeys
66
56
  end
67
57
 
58
+ #
68
59
  # Presses an arbitrary list of keys or key combinations. Provided
69
60
  # arguments are performed in sequence.
70
61
  #
@@ -90,6 +81,8 @@ class OperaWatir::Keys
90
81
  # browser.keys.send :control
91
82
  # browser.keys.send [:control, 'a']
92
83
  # browser.keys.send [:control, 'a'], :backspace
84
+ #
85
+
93
86
  def send(*list) # TODO rename?
94
87
  list.each do |item|
95
88
  case item
@@ -102,9 +95,9 @@ class OperaWatir::Keys
102
95
  down key
103
96
  else
104
97
  key key
105
- release
106
98
  end
107
99
  end
100
+ release
108
101
  when Symbol
109
102
  key item
110
103
  else
@@ -1,13 +1,104 @@
1
1
  class String
2
+
3
+ #
4
+ # Translates an Opera preferences key string into a Ruby method name.
5
+ # It will remove tabs and spaces at beginning of string, replace
6
+ # further spaces with an underscore and make the string lower-case.
7
+ #
8
+ # The method extends the String object and can be called as a regular
9
+ # method on any string in Ruby.
10
+ #
11
+
2
12
  def methodize
3
13
  self.gsub(/^\\t(\s+)/, '').gsub(/\s+/, '_').downcase
4
14
  end
5
15
 
16
+ #
17
+ # Translates a previously keyized Opera preferences method string into
18
+ # an Opera preferences key string. This is done by replacing
19
+ # underscores with spaces and capitalizing each word in the string.
20
+ #
21
+ # The method extends the String object and can be called as a regular
22
+ # method on any string in Ruby.
23
+ #
24
+
6
25
  def keyize
7
26
  self.gsub(/_/, ' ').gsub(/\b('?[a-z])/) { $1.capitalize }
8
27
  end
9
28
  end
10
29
 
30
+ #
31
+ # OperaWatir::Preferences enables you to access the browser preferences
32
+ # in the Opera web browser.
33
+ #
34
+ # @example
35
+ #
36
+ # The Preferences object is created automatically when creating a new
37
+ # Browser object and is exposed as an interface on that object:
38
+ #
39
+ # browser.preferences
40
+ # => <OperaWatir::Preferences>
41
+ #
42
+ # You can interact with this object as you would with any Ruby object.
43
+ # Sections and entries are exposed as Rubyized method names, which
44
+ # means that you can access them like this:
45
+ #
46
+ # browser.preferences.interface_colors # a section
47
+ # browser.preferences.interface_colors.background # an entry
48
+ #
49
+ # Over the preference object itself or over a section you can also use
50
+ # built-in Ruby convenience methods such as:
51
+ #
52
+ # browser.preferences.first # first section
53
+ # browser.preferences.interface_colors # first entry in section
54
+ # browser.preferences.size # number of sections
55
+ #
56
+ # This is a full list of available convenience methods:
57
+ #
58
+ # * []
59
+ # * each
60
+ # * length
61
+ # * size
62
+ # * first
63
+ # * last
64
+ # * empty?
65
+ #
66
+ # Essentially, the preference and section objects are collections
67
+ # (kind of like arrays) that allows you to also iterate over them:
68
+ #
69
+ # browser.preferences.each_with_index do |section, index|
70
+ # puts "Section No. #{index} is called `#{section.key}'"
71
+ # end
72
+ #
73
+ # browser.preferences.interface_colors.each { |e| e.value = '#cccccc' }
74
+ #
75
+ # browser.preferences.interface_colors[5].value
76
+ # => '#cccccc'
77
+ #
78
+ # On each section, the follow getters are available in addition to the
79
+ # convenience methods mentioned above:
80
+ #
81
+ # * section? # Returns true/false based on whether it's a section
82
+ # * exists? # Returns true/false based on whether it exists
83
+ #
84
+ # On each entry, the following getters and setters are available in
85
+ # addition to the convenience methods mentioned above:
86
+ #
87
+ # * value # Returns current preference's value
88
+ # * value= # Sets current preference's value to provided string
89
+ # * default # Returns current preference's default
90
+ # * default! # Sets current preference to its default
91
+ #
92
+ # This means you can do crazy stuff like resetting all the preferences
93
+ # in `opera:config` to their standard value like this:
94
+ #
95
+ # browser.preferences.each do |section|
96
+ # section.each do |entry|
97
+ # entry.default!
98
+ # end
99
+ # end
100
+ #
101
+
11
102
  class OperaWatir::Preferences
12
103
  extend Forwardable
13
104
  include Enumerable
@@ -27,10 +118,40 @@ class OperaWatir::Preferences
27
118
  'User Agent', 'User Display Mode', 'User Prefs', 'Visited Link',
28
119
  'Visited Link', 'Web Server', 'Widgets', 'Workspace']
29
120
 
121
+ #
122
+ # The OperaWatir::Preferences object is created automatically when you
123
+ # create an OperaWatir::Browser object, and is available as
124
+ # Browser#prefrences.
125
+ #
126
+ # @example
127
+ #
128
+ # browser.preferences.method_name
129
+ #
130
+ # @param [Object] browser An OperaWatir::Browser object.
131
+ #
132
+
30
133
  def initialize(browser)
31
134
  self.browser, self.driver = browser, browser.driver
32
135
  end
33
136
 
137
+ #
138
+ # When calling Preferences#any_method_name, the `any_method_name` will
139
+ # be caught by this method.
140
+ #
141
+ # This is the standard way of looking up sections. `any_method_name`
142
+ # should be replaced by a methodized version of the section as it
143
+ # appears in the Opera preferences list which you can find at
144
+ # `opera:config`.
145
+ #
146
+ # @example
147
+ #
148
+ # browser.preferences.interface_colors
149
+ # # will return section “Interface Colors”
150
+ #
151
+ # @param section Method to look up in preferences.
152
+ # @return [Object] A Preferences::Entry (section) object.
153
+ #
154
+
34
155
  def method_missing(section)
35
156
  if _prefs.any? { |s| s.method == section.to_s }
36
157
  _prefs.find { |s| s.method == section.to_s }
@@ -48,6 +169,15 @@ class OperaWatir::Preferences
48
169
  :last,
49
170
  :empty?
50
171
 
172
+ #
173
+ # Retrieves a human-readable list of Opera preferences available.
174
+ # This is used for convenience and should never be parsed. Consider
175
+ # using the built-in Ruby iterator #each (with friends) or
176
+ # Preferences#to_a for that.
177
+ #
178
+ # @return [String] List of preferences.
179
+ #
180
+
51
181
  def to_s
52
182
  text = ''
53
183
 
@@ -65,10 +195,26 @@ class OperaWatir::Preferences
65
195
  text
66
196
  end
67
197
 
198
+ #
199
+ # Returns a list of all preferences in array form. This can be used
200
+ # for external parsing. If you wish to manipulate or iterate through
201
+ # the list of preferences consider using the built-in Ruby iterator
202
+ # #each (with friends).
203
+ #
204
+ # @return [Array] List of preferences.
205
+ #
206
+
68
207
  def to_a
69
208
  _prefs.dup
70
209
  end
71
210
 
211
+ #
212
+ # Checks if any preferences exists in your Opera build. If true,
213
+ # there are preferences available, false otherwise.
214
+ #
215
+ # @return [Boolean] Whether any preferences exists.
216
+ #
217
+
72
218
  def exists?
73
219
  !_prefs.empty?
74
220
  end
@@ -88,6 +234,16 @@ private
88
234
 
89
235
  attr_accessor :parent, :method, :key, :value, :type, :default, :driver
90
236
 
237
+ #
238
+ # OperaWatir::Preferences::Entry is the object that represents
239
+ # either a section or a section's entry.
240
+ #
241
+ # It's created automatically when you query for entries using the
242
+ # Preference object itself.
243
+ #
244
+ # @return [Object] An OperaWatir::Preferences::Entry object.
245
+ #
246
+
91
247
  def initialize(parent, method, key=nil, type=nil)
92
248
  self.parent = parent
93
249
  self.method = method.to_s
@@ -96,22 +252,54 @@ private
96
252
  self.driver = parent.driver
97
253
  end
98
254
 
99
- def method_missing(key)
100
- key = key.to_s
255
+ #
256
+ # When calling Preferences::Entry#any_method_name, the
257
+ # `any_method_name` will be caught by this method.
258
+ #
259
+ # This is the standard way of looking up preference entries.
260
+ # `any_method_name` should be replaced by a methodized version of
261
+ # the entry as it appears in the Opera preferences list which you
262
+ # can find at `opera:config`.
263
+ #
264
+ # @example
265
+ #
266
+ # browser.preferences.interface_colors.background
267
+ # # will return the “Background” entry in section “Interface Colors”
268
+ #
269
+ # @param method Method to look up in section.
270
+ # @return [Object] A Preferences::Entry (entry) object.
271
+ #
272
+
273
+ def method_missing(method)
274
+ method = method.to_s
101
275
 
102
- if _keys.any? { |k| k.method == key }
103
- _keys.find { |k| k.method == key }
276
+ if _keys.any? { |k| k.method == method }
277
+ _keys.find { |k| k.method == method }
104
278
  else
105
- _keys << Entry.new(self, key)
279
+ _keys << Entry.new(self, method)
106
280
  _keys.last
107
281
  end
108
282
  end
109
283
 
284
+ #
285
+ # Returns the value of an entry in a section. Note that it's not
286
+ # possible to retrieve the value for sections.
287
+ #
288
+ # @return [String] Value of the entry.
289
+ #
290
+
110
291
  def value
111
292
  raise OperaWatir::Exceptions::PreferencesException, 'Sections do not have values' if section?
112
293
  @value ||= driver.getPref(parent.key, key)
113
294
  end
114
295
 
296
+ #
297
+ # Sets the entry's value to the specified string. Note that it's
298
+ # not possible to set a section's value.
299
+ #
300
+ # @param [String] value Value you wish to set for the entry.
301
+ #
302
+
115
303
  def value=(value)
116
304
  raise OperaWatir::Exceptions::PreferencesException, 'Sections cannot have values' if section?
117
305
  value = value.truthy? ? '1' : '0' if type.include?('Boolean')
@@ -119,19 +307,48 @@ private
119
307
  @value = value
120
308
  end
121
309
 
310
+ #
311
+ # Returns entry's default value. Note that it's not possible to
312
+ # return a section's default value.
313
+ #
314
+ # @return [String] The default value of the entry.
315
+ #
316
+
122
317
  def default
123
318
  raise OperaWatir::Exceptions::PreferencesException, 'Sections do not have defaults' if section?
124
319
  @default ||= driver.getDefaultPref parent.key, key
125
320
  end
126
321
 
322
+ #
323
+ # Returns and sets the default value of the entry. Note that it's
324
+ # not possible to return and set a section's default value.
325
+ #
326
+ # @return [String] The default value of the entry.
327
+ #
328
+
127
329
  def default!
128
330
  self.value=(default) # WTF? Bug in Ruby?
129
331
  end
130
332
 
333
+ #
334
+ # Is the current node a section?
335
+ #
336
+ # @return [Boolean] True/false based on whether you're
337
+ # interacting with a section or entry.
338
+ #
339
+
131
340
  def section?
132
341
  parent.kind_of? OperaWatir::Preferences
133
342
  end
134
343
 
344
+ #
345
+ # Does this entry/section exist?
346
+ #
347
+ # @return [Boolean] True/false based on whether the method you
348
+ # are attempting to access exists as a
349
+ # preference entry/section.
350
+ #
351
+
135
352
  def exists?
136
353
  section? ? SECTIONS.include?(key) : !type.empty?
137
354
  end
@@ -165,7 +382,7 @@ private
165
382
  p = p.to_s
166
383
 
167
384
  p =~ /^key: \"([a-zA-Z0-9\(\)\\\.\-\s]*)\"$/
168
- key = $1
385
+ key = $1.to_s
169
386
 
170
387
  p =~ /^type: ([A-Z]+)$/
171
388
  type = $1.to_s.capitalize