watir 1.6.2 → 1.6.5

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