watir-classic 3.3.0 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/CHANGES +17 -0
  2. data/Gemfile.lock +9 -8
  3. data/LICENSE +1 -0
  4. data/README.rdoc +6 -7
  5. data/Rakefile +3 -1
  6. data/VERSION +1 -1
  7. data/lib/watir-classic.rb +0 -5
  8. data/lib/watir-classic/browser.rb +58 -35
  9. data/lib/watir-classic/browsers.rb +1 -1
  10. data/lib/watir-classic/container.rb +39 -33
  11. data/lib/watir-classic/cookies.rb +32 -2
  12. data/lib/watir-classic/core.rb +0 -1
  13. data/lib/watir-classic/dialogs/alert.rb +12 -0
  14. data/lib/watir-classic/dialogs/file_field.rb +11 -0
  15. data/lib/watir-classic/drag_and_drop_helper.rb +14 -0
  16. data/lib/watir-classic/element.rb +292 -257
  17. data/lib/watir-classic/element_collection.rb +26 -8
  18. data/lib/watir-classic/element_extensions.rb +22 -16
  19. data/lib/watir-classic/exceptions.rb +4 -4
  20. data/lib/watir-classic/form.rb +52 -49
  21. data/lib/watir-classic/frame.rb +23 -14
  22. data/lib/watir-classic/ie-class.rb +363 -315
  23. data/lib/watir-classic/ie-process.rb +1 -0
  24. data/lib/watir-classic/ie.rb +0 -17
  25. data/lib/watir-classic/image.rb +58 -64
  26. data/lib/watir-classic/input_elements.rb +224 -219
  27. data/lib/watir-classic/link.rb +14 -15
  28. data/lib/watir-classic/locator.rb +12 -7
  29. data/lib/watir-classic/matches.rb +7 -3
  30. data/lib/watir-classic/modal_dialog.rb +38 -26
  31. data/lib/watir-classic/non_control_elements.rb +29 -0
  32. data/lib/watir-classic/options.rb +10 -15
  33. data/lib/watir-classic/page-container.rb +30 -48
  34. data/lib/watir-classic/process.rb +4 -2
  35. data/lib/watir-classic/screenshot.rb +6 -0
  36. data/lib/watir-classic/supported_elements.rb +36 -14
  37. data/lib/watir-classic/table.rb +81 -71
  38. data/lib/watir-classic/util.rb +9 -11
  39. data/lib/watir-classic/wait.rb +17 -4
  40. data/lib/watir-classic/wait_helper.rb +15 -2
  41. data/lib/watir-classic/win32.rb +2 -1
  42. data/lib/watir-classic/window.rb +35 -7
  43. data/lib/watir-classic/xpath_locator.rb +1 -0
  44. data/lib/watir-classic/yard/global_macros.rb +7 -0
  45. data/spec/frame_spec.rb +17 -0
  46. metadata +5 -7
  47. data/lib/watir-classic/close_all.rb +0 -31
  48. data/lib/watir-classic/contrib/enabled_popup.rb +0 -21
  49. data/lib/watir-classic/contrib/ie-new-process.rb +0 -27
  50. data/lib/watir-classic/contrib/page_checker.rb +0 -29
  51. data/watir.gif +0 -0
@@ -4,36 +4,19 @@ module Watir
4
4
  module PageContainer
5
5
  include Watir::Exception
6
6
 
7
- # This method checks the currently displayed page for http errors, 404, 500 etc
8
- # It gets called internally by the wait method, so a user does not need to call it explicitly
9
-
10
- def check_for_http_error
11
- # check for IE7
12
- n = self.document.invoke('parentWindow').navigator.appVersion
13
- m=/MSIE\s(.*?);/.match( n )
14
- if m and m[1] =='7.0'
15
- if m = /HTTP (\d\d\d.*)/.match( self.title )
16
- raise NavigationException, m[1]
17
- end
18
- else
19
- # assume its IE6
20
- url = self.document.location.href
21
- if /shdoclc.dll/.match(url)
22
- m = /id=IEText.*?>(.*?)</i.match(self.html)
23
- raise NavigationException, m[1] if m
24
- end
25
- end
26
- false
27
- end
28
-
29
- # The HTML Page
30
- def page
31
- document.documentelement
32
- end
33
-
34
- private :page
35
-
36
- # Execute the given JavaScript string
7
+ # Execute the given JavaScript string in the context of the current page.
8
+ #
9
+ # @example
10
+ # browser.execute_script "var a=1; var b=a+1; return b"
11
+ #
12
+ # @example
13
+ # browser.execute_script("return {a: 1, b: 2}")["b"] # => 1
14
+ #
15
+ # @note It is needed to call return inside of the JavaScript if the value
16
+ # is needed at Ruby side.
17
+ #
18
+ # @return [Object] appropriate type of the object, which is returned from the
19
+ # JavaScript via "return" keyword or nil when "return" is omitted.
37
20
  def execute_script(source)
38
21
  result = nil
39
22
  begin
@@ -50,36 +33,24 @@ module Watir
50
33
  MultiJson.load(result)["value"] rescue nil
51
34
  end
52
35
 
53
- # The HTML of the current page
36
+ # @return [String] html of the current page.
54
37
  def html
55
38
  page.outerhtml
56
39
  end
57
40
 
58
- # The url of the page object.
41
+ # @return [String] url of the page.
59
42
  def url
60
43
  page.document.location.href
61
44
  end
62
45
 
63
- # The text of the current page
46
+ # @return [String] text of the page.
64
47
  def text
65
48
  page.innertext.strip
66
49
  end
67
50
 
68
- def set_container container
69
- @container = container
70
- @page_container = self
71
- end
72
-
73
- # Search the current page for specified text or regexp.
74
- # Returns the index if the specified text was found.
75
- # Returns matchdata object if the specified regexp was found.
76
- #
77
- # *Deprecated*
78
- # Instead use
79
- # IE#text.include? target
80
- # or
81
- # IE#text.match target
51
+ # @deprecated Use "browser.text.include?(target)" or "browser.text.match(target) instead."
82
52
  def contains_text(target)
53
+ Kernel.warn "Deprecated(Element#contains_text) - use \"browser.text.include?(target)\" or \"browser.text.match(target)\" instead."
83
54
  if target.kind_of? Regexp
84
55
  self.text.match(target)
85
56
  elsif target.kind_of? String
@@ -89,6 +60,14 @@ module Watir
89
60
  end
90
61
  end
91
62
 
63
+ # @private
64
+ def set_container container
65
+ @container = container
66
+ @page_container = self
67
+ end
68
+
69
+ private
70
+
92
71
  def with_json2_if_needed source
93
72
  %Q[
94
73
  (function() {
@@ -104,7 +83,10 @@ module Watir
104
83
  ]
105
84
  end
106
85
 
107
- private :with_json2_if_needed
86
+ # The HTML Page
87
+ def page
88
+ document.documentelement
89
+ end
108
90
 
109
91
  end # module
110
92
  end
@@ -1,8 +1,9 @@
1
1
  module Watir
2
+ # @private
2
3
  module Process
3
4
 
4
5
  # Returns the number of windows processes running with the specified name.
5
- def self.count name
6
+ def self.count(name)
6
7
  mgmt = WIN32OLE.connect('winmgmts:\\\\.')
7
8
  processes = mgmt.InstancesOf('win32_process')
8
9
  processes.extend Enumerable
@@ -13,8 +14,9 @@ module Watir
13
14
 
14
15
  class IE
15
16
  # Returns the number of IEXPLORE processes currently running.
17
+ # @return [Fixnum] number of ie processes.
16
18
  def self.process_count
17
19
  Watir::Process.count 'iexplore.exe'
18
20
  end
19
21
  end
20
- end
22
+ end
@@ -3,15 +3,20 @@ require "base64"
3
3
  require "win32/screenshot"
4
4
 
5
5
  module Watir
6
+ # Returned by {IE#screenshot}.
6
7
  class Screenshot
7
8
  def initialize(browser_hwnd)
8
9
  @hwnd = browser_hwnd
9
10
  end
10
11
 
12
+ # Save screenshot to the file.
13
+ #
14
+ # @param [String] path path to the image.
11
15
  def save(path)
12
16
  screenshot.write(path)
13
17
  end
14
18
 
19
+ # @return [String] image in png format.
15
20
  def png
16
21
  path = File.expand_path "temporary-image-#{Time.now.to_i}.png", Dir.tmpdir
17
22
  save path
@@ -20,6 +25,7 @@ module Watir
20
25
  File.delete path rescue nil
21
26
  end
22
27
 
28
+ # @return [String] {#png} image formatted as base64.
23
29
  def base64
24
30
  Base64.encode64 png
25
31
  end
@@ -2,7 +2,30 @@ module Watir
2
2
  module Container
3
3
 
4
4
  class << self
5
- def support_element method_name, args={}
5
+
6
+ private
7
+
8
+ # @!macro support_element
9
+ # @!method $1
10
+ # Create an $1 html element instance.
11
+ #
12
+ # Elements can be searched by using different locators.
13
+ #
14
+ # @example Search by partial text:
15
+ # browser.$1(:text => /partial text/)
16
+ #
17
+ # @example Search by id:
18
+ # browser.$1(:id => "htmlid")
19
+ #
20
+ # @example Search by any arbitrary html attribute:
21
+ # browser.$1(:foo => "value-of-foo-attribute)
22
+ #
23
+ # @example Search by multiple attributes, all provided locators should evaluate to true - only then element is considered to be found:
24
+ # browser.$1(:text => "some text", :class => "css class")
25
+ #
26
+ # @example It is also possible to search for multiple elements of the same type like this:
27
+ # browser.divs(:class => "foo") # => instance of Watir::DivCollection
28
+ def support_element(method_name, args={})
6
29
  klass = args[:class] || method_name.to_s.capitalize
7
30
  super_class = args[:super_class] || "Element"
8
31
 
@@ -28,20 +51,8 @@ module Watir
28
51
  ]
29
52
  end
30
53
 
31
- private :support_element
32
- end
33
-
34
- def format_specifiers(tag_name, how, what)
35
- defaults = {:tag_name => [tag_name].flatten.map(&:to_s)}
36
- formatted_specifiers = defaults.merge(what ? {how => what} : how)
37
- if (formatted_specifiers[:css] || formatted_specifiers[:xpath]) && formatted_specifiers.size > 2
38
- raise ArgumentError, ":xpath and :css specifiers should be the only one when used in #{formatted_specifiers.inspect}"
39
- end
40
- formatted_specifiers
41
54
  end
42
55
 
43
- private :format_specifiers
44
-
45
56
  support_element :a, :class => :Link
46
57
  alias_method :link, :a
47
58
  alias_method :links, :as
@@ -103,7 +114,6 @@ module Watir
103
114
  support_element :hgroup
104
115
  support_element :hidden, :super_class => :TextField, :super_collection => :InputElement
105
116
  support_element :hr
106
- # html and htmls?!
107
117
  support_element :i
108
118
  support_element :img, :class => :Image
109
119
  alias_method :image, :img
@@ -168,5 +178,17 @@ module Watir
168
178
  support_element :var
169
179
  support_element :video
170
180
  support_element :wbr
181
+
182
+ private
183
+
184
+ def format_specifiers(tag_name, how, what)
185
+ defaults = {:tag_name => [tag_name].flatten.map(&:to_s)}
186
+ formatted_specifiers = defaults.merge(what ? {how => what} : how)
187
+ if (formatted_specifiers[:css] || formatted_specifiers[:xpath]) && formatted_specifiers.size > 2
188
+ raise ArgumentError, ":xpath and :css specifiers should be the only one when used in #{formatted_specifiers.inspect}"
189
+ end
190
+ formatted_specifiers
191
+ end
192
+
171
193
  end
172
194
  end
@@ -1,13 +1,16 @@
1
1
  module Watir
2
2
 
3
3
  module TableContainer
4
- # Returns a row in the table
5
- # * index - the index of the row
4
+ # @return [TableRow] a row in the {Table}.
5
+ # @param [Fixnum] index row number to retrieve.
6
+ # @macro exists
6
7
  def [](index)
7
8
  assert_exists
8
9
  TableRow.new(self, :ole_object => @o.rows.item(index))
9
10
  end
10
11
 
12
+ # @return [Array<String>] array of table element texts.
13
+ # @macro exists
11
14
  def strings
12
15
  assert_exists
13
16
  rows_memo = []
@@ -23,22 +26,28 @@ module Watir
23
26
  end
24
27
 
25
28
  module TableElementsContainer
29
+
30
+ private
31
+
26
32
  def table_elements(klass, tags, how, what, ole_collection)
27
33
  specifiers = format_specifiers(tags, how, what)
28
34
  klass.new(self, specifiers, ole_collection)
29
35
  end
30
36
 
31
- private :table_elements
32
37
  end
33
38
 
34
39
  module TableCellsContainer
35
40
  include TableElementsContainer
36
41
 
42
+ # @return [TableCellCollection] cells inside of the {Table}.
43
+ # @macro exists
37
44
  def cells(how={}, what=nil)
38
45
  assert_exists
39
46
  table_elements(TableCellCollection, [:th, :td], how, what, @o.cells)
40
47
  end
41
48
 
49
+ # @return [TableCell] cell inside of the {Table}.
50
+ # @macro exists
42
51
  def cell(how={}, what=nil)
43
52
  specifiers = format_specifiers([:th, :td], how, what)
44
53
  index = specifiers.delete(:index) || 0
@@ -49,11 +58,15 @@ module Watir
49
58
  module TableRowsContainer
50
59
  include TableElementsContainer
51
60
 
61
+ # @return [TableRowCollection] rows inside of the {Table}.
62
+ # @macro exists
52
63
  def rows(how={}, what=nil)
53
64
  assert_exists
54
65
  table_elements(TableRowCollection, [:tr], how, what, @o.rows)
55
66
  end
56
67
 
68
+ # @return [TableRow] row inside of the {Table}.
69
+ # @macro exists
57
70
  def row(how={}, what=nil)
58
71
  specifiers = format_specifiers([:tr], how, what)
59
72
  index = specifiers.delete(:index) || 0
@@ -61,11 +74,7 @@ module Watir
61
74
  end
62
75
  end
63
76
 
64
- # This class is used for dealing with tables.
65
- # Normally a user would not need to create this object as it is returned by the Watir::Container#table method
66
- #
67
- # many of the methods available to this object are inherited from the Element class
68
- #
77
+ # Returned by {Container#table}
69
78
  class Table < Element
70
79
  include TableContainer
71
80
  include TableRowsContainer
@@ -73,81 +82,39 @@ module Watir
73
82
 
74
83
  attr_ole :rules
75
84
 
76
- # override the highlight method, as if the tables rows are set to have a background color,
77
- # this will override the table background color, and the normal flash method won't work
78
- def highlight(set_or_clear)
79
- if set_or_clear == :set
80
- begin
81
- @original_border = @o.border.to_i
82
- if @o.border.to_i==1
83
- @o.border = 2
84
- else
85
- @o.border = 1
86
- end
87
- rescue
88
- @original_border = nil
89
- end
90
- else
91
- begin
92
- @o.border= @original_border unless @original_border == nil
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
- super
101
- end
102
-
103
- # this method is used to populate the properties in the to_s method
104
- def table_string_creator
105
- n = []
106
- n << "rows:".ljust(TO_S_SIZE) + self.row_count.to_s
107
- n << "cols:".ljust(TO_S_SIZE) + self.column_count.to_s
108
- return n
109
- end
110
- private :table_string_creator
111
-
112
- # returns the properties of the object in a string
113
- # raises an ObjectNotFound exception if the object cannot be found
114
- def to_s
115
- assert_exists
116
- r = string_creator
117
- r += table_string_creator
118
- return r.join("\n")
119
- end
120
-
121
- # Returns the number of rows inside the table, including rows in nested tables.
85
+ # @return [Fixnum] number of rows inside of the table, including rows from
86
+ # nested tables.
87
+ # @macro exists
122
88
  def row_count
123
89
  assert_exists
124
90
  rows.length
125
91
  end
126
92
 
127
- # This method returns the number of columns in a row of the table.
128
- # Raises an UnknownObjectException if the table doesn't exist.
129
- # * index - the index of the row
93
+ # @return [Fixnum] number of columns inside of the table, including columns from
94
+ # nested tables.
95
+ # @param [Fixnum] index the number of row.
96
+ # @macro exists
130
97
  def column_count(index=0)
131
98
  assert_exists
132
99
  rows[index].cells.length
133
100
  end
134
101
 
135
- # Returns an array containing all the text values in the specified column
136
- # Raises an UnknownCellException if the specified column does not exist in every
137
- # Raises an UnknownObjectException if the table doesn't exist.
138
- # row of the table
139
- # * columnnumber - column index to extract values from
102
+ # @return [Array<String>] array of each row's specified column text.
103
+ # @param [Fixnum] columnnumber the number of column to extract text from.
104
+ # @macro exists
140
105
  def column_values(columnnumber)
141
- return (0..row_count - 1).collect {|i| self[i][columnnumber].text}
106
+ (0..row_count - 1).collect {|i| self[i][columnnumber].text}
142
107
  end
143
108
 
144
- # Returns an array containing all the text values in the specified row
145
- # Raises an UnknownObjectException if the table doesn't exist.
146
- # * rownumber - row index to extract values from
109
+ # @return [Array<String>] array of each column's text on specified row.
110
+ # @param [Fixnum] rownumber the number of row to extract column texts from.
111
+ # @macro exists
147
112
  def row_values(rownumber)
148
- return (0..column_count(rownumber) - 1).collect {|i| self[rownumber][i].text}
113
+ (0..column_count(rownumber) - 1).collect {|i| self[rownumber][i].text}
149
114
  end
150
115
 
116
+ # @return [Array<Hash>] array with hashes of table data.
117
+ # @macro exists
151
118
  def hashes
152
119
  assert_exists
153
120
 
@@ -176,6 +143,41 @@ module Watir
176
143
  end
177
144
  rows_memo
178
145
  end
146
+
147
+ def to_s
148
+ assert_exists
149
+ r = string_creator
150
+ r += table_string_creator
151
+ r.join("\n")
152
+ end
153
+
154
+ private
155
+
156
+ # this method is used to populate the properties in the to_s method
157
+ def table_string_creator
158
+ n = []
159
+ n << "rows:".ljust(TO_S_SIZE) + self.row_count.to_s
160
+ n << "cols:".ljust(TO_S_SIZE) + self.column_count.to_s
161
+ n
162
+ end
163
+
164
+ # override the highlight method, as if the tables rows are set to have a background color,
165
+ # this will override the table background color, and the normal flash method won't work
166
+ def set_highlight
167
+ perform_highlight do
168
+ @original_border = @o.border.to_i
169
+ @o.border = @original_border + 1
170
+ super
171
+ end
172
+ end
173
+
174
+ def clear_highlight
175
+ perform_highlight do
176
+ @o.border = @original_border if @original_border
177
+ super
178
+ end
179
+ end
180
+
179
181
  end
180
182
 
181
183
  class TableSection < Element
@@ -184,24 +186,30 @@ module Watir
184
186
  include TableCellsContainer
185
187
  end
186
188
 
189
+ # Returned by {Container#tr}.
187
190
  class TableRow < Element
188
191
  include TableCellsContainer
189
192
 
190
- # this method iterates through each of the cells in the row. Yields a TableCell object
193
+ # Iterate over each of the cell in the row.
194
+ # @yieldparam [TableCell] cell cell instance.
191
195
  def each
192
196
  locate
193
197
  cells.each {|cell| yield cell}
194
198
  end
195
199
 
196
- # Returns an element from the row as a TableCell object
200
+ # @return [TableCell] cell from the row.
201
+ # @param [Fixnum] index cell index in the row.
202
+ # @macro exists
197
203
  def [](index)
198
204
  assert_exists
199
205
  if cells.length <= index
200
206
  raise UnknownCellException, "Unable to locate a cell at index #{index}"
201
207
  end
202
- return cells[index]
208
+ cells[index]
203
209
  end
204
210
 
211
+ # @return [Fixnum] cells count in the row.
212
+ # @macro exists
205
213
  def column_count
206
214
  assert_exists
207
215
  cells.length
@@ -209,12 +217,14 @@ module Watir
209
217
 
210
218
  end
211
219
 
212
- # this class is a table cell - when called via the Table object
220
+ # Returned by {Container#td} and {Container#th}.
213
221
  class TableCell < Element
214
222
  attr_ole :headers
215
223
 
216
224
  alias_method :to_s, :text
217
225
 
226
+ # @return [Fixnum] colspan attribute value.
227
+ # @macro exists
218
228
  def colspan
219
229
  locate
220
230
  @o.colSpan