watir 2.0.4 → 3.0.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +41 -0
- data/VERSION +1 -1
- data/lib/watir/collections.rb +9 -17
- data/lib/watir/container.rb +2 -14
- data/lib/watir/core.rb +1 -0
- data/lib/watir/dialogs/file_field.rb +4 -2
- data/lib/watir/element.rb +146 -90
- data/lib/watir/element_collections.rb +13 -11
- data/lib/watir/form.rb +4 -2
- data/lib/watir/frame.rb +15 -3
- data/lib/watir/ie-class.rb +100 -128
- data/lib/watir/image.rb +10 -13
- data/lib/watir/input_elements.rb +92 -156
- data/lib/watir/locator.rb +61 -66
- data/lib/watir/non_control_elements.rb +8 -1
- data/lib/watir/table.rb +89 -242
- data/lib/watir/window.rb +68 -0
- metadata +21 -14
@@ -65,8 +65,15 @@ module Watir
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
|
+
class FieldSet < NonControlElement
|
69
|
+
Watir::Container.module_eval do
|
70
|
+
alias_method :fieldset, :field_set
|
71
|
+
alias_method :fieldsets, :field_sets
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
68
75
|
%w[Pre P Div Span Map Area Li Ul H1 H2 H3 H4 H5 H6
|
69
|
-
Dl Dt Dd Strong Em Del
|
76
|
+
Dl Dt Dd Strong Em Del Ol Body Meta Font Frameset].each do |elem|
|
70
77
|
module_eval %Q{
|
71
78
|
class #{elem} < NonControlElement; end
|
72
79
|
}
|
data/lib/watir/table.rb
CHANGED
@@ -1,34 +1,36 @@
|
|
1
1
|
module Watir
|
2
2
|
|
3
|
+
module RowContainer
|
4
|
+
# Returns a row in the table
|
5
|
+
# * index - the index of the row
|
6
|
+
def [](index)
|
7
|
+
assert_exists
|
8
|
+
TableRow.new(self, :ole_object, @o.rows.item(index))
|
9
|
+
end
|
10
|
+
|
11
|
+
def strings
|
12
|
+
assert_exists
|
13
|
+
rows_memo = []
|
14
|
+
@o.rows.each do |row|
|
15
|
+
cells_memo = []
|
16
|
+
row.cells.each do |cell|
|
17
|
+
cells_memo << TableCell.new(self, :ole_object, cell).text
|
18
|
+
end
|
19
|
+
rows_memo << cells_memo
|
20
|
+
end
|
21
|
+
rows_memo
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
3
26
|
# This class is used for dealing with tables.
|
4
27
|
# Normally a user would not need to create this object as it is returned by the Watir::Container#table method
|
5
28
|
#
|
6
29
|
# many of the methods available to this object are inherited from the Element class
|
7
30
|
#
|
8
|
-
class Table <
|
9
|
-
include
|
31
|
+
class Table < NonControlElement
|
32
|
+
include RowContainer
|
10
33
|
|
11
|
-
# Returns the table object containing the element
|
12
|
-
# * container - an instance of an IE object
|
13
|
-
# * anElement - a Watir object (TextField, Button, etc.)
|
14
|
-
def Table.create_from_element(container, element)
|
15
|
-
element.locate if element.respond_to?(:locate)
|
16
|
-
o = element.ole_object.parentElement
|
17
|
-
o = o.parentElement until o.tagName == 'TABLE'
|
18
|
-
new container, :ole_object, o
|
19
|
-
end
|
20
|
-
|
21
|
-
# Returns an initialized instance of a table object
|
22
|
-
# * container - the container
|
23
|
-
# * how - symbol - how we access the table
|
24
|
-
# * what - what we use to access the table - id, name index etc
|
25
|
-
def initialize(container, how, what)
|
26
|
-
set_container container
|
27
|
-
@how = how
|
28
|
-
@what = what
|
29
|
-
super nil
|
30
|
-
end
|
31
|
-
|
32
34
|
# override the highlight method, as if the tables rows are set to have a background color,
|
33
35
|
# this will override the table background color, and the normal flash method won't work
|
34
36
|
def highlight(set_or_clear)
|
@@ -77,74 +79,25 @@ module Watir
|
|
77
79
|
# iterates through the rows in the table. Yields a TableRow object
|
78
80
|
def each
|
79
81
|
assert_exists
|
80
|
-
|
81
|
-
yield TableRow.new(
|
82
|
+
@o.rows.each do |row|
|
83
|
+
yield TableRow.new(self, :ole_object, row)
|
82
84
|
end
|
83
85
|
end
|
84
86
|
|
85
|
-
# Returns a row in the table
|
86
|
-
# * index - the index of the row
|
87
|
-
def [](index)
|
88
|
-
assert_exists
|
89
|
-
return TableRow.new(@container, :ole_object, _row(index))
|
90
|
-
end
|
91
|
-
|
92
87
|
# Returns the number of rows inside the table, including rows in nested tables.
|
93
88
|
def row_count
|
94
89
|
assert_exists
|
95
|
-
|
96
|
-
return @o.getElementsByTagName("TR").length
|
90
|
+
rows.length
|
97
91
|
end
|
98
92
|
|
99
|
-
# Returns the number of rows in the table, not including rows in nested tables.
|
100
|
-
def row_count_excluding_nested_tables
|
101
|
-
assert_exists
|
102
|
-
return @o.rows.length
|
103
|
-
end
|
104
|
-
|
105
93
|
# This method returns the number of columns in a row of the table.
|
106
94
|
# Raises an UnknownObjectException if the table doesn't exist.
|
107
95
|
# * index - the index of the row
|
108
96
|
def column_count(index=0)
|
109
97
|
assert_exists
|
110
|
-
|
98
|
+
row[index].cells.length
|
111
99
|
end
|
112
100
|
|
113
|
-
# Returns multi-dimensional array of the cell texts in a table.
|
114
|
-
#
|
115
|
-
# Works with tr, th, td elements, colspan, rowspan and nested tables.
|
116
|
-
# Takes an optional parameter *max_depth*, which is by default 1
|
117
|
-
def to_a(max_depth=1)
|
118
|
-
assert_exists
|
119
|
-
y = []
|
120
|
-
@o.rows.each do |row|
|
121
|
-
y << TableRow.new(@container, :ole_object, row).to_a(max_depth)
|
122
|
-
end
|
123
|
-
y
|
124
|
-
end
|
125
|
-
|
126
|
-
def table_body(index=0)
|
127
|
-
return @o.getElementsByTagName('TBODY')[index]
|
128
|
-
end
|
129
|
-
private :table_body
|
130
|
-
|
131
|
-
# returns a watir object
|
132
|
-
def body(how, what)
|
133
|
-
return TableBody.new(@container, how, what, self)
|
134
|
-
end
|
135
|
-
|
136
|
-
# returns a watir object
|
137
|
-
def bodies
|
138
|
-
assert_exists
|
139
|
-
return TableBodies.new(@container, @o)
|
140
|
-
end
|
141
|
-
|
142
|
-
# returns an ole object
|
143
|
-
def _row(index)
|
144
|
-
return @o.invoke("rows").item(index)
|
145
|
-
end
|
146
|
-
private :_row
|
147
|
-
|
148
101
|
# Returns an array containing all the text values in the specified column
|
149
102
|
# Raises an UnknownCellException if the specified column does not exist in every
|
150
103
|
# Raises an UnknownObjectException if the table doesn't exist.
|
@@ -161,123 +114,79 @@ module Watir
|
|
161
114
|
return (0..column_count(rownumber) - 1).collect {|i| self[rownumber][i].text}
|
162
115
|
end
|
163
116
|
|
164
|
-
|
165
|
-
|
166
|
-
# this class is a collection of the table body objects that exist in the table
|
167
|
-
# it wouldnt normally be created by a user, but gets returned by the bodies method of the Table object
|
168
|
-
# many of the methods available to this object are inherited from the Element class
|
169
|
-
#
|
170
|
-
class TableBodies < Element
|
171
|
-
def initialize(container, parent_table)
|
172
|
-
set_container container
|
173
|
-
@o = parent_table # in this case, @o is the parent table
|
174
|
-
end
|
175
|
-
|
176
|
-
# returns the number of TableBodies that exist in the table
|
177
|
-
def length
|
178
|
-
assert_exists
|
179
|
-
return @o.tBodies.length
|
180
|
-
end
|
181
|
-
|
182
|
-
# returns the n'th Body as a Watir TableBody object
|
183
|
-
def []n
|
117
|
+
def hashes
|
184
118
|
assert_exists
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
def ole_table_body_at_index(n)
|
190
|
-
return @o.tBodies.item(n)
|
191
|
-
end
|
192
|
-
|
193
|
-
# iterates through each of the TableBodies in the Table. Yields a TableBody object
|
194
|
-
def each
|
195
|
-
0.upto(@o.tBodies.length - 1) do |i|
|
196
|
-
yield TableBody.new(@container, :ole_object, ole_table_body_at_index(i))
|
197
|
-
end
|
198
|
-
end
|
199
|
-
|
200
|
-
end
|
201
|
-
|
202
|
-
# this class is a table body
|
203
|
-
class TableBody < Element
|
204
|
-
def locate
|
205
|
-
@o = nil
|
206
|
-
if @how == :ole_object
|
207
|
-
@o = @what # in this case, @o is the table body
|
208
|
-
elsif @how == :index
|
209
|
-
@o = @parent_table.bodies.ole_table_body_at_index(@what)
|
119
|
+
|
120
|
+
headers = []
|
121
|
+
@o.rows.item(0).cells.each do |cell|
|
122
|
+
headers << TableCell.new(self, :ole_object, cell).text
|
210
123
|
end
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
124
|
+
|
125
|
+
rows_memo = []
|
126
|
+
i = 0
|
127
|
+
@o.rows.each do |row|
|
128
|
+
next if row.uniqueID == @o.rows.item(0).uniqueID
|
129
|
+
|
130
|
+
cells_memo = {}
|
131
|
+
cells = row.cells
|
132
|
+
raise "row at index #{i} has #{cells.length} cells, expected #{headers.length}" if cells.length < headers.length
|
133
|
+
|
134
|
+
j = 0
|
135
|
+
cells.each do |cell|
|
136
|
+
cells_memo[headers[j]] = TableCell.new(self, :ole_object, cell).text
|
137
|
+
j += 1
|
215
138
|
end
|
139
|
+
|
140
|
+
rows_memo << cells_memo
|
141
|
+
i += 1
|
216
142
|
end
|
217
|
-
|
218
|
-
|
219
|
-
def initialize(container, how, what, parent_table=nil)
|
220
|
-
set_container container
|
221
|
-
@how = how
|
222
|
-
@what = what
|
223
|
-
@parent_table = parent_table
|
224
|
-
super nil
|
225
|
-
end
|
226
|
-
|
227
|
-
# returns the specified row as a TableRow object
|
228
|
-
def [](n)
|
229
|
-
assert_exists
|
230
|
-
return @rows[n]
|
231
|
-
end
|
232
|
-
|
233
|
-
# iterates through all the rows in the table body
|
234
|
-
def each
|
235
|
-
locate
|
236
|
-
0.upto(length - 1) { |i| yield @rows[i] }
|
237
|
-
end
|
238
|
-
|
239
|
-
# returns the number of rows in this table body.
|
240
|
-
def length
|
241
|
-
return @rows.length
|
143
|
+
rows_memo
|
242
144
|
end
|
243
145
|
end
|
244
|
-
|
245
|
-
class TableRow < Element
|
246
|
-
TAG = "TR"
|
247
|
-
|
248
|
-
def locate
|
249
|
-
super
|
250
|
-
cells if @o
|
251
|
-
end
|
252
146
|
|
253
|
-
|
254
|
-
|
147
|
+
class TableSection < NonControlElement
|
148
|
+
include RowContainer
|
255
149
|
|
256
|
-
|
257
|
-
|
258
|
-
|
150
|
+
Watir::Container.module_eval do
|
151
|
+
def tbody(how={}, what=nil)
|
152
|
+
how = {how => what} if what
|
153
|
+
TableSection.new(self, how.merge(:tag_name => "tbody"), nil)
|
259
154
|
end
|
260
|
-
@cells
|
261
|
-
end
|
262
155
|
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
156
|
+
def tbodys(how={}, what=nil)
|
157
|
+
how = {how => what} if what
|
158
|
+
TableSectionCollection.new(self, how.merge(:tag_name => "tbody"), nil)
|
159
|
+
end
|
160
|
+
|
161
|
+
def thead(how={}, what=nil)
|
162
|
+
how = {how => what} if what
|
163
|
+
TableSection.new(self, how.merge(:tag_name => "thead"), nil)
|
164
|
+
end
|
165
|
+
|
166
|
+
def theads(how={}, what=nil)
|
167
|
+
how = {how => what} if what
|
168
|
+
TableSectionCollection.new(self, how.merge(:tag_name => "thead"), nil)
|
169
|
+
end
|
170
|
+
|
171
|
+
def tfoot(how={}, what=nil)
|
172
|
+
how = {how => what} if what
|
173
|
+
TableSection.new(self, how.merge(:tag_name => "tfoot"), nil)
|
174
|
+
end
|
175
|
+
|
176
|
+
def tfoots(how={}, what=nil)
|
177
|
+
how = {how => what} if what
|
178
|
+
TableSectionCollection.new(self, how.merge(:tag_name => "tfoot"), nil)
|
179
|
+
end
|
275
180
|
end
|
181
|
+
end
|
182
|
+
|
183
|
+
class TableRow < NonControlElement
|
184
|
+
TAG = "TR"
|
276
185
|
|
277
186
|
# this method iterates through each of the cells in the row. Yields a TableCell object
|
278
187
|
def each
|
279
188
|
locate
|
280
|
-
|
189
|
+
cells.each {|cell| yield cell}
|
281
190
|
end
|
282
191
|
|
283
192
|
# Returns an element from the row as a TableCell object
|
@@ -299,44 +208,6 @@ module Watir
|
|
299
208
|
cells.length
|
300
209
|
end
|
301
210
|
|
302
|
-
# Returns (multi-dimensional) array of the cell texts in table's row.
|
303
|
-
#
|
304
|
-
# Works with th, td elements, colspan, rowspan and nested tables.
|
305
|
-
# Takes an optional parameter *max_depth*, which is by default 1
|
306
|
-
def to_a(max_depth=1)
|
307
|
-
assert_exists
|
308
|
-
y = []
|
309
|
-
@o.cells.each do |cell|
|
310
|
-
inner_tables = cell.getElementsByTagName("TABLE")
|
311
|
-
inner_tables.each do |inner_table|
|
312
|
-
# make sure that the inner table is directly child for this cell
|
313
|
-
if inner_table?(cell, inner_table)
|
314
|
-
max_depth -= 1
|
315
|
-
y << Table.new(@container, :ole_object, inner_table).to_a(max_depth) if max_depth >= 1
|
316
|
-
end
|
317
|
-
end
|
318
|
-
|
319
|
-
if inner_tables.length == 0
|
320
|
-
y << cell.innerText.strip
|
321
|
-
end
|
322
|
-
end
|
323
|
-
y
|
324
|
-
end
|
325
|
-
|
326
|
-
private
|
327
|
-
# Returns true if inner_table is direct child
|
328
|
-
# table for cell and there's not any table-s in between
|
329
|
-
def inner_table?(cell, inner_table)
|
330
|
-
parent_element = inner_table.parentElement
|
331
|
-
if parent_element.uniqueID == cell.uniqueID
|
332
|
-
return true
|
333
|
-
elsif parent_element.tagName == "TABLE"
|
334
|
-
return false
|
335
|
-
else
|
336
|
-
return inner_table?(cell, parent_element)
|
337
|
-
end
|
338
|
-
end
|
339
|
-
|
340
211
|
Watir::Container.module_eval do
|
341
212
|
def row(how={}, what=nil)
|
342
213
|
TableRow.new(self, how, what)
|
@@ -353,33 +224,9 @@ module Watir
|
|
353
224
|
end
|
354
225
|
|
355
226
|
# this class is a table cell - when called via the Table object
|
356
|
-
class TableCell <
|
357
|
-
|
358
|
-
include Container
|
227
|
+
class TableCell < NonControlElement
|
228
|
+
TAGS = ["TH", "TD"]
|
359
229
|
|
360
|
-
TAG = "TD"
|
361
|
-
|
362
|
-
# Returns an initialized instance of a table cell
|
363
|
-
# * container - an IE object
|
364
|
-
# * how - symbol - how we access the cell
|
365
|
-
# * what - what we use to access the cell - id, name index etc
|
366
|
-
def initialize(container, how, what)
|
367
|
-
set_container container
|
368
|
-
@how = how
|
369
|
-
@what = what
|
370
|
-
super nil
|
371
|
-
end
|
372
|
-
|
373
|
-
def __ole_inner_elements
|
374
|
-
locate
|
375
|
-
return @o.all
|
376
|
-
end
|
377
|
-
|
378
|
-
def document
|
379
|
-
locate
|
380
|
-
return @o
|
381
|
-
end
|
382
|
-
|
383
230
|
alias to_s text
|
384
231
|
|
385
232
|
def colspan
|
data/lib/watir/window.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
module Watir
|
2
|
+
class Window
|
3
|
+
include ElementExtensions
|
4
|
+
|
5
|
+
class << self
|
6
|
+
attr_accessor :__main_ie
|
7
|
+
|
8
|
+
def wrap *meths
|
9
|
+
meths.each do |meth|
|
10
|
+
define_method meth do
|
11
|
+
result = nil
|
12
|
+
use {result = browser.send(meth)}
|
13
|
+
result
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(main_browser, locators, browser=nil, &blk)
|
20
|
+
valid_locators = [:title, :url, :hwnd, :index]
|
21
|
+
locators.each_pair do |k, v|
|
22
|
+
raise ArgumentError, "Valid locators are #{valid_locators.join(", ")}" unless valid_locators.include?(k)
|
23
|
+
end
|
24
|
+
@main_browser = main_browser
|
25
|
+
self.class.__main_ie = main_browser.ie
|
26
|
+
@locators = locators
|
27
|
+
@browser = browser
|
28
|
+
end
|
29
|
+
|
30
|
+
wrap :url, :title, :hwnd, :close
|
31
|
+
|
32
|
+
def browser
|
33
|
+
@browser ||= begin
|
34
|
+
IE.find(@locators.keys.first, @locators.values.first)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def use(&blk)
|
39
|
+
@main_browser.ie = browser.ie
|
40
|
+
if blk
|
41
|
+
begin
|
42
|
+
blk.call
|
43
|
+
ensure
|
44
|
+
@main_browser.ie = self.class.__main_ie
|
45
|
+
# try to find some existing IE when needed
|
46
|
+
@main_browser.ie = IE._find(:index, 0) unless @main_browser.exists?
|
47
|
+
end
|
48
|
+
end
|
49
|
+
self
|
50
|
+
end
|
51
|
+
|
52
|
+
def current?
|
53
|
+
@main_browser.hwnd == browser.hwnd
|
54
|
+
end
|
55
|
+
|
56
|
+
def ==(other)
|
57
|
+
browser.hwnd == other.hwnd
|
58
|
+
end
|
59
|
+
|
60
|
+
alias_method :eql?, :==
|
61
|
+
|
62
|
+
def present?
|
63
|
+
@browser = nil
|
64
|
+
browser && browser.exists?
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|