watir 1.5.2 → 1.5.3

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