watir 1.5.2 → 1.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,131 @@
1
+ module Watir
2
+
3
+ # This class is the means of accessing an image on a page.
4
+ # Normally a user would not need to create this object as it is returned by the Watir::Container#image method
5
+ #
6
+ # many of the methods available to this object are inherited from the Element class
7
+ #
8
+ class Image < Element
9
+ def initialize(container, how, what)
10
+ set_container container
11
+ @how = how
12
+ @what = what
13
+ super nil
14
+ end
15
+
16
+ def locate
17
+ if @how == :xpath
18
+ @o = @container.element_by_xpath(@what)
19
+ else
20
+ @o = @container.locate_tagged_element('IMG', @how, @what)
21
+ end
22
+ end
23
+
24
+ # this method produces the properties for an image as an array
25
+ def image_string_creator
26
+ n = []
27
+ n << "src:".ljust(TO_S_SIZE) + self.src.to_s
28
+ n << "file date:".ljust(TO_S_SIZE) + self.fileCreatedDate.to_s
29
+ n << "file size:".ljust(TO_S_SIZE) + self.fileSize.to_s
30
+ n << "width:".ljust(TO_S_SIZE) + self.width.to_s
31
+ n << "height:".ljust(TO_S_SIZE) + self.height.to_s
32
+ n << "alt:".ljust(TO_S_SIZE) + self.alt.to_s
33
+ return n
34
+ end
35
+ private :image_string_creator
36
+
37
+ # returns a string representation of the object
38
+ def to_s
39
+ assert_exists
40
+ r = string_creator
41
+ r += image_string_creator
42
+ return r.join("\n")
43
+ end
44
+
45
+ # this method returns the file created date of the image
46
+ def fileCreatedDate
47
+ assert_exists
48
+ return @o.invoke("fileCreatedDate")
49
+ end
50
+
51
+ # this method returns the filesize of the image
52
+ def fileSize
53
+ assert_exists
54
+ return @o.invoke("fileSize").to_s
55
+ end
56
+
57
+ # returns the width in pixels of the image, as a string
58
+ def width
59
+ assert_exists
60
+ return @o.invoke("width").to_s
61
+ end
62
+
63
+ # returns the height in pixels of the image, as a string
64
+ def height
65
+ assert_exists
66
+ return @o.invoke("height").to_s
67
+ end
68
+
69
+ # This method attempts to find out if the image was actually loaded by the web browser.
70
+ # If the image was not loaded, the browser is unable to determine some of the properties.
71
+ # We look for these missing properties to see if the image is really there or not.
72
+ # If the Disk cache is full (tools menu -> Internet options -> Temporary Internet Files), it may produce incorrect responses.
73
+ def hasLoaded?
74
+ locate
75
+ raise UnknownObjectException, "Unable to locate image using #{@how} and #{@what}" if @o == nil
76
+ return false if @o.fileCreatedDate == "" and @o.fileSize.to_i == -1
77
+ return true
78
+ end
79
+
80
+ # this method highlights the image (in fact it adds or removes a border around the image)
81
+ # * set_or_clear - symbol - :set to set the border, :clear to remove it
82
+ def highlight(set_or_clear)
83
+ if set_or_clear == :set
84
+ begin
85
+ @original_border = @o.border
86
+ @o.border = 1
87
+ rescue
88
+ @original_border = nil
89
+ end
90
+ else
91
+ begin
92
+ @o.border = @original_border
93
+ @original_border = nil
94
+ rescue
95
+ # we could be here for a number of reasons...
96
+ ensure
97
+ @original_border = nil
98
+ end
99
+ end
100
+ end
101
+ private :highlight
102
+
103
+ # This method saves the image to the file path that is given. The
104
+ # path must be in windows format (c:\\dirname\\somename.gif). This method
105
+ # will not overwrite a previously existing image. If an image already
106
+ # exists at the given path then a dialog will be displayed prompting
107
+ # for overwrite.
108
+ # Raises a WatirException if AutoIt is not correctly installed
109
+ # path - directory path and file name of where image should be saved
110
+ def save(path)
111
+ require 'watir/windowhelper'
112
+ WindowHelper.check_autoit_installed
113
+ @container.goto(src)
114
+ begin
115
+ thrd = fill_save_image_dialog(path)
116
+ @container.document.execCommand("SaveAs")
117
+ thrd.join(5)
118
+ ensure
119
+ @container.back
120
+ end
121
+ end
122
+
123
+ def fill_save_image_dialog(path)
124
+ Thread.new do
125
+ system("ruby -e \"require 'win32ole'; @autoit=WIN32OLE.new('AutoItX3.Control'); waitresult=@autoit.WinWait 'Save Picture', '', 15; if waitresult == 1\" -e \"@autoit.ControlSetText 'Save Picture', '', '1148', '#{path}'; @autoit.ControlSend 'Save Picture', '', '1', '{ENTER}';\" -e \"end\"")
126
+ end
127
+ end
128
+ private :fill_save_image_dialog
129
+ end
130
+
131
+ end
@@ -0,0 +1,518 @@
1
+ module Watir
2
+
3
+ class InputElement < Element
4
+ def locate
5
+ if @how == :xpath
6
+ @o = @container.element_by_xpath(@what)
7
+ elsif @how == :ole_object
8
+ @o = @what
9
+ else
10
+ @o = @container.locate_input_element(@how, @what, self.class::INPUT_TYPES)
11
+ end
12
+ end
13
+ def initialize(container, how, what)
14
+ set_container container
15
+ @how = how
16
+ @what = what
17
+ super(nil)
18
+ end
19
+ end
20
+
21
+ # This class is the way in which select boxes are manipulated.
22
+ # Normally a user would not need to create this object as it is returned by the Watir::Container#select_list method
23
+ class SelectList < InputElement
24
+ INPUT_TYPES = ["select-one", "select-multiple"]
25
+
26
+ attr_accessor :o
27
+
28
+ # This method clears the selected items in the select box
29
+ def clearSelection
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
+ # private :clearSelection
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 or an array of string and reg exps
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)
64
+ assert_exists
65
+ highlight(:set)
66
+ doBreak = false
67
+ @container.log "Setting box #{@o.name} to #{attribute} #{value} "
68
+ @o.each do |option| # items in the list
69
+ if value.matches(option.invoke(attribute.to_s))
70
+ if option.selected
71
+ doBreak = true
72
+ break
73
+ else
74
+ option.selected = true
75
+ @o.fireEvent("onChange")
76
+ @container.wait
77
+ doBreak = true
78
+ break
79
+ end
80
+ end
81
+ end
82
+ unless doBreak
83
+ raise NoValueFoundException,
84
+ "No option with #{attribute.to_s} of #{value} in this select element"
85
+ end
86
+ highlight(:clear)
87
+ end
88
+
89
+ # Returns all the items in the select list as an array.
90
+ # An empty array is returned if the select box has no contents.
91
+ # Raises UnknownObjectException if the select box is not found
92
+ def getAllContents # BUG: camel_case.rb
93
+ assert_exists
94
+ @container.log "There are #{@o.length} items"
95
+ returnArray = []
96
+ @o.each { |thisItem| returnArray << thisItem.text }
97
+ return returnArray
98
+ end
99
+
100
+ # Returns the selected items as an array.
101
+ # Raises UnknownObjectException if the select box is not found.
102
+ def getSelectedItems
103
+ assert_exists
104
+ returnArray = []
105
+ @container.log "There are #{@o.length} items"
106
+ @o.each do |thisItem|
107
+ if thisItem.selected
108
+ @container.log "Item (#{thisItem.text}) is selected"
109
+ returnArray << thisItem.text
110
+ end
111
+ end
112
+ return returnArray
113
+ end
114
+
115
+ # Does the SelectList include the specified option (text)?
116
+ def includes? text
117
+ getAllContents.include? text
118
+ end
119
+
120
+ # Is the specified option (text) selected? Raises exception of option does not exist.
121
+ def selected? text
122
+ unless includes? text
123
+ raise UnknownObjectException, "Option #{text} not found."
124
+ end
125
+ getSelectedItems.include? text
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
+ # This is the main class for accessing buttons.
189
+ # Normally a user would not need to create this object as it is
190
+ # returned by the Watir::Container#button method
191
+ class Button < InputElement
192
+ INPUT_TYPES = ["button", "submit", "image", "reset"]
193
+ end
194
+
195
+ # This class is the main class for Text Fields
196
+ # Normally a user would not need to create this object as it is returned by the Watir::Container#text_field method
197
+ class TextField < InputElement
198
+ INPUT_TYPES = ["text", "password", "textarea"]
199
+
200
+ def_wrap_guard :size
201
+
202
+ def maxlength
203
+ assert_exists
204
+ begin
205
+ ole_object.invoke('maxlength').to_i
206
+ rescue
207
+ 0
208
+ end
209
+ end
210
+
211
+
212
+ # Returns true or false if the text field is read only.
213
+ # Raises UnknownObjectException if the object can't be found.
214
+ def_wrap :readonly?, :readOnly
215
+
216
+ def text_string_creator
217
+ n = []
218
+ n << "length:".ljust(TO_S_SIZE) + self.size.to_s
219
+ n << "max length:".ljust(TO_S_SIZE) + self.maxlength.to_s
220
+ n << "read only:".ljust(TO_S_SIZE) + self.readonly?.to_s
221
+
222
+ return n
223
+ end
224
+ private :text_string_creator
225
+
226
+ def to_s
227
+ assert_exists
228
+ r = string_creator
229
+ r += text_string_creator
230
+ return r.join("\n")
231
+ end
232
+
233
+ def assert_not_readonly
234
+ raise ObjectReadOnlyException, "Textfield #{@how} and #{@what} is read only." if self.readonly?
235
+ end
236
+
237
+ # This method returns true or false if the text field contents is either a string match
238
+ # or a regular expression match to the supplied value.
239
+ # Raises UnknownObjectException if the object can't be found
240
+ # * containsThis - string or reg exp - the text to verify
241
+ def verify_contains(containsThis) # FIXME: verify_contains should have same name and semantics as IE#contains_text (prolly make this work for all elements)
242
+ assert_exists
243
+ if containsThis.kind_of? String
244
+ return true if self.value == containsThis
245
+ elsif containsThis.kind_of? Regexp
246
+ return true if self.value.match(containsThis) != nil
247
+ end
248
+ return false
249
+ end
250
+
251
+ # this method is used to drag the entire contents of the text field to another text field
252
+ # 19 Jan 2005 - It is added as prototype functionality, and may change
253
+ # * destination_how - symbol, :id, :name how we identify the drop target
254
+ # * destination_what - string or regular expression, the name, id, etc of the text field that will be the drop target
255
+ def dragContentsTo(destination_how, destination_what)
256
+ assert_exists
257
+ destination = @container.text_field(destination_how, destination_what)
258
+ raise UnknownObjectException, "Unable to locate destination using #{destination_how } and #{destination_what } " if destination.exists? == false
259
+
260
+ @o.focus
261
+ @o.select
262
+ value = self.value
263
+
264
+ @o.fireEvent("onSelect")
265
+ @o.fireEvent("ondragstart")
266
+ @o.fireEvent("ondrag")
267
+ destination.fireEvent("onDragEnter")
268
+ destination.fireEvent("onDragOver")
269
+ destination.fireEvent("ondrop")
270
+
271
+ @o.fireEvent("ondragend")
272
+ destination.value = destination.value + value.to_s
273
+ self.value = ""
274
+ end
275
+
276
+ # This method clears the contents of the text box.
277
+ # Raises UnknownObjectException if the object can't be found
278
+ # Raises ObjectDisabledException if the object is disabled
279
+ # Raises ObjectReadOnlyException if the object is read only
280
+ def clear
281
+ assert_enabled
282
+ assert_not_readonly
283
+
284
+ highlight(:set)
285
+
286
+ @o.scrollIntoView
287
+ @o.focus
288
+ @o.select
289
+ @o.fireEvent("onSelect")
290
+ @o.value = ""
291
+ @o.fireEvent("onKeyPress")
292
+ @o.fireEvent("onChange")
293
+ @container.wait
294
+ highlight(:clear)
295
+ end
296
+
297
+ # This method appens the supplied text to the contents of the text box.
298
+ # Raises UnknownObjectException if the object cant be found
299
+ # Raises ObjectDisabledException if the object is disabled
300
+ # Raises ObjectReadOnlyException if the object is read only
301
+ # * setThis - string - the text to append
302
+ def append(setThis)
303
+ assert_enabled
304
+ assert_not_readonly
305
+
306
+ highlight(:set)
307
+ @o.scrollIntoView
308
+ @o.focus
309
+ doKeyPress(setThis)
310
+ highlight(:clear)
311
+ end
312
+
313
+ # This method sets the contents of the text box to the supplied text
314
+ # Raises UnknownObjectException if the object cant be found
315
+ # Raises ObjectDisabledException if the object is disabled
316
+ # Raises ObjectReadOnlyException if the object is read only
317
+ # * setThis - string - the text to set
318
+ def set(setThis)
319
+ assert_enabled
320
+ assert_not_readonly
321
+
322
+ highlight(:set)
323
+ @o.scrollIntoView
324
+ @o.focus
325
+ @o.select
326
+ @o.fireEvent("onSelect")
327
+ @o.value = ""
328
+ @o.fireEvent("onKeyPress")
329
+ doKeyPress(setThis)
330
+ highlight(:clear)
331
+ @o.fireEvent("onChange")
332
+ @o.fireEvent("onBlur")
333
+ end
334
+
335
+ # this method sets the value of the text field directly. It causes no events to be fired or exceptions to be raised, so generally shouldnt be used
336
+ # it is preffered to use the set method.
337
+ def value=(v)
338
+ assert_exists
339
+ @o.value = v.to_s
340
+ end
341
+
342
+ private
343
+
344
+ # This method is used internally by setText and appendText
345
+ # It should not be used externally.
346
+ # * value - string - The string to enter into the text field
347
+ def doKeyPress(value)
348
+ value = limit_to_maxlength(value)
349
+ for i in 0 .. value.length - 1
350
+ sleep @container.typingspeed
351
+ c = value[i,1]
352
+ @o.value = @o.value.to_s + c
353
+ @o.fireEvent("onKeyDown")
354
+ @o.fireEvent("onKeyPress")
355
+ @o.fireEvent("onKeyUp")
356
+ end
357
+ end
358
+
359
+ # Return the value (a string), limited to the maxlength of the element.
360
+ def limit_to_maxlength(value)
361
+ return value if @o.invoke('type') =~ /textarea/i # text areas don't have maxlength
362
+ if value.length > maxlength
363
+ value = value[0 .. maxlength - 1]
364
+ @container.log " Supplied string is #{value.length} chars, which exceeds the max length (#{maxlength}) of the field. Using value: #{value}"
365
+ end
366
+ value
367
+ end
368
+ end
369
+
370
+ # this class can be used to access hidden field objects
371
+ # Normally a user would not need to create this object as it is returned by the Watir::Container#hidden method
372
+ class Hidden < TextField
373
+ INPUT_TYPES = ["hidden"]
374
+
375
+ # set is overriden in this class, as there is no way to set focus to a hidden field
376
+ def set(n)
377
+ self.value = n
378
+ end
379
+
380
+ # override the append method, so that focus isnt set to the hidden object
381
+ def append(n)
382
+ self.value = self.value.to_s + n.to_s
383
+ end
384
+
385
+ # override the clear method, so that focus isnt set to the hidden object
386
+ def clear
387
+ self.value = ""
388
+ end
389
+
390
+ # this method will do nothing, as you cant set focus to a hidden field
391
+ def focus
392
+ end
393
+
394
+ end
395
+
396
+ # This class is the class for fields that accept file uploads
397
+ # Windows dialog is opened and handled in this case by autoit
398
+ # launching into a new process.
399
+ class FileField < InputElement
400
+ INPUT_TYPES = ["file"]
401
+
402
+ # set the file location in the Choose file dialog in a new process
403
+ # will raise a Watir Exception if AutoIt is not correctly installed
404
+ def set(setPath)
405
+ assert_exists
406
+ require 'watir/windowhelper'
407
+ WindowHelper.check_autoit_installed
408
+ begin
409
+ thrd = Thread.new do
410
+ system("rubyw -e \"require 'win32ole'; @autoit=WIN32OLE.new('AutoItX3.Control'); waitresult=@autoit.WinWait 'Choose file', '', 15; if waitresult == 1\" -e \"@autoit.ControlSetText 'Choose file', '', 'Edit1', '#{setPath}'; @autoit.ControlSend 'Choose file', '', 'Button2', '{ENTER}';\" -e \"end\"")
411
+ end
412
+ thrd.join(1)
413
+ rescue
414
+ raise Watir::Exception::WatirException, "Problem accessing Choose file dialog"
415
+ end
416
+ click
417
+ end
418
+ end
419
+
420
+ # This class is the class for radio buttons and check boxes.
421
+ # It contains methods common to both.
422
+ # Normally a user would not need to create this object as it is returned by the Watir::Container#checkbox or Watir::Container#radio methods
423
+ #
424
+ # most of the methods available to this element are inherited from the Element class
425
+ #
426
+ class RadioCheckCommon < Element
427
+ def locate
428
+ if @how == :xpath
429
+ @o = @container.element_by_xpath(@what)
430
+ else
431
+ @o = @container.locate_input_element(@how, @what, @type, @value)
432
+ end
433
+ end
434
+ def initialize(container, how, what, type, value=nil)
435
+ set_container container
436
+ @how = how
437
+ @what = what
438
+ @type = type
439
+ @value = value
440
+ super(nil)
441
+ end
442
+
443
+ # BUG: rename me
444
+ # This method determines if a radio button or check box is set.
445
+ # Returns true is set/checked or false if not set/checked.
446
+ # Raises UnknownObjectException if its unable to locate an object.
447
+ def isSet?
448
+ assert_exists
449
+ return @o.checked
450
+ end
451
+ alias getState isSet?
452
+ alias checked? isSet?
453
+
454
+ # This method clears a radio button or check box. Note, with radio buttons one of them will almost always be set.
455
+ # Returns true if set or false if not set.
456
+ # Raises UnknownObjectException if its unable to locate an object
457
+ # ObjectDisabledException IF THE OBJECT IS DISABLED
458
+ def clear
459
+ assert_enabled
460
+ highlight(:set)
461
+ set_clear_item(false)
462
+ highlight(:clear)
463
+ end
464
+
465
+ # This method sets the radio list item or check box.
466
+ # Raises UnknownObjectException if it's unable to locate an object
467
+ # ObjectDisabledException if the object is disabled
468
+ def set
469
+ assert_enabled
470
+ highlight(:set)
471
+ set_clear_item(true)
472
+ highlight(:clear)
473
+ end
474
+
475
+ # This method is the common code for setting or clearing checkboxes and radio.
476
+ def set_clear_item(set)
477
+ @o.checked = set
478
+ @o.fireEvent("onClick")
479
+ @container.wait
480
+ end
481
+ private :set_clear_item
482
+
483
+ end
484
+
485
+ #--
486
+ # this class makes the docs better
487
+ #++
488
+ # This class is the watir representation of a radio button.
489
+ class Radio < RadioCheckCommon
490
+ end
491
+
492
+ # This class is the watir representation of a check box.
493
+ class CheckBox < RadioCheckCommon
494
+
495
+ # With no arguments supplied, sets the check box.
496
+ # If the optional value is supplied, the checkbox is set, when its true and
497
+ # cleared when its false
498
+ # Raises UnknownObjectException if it's unable to locate an object
499
+ # ObjectDisabledException if the object is disabled
500
+ def set(value=true)
501
+ assert_enabled
502
+ highlight :set
503
+ unless @o.checked == value
504
+ set_clear_item value
505
+ end
506
+ highlight :clear
507
+ end
508
+
509
+ # Clears a check box.
510
+ # Raises UnknownObjectException if its unable to locate an object
511
+ # ObjectDisabledException if the object is disabled
512
+ def clear
513
+ set false
514
+ end
515
+
516
+ end
517
+
518
+ end