watir 2.0.4 → 3.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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