watir 1.6.5 → 1.6.6.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (186) hide show
  1. data/CHANGES +461 -326
  2. data/VERSION +1 -0
  3. data/bin/watir-console +6 -6
  4. data/lib/changes.rb +3 -3
  5. data/lib/license.rb +38 -38
  6. data/lib/readme.rb +140 -140
  7. data/lib/watir/WindowHelper.rb +49 -49
  8. data/lib/watir/camel_case.rb +66 -66
  9. data/lib/watir/clickJSDialog.rb +19 -19
  10. data/lib/watir/close_all.rb +37 -37
  11. data/lib/watir/collections.rb +392 -344
  12. data/lib/watir/container.rb +857 -815
  13. data/lib/watir/contrib/enabled_popup.rb +20 -20
  14. data/lib/watir/contrib/ie-new-process.rb +27 -27
  15. data/lib/watir/contrib/page_checker.rb +29 -29
  16. data/lib/watir/cookiemanager.rb +55 -55
  17. data/lib/watir/core.rb +28 -0
  18. data/lib/watir/core_ext.rb +17 -17
  19. data/lib/watir/datahandler.rb +107 -107
  20. data/lib/watir/dialog.rb +46 -46
  21. data/lib/watir/element.rb +351 -343
  22. data/lib/watir/element_collections.rb +97 -97
  23. data/lib/watir/form.rb +170 -170
  24. data/lib/watir/frame.rb +59 -59
  25. data/lib/watir/html_element.rb +22 -0
  26. data/lib/watir/ie-class.rb +1006 -1009
  27. data/lib/watir/ie-process.rb +39 -39
  28. data/lib/watir/ie.rb +70 -133
  29. data/lib/watir/image.rb +130 -130
  30. data/lib/watir/input_elements.rb +614 -572
  31. data/lib/watir/irb-history.rb +30 -30
  32. data/lib/watir/link.rb +64 -64
  33. data/lib/watir/locator.rb +200 -176
  34. data/lib/watir/logger.rb +19 -19
  35. data/lib/watir/modal_dialog.rb +122 -122
  36. data/lib/watir/module.rb +37 -0
  37. data/lib/watir/non_control_elements.rb +145 -145
  38. data/lib/watir/page-container.rb +116 -107
  39. data/lib/watir/popup.rb +29 -29
  40. data/lib/watir/process.rb +19 -19
  41. data/lib/watir/screen_capture.rb +115 -115
  42. data/lib/watir/setFileDialog.rb +16 -16
  43. data/lib/watir/table.rb +395 -362
  44. data/lib/watir/watir_simple.rb +475 -475
  45. data/lib/watir/win32.rb +35 -35
  46. data/lib/watir/win32ole.rb +14 -14
  47. data/lib/watir/winClicker.rb +496 -496
  48. data/rakefile.rb +70 -0
  49. data/unittests/all_tests.rb +10 -10
  50. data/unittests/buttons_xpath_test.rb +69 -69
  51. data/unittests/checkbox_test.rb +179 -179
  52. data/unittests/checkbox_xpath_test.rb +107 -107
  53. data/unittests/click_no_wait_test.rb +21 -0
  54. data/unittests/core_tests.rb +17 -17
  55. data/unittests/css_test.rb +42 -35
  56. data/unittests/defer_test.rb +46 -46
  57. data/unittests/dialog_test.rb +77 -77
  58. data/unittests/div2_xpath_test.rb +21 -21
  59. data/unittests/div_test.rb +188 -188
  60. data/unittests/div_xpath_test.rb +96 -96
  61. data/unittests/element_test.rb +49 -0
  62. data/unittests/errorchecker_test.rb +32 -22
  63. data/unittests/filefield_test.rb +39 -39
  64. data/unittests/filefield_xpath_test.rb +33 -33
  65. data/unittests/form_test.rb +280 -280
  66. data/unittests/form_xpath_test.rb +252 -252
  67. data/unittests/frame_test.rb +155 -155
  68. data/unittests/google_form_test.rb +15 -15
  69. data/unittests/html/JavascriptClick.html +39 -39
  70. data/unittests/html/blankpage.html +11 -11
  71. data/unittests/html/buttons1.html +40 -40
  72. data/unittests/html/checkboxes1.html +89 -89
  73. data/unittests/html/click_no_wait.html +14 -0
  74. data/unittests/html/complex_table.html +36 -36
  75. data/unittests/html/cssTest.html +42 -42
  76. data/unittests/html/depot_store.html +59 -59
  77. data/unittests/html/div.html +93 -93
  78. data/unittests/html/div_xml.html +20 -20
  79. data/unittests/html/fileupload.html +45 -45
  80. data/unittests/html/formTest1.html +38 -38
  81. data/unittests/html/forms2.html +44 -44
  82. data/unittests/html/forms3.html +131 -131
  83. data/unittests/html/forms4.html +27 -27
  84. data/unittests/html/frame_buttons.html +3 -3
  85. data/unittests/html/frame_links.html +3 -3
  86. data/unittests/html/frame_multi.html +4 -4
  87. data/unittests/html/google_india.html +119 -119
  88. data/unittests/html/iframeTest.html +12 -12
  89. data/unittests/html/iframeTest1.html +6 -6
  90. data/unittests/html/iframeTest2.html +5 -5
  91. data/unittests/html/images1.html +66 -66
  92. data/unittests/html/javascriptevents.html +35 -35
  93. data/unittests/html/link_pass.html +10 -10
  94. data/unittests/html/links1.html +38 -38
  95. data/unittests/html/links2.html +10 -10
  96. data/unittests/html/links_multi.html +14 -14
  97. data/unittests/html/list_matters.html +720 -720
  98. data/unittests/html/lists.html +17 -17
  99. data/unittests/html/map_test.html +31 -31
  100. data/unittests/html/modal_dialog.html +10 -10
  101. data/unittests/html/modal_dialog_launcher.html +11 -11
  102. data/unittests/html/nestedFrames.html +6 -6
  103. data/unittests/html/new_browser.html +16 -16
  104. data/unittests/html/pass.html +12 -12
  105. data/unittests/html/popups1.html +59 -59
  106. data/unittests/html/pre.html +27 -27
  107. data/unittests/html/radioButtons1.html +71 -71
  108. data/unittests/html/select_tealeaf.html +54 -54
  109. data/unittests/html/selectboxes1.html +52 -52
  110. data/unittests/html/simple_table.html +26 -26
  111. data/unittests/html/simple_table_buttons.html +104 -104
  112. data/unittests/html/simple_table_columns.html +76 -76
  113. data/unittests/html/table1.html +181 -181
  114. data/unittests/html/tableCell_using_xpath.html +19 -19
  115. data/unittests/html/table_and_tablerow_to_a.html +174 -0
  116. data/unittests/html/textarea.html +30 -30
  117. data/unittests/html/textfields1.html +88 -88
  118. data/unittests/html/textsearch.html +44 -44
  119. data/unittests/html/wallofcheckboxes.html +1003 -1003
  120. data/unittests/html/xpath_nbsp.html +12 -12
  121. data/unittests/ie_exists_test.rb +33 -33
  122. data/unittests/ie_mock.rb +94 -94
  123. data/unittests/ie_test.rb +51 -51
  124. data/unittests/images_test.rb +157 -157
  125. data/unittests/images_xpath_test.rb +91 -91
  126. data/unittests/links_multi_test.rb +48 -48
  127. data/unittests/links_test.rb +175 -175
  128. data/unittests/links_xpath_test.rb +39 -39
  129. data/unittests/lists_test.rb +32 -32
  130. data/unittests/map_test.rb +98 -98
  131. data/unittests/minmax_test.rb +31 -31
  132. data/unittests/navigate_test.rb +39 -39
  133. data/unittests/nbsp_xpath_test.rb +16 -16
  134. data/unittests/non_core_tests.rb +12 -12
  135. data/unittests/other/WindowLogonExample.rb +27 -27
  136. data/unittests/other/WindowLogonExtra.rb +6 -6
  137. data/unittests/other/all_tests_concurrent.rb +57 -57
  138. data/unittests/other/jscriptExtraAlert.rb +6 -6
  139. data/unittests/other/jscriptExtraConfirmCancel.rb +6 -6
  140. data/unittests/other/jscriptExtraConfirmOk.rb +6 -6
  141. data/unittests/other/jscriptPushButton.rb +6 -6
  142. data/unittests/other/jscript_test.rb +63 -63
  143. data/unittests/other/navigate_exception_test.rb +24 -24
  144. data/unittests/other/rexml_unit_test.rb +27 -27
  145. data/unittests/other/screen_capture_test.rb +54 -54
  146. data/unittests/other/testcase_method_order_test.rb +35 -35
  147. data/unittests/other/testcase_verify_test.rb +24 -24
  148. data/unittests/other/wait_until_test.rb +99 -99
  149. data/unittests/pagecontainstext_test.rb +69 -69
  150. data/unittests/parent_child_test.rb +43 -43
  151. data/unittests/perf_test.rb +20 -20
  152. data/unittests/popups_test.rb +43 -43
  153. data/unittests/pre_test.rb +53 -53
  154. data/unittests/radios_test.rb +212 -212
  155. data/unittests/radios_xpath_test.rb +101 -101
  156. data/unittests/security_setting_test.rb +23 -23
  157. data/unittests/selectbox_test.rb +148 -148
  158. data/unittests/selectbox_xpath_test.rb +113 -113
  159. data/unittests/setup.rb +87 -77
  160. data/unittests/speed_settings_test.rb +67 -67
  161. data/unittests/table_and_tablerow_to_a_test.rb +117 -0
  162. data/unittests/table_cell_using_xpath_test.rb +35 -35
  163. data/unittests/table_test.rb +376 -376
  164. data/unittests/table_xpath_test.rb +110 -110
  165. data/unittests/test_tests.rb +9 -9
  166. data/unittests/textarea_test.rb +92 -92
  167. data/unittests/textarea_xpath_test.rb +78 -78
  168. data/unittests/textfield_for_ch_char_test.rb +31 -31
  169. data/unittests/textfields_test.rb +218 -218
  170. data/unittests/textfields_xpath_test.rb +111 -111
  171. data/unittests/window_tests.rb +10 -10
  172. data/unittests/windows/attach_to_existing_window_test.rb +53 -53
  173. data/unittests/windows/attach_to_new_window_test.rb +83 -83
  174. data/unittests/windows/close_window_test.rb +20 -20
  175. data/unittests/windows/frame_links_test.rb +25 -25
  176. data/unittests/windows/ie-each_test.rb +47 -47
  177. data/unittests/windows/iedialog_test.rb +54 -54
  178. data/unittests/windows/js_events_test.rb +42 -55
  179. data/unittests/windows/modal_dialog_test.rb +128 -128
  180. data/unittests/windows/new_test.rb +57 -57
  181. data/unittests/windows/open_close_test.rb +18 -18
  182. data/unittests/windows/send_keys_test.rb +33 -33
  183. data/unittests/xpath_tests.rb +10 -10
  184. metadata +85 -31
  185. data/lib/watir/utils.rb +0 -20
  186. data/lib/watir/version.rb +0 -5
@@ -1,573 +1,615 @@
1
- module Watir
2
-
3
- class InputElement < Element
4
- def locate
5
- @o = @container.locate_input_element(@how, @what, self.class::INPUT_TYPES)
6
- end
7
- def initialize(container, how, what)
8
- set_container container
9
- @how = how
10
- @what = what
11
- super(nil)
12
- end
13
- end
14
-
15
- #
16
- # Input: Select
17
- #
18
-
19
- # This class is the way in which select boxes are manipulated.
20
- # Normally a user would not need to create this object as it is returned by the Watir::Container#select_list method
21
- class SelectList < InputElement
22
- INPUT_TYPES = ["select-one", "select-multiple"]
23
-
24
- attr_accessor :o
25
-
26
- # This method clears the selected items in the select box
27
- def clear
28
- assert_exists
29
- highlight(:set)
30
- wait = false
31
- @o.each do |selectBoxItem|
32
- if selectBoxItem.selected
33
- selectBoxItem.selected = false
34
- wait = true
35
- end
36
- end
37
- @container.wait if wait
38
- highlight(:clear)
39
- end
40
-
41
-
42
- # This method selects an item, or items in a select box, by text.
43
- # Raises NoValueFoundException if the specified value is not found.
44
- # * item - the thing to select, string or reg exp
45
- def select(item)
46
- select_item_in_select_list(:text, item)
47
- end
48
- alias :set :select
49
-
50
- # Selects an item, or items in a select box, by value.
51
- # Raises NoValueFoundException if the specified value is not found.
52
- # * item - the value of the thing to select, string, reg exp
53
- def select_value(item)
54
- select_item_in_select_list(:value, item)
55
- end
56
-
57
- # BUG: Should be private
58
- # Selects something from the select box
59
- # * name - symbol :value or :text - how we find an item in the select box
60
- # * item - string or reg exp - what we are looking for
61
- def select_item_in_select_list(attribute, value)
62
- assert_exists
63
- highlight(:set)
64
- found = false
65
-
66
- value = value.to_s unless [Regexp, String].any? { |e| value.kind_of? e }
67
-
68
- @container.log "Setting box #{@o.name} to #{attribute.inspect} => #{value.inspect}"
69
- @o.each do |option| # items in the list
70
- if value.matches(option.invoke(attribute.to_s))
71
- if option.selected
72
- found = true
73
- break
74
- else
75
- option.selected = true
76
- @o.fireEvent("onChange")
77
- @container.wait
78
- found = true
79
- break
80
- end
81
- end
82
- end
83
-
84
- unless found
85
- raise NoValueFoundException, "No option with #{attribute.inspect} of #{value.inspect} in this select element"
86
- end
87
- highlight(:clear)
88
- end
89
-
90
- # Returns all the items in the select list as an array.
91
- # An empty array is returned if the select box has no contents.
92
- # Raises UnknownObjectException if the select box is not found
93
- def options
94
- assert_exists
95
- @container.log "There are #{@o.length} items"
96
- returnArray = []
97
- @o.each { |thisItem| returnArray << thisItem.text }
98
- return returnArray
99
- end
100
-
101
- # Returns the selected items as an array.
102
- # Raises UnknownObjectException if the select box is not found.
103
- def selected_options
104
- assert_exists
105
- returnArray = []
106
- @container.log "There are #{@o.length} items"
107
- @o.each do |thisItem|
108
- if thisItem.selected
109
- @container.log "Item (#{thisItem.text}) is selected"
110
- returnArray << thisItem.text
111
- end
112
- end
113
- return returnArray
114
- end
115
-
116
- # Does the SelectList include the specified option (text)?
117
- def include? text_or_regexp
118
- getAllContents.grep(text_or_regexp).size > 0
119
- end
120
-
121
- # Is the specified option (text) selected? Raises exception of option does not exist.
122
- def selected? text_or_regexp
123
- unless includes? text_or_regexp
124
- raise UnknownObjectException, "Option #{text_or_regexp.inspect} not found."
125
- end
126
-
127
- getSelectedItems.grep(text_or_regexp).size > 0
128
- end
129
-
130
- def option(attribute, value)
131
- assert_exists
132
- Option.new(self, attribute, value)
133
- end
134
- end
135
-
136
- module OptionAccess
137
- def text
138
- @option.text
139
- end
140
- def value
141
- @option.value
142
- end
143
- def selected
144
- @option.selected
145
- end
146
- end
147
-
148
- class OptionWrapper
149
- include OptionAccess
150
- def initialize(option)
151
- @option = option
152
- end
153
- end
154
-
155
- # An item in a select list
156
- class Option
157
- include OptionAccess
158
- include Watir::Exception
159
- def initialize(select_list, attribute, value)
160
- @select_list = select_list
161
- @how = attribute
162
- @what = value
163
- @option = nil
164
-
165
- unless [:text, :value, :label].include? attribute
166
- raise MissingWayOfFindingObjectException,
167
- "Option does not support attribute #{@how}"
168
- end
169
- @select_list.o.each do |option| # items in the list
170
- if value.matches(option.invoke(attribute.to_s))
171
- @option = option
172
- break
173
- end
174
- end
175
-
176
- end
177
- def assert_exists
178
- unless @option
179
- raise UnknownObjectException,
180
- "Unable to locate an option using #{@how} and #{@what}"
181
- end
182
- end
183
- private :assert_exists
184
- def select
185
- assert_exists
186
- @select_list.select_item_in_select_list(@how, @what)
187
- end
188
- end
189
-
190
- #
191
- # Input: Button
192
- #
193
-
194
- # Returned by the Watir::Container#button method
195
- class Button < InputElement
196
- INPUT_TYPES = ["button", "submit", "image", "reset"]
197
- end
198
-
199
- #
200
- # Input: Text
201
- #
202
-
203
- # This class is the main class for Text Fields
204
- # Normally a user would not need to create this object as it is returned by the Watir::Container#text_field method
205
- class TextField < InputElement
206
- INPUT_TYPES = ["text", "password", "textarea"]
207
-
208
- def_wrap_guard :size
209
-
210
- def maxlength
211
- assert_exists
212
- begin
213
- ole_object.invoke('maxlength').to_i
214
- rescue WIN32OLERuntimeError
215
- 0
216
- end
217
- end
218
-
219
- # Returns true or false if the text field is read only.
220
- # Raises UnknownObjectException if the object can't be found.
221
- def_wrap :readonly?, :readOnly
222
-
223
- def text_string_creator
224
- n = []
225
- n << "length:".ljust(TO_S_SIZE) + self.size.to_s
226
- n << "max length:".ljust(TO_S_SIZE) + self.maxlength.to_s
227
- n << "read only:".ljust(TO_S_SIZE) + self.readonly?.to_s
228
- n
229
- end
230
- private :text_string_creator
231
-
232
- def to_s
233
- assert_exists
234
- r = string_creator
235
- r += text_string_creator
236
- r.join("\n")
237
- end
238
-
239
- def assert_not_readonly
240
- if self.readonly?
241
- raise ObjectReadOnlyException,
242
- "Textfield #{@how} and #{@what} is read only."
243
- end
244
- end
245
-
246
- # Returns true if the text field contents is matches the specified target,
247
- # which can be either a string or a regular expression.
248
- # Raises UnknownObjectException if the object can't be found
249
- def verify_contains(target) # FIXME: verify_contains should have same name and semantics as IE#contains_text (prolly make this work for all elements)
250
- assert_exists
251
- if target.kind_of? String
252
- return true if self.value == target
253
- elsif target.kind_of? Regexp
254
- return true if self.value.match(target) != nil
255
- end
256
- return false
257
- end
258
-
259
- # Drag the entire contents of the text field to another text field
260
- # 19 Jan 2005 - It is added as prototype functionality, and may change
261
- # * destination_how - symbol, :id, :name how we identify the drop target
262
- # * destination_what - string or regular expression, the name, id, etc of the text field that will be the drop target
263
- def drag_contents_to(destination_how, destination_what)
264
- assert_exists
265
- destination = @container.text_field(destination_how, destination_what)
266
- unless destination.exists?
267
- raise UnknownObjectException, "Unable to locate destination using #{destination_how } and #{destination_what } "
268
- end
269
-
270
- @o.focus
271
- @o.select
272
- value = self.value
273
-
274
- @o.fireEvent("onSelect")
275
- @o.fireEvent("ondragstart")
276
- @o.fireEvent("ondrag")
277
- destination.fireEvent("onDragEnter")
278
- destination.fireEvent("onDragOver")
279
- destination.fireEvent("ondrop")
280
-
281
- @o.fireEvent("ondragend")
282
- destination.value = destination.value + value.to_s
283
- self.value = ""
284
- end
285
-
286
- # Clears the contents of the text box.
287
- # Raises UnknownObjectException if the object can't be found
288
- # Raises ObjectDisabledException if the object is disabled
289
- # Raises ObjectReadOnlyException if the object is read only
290
- def clear
291
- assert_enabled
292
- assert_not_readonly
293
-
294
- highlight(:set)
295
-
296
- @o.scrollIntoView
297
- @o.focus
298
- @o.select
299
- @o.fireEvent("onSelect")
300
- @o.value = ""
301
- @o.fireEvent("onKeyPress")
302
- @o.fireEvent("onChange")
303
- @container.wait
304
- highlight(:clear)
305
- end
306
-
307
- # Appends the specified string value to the contents of the text box.
308
- # Raises UnknownObjectException if the object cant be found
309
- # Raises ObjectDisabledException if the object is disabled
310
- # Raises ObjectReadOnlyException if the object is read only
311
- def append(value)
312
- assert_enabled
313
- assert_not_readonly
314
-
315
- highlight(:set)
316
- @o.scrollIntoView
317
- @o.focus
318
- type_by_character(value)
319
- highlight(:clear)
320
- end
321
-
322
- # Sets the contents of the text box to the specified text value
323
- # Raises UnknownObjectException if the object cant be found
324
- # Raises ObjectDisabledException if the object is disabled
325
- # Raises ObjectReadOnlyException if the object is read only
326
- def set(value)
327
- assert_enabled
328
- assert_not_readonly
329
-
330
- highlight(:set)
331
- @o.scrollIntoView
332
- if type_keys
333
- @o.focus
334
- @o.select
335
- @o.fireEvent("onSelect")
336
- @o.fireEvent("onKeyPress")
337
- @o.value = ""
338
- type_by_character(value)
339
- @o.fireEvent("onChange")
340
- @o.fireEvent("onBlur")
341
- else
342
- @o.value = limit_to_maxlength(value)
343
- end
344
- highlight(:clear)
345
- end
346
-
347
- # Sets the value of the text field directly.
348
- # It causes no events to be fired or exceptions to be raised,
349
- # so generally shouldn't be used.
350
- # It is preffered to use the set method.
351
- def value=(v)
352
- assert_exists
353
- @o.value = v.to_s
354
- end
355
-
356
- def requires_typing
357
- @type_keys = true
358
- self
359
- end
360
- def abhors_typing
361
- @type_keys = false
362
- self
363
- end
364
-
365
- private
366
-
367
- # Type the characters in the specified string (value) one by one.
368
- # It should not be used externally.
369
- # * value - string - The string to enter into the text field
370
- def type_by_character(value)
371
- value = limit_to_maxlength(value)
372
- characters_in(value) do |c|
373
- sleep @container.typingspeed
374
- @o.value = @o.value.to_s + c
375
- @o.fireEvent("onKeyDown")
376
- @o.fireEvent("onKeyPress")
377
- @o.fireEvent("onKeyUp")
378
- end
379
- end
380
-
381
- # Supports double-byte characters
382
- def characters_in(value, &blk)
383
- if RUBY_VERSION =~ /^1\.8/
384
- index = 0
385
- while index < value.length
386
- len = value[index] > 128 ? 2 : 1
387
- yield value[index, len]
388
- index += len
389
- end
390
- else
391
- value.each_char(&blk)
392
- end
393
- end
394
-
395
- # Return the value (a string), limited to the maxlength of the element.
396
- def limit_to_maxlength(value)
397
- return value if @o.invoke('type') =~ /textarea/i # text areas don't have maxlength
398
- if value.length > maxlength
399
- value = value[0 .. maxlength - 1]
400
- @container.log " Supplied string is #{value.length} chars, which exceeds the max length (#{maxlength}) of the field. Using value: #{value}"
401
- end
402
- value
403
- end
404
- end
405
-
406
- # this class can be used to access hidden field objects
407
- # Normally a user would not need to create this object as it is returned by the Watir::Container#hidden method
408
- class Hidden < TextField
409
- INPUT_TYPES = ["hidden"]
410
-
411
- # set is overriden in this class, as there is no way to set focus to a hidden field
412
- def set(n)
413
- self.value = n
414
- end
415
-
416
- # override the append method, so that focus isnt set to the hidden object
417
- def append(n)
418
- self.value = self.value.to_s + n.to_s
419
- end
420
-
421
- # override the clear method, so that focus isnt set to the hidden object
422
- def clear
423
- self.value = ""
424
- end
425
-
426
- # this method will do nothing, as you cant set focus to a hidden field
427
- def focus
428
- end
429
-
430
- # Hidden element is never visible - returns false.
431
- def visible?
432
- assert_exists
433
- false
434
- end
435
-
436
- end
437
-
438
- # For fields that accept file uploads
439
- # Windows dialog is opened and handled in this case by autoit
440
- # launching into a new process.
441
- class FileField < InputElement
442
- INPUT_TYPES = ["file"]
443
- POPUP_TITLES = ['Choose file', 'Choose File to Upload']
444
-
445
- # set the file location in the Choose file dialog in a new process
446
- # will raise a Watir Exception if AutoIt is not correctly installed
447
- def set(path_to_file)
448
- assert_exists
449
- require 'watir/windowhelper'
450
- WindowHelper.check_autoit_installed
451
- begin
452
- Thread.new do
453
- sleep 1 # it takes some time for popup to appear
454
-
455
- system %{ruby -e '
456
- require "win32ole"
457
-
458
- @autoit = WIN32OLE.new("AutoItX3.Control")
459
- time = Time.now
460
-
461
- while (Time.now - time) < 15 # the loop will wait up to 15 seconds for popup to appear
462
- #{POPUP_TITLES.inspect}.each do |popup_title|
463
- next unless @autoit.WinWait(popup_title, "", 1) == 1
464
-
465
- @autoit.ControlSetText(popup_title, "", "Edit1", #{path_to_file.inspect})
466
- @autoit.ControlSend(popup_title, "", "Button2", "{ENTER}")
467
- exit
468
- end # each
469
- end # while
470
- '}
471
- end.join(1)
472
- rescue
473
- raise Watir::Exception::WatirException, "Problem accessing Choose file dialog"
474
- end
475
- click
476
- end
477
- end
478
-
479
- # This class is the class for radio buttons and check boxes.
480
- # It contains methods common to both.
481
- # Normally a user would not need to create this object as it is returned by the Watir::Container#checkbox or Watir::Container#radio methods
482
- #
483
- # most of the methods available to this element are inherited from the Element class
484
- #
485
- class RadioCheckCommon < InputElement
486
- def locate
487
- @o = @container.locate_input_element(@how, @what, self.class::INPUT_TYPES, @value)
488
- end
489
- def initialize(container, how, what, value=nil)
490
- super container, how, what
491
- @value = value
492
- end
493
-
494
- def inspect
495
- '#<%s:0x%x located=%s how=%s what=%s value=%s>' % [self.class, hash*2, !!ole_object, @how.inspect, @what.inspect, @value.inspect]
496
- end
497
-
498
- # This method determines if a radio button or check box is set.
499
- # Returns true is set/checked or false if not set/checked.
500
- # Raises UnknownObjectException if its unable to locate an object.
501
- def set? # could be just "checked?"
502
- assert_exists
503
- return @o.checked
504
- end
505
- alias checked? set?
506
-
507
- # This method is the common code for setting or clearing checkboxes and radio.
508
- def set_clear_item(set)
509
- @o.checked = set
510
- @o.fireEvent("onClick")
511
- @container.wait
512
- end
513
- private :set_clear_item
514
-
515
- end
516
-
517
- #--
518
- # this class makes the docs better
519
- #++
520
- # This class is the watir representation of a radio button.
521
- class Radio < RadioCheckCommon
522
- INPUT_TYPES = ["radio"]
523
- # This method clears a radio button. One of them will almost always be set.
524
- # Returns true if set or false if not set.
525
- # Raises UnknownObjectException if its unable to locate an object
526
- # ObjectDisabledException IF THE OBJECT IS DISABLED
527
- def clear
528
- assert_enabled
529
- highlight(:set)
530
- set_clear_item(false)
531
- highlight(:clear)
532
- end
533
-
534
- # This method sets the radio list item.
535
- # Raises UnknownObjectException if it's unable to locate an object
536
- # ObjectDisabledException if the object is disabled
537
- def set
538
- assert_enabled
539
- highlight(:set)
540
- @o.scrollIntoView
541
- set_clear_item(true)
542
- highlight(:clear)
543
- end
544
-
545
- end
546
-
547
- # This class is the watir representation of a check box.
548
- class CheckBox < RadioCheckCommon
549
- INPUT_TYPES = ["checkbox"]
550
- # With no arguments supplied, sets the check box.
551
- # If the optional value is supplied, the checkbox is set, when its true and
552
- # cleared when its false
553
- # Raises UnknownObjectException if it's unable to locate an object
554
- # ObjectDisabledException if the object is disabled
555
- def set(value=true)
556
- assert_enabled
557
- highlight :set
558
- unless @o.checked == value
559
- set_clear_item value
560
- end
561
- highlight :clear
562
- end
563
-
564
- # Clears a check box.
565
- # Raises UnknownObjectException if its unable to locate an object
566
- # ObjectDisabledException if the object is disabled
567
- def clear
568
- set false
569
- end
570
-
571
- end
572
-
1
+ module Watir
2
+
3
+ class InputElement < Element #:nodoc:all
4
+ def locate
5
+ @o = @container.locate_input_element(@how, @what, self.class::INPUT_TYPES)
6
+ end
7
+ def initialize(container, how, what)
8
+ set_container container
9
+ @how = how
10
+ @what = what
11
+ super(nil)
12
+ end
13
+ end
14
+
15
+ #
16
+ # Input: Select
17
+ #
18
+
19
+ # This class is the way in which select boxes are manipulated.
20
+ # Normally a user would not need to create this object as it is returned by the Watir::Container#select_list method
21
+ class SelectList < InputElement
22
+ #:stopdoc:
23
+ INPUT_TYPES = ["select-one", "select-multiple"]
24
+ #exposed to Option class
25
+ attr_accessor :o
26
+ #:startdoc:
27
+
28
+ # This method clears the selected items in the select box
29
+ def clear
30
+ assert_exists
31
+ highlight(:set)
32
+ wait = false
33
+ @o.each do |selectBoxItem|
34
+ if selectBoxItem.selected
35
+ selectBoxItem.selected = false
36
+ wait = true
37
+ end
38
+ end
39
+ @container.wait if wait
40
+ highlight(:clear)
41
+ end
42
+
43
+
44
+ # This method selects an item, or items in a select box, by text.
45
+ # Raises NoValueFoundException if the specified value is not found.
46
+ # * item - the thing to select, string or reg exp
47
+ def select(item)
48
+ select_item_in_select_list(:text, item)
49
+ end
50
+ alias :set :select
51
+
52
+ # Selects an item, or items in a select box, by value.
53
+ # Raises NoValueFoundException if the specified value is not found.
54
+ # * item - the value of the thing to select, string, reg exp
55
+ def select_value(item)
56
+ select_item_in_select_list(:value, item)
57
+ end
58
+
59
+ # BUG: Should be private
60
+ # Selects something from the select box
61
+ # * name - symbol :value or :text - how we find an item in the select box
62
+ # * item - string or reg exp - what we are looking for
63
+ def select_item_in_select_list(attribute, value) #:nodoc:
64
+ assert_exists
65
+ highlight(:set)
66
+ found = false
67
+
68
+ value = value.to_s unless [Regexp, String].any? { |e| value.kind_of? e }
69
+
70
+ @container.log "Setting box #{@o.name} to #{attribute.inspect} => #{value.inspect}"
71
+ @o.each do |option| # items in the list
72
+ if value.matches(option.invoke(attribute.to_s))
73
+ if option.selected
74
+ found = true
75
+ break
76
+ else
77
+ option.selected = true
78
+ @o.fireEvent("onChange")
79
+ @container.wait
80
+ found = true
81
+ break
82
+ end
83
+ end
84
+ end
85
+
86
+ unless found
87
+ raise NoValueFoundException, "No option with #{attribute.inspect} of #{value.inspect} in this select element"
88
+ end
89
+ highlight(:clear)
90
+ end
91
+
92
+ # Returns array of all text items displayed in a select box
93
+ # An empty array is returned if the select box has no contents.
94
+ # Raises UnknownObjectException if the select box is not found
95
+ def options
96
+ assert_exists
97
+ @container.log "There are #{@o.length} items"
98
+ returnArray = []
99
+ @o.each { |thisItem| returnArray << thisItem.text }
100
+ return returnArray
101
+ end
102
+
103
+ # Returns array of the selected text items in a select box
104
+ # Raises UnknownObjectException if the select box is not found.
105
+ def selected_options
106
+ assert_exists
107
+ returnArray = []
108
+ @container.log "There are #{@o.length} items"
109
+ @o.each do |thisItem|
110
+ if thisItem.selected
111
+ @container.log "Item (#{thisItem.text}) is selected"
112
+ returnArray << thisItem.text
113
+ end
114
+ end
115
+ return returnArray
116
+ end
117
+
118
+ # Does the SelectList include the specified option (text)?
119
+ def include? text_or_regexp
120
+ getAllContents.grep(text_or_regexp).size > 0
121
+ end
122
+
123
+ # Is the specified option (text) selected? Raises exception of option does not exist.
124
+ def selected? text_or_regexp
125
+ unless includes? text_or_regexp
126
+ raise UnknownObjectException, "Option #{text_or_regexp.inspect} not found."
127
+ end
128
+
129
+ getSelectedItems.grep(text_or_regexp).size > 0
130
+ end
131
+
132
+ # this method provides the access to the <tt><option></tt> item in select_list
133
+ #
134
+ # Usage example:
135
+ #
136
+ # Given the following html:
137
+ #
138
+ # <select id="gender">
139
+ # <option value="U">Unknown</option>
140
+ # <option value="M" selected>Male</option>
141
+ # <option value="F">Female</option>
142
+ # </select>
143
+ #
144
+ # get the +value+ attribute of option with visible +text+ 'Female'
145
+ # browser.select_list(:id, 'gender').option(:text, 'Female').value #=> 'F'
146
+ # or find out if the +value+ 'M' is selected
147
+ # browser.select_list(:id, 'gender').option(:value, 'M').selected #=> true
148
+ #
149
+ # * attribute - Symbol :value, :text or other attribute - how we find an item in the select box
150
+ # * value - string or reg exp - what we are looking for
151
+ def option(attribute, value)
152
+ assert_exists
153
+ Option.new(self, attribute, value)
154
+ end
155
+ end
156
+
157
+ module OptionAccess
158
+ # text of SelectList#option
159
+ def text
160
+ @option.text
161
+ end
162
+ # value of SelectList#option
163
+ def value
164
+ @option.value
165
+ end
166
+ # return true if SelectList#option is selected, else false
167
+ def selected
168
+ @option.selected
169
+ end
170
+ end
171
+
172
+ class OptionWrapper #:nodoc:all
173
+ include OptionAccess
174
+ def initialize(option)
175
+ @option = option
176
+ end
177
+ end
178
+
179
+ # An item in a select list.
180
+ # Normally a user would not need to create this object as it is returned by the Watir::SelectList#option method
181
+ class Option
182
+ include OptionAccess
183
+ include Watir::Exception
184
+ def initialize(select_list, attribute, value)
185
+ @select_list = select_list
186
+ @how = attribute
187
+ @what = value
188
+ @option = nil
189
+
190
+ unless [:text, :value, :label].include? attribute
191
+ raise MissingWayOfFindingObjectException,
192
+ "Option does not support attribute #{@how}"
193
+ end
194
+ @select_list.o.each do |option| # items in the list
195
+ if value.matches(option.invoke(attribute.to_s))
196
+ @option = option
197
+ break
198
+ end
199
+ end
200
+
201
+ end
202
+ def assert_exists
203
+ unless @option
204
+ raise UnknownObjectException,
205
+ "Unable to locate an option using #{@how} and #{@what}"
206
+ end
207
+ end
208
+ private :assert_exists
209
+
210
+ # select the accessed option in select_list
211
+ def select
212
+ assert_exists
213
+ @select_list.select_item_in_select_list(@how, @what)
214
+ end
215
+ end
216
+
217
+ #
218
+ # Input: Button
219
+ #
220
+
221
+ # Returned by the Watir::Container#button method
222
+ class Button < InputElement
223
+ #:stopdoc:
224
+ INPUT_TYPES = ["button", "submit", "image", "reset"]
225
+ #:startdoc:
226
+ end
227
+
228
+ #
229
+ # Input: Text
230
+ #
231
+
232
+ # This class is the main class for Text Fields
233
+ # Normally a user would not need to create this object as it is returned by the Watir::Container#text_field method
234
+ class TextField < InputElement
235
+ #:stopdoc:
236
+ INPUT_TYPES = ["text", "password", "textarea"]
237
+
238
+ def_wrap_guard :size
239
+
240
+ # Returns true or false if the text field is read only.
241
+ # Raises UnknownObjectException if the object can't be found.
242
+ def_wrap :readonly?, :readOnly
243
+
244
+ #:startdoc:
245
+
246
+ # return number of maxlength attribute
247
+ def maxlength
248
+ assert_exists
249
+ begin
250
+ ole_object.invoke('maxlength').to_i
251
+ rescue WIN32OLERuntimeError
252
+ 0
253
+ end
254
+ end
255
+
256
+
257
+ def text_string_creator
258
+ n = []
259
+ n << "length:".ljust(TO_S_SIZE) + self.size.to_s
260
+ n << "max length:".ljust(TO_S_SIZE) + self.maxlength.to_s
261
+ n << "read only:".ljust(TO_S_SIZE) + self.readonly?.to_s
262
+ n
263
+ end
264
+ private :text_string_creator
265
+
266
+ def to_s
267
+ assert_exists
268
+ r = string_creator
269
+ r += text_string_creator
270
+ r.join("\n")
271
+ end
272
+
273
+ def assert_not_readonly #:nodoc:
274
+ if self.readonly?
275
+ raise ObjectReadOnlyException,
276
+ "Textfield #{@how} and #{@what} is read only."
277
+ end
278
+ end
279
+
280
+ # Returns true if the text field contents is matches the specified target,
281
+ # which can be either a string or a regular expression.
282
+ # Raises UnknownObjectException if the object can't be found
283
+ #--
284
+ # I vote for deprecating this
285
+ # we should use text_field().text.include?(some) or text.match(/some/) instead of this method
286
+ def verify_contains(target) #:nodoc:
287
+ assert_exists
288
+ if target.kind_of? String
289
+ return true if self.value == target
290
+ elsif target.kind_of? Regexp
291
+ return true if self.value.match(target) != nil
292
+ end
293
+ return false
294
+ end
295
+
296
+ # Drag the entire contents of the text field to another text field
297
+ # 19 Jan 2005 - It is added as prototype functionality, and may change
298
+ # * destination_how - symbol, :id, :name how we identify the drop target
299
+ # * destination_what - string or regular expression, the name, id, etc of the text field that will be the drop target
300
+ def drag_contents_to(destination_how, destination_what)
301
+ assert_exists
302
+ destination = @container.text_field(destination_how, destination_what)
303
+ unless destination.exists?
304
+ raise UnknownObjectException, "Unable to locate destination using #{destination_how } and #{destination_what } "
305
+ end
306
+
307
+ @o.focus
308
+ @o.select
309
+ value = self.value
310
+
311
+ @o.fireEvent("onSelect")
312
+ @o.fireEvent("ondragstart")
313
+ @o.fireEvent("ondrag")
314
+ destination.fireEvent("onDragEnter")
315
+ destination.fireEvent("onDragOver")
316
+ destination.fireEvent("ondrop")
317
+
318
+ @o.fireEvent("ondragend")
319
+ destination.value = destination.value + value.to_s
320
+ self.value = ""
321
+ end
322
+
323
+ # Clears the contents of the text box.
324
+ # Raises UnknownObjectException if the object can't be found
325
+ # Raises ObjectDisabledException if the object is disabled
326
+ # Raises ObjectReadOnlyException if the object is read only
327
+ def clear
328
+ assert_enabled
329
+ assert_not_readonly
330
+
331
+ highlight(:set)
332
+
333
+ @o.scrollIntoView
334
+ @o.focus
335
+ @o.select
336
+ @o.fireEvent("onSelect")
337
+ @o.value = ""
338
+ @o.fireEvent("onKeyPress")
339
+ @o.fireEvent("onChange")
340
+ @container.wait
341
+ highlight(:clear)
342
+ end
343
+
344
+ # Appends the specified string value to the contents of the text box.
345
+ # Raises UnknownObjectException if the object cant be found
346
+ # Raises ObjectDisabledException if the object is disabled
347
+ # Raises ObjectReadOnlyException if the object is read only
348
+ def append(value)
349
+ assert_enabled
350
+ assert_not_readonly
351
+
352
+ highlight(:set)
353
+ @o.scrollIntoView
354
+ @o.focus
355
+ type_by_character(value)
356
+ highlight(:clear)
357
+ end
358
+
359
+ # Sets the contents of the text box to the specified text value
360
+ # Raises UnknownObjectException if the object cant be found
361
+ # Raises ObjectDisabledException if the object is disabled
362
+ # Raises ObjectReadOnlyException if the object is read only
363
+ def set(value)
364
+ assert_enabled
365
+ assert_not_readonly
366
+
367
+ highlight(:set)
368
+ @o.scrollIntoView
369
+ if type_keys
370
+ @o.focus
371
+ @o.select
372
+ @o.fireEvent("onSelect")
373
+ @o.fireEvent("onKeyPress")
374
+ @o.value = ""
375
+ type_by_character(value)
376
+ @o.fireEvent("onChange")
377
+ @o.fireEvent("onBlur")
378
+ else
379
+ @o.value = limit_to_maxlength(value)
380
+ end
381
+ highlight(:clear)
382
+ end
383
+
384
+ # Sets the value of the text field directly.
385
+ # It causes no events to be fired or exceptions to be raised,
386
+ # so generally shouldn't be used.
387
+ # It is preffered to use the set method.
388
+ def value=(v)
389
+ assert_exists
390
+ @o.value = v.to_s
391
+ end
392
+
393
+ def requires_typing #:nodoc:
394
+ @type_keys = true
395
+ self
396
+ end
397
+ def abhors_typing #:nodoc:
398
+ @type_keys = false
399
+ self
400
+ end
401
+
402
+ private
403
+
404
+ # Type the characters in the specified string (value) one by one.
405
+ # It should not be used externally.
406
+ # * value - string - The string to enter into the text field
407
+ def type_by_character(value)
408
+ value = limit_to_maxlength(value)
409
+ characters_in(value) do |c|
410
+ sleep @container.typingspeed
411
+ @o.value = @o.value.to_s + c
412
+ @o.fireEvent("onKeyDown")
413
+ @o.fireEvent("onKeyPress")
414
+ @o.fireEvent("onKeyUp")
415
+ end
416
+ end
417
+
418
+ # Supports double-byte characters
419
+ def characters_in(value, &blk)
420
+ if RUBY_VERSION =~ /^1\.8/
421
+ index = 0
422
+ while index < value.length
423
+ len = value[index] > 128 ? 2 : 1
424
+ yield value[index, len]
425
+ index += len
426
+ end
427
+ else
428
+ value.each_char(&blk)
429
+ end
430
+ end
431
+
432
+ # Return the value (a string), limited to the maxlength of the element.
433
+ def limit_to_maxlength(value)
434
+ return value if @o.invoke('type') =~ /textarea/i # text areas don't have maxlength
435
+ if value.length > maxlength
436
+ value = value[0 .. maxlength - 1]
437
+ @container.log " Supplied string is #{value.length} chars, which exceeds the max length (#{maxlength}) of the field. Using value: #{value}"
438
+ end
439
+ value
440
+ end
441
+ end
442
+
443
+ # this class can be used to access hidden field objects
444
+ # Normally a user would not need to create this object as it is returned by the Watir::Container#hidden method
445
+ class Hidden < TextField
446
+ #:stopdoc:
447
+ INPUT_TYPES = ["hidden"]
448
+ #:startdoc:
449
+
450
+ # set is overriden in this class, as there is no way to set focus to a hidden field
451
+ def set(n)
452
+ self.value = n
453
+ end
454
+
455
+ # override the append method, so that focus isnt set to the hidden object
456
+ def append(n)
457
+ self.value = self.value.to_s + n.to_s
458
+ end
459
+
460
+ # override the clear method, so that focus isnt set to the hidden object
461
+ def clear
462
+ self.value = ""
463
+ end
464
+
465
+ # this method will do nothing, as you cant set focus to a hidden field
466
+ def focus
467
+ end
468
+
469
+ # Hidden element is never visible - returns false.
470
+ def visible?
471
+ assert_exists
472
+ false
473
+ end
474
+
475
+ end
476
+
477
+ # For fields that accept file uploads
478
+ # Windows dialog is opened and handled in this case by autoit
479
+ # launching into a new process.
480
+ # Normally a user would not need to create this object as it is returned by the Watir::Container#file_field method
481
+ class FileField < InputElement
482
+ #:stopdoc:
483
+ INPUT_TYPES = ["file"]
484
+ POPUP_TITLES = ['Choose file', 'Choose File to Upload']
485
+ #:startdoc:
486
+
487
+ # set the file location in the Choose file dialog in a new process
488
+ # will raise a WatirException if AutoIt is not correctly installed
489
+ def set(path_to_file)
490
+ assert_exists
491
+ require 'watir/windowhelper'
492
+ WindowHelper.check_autoit_installed
493
+ begin
494
+ Thread.new do
495
+ sleep 1 # it takes some time for popup to appear
496
+
497
+ system %{ruby -e '
498
+ require "win32ole"
499
+
500
+ @autoit = WIN32OLE.new("AutoItX3.Control")
501
+ time = Time.now
502
+
503
+ while (Time.now - time) < 15 # the loop will wait up to 15 seconds for popup to appear
504
+ #{POPUP_TITLES.inspect}.each do |popup_title|
505
+ next unless @autoit.WinWait(popup_title, "", 1) == 1
506
+
507
+ @autoit.ControlSetText(popup_title, "", "Edit1", #{path_to_file.inspect})
508
+ @autoit.ControlSend(popup_title, "", "Button2", "{ENTER}")
509
+ exit
510
+ end # each
511
+ end # while
512
+ '}
513
+ end.join(1)
514
+ rescue
515
+ raise Watir::Exception::WatirException, "Problem accessing Choose file dialog"
516
+ end
517
+ click
518
+ end
519
+ end
520
+
521
+ # This class contains common methods to both radio buttons and check boxes.
522
+ # Normally a user would not need to create this object as it is returned by the Watir::Container#checkbox or by Watir::Container#radio methods
523
+ #--
524
+ # most of the methods available to this element are inherited from the Element class
525
+ class RadioCheckCommon < InputElement
526
+ def locate #:nodoc:
527
+ @o = @container.locate_input_element(@how, @what, self.class::INPUT_TYPES, @value)
528
+ end
529
+ def initialize(container, how, what, value=nil)
530
+ super container, how, what
531
+ @value = value
532
+ end
533
+
534
+ def inspect
535
+ '#<%s:0x%x located=%s how=%s what=%s value=%s>' % [self.class, hash*2, !!ole_object, @how.inspect, @what.inspect, @value.inspect]
536
+ end
537
+
538
+ # This method determines if a radio button or check box is set.
539
+ # Returns true if set/checked; false if not set/checked.
540
+ # Raises UnknownObjectException if its unable to locate an object.
541
+ def set?
542
+ assert_exists
543
+ return @o.checked
544
+ end
545
+ alias checked? set?
546
+
547
+ # This method is the common code for setting or clearing checkboxes and radio.
548
+ def set_clear_item(set)
549
+ @o.checked = set
550
+ @o.fireEvent("onClick")
551
+ @container.wait
552
+ end
553
+ private :set_clear_item
554
+
555
+ end
556
+
557
+ #--
558
+ # this class makes the docs better
559
+ #++
560
+ # This class is the watir representation of a radio button.
561
+ # Normally a user would not need to create this object as it is returned by the Watir::Container#radio method
562
+ class Radio < RadioCheckCommon
563
+ INPUT_TYPES = ["radio"]
564
+ # This method clears a radio button. One of them will almost always be set.
565
+ # Returns true if set or false if not set.
566
+ # Raises UnknownObjectException if its unable to locate an object
567
+ # ObjectDisabledException IF THE OBJECT IS DISABLED
568
+ def clear
569
+ assert_enabled
570
+ highlight(:set)
571
+ set_clear_item(false)
572
+ highlight(:clear)
573
+ end
574
+
575
+ # This method sets the radio list item.
576
+ # Raises UnknownObjectException if it's unable to locate an object
577
+ # ObjectDisabledException if the object is disabled
578
+ def set
579
+ assert_enabled
580
+ highlight(:set)
581
+ @o.scrollIntoView
582
+ set_clear_item(true)
583
+ highlight(:clear)
584
+ end
585
+
586
+ end
587
+
588
+ # This class is the watir representation of a check box.
589
+ # Normally a user would not need to create this object as it is returned by the Watir::Container#checkbox method
590
+ class CheckBox < RadioCheckCommon
591
+ INPUT_TYPES = ["checkbox"]
592
+ # This method checks or unchecks the checkbox.
593
+ # With no arguments supplied it sets the checkbox.
594
+ # Setting false argument unchecks/clears the checkbox.
595
+ # Raises UnknownObjectException if it's unable to locate an object
596
+ # ObjectDisabledException if the object is disabled
597
+ def set(value=true)
598
+ assert_enabled
599
+ highlight :set
600
+ unless @o.checked == value
601
+ set_clear_item value
602
+ end
603
+ highlight :clear
604
+ end
605
+
606
+ # Clears a check box.
607
+ # Raises UnknownObjectException if its unable to locate an object
608
+ # ObjectDisabledException if the object is disabled
609
+ def clear
610
+ set false
611
+ end
612
+
613
+ end
614
+
573
615
  end