watir 3.0.0.rc2 → 3.0.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/CHANGES +19 -0
  2. data/VERSION +1 -1
  3. data/lib/watir/close_all.rb +2 -2
  4. data/lib/watir/container.rb +6 -4
  5. data/lib/watir/cookies.rb +80 -0
  6. data/lib/watir/core.rb +7 -3
  7. data/lib/watir/dialogs/file_field.rb +0 -4
  8. data/lib/watir/drag_and_drop_helper.rb +68 -0
  9. data/lib/watir/element.rb +58 -156
  10. data/lib/watir/element_collection.rb +109 -0
  11. data/lib/watir/form.rb +7 -14
  12. data/lib/watir/frame.rb +11 -26
  13. data/lib/watir/ie-class.rb +17 -307
  14. data/lib/watir/ie.rb +0 -9
  15. data/lib/watir/image.rb +8 -25
  16. data/lib/watir/input_elements.rb +32 -81
  17. data/lib/watir/link.rb +2 -17
  18. data/lib/watir/locator.rb +29 -25
  19. data/lib/watir/modal_dialog.rb +26 -40
  20. data/lib/watir/non_control_elements.rb +111 -79
  21. data/lib/watir/page-container.rb +12 -1
  22. data/lib/watir/supported_elements.rb +172 -0
  23. data/lib/watir/table.rb +61 -89
  24. data/lib/watir/win32ole.rb +2 -3
  25. data/lib/watir/win32ole/1.9.3/win32ole.so +0 -0
  26. data/lib/watir/xpath_locator.rb +52 -0
  27. data/rakefile.rb +1 -1
  28. data/unittests/checkbox_test.rb +22 -32
  29. data/unittests/css_selector_test.rb +1 -6
  30. data/unittests/css_test.rb +1 -4
  31. data/unittests/div_test.rb +3 -21
  32. data/unittests/document_standards.rb +0 -4
  33. data/unittests/element_collections_test.rb +2 -2
  34. data/unittests/element_test.rb +1 -1
  35. data/unittests/form_test.rb +0 -30
  36. data/unittests/frame_test.rb +8 -49
  37. data/unittests/ie_test.rb +5 -9
  38. data/unittests/images_test.rb +6 -6
  39. data/unittests/index_specifier_test.rb +0 -1
  40. data/unittests/js_events_test.rb +1 -1
  41. data/unittests/links_multi_test.rb +0 -14
  42. data/unittests/links_test.rb +8 -51
  43. data/unittests/lists_test.rb +0 -9
  44. data/unittests/navigate_test.rb +1 -1
  45. data/unittests/nbsp_xpath_test.rb +1 -1
  46. data/unittests/no_wait_test.rb +3 -3
  47. data/unittests/parent_child_test.rb +0 -17
  48. data/unittests/pre_test.rb +0 -3
  49. data/unittests/radios_test.rb +31 -42
  50. data/unittests/selectbox_test.rb +18 -21
  51. data/unittests/selectbox_xpath_test.rb +11 -26
  52. data/unittests/table_test.rb +14 -79
  53. data/unittests/textfields_test.rb +8 -47
  54. data/unittests/windows/attach_to_new_window_test.rb +0 -8
  55. data/unittests/windows/frame_links_test.rb +5 -5
  56. data/unittests/windows/ie-each_test.rb +1 -1
  57. data/unittests/windows/modal_dialog_test.rb +2 -2
  58. data/watir.gemspec +3 -3
  59. metadata +81 -126
  60. data/lib/watir/camel_case.rb +0 -67
  61. data/lib/watir/collections.rb +0 -48
  62. data/lib/watir/cookiemanager.rb +0 -56
  63. data/lib/watir/element_collections.rb +0 -81
  64. data/lib/watir/html_element.rb +0 -30
  65. data/unittests/defer_test.rb +0 -47
  66. data/unittests/multiple_specifiers_test.rb +0 -29
  67. data/unittests/table_and_tablerow_to_a_test.rb +0 -117
  68. data/unittests/windows/iedialog_test.rb +0 -53
@@ -18,12 +18,3 @@ $FAST_SPEED = ARGV.delete('-f')
18
18
 
19
19
  # Eat the -s command line switch (deprecated)
20
20
  ARGV.delete('-s')
21
-
22
- require 'watir/win32'
23
- require 'watir/modal_dialog'
24
- require 'watir/collections'
25
-
26
- require 'watir/camel_case'
27
-
28
-
29
-
@@ -6,15 +6,10 @@ module Watir
6
6
  # many of the methods available to this object are inherited from the Element class
7
7
  #
8
8
  class Image < Element
9
- TAG = "IMG"
9
+ attr_ole :alt
10
+ attr_ole :src
11
+ attr_ole :file_created_date, :fileCreatedDate
10
12
 
11
- def initialize(container, how, what)
12
- set_container container
13
- @how = how
14
- @what = what
15
- super nil
16
- end
17
-
18
13
  # this method produces the properties for an image as an array
19
14
  def image_string_creator
20
15
  n = []
@@ -36,28 +31,22 @@ module Watir
36
31
  return r.join("\n")
37
32
  end
38
33
 
39
- # this method returns the file created date of the image
40
- def file_created_date
41
- assert_exists
42
- return @o.invoke("fileCreatedDate")
43
- end
44
-
45
34
  # this method returns the filesize of the image, as an int
46
35
  def file_size
47
36
  assert_exists
48
- return @o.invoke("fileSize").to_i
37
+ @o.invoke("fileSize").to_i
49
38
  end
50
39
 
51
40
  # returns the width in pixels of the image, as an int
52
41
  def width
53
42
  assert_exists
54
- return @o.invoke("width").to_i
43
+ @o.invoke("width").to_i
55
44
  end
56
45
 
57
46
  # returns the height in pixels of the image, as an int
58
47
  def height
59
48
  assert_exists
60
- return @o.invoke("height").to_i
49
+ @o.invoke("height").to_i
61
50
  end
62
51
 
63
52
  # This method attempts to find out if the image was actually loaded by the web browser.
@@ -65,10 +54,8 @@ module Watir
65
54
  # We look for these missing properties to see if the image is really there or not.
66
55
  # If the Disk cache is full (tools menu -> Internet options -> Temporary Internet Files), it may produce incorrect responses.
67
56
  def loaded?
68
- locate
69
- raise UnknownObjectException, "Unable to locate image using #{@how} and #{@what}" if @o == nil
70
- return false if @o.fileCreatedDate == "" and @o.fileSize.to_i == -1
71
- return true
57
+ assert_exists
58
+ !file_created_date.empty? && file_size != -1
72
59
  end
73
60
 
74
61
  # this method highlights the image (in fact it adds or removes a border around the image)
@@ -119,10 +106,6 @@ module Watir
119
106
  end
120
107
  private :fill_save_image_dialog
121
108
 
122
- Watir::Container.module_eval do
123
- alias_method :img, :image
124
- alias_method :imgs, :images
125
- end
126
109
  end
127
110
 
128
111
  end
@@ -2,15 +2,15 @@ module Watir
2
2
 
3
3
  class InputElement < Element #:nodoc:all
4
4
  def locate
5
- @o = @container.locator_for(InputElementLocator, self.class::INPUT_TYPES, @how, @what, self.class).locate
5
+ @o = @container.locator_for(InputElementLocator, @specifiers, self.class).locate
6
6
  end
7
7
 
8
- def initialize(container, how, what)
9
- set_container container
10
- @how = how
11
- @what = what
12
- super(nil)
13
- end
8
+ attr_ole :disabled?
9
+ attr_ole :name
10
+ attr_ole :value
11
+ attr_ole :alt
12
+ attr_ole :src
13
+ attr_ole :type
14
14
  end
15
15
 
16
16
  #
@@ -20,11 +20,7 @@ module Watir
20
20
  # This class is the way in which select boxes are manipulated.
21
21
  # Normally a user would not need to create this object as it is returned by the Watir::Container#select_list method
22
22
  class SelectList < InputElement
23
- #:stopdoc:
24
- INPUT_TYPES = ["select-one", "select-multiple"]
25
- #:startdoc:
26
-
27
- def_wrap :multiple?, :multiple
23
+ attr_ole :multiple?
28
24
 
29
25
  # This method clears the selected items in the select box
30
26
  def clear
@@ -82,7 +78,7 @@ module Watir
82
78
  if value.is_a?(Regexp)
83
79
  opt.send(attribute) =~ value
84
80
  elsif value.is_a?(String) || value.is_a?(Numeric)
85
- opt.send(attribute) == value
81
+ opt.send(attribute) == value.to_s
86
82
  else
87
83
  raise TypeError, "#{value.inspect} can be only String, Regexp or Numeric!"
88
84
  end
@@ -90,7 +86,11 @@ module Watir
90
86
  end
91
87
  end
92
88
 
93
- class Option < NonControlElement
89
+ class Option < Element
90
+ attr_ole :disabled?
91
+ attr_ole :name
92
+ attr_ole :value
93
+ attr_ole :label
94
94
 
95
95
  def select
96
96
  perform_action do
@@ -142,10 +142,6 @@ module Watir
142
142
 
143
143
  # Returned by the Watir::Container#button method
144
144
  class Button < InputElement
145
- #:stopdoc:
146
- INPUT_TYPES = ["button", "submit", "image", "reset"]
147
- #:startdoc:
148
-
149
145
  alias_method :__value, :value
150
146
 
151
147
  def text
@@ -154,7 +150,6 @@ module Watir
154
150
  end
155
151
 
156
152
  alias_method :value, :text
157
-
158
153
  end
159
154
 
160
155
  #
@@ -164,15 +159,8 @@ module Watir
164
159
  # This class is the main class for Text Fields
165
160
  # Normally a user would not need to create this object as it is returned by the Watir::Container#text_field method
166
161
  class TextField < InputElement
167
- #:stopdoc:
168
- INPUT_TYPES = ["text", "password", "textarea"]
169
-
170
- def_wrap_guard :size
171
-
172
- # Returns true or false if the text field is read only.
173
- # Raises UnknownObjectException if the object can't be found.
174
- def_wrap :readonly?, :readOnly
175
-
162
+ attr_ole :size
163
+ attr_ole :readonly?
176
164
  alias_method :text, :value
177
165
 
178
166
  #:startdoc:
@@ -206,7 +194,7 @@ module Watir
206
194
  def assert_not_readonly #:nodoc:
207
195
  if self.readonly?
208
196
  raise ObjectReadOnlyException,
209
- "Textfield #{@how} and #{@what} is read only."
197
+ "Textfield #{@specifiers.inspect} is read only."
210
198
  end
211
199
  end
212
200
 
@@ -381,27 +369,9 @@ module Watir
381
369
 
382
370
  end
383
371
 
384
- class TextArea < TextField
385
- INPUT_TYPES = ["textarea"]
386
-
387
- Watir::Container.module_eval do
388
- def textareas(how={}, what=nil)
389
- TextAreas.new(self, how, what)
390
- end
391
-
392
- def textarea(how={}, what=nil)
393
- TextArea.new(self, how, what)
394
- end
395
- end
396
- end
397
-
398
372
  # this class can be used to access hidden field objects
399
373
  # Normally a user would not need to create this object as it is returned by the Watir::Container#hidden method
400
374
  class Hidden < TextField
401
- #:stopdoc:
402
- INPUT_TYPES = ["hidden"]
403
- #:startdoc:
404
-
405
375
  # set is overriden in this class, as there is no way to set focus to a hidden field
406
376
  def set(n)
407
377
  self.value = n
@@ -426,36 +396,30 @@ module Watir
426
396
  assert_exists
427
397
  false
428
398
  end
429
-
430
399
  end
431
400
 
432
- # This class contains common methods to both radio buttons and check boxes.
401
+ # This module contains common methods to both radio buttons and check boxes.
433
402
  # 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
434
- #--
435
- # most of the methods available to this element are inherited from the Element class
436
- class RadioCheckCommon < InputElement
437
- def inspect
438
- '#<%s:0x%x located=%s how=%s what=%s value=%s>' % [self.class, hash*2, !!ole_object, @how.inspect, @what.inspect, @value.inspect]
403
+ module RadioCheckCommon
404
+ def self.included(base)
405
+ base.instance_eval do
406
+ attr_ole :set?, :checked
407
+ alias_method :checked?, :set?
408
+ end
439
409
  end
440
-
441
- # This method determines if a radio button or check box is set.
442
- # Returns true if set/checked; false if not set/checked.
443
- # Raises UnknownObjectException if its unable to locate an object.
444
- def set?
445
- assert_exists
446
- return @o.checked
410
+
411
+ def inspect
412
+ '#<%s:0x%x located=%s specifiers=%s value=%s>' % [self.class, hash*2, !!ole_object, @specifiers.inspect, @value.inspect]
447
413
  end
448
- alias checked? set?
449
-
450
- end
414
+ end
451
415
 
452
416
  #--
453
417
  # this class makes the docs better
454
418
  #++
455
419
  # This class is the watir representation of a radio button.
456
420
  # Normally a user would not need to create this object as it is returned by the Watir::Container#radio method
457
- class Radio < RadioCheckCommon
458
- INPUT_TYPES = ["radio"]
421
+ class Radio < InputElement
422
+ include RadioCheckCommon
459
423
  # This method clears a radio button. One of them will almost always be set.
460
424
  # Returns true if set or false if not set.
461
425
  # Raises UnknownObjectException if its unable to locate an object
@@ -486,8 +450,8 @@ module Watir
486
450
 
487
451
  # This class is the watir representation of a check box.
488
452
  # Normally a user would not need to create this object as it is returned by the Watir::Container#checkbox method
489
- class CheckBox < RadioCheckCommon
490
- INPUT_TYPES = ["checkbox"]
453
+ class CheckBox < InputElement
454
+ include RadioCheckCommon
491
455
  # This method checks or unchecks the checkbox.
492
456
  # With no arguments supplied it sets the checkbox.
493
457
  # Setting false argument unchecks/clears the checkbox.
@@ -511,19 +475,6 @@ module Watir
511
475
  set false
512
476
  end
513
477
 
514
- Watir::Container.module_eval do
515
- remove_method :check_boxs
516
-
517
- def checkboxes(how={}, what=nil)
518
- CheckBoxes.new(self, how, what)
519
- end
520
-
521
- remove_method :check_box
522
-
523
- def checkbox(how={}, what=nil)
524
- CheckBox.new(self, how, what)
525
- end
526
- end
527
478
  end
528
479
 
529
480
  end
@@ -5,19 +5,9 @@ module Watir
5
5
  # many of the methods available to this object are inherited from the Element class
6
6
  #
7
7
  class Link < Element
8
- TAG = "A"
8
+ attr_ole :type
9
+ attr_ole :href
9
10
 
10
- # Returns an initialized instance of a link object
11
- # * container - an instance of a container
12
- # * how - symbol - how we access the link
13
- # * what - what we use to access the link, text, url, index etc
14
- def initialize(container, how, what)
15
- set_container container
16
- @how = how
17
- @what = what
18
- super(nil)
19
- end
20
-
21
11
  # if an image is used as part of the link, this will return true
22
12
  def link_has_image
23
13
  assert_exists
@@ -51,11 +41,6 @@ module Watir
51
41
  return r.join("\n")
52
42
  end
53
43
 
54
- Watir::Container.module_eval do
55
- alias_method :a, :link
56
- alias_method :as, :links
57
- end
58
-
59
44
  end
60
45
 
61
46
  end
@@ -2,10 +2,12 @@ module Watir
2
2
  class Locator
3
3
  include Watir
4
4
  include Watir::Exception
5
+ include XpathLocator
5
6
 
6
- def initialize container, tags, klass
7
+ def initialize container, specifiers, klass
7
8
  @container = container
8
- @tags = tags
9
+ @specifiers = {:index => Watir::IE.base_index}.merge(normalize_specifiers(specifiers))
10
+ @tags = @specifiers.delete(:tag_name)
9
11
  @klass = klass
10
12
  end
11
13
 
@@ -29,8 +31,9 @@ module Watir
29
31
  @document ||= @container.document
30
32
  end
31
33
 
32
- def normalize_specifiers!(specifiers)
33
- specifiers.each do |how, what|
34
+ def normalize_specifiers(specifiers)
35
+ specifiers.reduce({}) do |memo, pair|
36
+ how, what = *pair
34
37
  case how
35
38
  when :index
36
39
  what = what.to_i
@@ -46,7 +49,8 @@ module Watir
46
49
  what = what.is_a?(Regexp) ? what : what.to_s
47
50
  end
48
51
 
49
- @specifiers[how] = what
52
+ memo[how] = what
53
+ memo
50
54
  end
51
55
  end
52
56
 
@@ -80,12 +84,6 @@ module Watir
80
84
  @specifiers.keys.any? {|specifier| [:css, :xpath, :ole_object].include? specifier}
81
85
  end
82
86
 
83
- def set_specifier(how, what=nil)
84
- specifiers = what ? {how => what} : how
85
- @specifiers = {:index => Watir::IE.base_index} # default if not specified
86
- normalize_specifiers! specifiers
87
- end
88
-
89
87
  def locate_by_id
90
88
  # Searching through all elements returned by __ole_inner_elements
91
89
  # is *significantly* slower than IE's getElementById() and
@@ -110,9 +108,9 @@ module Watir
110
108
  els = []
111
109
 
112
110
  if @specifiers[:xpath]
113
- els = @container.send(:elements_by_xpath, @specifiers[:xpath])
111
+ els = elements_by_xpath(@specifiers[:xpath])
114
112
  elsif @specifiers[:css]
115
- els = @container.send(:elements_by_css, @specifiers[:css])
113
+ els = elements_by_css(@specifiers[:css])
116
114
  elsif @specifiers[:ole_object]
117
115
  return [@specifiers[:ole_object]]
118
116
  end
@@ -122,18 +120,13 @@ module Watir
122
120
 
123
121
  def type_matches?(el)
124
122
  @tags == ["*"] ||
125
- @tags.include?(el.tagName) ||
126
- @tags.include?(el.invoke('type')) rescue false
123
+ @tags.include?(el.tagName.downcase) ||
124
+ @tags.include?(el.invoke('type').downcase) rescue false
127
125
  end
128
126
 
129
127
  def create_element ole_object
130
- if @klass == Element
131
- element = Element.new(ole_object)
132
- else
133
- element = @klass.new(@container, @specifiers, nil)
134
- element.ole_object = ole_object
135
- def element.locate; @o; end
136
- end
128
+ element = @klass.new(@container, @specifiers.merge(:ole_object => ole_object))
129
+ def element.locate; @o; end
137
130
  element
138
131
  end
139
132
  end
@@ -161,7 +154,7 @@ module Watir
161
154
 
162
155
  class FrameLocator < TaggedElementLocator
163
156
  def each_element(tag)
164
- frames = document.frames
157
+ frames = @container.page_container.document.frames
165
158
  i = 0
166
159
  document.getElementsByTagName(tag).each do |ole_object|
167
160
  frame = create_element ole_object
@@ -172,14 +165,25 @@ module Watir
172
165
  end
173
166
 
174
167
  def locate
175
- # do not locate frames by getElementById or by xpath since can't get the correct
176
- # 'document' related with that ole_object like it's done in #each_element
177
168
  count = Watir::IE.base_index - 1
178
169
  each do |frame|
179
170
  count += 1
180
171
  return frame.ole_object, frame.document if count == @specifiers[:index]
181
172
  end
182
173
  end
174
+
175
+ def locate_elements_by_xpath_css_ole
176
+ super.map do |frame|
177
+ frame = create_element frame
178
+ each_element(frame.tag_name) do |frame_with_document|
179
+ if frame_with_document == frame
180
+ frame = frame_with_document
181
+ break
182
+ end
183
+ end
184
+ frame
185
+ end
186
+ end
183
187
  end
184
188
 
185
189
  class FormLocator < TaggedElementLocator
@@ -16,48 +16,44 @@ module Watir
16
16
  end
17
17
 
18
18
  def locate
19
+ @modal.wait_until_present rescue raise NoMatchingWindowFoundException
20
+
19
21
  intUnknown = 0
20
- begin
21
- Watir::until_with_timeout do
22
- intPointer = " " * 4 # will contain the int value of the IUnknown*
23
- GetUnknown.call(hwnd, intPointer)
24
- intArray = intPointer.unpack('L')
25
- intUnknown = intArray.first
26
- intUnknown > 0
27
- end
28
- rescue Wait::TimeoutError => e
29
- raise NoMatchingWindowFoundException,
30
- "Unable to attach to Modal Window after #{e.duration} seconds."
22
+ Watir::until_with_timeout do
23
+ intPointer = " " * 4 # will contain the int value of the IUnknown*
24
+ GetUnknown.call(hwnd, intPointer)
25
+ intArray = intPointer.unpack('L')
26
+ intUnknown = intArray.first
27
+ intUnknown > 0
31
28
  end
32
- @document = WIN32OLE.connect_unknown(intUnknown)
29
+
30
+ WIN32OLE.connect_unknown(intUnknown)
31
+ rescue NoMatchingWindowFoundException, Wait::TimeoutError
32
+ raise NoMatchingWindowFoundException,
33
+ "Unable to attach to Modal Window."
33
34
  end
34
35
 
35
- def document
36
- locate
37
- @document
38
- end
39
-
36
+ alias_method :document, :locate
37
+
40
38
  def title
41
39
  document.title
42
40
  end
43
41
 
44
- def close
42
+ def close(timeout=5)
43
+ return unless exists?
45
44
  document.parentWindow.close
45
+ Watir::Wait.until(timeout) {!exists?} rescue nil
46
+ wait
46
47
  end
47
48
 
48
49
  def attach_command
49
50
  "Watir::IE.find(:hwnd, #{@container.hwnd}).modal_dialog"
50
51
  end
51
-
52
+
52
53
  def wait(no_sleep=false)
53
- sleep 1
54
- if exists?
55
- # do nothing
56
- else
57
- @container.page_container.wait
58
- end
54
+ @container.page_container.wait unless exists?
59
55
  end
60
-
56
+
61
57
  def hwnd
62
58
  @modal.hwnd
63
59
  end
@@ -66,21 +62,11 @@ module Watir
66
62
  @modal.active?
67
63
  end
68
64
 
69
- # When checking to see if the modal exists we give it some time to
70
- # find it. So if it does see a modal it returns immediately, otherwise it waits and checks
71
- def exists?(timeout=5)
72
- begin
73
- Watir::Wait.until(timeout) {@modal.exists?}
74
- rescue Watir::Wait::TimeoutError
75
- end
76
- return @modal.exists?
65
+ def exists?
66
+ @modal.exists?
77
67
  end
78
- alias :exist? :exists?
79
68
 
80
- Watir::Container.module_eval do
81
- def modal_dialog(*args)
82
- ModalDialog.new(self)
83
- end
84
- end
69
+ alias_method :exist?, :exists?
70
+
85
71
  end
86
72
  end