watir 2.0.4 → 3.0.0.rc1

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.
@@ -42,22 +42,22 @@ module Watir
42
42
  return @o.invoke("fileCreatedDate")
43
43
  end
44
44
 
45
- # this method returns the filesize of the image
45
+ # this method returns the filesize of the image, as an int
46
46
  def file_size
47
47
  assert_exists
48
- return @o.invoke("fileSize").to_s
48
+ return @o.invoke("fileSize").to_i
49
49
  end
50
50
 
51
- # returns the width in pixels of the image, as a string
51
+ # returns the width in pixels of the image, as an int
52
52
  def width
53
53
  assert_exists
54
- return @o.invoke("width").to_s
54
+ return @o.invoke("width").to_i
55
55
  end
56
56
 
57
- # returns the height in pixels of the image, as a string
57
+ # returns the height in pixels of the image, as an int
58
58
  def height
59
59
  assert_exists
60
- return @o.invoke("height").to_s
60
+ return @o.invoke("height").to_i
61
61
  end
62
62
 
63
63
  # This method attempts to find out if the image was actually loaded by the web browser.
@@ -103,22 +103,19 @@ module Watir
103
103
  def save(path)
104
104
  @container.goto(src)
105
105
  begin
106
- thrd = fill_save_image_dialog(path)
106
+ fill_save_image_dialog(path)
107
107
  @container.document.execCommand("SaveAs")
108
- thrd.join(5)
109
108
  ensure
110
109
  @container.back
111
110
  end
112
111
  end
113
112
 
114
113
  def fill_save_image_dialog(path)
115
- command = "require 'rautomation';" <<
114
+ command = "require 'rubygems';require 'rautomation';" <<
116
115
  "window=::RAutomation::Window.new(:title => 'Save Picture');" <<
117
- "window.text_field(:class => 'Edit', :index => 0).set('#{path}');" <<
116
+ "window.text_field(:class => 'Edit', :index => 0).set('#{path.gsub(File::SEPARATOR, File::ALT_SEPARATOR)}');" <<
118
117
  "window.button(:value => '&Save').click"
119
- Thread.new do
120
- system("ruby -e \"#{command}\"")
121
- end
118
+ IO.popen("ruby -e \"#{command}\"")
122
119
  end
123
120
  private :fill_save_image_dialog
124
121
 
@@ -2,9 +2,9 @@ module Watir
2
2
 
3
3
  class InputElement < Element #:nodoc:all
4
4
  def locate
5
- locator_or_element = @container.input_element_locator(@how, @what, self.class::INPUT_TYPES, self.class)
6
- @o = locator_or_element.is_a?(WIN32OLE) ? locator_or_element : locator_or_element.locate
5
+ @o = @container.locator_for(InputElementLocator, self.class::INPUT_TYPES, @how, @what, self.class).locate
7
6
  end
7
+
8
8
  def initialize(container, how, what)
9
9
  set_container container
10
10
  @how = how
@@ -22,199 +22,120 @@ module Watir
22
22
  class SelectList < InputElement
23
23
  #:stopdoc:
24
24
  INPUT_TYPES = ["select-one", "select-multiple"]
25
- #exposed to Option class
26
- attr_accessor :o
27
25
  #:startdoc:
28
26
 
27
+ def_wrap :multiple?, :multiple
28
+
29
29
  # This method clears the selected items in the select box
30
30
  def clear
31
- assert_exists
32
- highlight(:set)
33
- wait = false
34
- @o.each do |selectBoxItem|
35
- if selectBoxItem.selected
36
- selectBoxItem.selected = false
37
- wait = true
38
- end
31
+ perform_action do
32
+ options.each {|option| option.clear}
39
33
  end
40
- @container.wait if wait
41
- highlight(:clear)
42
34
  end
43
35
 
44
-
45
36
  # This method selects an item, or items in a select box, by text.
46
37
  # Raises NoValueFoundException if the specified value is not found.
47
38
  # * item - the thing to select, string or reg exp
48
39
  def select(item)
49
- select_item_in_select_list(:text, item)
40
+ matching_options = []
41
+ perform_action do
42
+ matching_options = matching_items_in_select_list(:text, item) +
43
+ matching_items_in_select_list(:label, item) +
44
+ matching_items_in_select_list(:value, item)
45
+ raise NoValueFoundException, "No option with :text, :label or :value of #{item.inspect} in this select element" if matching_options.empty?
46
+ matching_options.each(&:select)
47
+ end
48
+ matching_options.first.text
50
49
  end
51
- alias :set :select
52
50
 
53
51
  # Selects an item, or items in a select box, by value.
54
- # Raises NoValueFoundException if the specified value is not found.
55
- # * item - the value of the thing to select, string, reg exp
52
+ # Raises NoValueFoundException if the specified value is not found.
53
+ # * item - the value of the thing to select, string or reg exp
56
54
  def select_value(item)
57
- select_item_in_select_list(:value, item)
58
- end
59
-
60
- # BUG: Should be private
61
- # Selects something from the select box
62
- # * name - symbol :value or :text - how we find an item in the select box
63
- # * item - string or reg exp - what we are looking for
64
- def select_item_in_select_list(attribute, value) #:nodoc:
65
- assert_exists
66
- highlight(:set)
67
- found = false
68
-
69
- value = value.to_s unless [Regexp, String].any? { |e| value.kind_of? e }
70
-
71
- @container.log "Setting box #{@o.name} to #{attribute.inspect} => #{value.inspect}"
72
- @o.each do |option| # items in the list
73
- if value.matches(option.invoke(attribute.to_s))
74
- if option.selected
75
- found = true
76
- break
77
- else
78
- option.selected = true
79
- dispatch_event("onChange")
80
- @container.wait
81
- found = true
82
- break
83
- end
84
- end
85
- end
86
-
87
- unless found
88
- raise NoValueFoundException, "No option with #{attribute.inspect} of #{value.inspect} in this select element"
89
- end
90
- highlight(:clear)
91
- end
92
-
93
- # Returns array of all text items displayed in a select box
94
- # An empty array is returned if the select box has no contents.
95
- # Raises UnknownObjectException if the select box is not found
96
- def options
97
- assert_exists
98
- @container.log "There are #{@o.length} items"
99
- returnArray = []
100
- @o.each { |thisItem| returnArray << thisItem.text }
101
- return returnArray
55
+ matching_options = matching_items_in_select_list(:value, item)
56
+ raise NoValueFoundException, "No option with :value of #{item.inspect} in this select element" if matching_options.empty?
57
+ matching_options.each(&:select)
58
+ matching_options.first.value
102
59
  end
103
60
 
104
61
  # Returns array of the selected text items in a select box
105
62
  # Raises UnknownObjectException if the select box is not found.
106
63
  def selected_options
107
- assert_exists
108
- returnArray = []
109
- @container.log "There are #{@o.length} items"
110
- @o.each do |thisItem|
111
- if thisItem.selected
112
- @container.log "Item (#{thisItem.text}) is selected"
113
- returnArray << thisItem.text
114
- end
115
- end
116
- return returnArray
64
+ options.select(&:selected?)
117
65
  end
118
66
 
119
67
  # Does the SelectList include the specified option (text)?
120
68
  def include? text_or_regexp
121
- getAllContents.grep(text_or_regexp).size > 0
69
+ !options.map(&:text).grep(text_or_regexp).empty?
122
70
  end
123
71
 
124
72
  # Is the specified option (text) selected? Raises exception of option does not exist.
125
73
  def selected? text_or_regexp
126
- unless includes? text_or_regexp
127
- raise UnknownObjectException, "Option #{text_or_regexp.inspect} not found."
128
- end
129
-
130
- getSelectedItems.grep(text_or_regexp).size > 0
131
- end
132
-
133
- # this method provides the access to the <tt><option></tt> item in select_list
134
- #
135
- # Usage example:
136
- #
137
- # Given the following html:
138
- #
139
- # <select id="gender">
140
- # <option value="U">Unknown</option>
141
- # <option value="M" selected>Male</option>
142
- # <option value="F">Female</option>
143
- # </select>
144
- #
145
- # get the +value+ attribute of option with visible +text+ 'Female'
146
- # browser.select_list(:id, 'gender').option(:text, 'Female').value #=> 'F'
147
- # or find out if the +value+ 'M' is selected
148
- # browser.select_list(:id, 'gender').option(:value, 'M').selected #=> true
149
- #
150
- # * attribute - Symbol :value, :text or other attribute - how we find an item in the select box
151
- # * value - string or reg exp - what we are looking for
152
- def option(attribute, value)
153
- assert_exists
154
- Option.new(self, attribute, value)
74
+ raise UnknownObjectException, "Option #{text_or_regexp.inspect} not found." unless include? text_or_regexp
75
+ !selected_options.map(&:text).grep(text_or_regexp).empty?
155
76
  end
156
- end
157
-
158
- module OptionAccess
159
- # text of SelectList#option
160
- def text
161
- @option.text
162
- end
163
- # value of SelectList#option
164
- def value
165
- @option.value
166
- end
167
- # return true if SelectList#option is selected, else false
168
- def selected
169
- @option.selected
170
- end
171
- end
172
-
173
- class OptionWrapper #:nodoc:all
174
- include OptionAccess
175
- def initialize(option)
176
- @option = option
77
+
78
+ private
79
+
80
+ def matching_items_in_select_list(attribute, value)
81
+ options.select do |opt|
82
+ if value.is_a?(Regexp)
83
+ opt.send(attribute) =~ value
84
+ elsif value.is_a?(String) || value.is_a?(Numeric)
85
+ opt.send(attribute) == value
86
+ else
87
+ raise TypeError, "#{value.inspect} can be only String, Regexp or Numeric!"
88
+ end
89
+ end
177
90
  end
178
91
  end
179
92
 
180
- # An item in a select list.
181
- # Normally a user would not need to create this object as it is returned by the Watir::SelectList#option method
182
- class Option
183
- include OptionAccess
184
- include Watir::Exception
185
- def initialize(select_list, attribute, value)
186
- @select_list = select_list
187
- @how = attribute
188
- @what = value
189
- @option = nil
190
-
191
- unless [:text, :value, :label].include? attribute
192
- raise MissingWayOfFindingObjectException,
193
- "Option does not support attribute #{@how}"
194
- end
195
- @select_list.o.each do |option| # items in the list
196
- if value.matches(option.invoke(attribute.to_s))
197
- @option = option
198
- break
93
+ class Option < NonControlElement
94
+
95
+ def select
96
+ perform_action do
97
+ unless selected?
98
+ ole_object.selected = true
99
+ select_list.dispatch_event("onChange")
100
+ @container.wait
199
101
  end
200
102
  end
201
-
202
103
  end
203
- def assert_exists
204
- unless @option
205
- raise UnknownObjectException,
206
- "Unable to locate an option using #{@how} and #{@what}"
104
+
105
+ def clear
106
+ raise TypeError, "you can only clear multi-selects" unless select_list.multiple?
107
+
108
+ perform_action do
109
+ if selected?
110
+ ole_object.selected = false
111
+ select_list.dispatch_event("onChange")
112
+ @container.wait
113
+ end
207
114
  end
208
115
  end
209
- private :assert_exists
210
-
211
- # select the accessed option in select_list
212
- def select
116
+
117
+ def selected?
213
118
  assert_exists
214
- @select_list.select_item_in_select_list(@how, @what)
119
+ ole_object.selected
120
+ end
121
+
122
+ def text
123
+ l = label
124
+ l.empty? ? super : l rescue ''
125
+ end
126
+
127
+ private
128
+
129
+ def select_list
130
+ return @select_list if @select_list
131
+ el = parent
132
+ el = el.parent until el.is_a?(SelectList)
133
+
134
+ raise "SELECT element was not found for #{self}!" unless el
135
+ @select_list = el
215
136
  end
216
137
  end
217
-
138
+
218
139
  #
219
140
  # Input: Button
220
141
  #
@@ -224,6 +145,16 @@ module Watir
224
145
  #:stopdoc:
225
146
  INPUT_TYPES = ["button", "submit", "image", "reset"]
226
147
  #:startdoc:
148
+
149
+ alias_method :__value, :value
150
+
151
+ def text
152
+ val = __value
153
+ val.empty? ? super : val
154
+ end
155
+
156
+ alias_method :value, :text
157
+
227
158
  end
228
159
 
229
160
  #
@@ -242,6 +173,8 @@ module Watir
242
173
  # Raises UnknownObjectException if the object can't be found.
243
174
  def_wrap :readonly?, :readOnly
244
175
 
176
+ alias_method :text, :value
177
+
245
178
  #:startdoc:
246
179
 
247
180
  # return number of maxlength attribute
@@ -254,7 +187,6 @@ module Watir
254
187
  end
255
188
  end
256
189
 
257
-
258
190
  def text_string_creator
259
191
  n = []
260
192
  n << "length:".ljust(TO_S_SIZE) + self.size.to_s
@@ -442,6 +374,10 @@ module Watir
442
374
  end
443
375
  value
444
376
  end
377
+
378
+ def label
379
+ @container.label(:for => name).text
380
+ end
445
381
  end
446
382
 
447
383
  # this class can be used to access hidden field objects
@@ -3,6 +3,28 @@ module Watir
3
3
  include Watir
4
4
  include Watir::Exception
5
5
 
6
+ def initialize container, tags, klass
7
+ @container = container
8
+ @tags = tags
9
+ @klass = klass
10
+ end
11
+
12
+ def each
13
+ if has_excluding_specifiers?
14
+ locate_elements_by_xpath_css_ole.each do |element|
15
+ yield element
16
+ end
17
+ else
18
+ @tags.each do |tag|
19
+ each_element(tag) do |element|
20
+ next unless type_matches?(element.ole_object) && match_with_specifiers?(element)
21
+ yield element
22
+ end
23
+ end
24
+ end
25
+ nil
26
+ end
27
+
6
28
  def document
7
29
  @document ||= @container.document
8
30
  end
@@ -30,7 +52,11 @@ module Watir
30
52
 
31
53
  def match_with_specifiers?(element)
32
54
  return true if has_excluding_specifiers?
33
- @specifiers.all? {|how, what| how == :index || match?(element, how, what)}
55
+ @specifiers.all? do |how, what|
56
+ how == :index ||
57
+ (how.to_s =~ /^data_.*/ && element.send(how) == what) ||
58
+ match?(element, how, what)
59
+ end
34
60
  end
35
61
 
36
62
  def has_excluding_specifiers?
@@ -42,7 +68,7 @@ module Watir
42
68
  @specifiers = {:index => Watir::IE.base_index} # default if not specified
43
69
  normalize_specifiers! specifiers
44
70
  end
45
-
71
+
46
72
  def locate_by_id
47
73
  # Searching through all elements returned by __ole_inner_elements
48
74
  # is *significantly* slower than IE's getElementById() and
@@ -57,20 +83,30 @@ module Watir
57
83
  if the_id && the_id.class == String
58
84
  element = document.getElementById(the_id) rescue nil
59
85
  # Return if our fast match really HAS a matching :id
60
- return element if element && element.invoke('id') == the_id
86
+ return element if element && element.invoke('id') == the_id && type_matches?(element) && match_with_specifiers?(create_element element)
61
87
  end
62
88
 
63
89
  nil
64
90
  end
65
91
 
66
- def locate_by_xpath_css_ole
92
+ def locate_elements_by_xpath_css_ole
93
+ els = []
94
+
67
95
  if @specifiers[:xpath]
68
- return @container.element_by_xpath(@specifiers[:xpath])
96
+ els = @container.send(:elements_by_xpath, @specifiers[:xpath])
69
97
  elsif @specifiers[:css]
70
- return @container.element_by_css(@specifiers[:css])
98
+ els = @container.send(:elements_by_css, @specifiers[:css])
71
99
  elsif @specifiers[:ole_object]
72
- return @specifiers[:ole_object]
100
+ return [@specifiers[:ole_object]]
73
101
  end
102
+
103
+ els.select {|element| type_matches?(element) && match_with_specifiers?(create_element element)}
104
+ end
105
+
106
+ def type_matches?(el)
107
+ @tags == ["*"] ||
108
+ @tags.include?(el.tagName) ||
109
+ @tags.include?(el.invoke('type')) rescue false
74
110
  end
75
111
 
76
112
  def create_element ole_object
@@ -86,30 +122,16 @@ module Watir
86
122
  end
87
123
 
88
124
  class TaggedElementLocator < Locator
89
- def initialize(container, tag, klass)
90
- @container = container
91
- @tag = tag
92
- @klass = klass || Element
93
- end
94
-
95
- def each_element tag
125
+ def each_element(tag)
96
126
  document.getElementsByTagName(tag).each do |ole_object|
97
127
  yield create_element ole_object
98
128
  end
99
129
  end
100
130
 
101
- def each
102
- each_element(@tag) do |element|
103
- next unless match_with_specifiers?(element)
104
- yield element
105
- end
106
- nil
107
- end
108
-
109
131
  def locate
110
132
  el = locate_by_id
111
133
  return el if el
112
- return locate_by_xpath_css_ole if has_excluding_specifiers?
134
+ return locate_elements_by_xpath_css_ole[0] if has_excluding_specifiers?
113
135
 
114
136
  count = Watir::IE.base_index - 1
115
137
  each do |element|
@@ -124,7 +146,7 @@ module Watir
124
146
  method = element.method(how)
125
147
  rescue NameError
126
148
  raise MissingWayOfFindingObjectException,
127
- "#{how} is an unknown way of finding a <#{@tag || @tags.join(", ")}> element (#{what})"
149
+ "#{how} is an unknown way of finding a <#{@tags.join(", ")}> element (#{what})"
128
150
  end
129
151
  case method.arity
130
152
  when 0
@@ -133,18 +155,14 @@ module Watir
133
155
  method.call(what)
134
156
  else
135
157
  raise MissingWayOfFindingObjectException,
136
- "#{how} is an unknown way of finding a <#{@tag || @tags.join(", ")}> element (#{what})"
158
+ "#{how} is an unknown way of finding a <#{@tags.join(", ")}> element (#{what})"
137
159
  end
138
160
  end
139
161
 
140
162
  end
141
163
 
142
164
  class FrameLocator < TaggedElementLocator
143
- def initialize(container)
144
- super(container, Frame::TAG, Frame)
145
- end
146
-
147
- def each_element tag
165
+ def each_element(tag)
148
166
  frames = document.frames
149
167
  i = 0
150
168
  document.getElementsByTagName(tag).each do |ole_object|
@@ -155,21 +173,9 @@ module Watir
155
173
  end
156
174
  end
157
175
 
158
- def each
159
- @tag.each do |t|
160
- each_element(t) do |element|
161
- next unless match_with_specifiers?(element)
162
- yield element
163
- end
164
- end
165
- nil
166
- end
167
-
168
176
  def locate
169
- # do not locate frames by getElementById since can't get the correct
177
+ # do not locate frames by getElementById or by xpath since can't get the correct
170
178
  # 'document' related with that ole_object like it's done in #each_element
171
- return locate_by_xpath_css_ole if has_excluding_specifiers?
172
-
173
179
  count = Watir::IE.base_index - 1
174
180
  each do |frame|
175
181
  count += 1
@@ -179,10 +185,6 @@ module Watir
179
185
  end
180
186
 
181
187
  class FormLocator < TaggedElementLocator
182
- def initialize(container)
183
- super(container, 'FORM', Form)
184
- end
185
-
186
188
  def each_element(tag)
187
189
  document.forms.each do |form|
188
190
  yield create_element form
@@ -191,12 +193,6 @@ module Watir
191
193
  end
192
194
 
193
195
  class InputElementLocator < Locator
194
- def initialize container, types, klass
195
- @container = container
196
- @types = types
197
- @klass = klass || Element
198
- end
199
-
200
196
  def each_element
201
197
  elements = locate_by_name || @container.__ole_inner_elements
202
198
  elements.each do |object|
@@ -208,7 +204,7 @@ module Watir
208
204
  def locate
209
205
  el = locate_by_id
210
206
  return el if el
211
- return locate_by_xpath_css_ole if has_excluding_specifiers?
207
+ return locate_elements_by_xpath_css_ole[0] if has_excluding_specifiers?
212
208
 
213
209
  count = Watir::IE.base_index - 1
214
210
  each do |element|
@@ -218,13 +214,19 @@ module Watir
218
214
  end
219
215
 
220
216
  def each
221
- each_element do |element|
222
- next unless @types.include?(element.type) && match_with_specifiers?(element)
223
- yield element
224
- end
217
+ if has_excluding_specifiers?
218
+ locate_elements_by_xpath_css_ole.each do |element|
219
+ yield element
220
+ end
221
+ else
222
+ each_element do |element|
223
+ next unless type_matches?(element.ole_object) && match_with_specifiers?(element)
224
+ yield element
225
+ end
226
+ end
225
227
  nil
226
228
  end
227
-
229
+
228
230
  # return true if the element matches the provided how and what
229
231
  def match? element, how, what
230
232
  begin
@@ -248,11 +250,4 @@ module Watir
248
250
  end
249
251
  end
250
252
 
251
- # This is like the TaggedElementLocator but
252
- # get all the elements by forcing @tag to be '*'
253
- class ElementLocator < TaggedElementLocator
254
- def initialize(container)
255
- super(container, "*", Element)
256
- end
257
- end
258
253
  end