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.
- data/readme.rb +20 -12
- data/unittests/html/table1.html +41 -1
- data/unittests/links_test.rb +2 -2
- data/unittests/navigate_test.rb +2 -2
- data/unittests/parent_child_test.rb +0 -15
- data/unittests/table_test.rb +5 -2
- data/unittests/textarea_test.rb +55 -39
- data/unittests/windows/iedialog_test.rb +2 -2
- data/watir.rb +20 -4386
- data/watir/{elements.rb → bonus-elements.rb} +0 -0
- data/watir/collections.rb +317 -0
- data/watir/container.rb +883 -0
- data/watir/element.rb +306 -0
- data/watir/element_collections.rb +82 -0
- data/watir/form.rb +151 -0
- data/watir/frame.rb +60 -0
- data/watir/ie.rb +973 -0
- data/watir/image.rb +131 -0
- data/watir/input_elements.rb +518 -0
- data/watir/link.rb +65 -0
- data/watir/locator.rb +79 -0
- data/watir/logger.rb +19 -0
- data/watir/modal_dialog.rb +123 -0
- data/watir/non_control_elements.rb +91 -0
- data/watir/page-container.rb +106 -0
- data/watir/popup.rb +30 -0
- data/watir/table.rb +356 -0
- data/watir/win32.rb +29 -0
- metadata +21 -3
data/readme.rb
CHANGED
@@ -2,17 +2,25 @@
|
|
2
2
|
|
3
3
|
This is Watir - Web Application Testing In Ruby http://wtr.rubyforge.org
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
5
|
+
Install Ruby http://ruby-lang.org
|
6
|
+
First you need to install Ruby using the one-click installer for Windows. We
|
7
|
+
recommend Ruby 1.8.5. (Ruby 1.8.6 has problems.)
|
8
|
+
|
9
|
+
However, if you wish to use Watir's support for the IE showModalDialog then
|
10
|
+
you must use Ruby 1.8.2-15 (or 1.8.2-14) and not a more recent version. This
|
11
|
+
dialog is the one that is posted with the showModalDialog() JavaScript
|
12
|
+
command and is supported with Watir's ie.modal_dialog command.
|
13
|
+
|
14
|
+
Install Watir
|
15
|
+
Watir is packaged as a gem, a Ruby library that can be installed over the
|
16
|
+
internet.
|
17
|
+
|
18
|
+
Watir 1.5 was released in September 2007. To install it, type this at a
|
19
|
+
command prompt:
|
20
|
+
gem install watir
|
21
|
+
|
22
|
+
Watir 1.4 was released in August 2005. If you are upgrading from it, see
|
23
|
+
these notes: http://wiki.openqa.org/display/WTR/Development+Builds
|
16
24
|
|
17
25
|
How To Use:
|
18
26
|
This only works on Windows.
|
@@ -93,7 +101,7 @@ Contacts:
|
|
93
101
|
Paul Rogers (paul.rogers@shaw.ca)
|
94
102
|
Bret Pettichord (bret@pettichord.com)
|
95
103
|
Charley Baker (charley.baker@gmail.com)
|
96
|
-
The mailing list: http://
|
104
|
+
The mailing list: http://groups.google.com/group/watir-general
|
97
105
|
|
98
106
|
Contributors:
|
99
107
|
Bret Pettichord
|
data/unittests/html/table1.html
CHANGED
@@ -6,6 +6,33 @@ Test page for Tables
|
|
6
6
|
</head>
|
7
7
|
<body>
|
8
8
|
|
9
|
+
<style type="text/css">
|
10
|
+
table.sample {
|
11
|
+
border-width: 1px 1px 1px 1px;
|
12
|
+
border-spacing: 2px;
|
13
|
+
border-style: outset outset outset outset;
|
14
|
+
border-color: gray gray gray gray;
|
15
|
+
border-collapse: separate;
|
16
|
+
background-color: white;
|
17
|
+
}
|
18
|
+
table.sample th {
|
19
|
+
border-width: 1px 1px 1px 1px;
|
20
|
+
padding: 1px 1px 1px 1px;
|
21
|
+
border-style: inset inset inset inset;
|
22
|
+
border-color: gray gray gray gray;
|
23
|
+
background-color: white;
|
24
|
+
-moz-border-radius: 0px 0px 0px 0px;
|
25
|
+
}
|
26
|
+
table.sample td {
|
27
|
+
border-width: 1px 1px 1px 1px;
|
28
|
+
padding: 1px 1px 1px 1px;
|
29
|
+
border-style: inset inset inset inset;
|
30
|
+
border-color: gray gray gray gray;
|
31
|
+
background-color: white;
|
32
|
+
-moz-border-radius: 0px 0px 0px 0px;
|
33
|
+
}
|
34
|
+
</style>
|
35
|
+
|
9
36
|
<script language=javascript>
|
10
37
|
|
11
38
|
function addRow() {
|
@@ -32,7 +59,7 @@ function addRow() {
|
|
32
59
|
</script>
|
33
60
|
|
34
61
|
|
35
|
-
CVS Revision: "$Revision:
|
62
|
+
CVS Revision: "$Revision: 1239 $"
|
36
63
|
<br>
|
37
64
|
<br>
|
38
65
|
<table >
|
@@ -137,6 +164,19 @@ This text is in the THIRD TBODY.
|
|
137
164
|
|
138
165
|
|
139
166
|
|
167
|
+
<table class="sample">
|
168
|
+
<tr>
|
169
|
+
<th>Header</th>
|
170
|
+
<td>First table with css class</td>
|
171
|
+
</tr>
|
172
|
+
</table>
|
173
|
+
|
174
|
+
<table class="sample">
|
175
|
+
<tr>
|
176
|
+
<td>Second table with css class</td>
|
177
|
+
</tr>
|
178
|
+
</table>
|
179
|
+
|
140
180
|
|
141
181
|
</body>
|
142
182
|
</html>
|
data/unittests/links_test.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# feature tests for Links
|
2
|
-
# revision: $Revision:
|
2
|
+
# revision: $Revision: 1277 $
|
3
3
|
|
4
4
|
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..') if $0 == __FILE__
|
5
5
|
require 'unittests/setup'
|
6
|
-
require '
|
6
|
+
require 'cgi'
|
7
7
|
|
8
8
|
class TC_Links < Test::Unit::TestCase
|
9
9
|
include Watir
|
data/unittests/navigate_test.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
# feature tests for navigation
|
2
|
-
# revision: $Revision:
|
2
|
+
# revision: $Revision: 1277 $
|
3
3
|
|
4
4
|
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..') if $0 == __FILE__
|
5
5
|
require 'unittests/setup'
|
6
|
-
require '
|
6
|
+
require 'cgi'
|
7
7
|
|
8
8
|
class TC_Navigate < Test::Unit::TestCase
|
9
9
|
include Watir
|
@@ -3,21 +3,6 @@
|
|
3
3
|
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..') if $0 == __FILE__
|
4
4
|
require 'unittests/setup'
|
5
5
|
|
6
|
-
# These tests are based on the rails depot application, which requires some
|
7
|
-
# modifications...
|
8
|
-
|
9
|
-
module Watir
|
10
|
-
class H3 < NonControlElement
|
11
|
-
TAG = 'h3'
|
12
|
-
end
|
13
|
-
module Container
|
14
|
-
def h3(how, what)
|
15
|
-
return H3.new(self, how, what)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
|
21
6
|
class TC_Relative < Test::Unit::TestCase
|
22
7
|
|
23
8
|
def setup
|
data/unittests/table_test.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# feature tests for Tables
|
2
|
-
# revision: $Revision:
|
2
|
+
# revision: $Revision: 1246 $
|
3
3
|
|
4
4
|
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..') if $0 == __FILE__
|
5
5
|
require 'unittests/setup'
|
@@ -54,7 +54,6 @@ class TC_Tables < Test::Unit::TestCase
|
|
54
54
|
def test_dynamic_tables
|
55
55
|
t = $ie.table(:id, 't1')
|
56
56
|
assert_equal(5, t.row_count)
|
57
|
-
|
58
57
|
$ie.button(:value, 'add row').click
|
59
58
|
assert_equal(6, t.row_count)
|
60
59
|
end
|
@@ -176,6 +175,10 @@ class TC_Tables < Test::Unit::TestCase
|
|
176
175
|
def test_table_container
|
177
176
|
assert_nothing_raised { $ie.table(:id, 't1').html }
|
178
177
|
end
|
178
|
+
|
179
|
+
def test_multiple_selector
|
180
|
+
assert( $ie.table(:class => 'sample', :index => 2)[1][1].text, '')
|
181
|
+
end
|
179
182
|
end
|
180
183
|
|
181
184
|
class TC_Tables_Simple < Test::Unit::TestCase
|
data/unittests/textarea_test.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
#
|
2
|
-
# revision: $Revision:
|
1
|
+
# tests for textarea elements
|
2
|
+
# revision: $Revision: 1260 $
|
3
3
|
|
4
4
|
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..') if $0 == __FILE__
|
5
5
|
require 'unittests/setup'
|
@@ -7,13 +7,15 @@ require 'unittests/setup'
|
|
7
7
|
class TC_TextArea < Test::Unit::TestCase
|
8
8
|
include Watir
|
9
9
|
|
10
|
-
def
|
11
|
-
$ie.goto($htmlRoot +
|
10
|
+
def use_page page
|
11
|
+
$ie.goto($htmlRoot + page)
|
12
|
+
end
|
13
|
+
|
14
|
+
def setup
|
15
|
+
use_page 'textarea.html'
|
12
16
|
end
|
13
17
|
|
14
|
-
def
|
15
|
-
goto_page
|
16
|
-
#test for existance of 4 text area
|
18
|
+
def test_elements_exist_or_not
|
17
19
|
assert($ie.text_field(:name,"txtMultiLine1").exists?)
|
18
20
|
assert($ie.text_field(:name,"txtMultiLine2").exists?)
|
19
21
|
assert($ie.text_field(:name,"txtMultiLine3").exists?)
|
@@ -23,59 +25,73 @@ class TC_TextArea < Test::Unit::TestCase
|
|
23
25
|
assert($ie.text_field(:id,"txtMultiLine2").exists?)
|
24
26
|
assert($ie.text_field(:id,"txtMultiLine3").exists?)
|
25
27
|
assert($ie.text_field(:id,"txtReadOnly").exists?)
|
26
|
-
|
28
|
+
|
27
29
|
assert(!$ie.text_field(:name, "missing").exists?)
|
28
30
|
assert(!$ie.text_field(:name,"txtMultiLine4").exists?)
|
29
31
|
end
|
30
32
|
|
31
|
-
def
|
33
|
+
def test_to_s_bug
|
32
34
|
# from a bug reported by Zeljko Filipin
|
33
35
|
assert_nothing_raised { $ie.text_field(:id,"txtMultiLine3").to_s }
|
34
36
|
end
|
35
37
|
|
36
|
-
def
|
37
|
-
|
38
|
-
|
39
|
-
|
38
|
+
def test_maxlength_bug
|
39
|
+
# from another bug
|
40
|
+
assert_nothing_raised { $ie.text_field(:id,"txtMultiLine3").append('foo')}
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_readonly_and_enabled
|
40
44
|
assert(!$ie.text_field(:name, "txtMultiLine1").readonly? )
|
41
45
|
assert($ie.text_field(:name,"txtReadOnly").readonly?)
|
42
46
|
|
43
|
-
# test for enabled? method
|
44
47
|
assert(!$ie.text_field(:name, "txtDisabled").enabled? )
|
45
48
|
assert($ie.text_field(:id, "txtMultiLine1").enabled? )
|
46
|
-
|
47
|
-
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_verify_contains
|
48
52
|
t1 = $ie.text_field(:name, "txtMultiLine1")
|
49
53
|
assert(t1.verify_contains("Hello World") )
|
50
54
|
assert(t1.verify_contains(/el/) )
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
assert_raises(
|
59
|
-
|
60
|
-
|
61
|
-
|
55
|
+
assert($ie.text_field(:name, "txtMultiLine2").verify_contains(/IE/))
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_no_such_element
|
59
|
+
assert_raises(UnknownObjectException) do
|
60
|
+
$ie.text_field(:name, "NoName").verify_contains("de nada")
|
61
|
+
end
|
62
|
+
assert_raises(UnknownObjectException) do
|
63
|
+
$ie.text_field(:id, "noID").verify_contains("de nada")
|
64
|
+
end
|
65
|
+
assert_raises(UnknownObjectException) do
|
66
|
+
$ie.text_field(:name, "txtNone").append("de nada")
|
67
|
+
end
|
68
|
+
end
|
69
|
+
def test_readonly_and_disabled_errors
|
70
|
+
assert_raises(ObjectReadOnlyException) do
|
71
|
+
$ie.text_field(:id, "txtReadOnly").append("de nada")
|
72
|
+
end
|
73
|
+
assert_raises(ObjectDisabledException) do
|
74
|
+
$ie.text_field(:name, "txtDisabled").append("de nada")
|
75
|
+
end
|
76
|
+
assert_raises(ObjectReadOnlyException) do
|
77
|
+
$ie.text_field(:id, "txtReadOnly").append("Some Text")
|
78
|
+
end
|
79
|
+
assert_raises(ObjectDisabledException) do
|
80
|
+
$ie.text_field(:name, "txtDisabled").append("Some Text")
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_append_set_and_clear
|
62
85
|
$ie.text_field(:name, "txtMultiLine1").append(" Some Text")
|
63
|
-
assert_equal(
|
64
|
-
|
65
|
-
assert_raises(ObjectReadOnlyException , "ObjectReadOnlyException was supposed to be thrown" ) { $ie.text_field(:id, "txtReadOnly").append("Some Text") }
|
66
|
-
assert_raises(ObjectDisabledException , "ObjectReadOnlyException was supposed to be thrown" ) { $ie.text_field(:name, "txtDisabled").append("Some Text") }
|
67
|
-
assert_raises(UnknownObjectException , "ObjectReadOnlyException was supposed to be thrown" ) { $ie.text_field(:name, "missing_field").append("Some Text") }
|
86
|
+
assert_equal("Hello World Some Text",
|
87
|
+
$ie.text_field(:name, "txtMultiLine1").getContents )
|
68
88
|
|
69
89
|
$ie.text_field(:name, "txtMultiLine1").set("watir IE Controller")
|
70
|
-
assert_equal(
|
71
|
-
|
72
|
-
assert_raises(ObjectReadOnlyException , "ObjectReadOnlyException was supposed to be thrown" ) { $ie.text_field(:id, "txtReadOnly").append("Some Text") }
|
73
|
-
assert_raises(ObjectDisabledException , "ObjectReadOnlyException was supposed to be thrown" ) { $ie.text_field(:name, "txtDisabled").append("Some Text") }
|
74
|
-
assert_raises(UnknownObjectException , "ObjectReadOnlyException was supposed to be thrown" ) { $ie.text_field(:name, "missing_field").append("Some Text") }
|
90
|
+
assert_equal("watir IE Controller",
|
91
|
+
$ie.text_field(:name, "txtMultiLine1").getContents )
|
75
92
|
|
76
93
|
$ie.text_field(:name, "txtMultiLine2").clear
|
77
|
-
assert_equal(
|
78
|
-
|
94
|
+
assert_equal("" , $ie.text_field(:name, "txtMultiLine2").getContents )
|
79
95
|
end
|
80
96
|
|
81
97
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# unit tests for iedialog.dll and customized win32ole.so
|
2
|
-
# revision: $Revision:
|
2
|
+
# revision: $Revision: 1278 $
|
3
3
|
|
4
4
|
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', '..') if $0 == __FILE__
|
5
5
|
require 'unittests/setup'
|
@@ -10,7 +10,7 @@ class TC_IEDialog < Test::Unit::TestCase
|
|
10
10
|
include Watir
|
11
11
|
|
12
12
|
# this will find the IEDialog.dll file in its build location
|
13
|
-
@@iedialog_file = (File.expand_path(File.dirname(__FILE__)) + "
|
13
|
+
@@iedialog_file = (File.expand_path(File.dirname(__FILE__)) + "/../../watir/IEDialog/Release/IEDialog.dll").gsub('/', '\\')
|
14
14
|
|
15
15
|
# commented out because it currently requires a manual click
|
16
16
|
# a better idea would be to automate the click...
|
data/watir.rb
CHANGED
@@ -86,6 +86,25 @@ $FAST_SPEED = command_line_flag('-f')
|
|
86
86
|
# Eat the -s command line switch (deprecated)
|
87
87
|
command_line_flag('-s')
|
88
88
|
|
89
|
+
require 'watir/logger'
|
90
|
+
require 'watir/win32'
|
91
|
+
require 'watir/container'
|
92
|
+
require 'watir/locator'
|
93
|
+
require 'watir/page-container'
|
94
|
+
require 'watir/ie'
|
95
|
+
require 'watir/popup'
|
96
|
+
require 'watir/element'
|
97
|
+
require 'watir/frame'
|
98
|
+
require 'watir/modal_dialog'
|
99
|
+
require 'watir/element_collections'
|
100
|
+
require 'watir/form'
|
101
|
+
require 'watir/non_control_elements'
|
102
|
+
require 'watir/input_elements'
|
103
|
+
require 'watir/table'
|
104
|
+
require 'watir/image'
|
105
|
+
require 'watir/link'
|
106
|
+
require 'watir/collections'
|
107
|
+
|
89
108
|
module Watir
|
90
109
|
include Watir::Exception
|
91
110
|
|
@@ -103,4393 +122,8 @@ module Watir
|
|
103
122
|
ATTACHER.timeout = IE.attach_timeout
|
104
123
|
ATTACHER.wait_until { yield }
|
105
124
|
end
|
106
|
-
|
107
|
-
class WatirLogger < Logger
|
108
|
-
def initialize(filName, logsToKeep, maxLogSize)
|
109
|
-
super(filName, logsToKeep, maxLogSize)
|
110
|
-
self.level = Logger::DEBUG
|
111
|
-
self.datetime_format = "%d-%b-%Y %H:%M:%S"
|
112
|
-
self.debug("Watir starting")
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
class DefaultLogger < Logger
|
117
|
-
def initialize
|
118
|
-
super(STDERR)
|
119
|
-
self.level = Logger::WARN
|
120
|
-
self.datetime_format = "%d-%b-%Y %H:%M:%S"
|
121
|
-
self.info "Log started"
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
module Win32
|
126
|
-
# this will find the IEDialog.dll file in its build location
|
127
|
-
@@iedialog_file = (File.expand_path(File.dirname(__FILE__)) + "/watir/IEDialog/Release/IEDialog.dll").gsub('/', '\\')
|
128
|
-
|
129
|
-
GetUnknown = Win32API.new(@@iedialog_file, 'GetUnknown', ['l', 'p'], 'v')
|
130
|
-
User32 = DL.dlopen('user32')
|
131
|
-
FindWindowEx = User32['FindWindowEx', 'LLLpp']
|
132
|
-
# method for this found in wet-winobj/wet/winobjects/WinUtils.rb
|
133
|
-
GetWindow = User32['GetWindow', 'ILL']
|
134
|
-
|
135
|
-
## GetWindows Constants
|
136
|
-
GW_HWNDFIRST = 0
|
137
|
-
GW_HWNDLAST = 1
|
138
|
-
GW_HWNDNEXT = 2
|
139
|
-
GW_HWNDPREV = 3
|
140
|
-
GW_OWNER = 4
|
141
|
-
GW_CHILD = 5
|
142
|
-
GW_ENABLEDPOPUP = 6
|
143
|
-
GW_MAX = 6
|
144
|
-
|
145
|
-
IsWindow = User32['IsWindow', 'II']
|
146
|
-
# Does the window with the specified window handle (hwnd) exist?
|
147
|
-
def self.window_exists? hwnd
|
148
|
-
rtn, junk = IsWindow[hwnd]
|
149
|
-
rtn == 1
|
150
|
-
end
|
151
|
-
end
|
152
|
-
|
153
|
-
# This module contains the factory methods that are used to access most html objects
|
154
|
-
#
|
155
|
-
# For example, to access a button on a web page that has the following html
|
156
|
-
# <input type = button name= 'b1' value='Click Me' onClick='javascript:doSomething()'>
|
157
|
-
#
|
158
|
-
# the following watir code could be used
|
159
|
-
#
|
160
|
-
# ie.button(:name, 'b1').click
|
161
|
-
#
|
162
|
-
# or
|
163
|
-
#
|
164
|
-
# ie.button(:value, 'Click Me').to_s
|
165
|
-
#
|
166
|
-
# there are many methods available to the Button object
|
167
|
-
#
|
168
|
-
# Is includable for classes that have @container, document and ole_inner_elements
|
169
|
-
module Container
|
170
|
-
include Watir::Exception
|
171
|
-
|
172
|
-
# Note: @container is the container of this object, i.e. the container
|
173
|
-
# of this container.
|
174
|
-
# In other words, for ie.table().this_thing().text_field().set,
|
175
|
-
# container of this_thing is the table.
|
176
|
-
|
177
|
-
# This is used to change the typing speed when entering text on a page.
|
178
|
-
attr_accessor :typingspeed
|
179
|
-
# The color we want to use for the active object. This can be any valid web-friendly color.
|
180
|
-
attr_accessor :activeObjectHighLightColor
|
181
|
-
# The PageContainer object containing this element
|
182
|
-
attr_accessor :page_container
|
183
|
-
|
184
|
-
def copy_test_config(container) # only used by form and frame
|
185
|
-
@typingspeed = container.typingspeed
|
186
|
-
@activeObjectHighLightColor = container.activeObjectHighLightColor
|
187
|
-
end
|
188
|
-
private :copy_test_config
|
189
|
-
|
190
|
-
# Write the specified string to the log.
|
191
|
-
def log(what)
|
192
|
-
@container.logger.debug(what) if @logger
|
193
|
-
end
|
194
|
-
|
195
|
-
# Wait until Internet Explorer has finished loading the page.
|
196
|
-
def wait(no_sleep=false)
|
197
|
-
@container.wait(no_sleep)
|
198
|
-
end
|
199
|
-
|
200
|
-
# Determine the how and what when defaults are possible.
|
201
|
-
def process_default(default_attribute, how, what)
|
202
|
-
if how.class == String && what == nil
|
203
|
-
what = how
|
204
|
-
how = default_attribute
|
205
|
-
end
|
206
|
-
return how, what
|
207
|
-
end
|
208
|
-
private :process_default
|
209
|
-
|
210
|
-
def set_container container
|
211
|
-
@container = container
|
212
|
-
@page_container = container.page_container
|
213
|
-
end
|
214
|
-
|
215
|
-
private
|
216
|
-
def self.def_creator(method_name, klass_name=nil)
|
217
|
-
klass_name ||= method_name.to_s.capitalize
|
218
|
-
class_eval "def #{method_name}(how, what=nil)
|
219
|
-
#{klass_name}.new(self, how, what)
|
220
|
-
end"
|
221
|
-
end
|
222
|
-
|
223
|
-
def self.def_creator_with_default(method_name, default_symbol)
|
224
|
-
klass_name = method_name.to_s.capitalize
|
225
|
-
class_eval "def #{method_name}(how, what=nil)
|
226
|
-
how, what = process_default :#{default_symbol}, how, what
|
227
|
-
#{klass_name}.new(self, how, what)
|
228
|
-
end"
|
229
|
-
end
|
230
|
-
|
231
|
-
#
|
232
|
-
# Factory Methods
|
233
|
-
#
|
234
|
-
|
235
|
-
# this method is the main way of accessing a frame
|
236
|
-
# * how - how the frame is accessed. This can also just be the name of the frame.
|
237
|
-
# * what - what we want to access.
|
238
|
-
#
|
239
|
-
# Valid values for 'how' are listed in the Watir Wiki - http://wiki.openqa.org/display/WTR/Methods+supported+by+Element
|
240
|
-
#
|
241
|
-
# returns a Frame object
|
242
|
-
#
|
243
|
-
# Typical usage:
|
244
|
-
#
|
245
|
-
# ie.frame(:index, 1)
|
246
|
-
# ie.frame(:name, 'main_frame')
|
247
|
-
# ie.frame('main_frame') # in this case, just a name is supplied
|
248
|
-
public
|
249
|
-
def frame(how, what=nil)
|
250
|
-
how, what = process_default :name, how, what
|
251
|
-
Frame.new(self, how, what)
|
252
|
-
end
|
253
|
-
|
254
|
-
# this method is used to access a form.
|
255
|
-
# available ways of accessing it are, :index, :name, :id, :method, :action, :xpath
|
256
|
-
# * how - symbol - What mecahnism we use to find the form, one of
|
257
|
-
# the above. NOTE if what is not supplied this parameter is the NAME of the form
|
258
|
-
# * what - String - the text associated with the symbol
|
259
|
-
#
|
260
|
-
# Valid values for 'how' are listed in the Watir Wiki - http://wiki.openqa.org/display/WTR/Methods+supported+by+Element
|
261
|
-
#
|
262
|
-
# returns a Form object
|
263
|
-
def form(how, what=nil)
|
264
|
-
how, what = process_default :name, how, what
|
265
|
-
Form.new(self, how, what)
|
266
|
-
end
|
267
|
-
|
268
|
-
# This method is used to get a table from the page.
|
269
|
-
# :index (1 based counting) and :id are supported.
|
270
|
-
# NOTE :name is not supported, as the table tag does not have a name attribute. It is not part of the DOM.
|
271
|
-
# :index can be used when there are multiple tables on a page.
|
272
|
-
# :xpath can be used to select table using XPath query.
|
273
|
-
# The first form can be accessed with :index 1, the second :index 2, etc.
|
274
|
-
# * how - symbol - how we access the table, :index, :id, :xpath etc
|
275
|
-
# * what - string the thing we are looking for, ex. id, index or xpath query, of the object we are looking for
|
276
|
-
#
|
277
|
-
# Valid values for 'how' are listed in the Watir Wiki - http://wiki.openqa.org/display/WTR/Methods+supported+by+Element
|
278
|
-
#
|
279
|
-
# returns a Table object
|
280
|
-
def table(how, what=nil)
|
281
|
-
Table.new(self, how, what)
|
282
|
-
end
|
283
|
-
|
284
|
-
# this is the main method for accessing the tables iterator. It returns a Tables object
|
285
|
-
#
|
286
|
-
# Typical usage:
|
287
|
-
#
|
288
|
-
# ie.tables.each { |t| puts t.to_s } # iterate through all the tables on the page
|
289
|
-
# ie.tables[1].to_s # goto the first table on the page
|
290
|
-
# ie.tables.length # show how many tables are on the page. Tables that are nested will be included in this
|
291
|
-
def tables
|
292
|
-
Tables.new(self)
|
293
|
-
end
|
294
|
-
|
295
|
-
# this method accesses a table cell.
|
296
|
-
# how - symbol - how we access the cell, valid values are
|
297
|
-
# :id - find the table cell with given id.
|
298
|
-
# :xpath - find the table cell using xpath query.
|
299
|
-
#
|
300
|
-
# returns a TableCell Object
|
301
|
-
def cell(how, what=nil)
|
302
|
-
TableCell.new(self, how, what)
|
303
|
-
end
|
304
|
-
def cells
|
305
|
-
TableCells.new(self)
|
306
|
-
end
|
307
|
-
|
308
|
-
# this method accesses a table row.
|
309
|
-
# how - symbol - how we access the row, valid values are
|
310
|
-
# :id - find the table row with given id.
|
311
|
-
# :xpath - find the table row using xpath query.
|
312
|
-
#
|
313
|
-
# returns a TableRow object
|
314
|
-
def row(how, what=nil)
|
315
|
-
TableRow.new(self, how, what)
|
316
|
-
end
|
317
|
-
def rows
|
318
|
-
TableRows.new(self)
|
319
|
-
end
|
320
|
-
|
321
|
-
# Access a modal web dialog, which is a PageContainer, like IE or Frame.
|
322
|
-
# Returns a ModalDialog object.
|
323
|
-
#
|
324
|
-
# Typical Usage
|
325
|
-
# ie.modal_dialog # access the modal dialog of ie
|
326
|
-
# ie.modal_dialog(:title, 'Title') # access the modal dialog by title
|
327
|
-
# ie.modal_dialog.modal_dialog # access a modal dialog's modal dialog XXX untested!
|
328
|
-
#
|
329
|
-
# This method will not work when
|
330
|
-
# Watir/Ruby is run under a service (instead of a user).
|
331
|
-
# Note: unlike Watir.attach, this returns before the page is assured to have
|
332
|
-
# loaded.
|
333
|
-
|
334
|
-
def modal_dialog(how=nil, what=nil)
|
335
|
-
ModalDialog.new(self, how, what)
|
336
|
-
end
|
337
|
-
|
338
|
-
# This is the main method for accessing a button. Often declared as an <input type = submit> tag.
|
339
|
-
# * how - symbol - how we access the button, :index, :id, :name etc
|
340
|
-
# * what - string, integer or regular expression - what we are looking for,
|
341
|
-
#
|
342
|
-
# Valid values for 'how' are listed in the Watir Wiki - http://wiki.openqa.org/display/WTR/Methods+supported+by+Element
|
343
|
-
#
|
344
|
-
# Returns a Button object.
|
345
|
-
#
|
346
|
-
# Typical usage
|
347
|
-
#
|
348
|
-
# ie.button(:id, 'b_1') # access the button with an ID of b_1
|
349
|
-
# ie.button(:name, 'verify_data') # access the button with a name of verify_data
|
350
|
-
# ie.button(:value, 'Login') # access the button with a value (the text displayed on the button) of Login
|
351
|
-
# ie.button(:caption, 'Login') # same as above
|
352
|
-
# ie.button(:value, /Log/) # access the button that has text matching /Log/
|
353
|
-
# ie.button(:index, 2) # access the second button on the page (1 based, so the first button is accessed with :index,1)
|
354
|
-
# ie.button(:class, 'my_custom_button_class') # access the button with a class of my_custom_button_class
|
355
|
-
# ie.button(:xpath, "//input[@value='Click Me']/") # access the button with a value of Click Me
|
356
|
-
#
|
357
|
-
# Accessing a Button nested within another element
|
358
|
-
# ie.div(:class, 'xyz').button(:index, 2) # access a div of class xyz, and the 2nd button within that div
|
359
|
-
#
|
360
|
-
# If only a single parameter is supplied, then :value is used
|
361
|
-
# ie.button('Click Me') # access the button with a value of Click Me
|
362
|
-
def button(how, what=nil)
|
363
|
-
how, what = process_default :value, how, what
|
364
|
-
Button.new(self, how, what)
|
365
|
-
end
|
366
|
-
|
367
|
-
# this is the main method for accessing the buttons iterator. It returns a Buttons object
|
368
|
-
#
|
369
|
-
# Typical usage:
|
370
|
-
#
|
371
|
-
# ie.buttons.each { |b| puts b.to_s } # iterate through all the buttons on the page
|
372
|
-
# ie.buttons[1].to_s # goto the first button on the page
|
373
|
-
# ie.buttons.length # show how many buttons are on the page.
|
374
|
-
def buttons
|
375
|
-
Buttons.new(self)
|
376
|
-
end
|
377
|
-
|
378
|
-
# This is the main method for accessing a file field. Usually an <input type = file> HTML tag.
|
379
|
-
# * how - symbol - how we access the field, valid values are
|
380
|
-
# :index - find the file field using index
|
381
|
-
# :id - find the file field using id attribute
|
382
|
-
# :name - find the file field using name attribute
|
383
|
-
# :xpath - find the file field using xpath query
|
384
|
-
# * what - string, integer, regular expression, or xpath query - what we are looking for,
|
385
|
-
#
|
386
|
-
# returns a FileField object
|
387
|
-
#
|
388
|
-
# Typical Usage
|
389
|
-
#
|
390
|
-
# ie.file_field(:id, 'up_1') # access the file upload field with an ID of up_1
|
391
|
-
# ie.file_field(:name, 'upload') # access the file upload field with a name of upload
|
392
|
-
# ie.file_field(:index, 2) # access the second file upload on the page (1 based, so the first field is accessed with :index,1)
|
393
|
-
#
|
394
|
-
def file_field(how, what=nil)
|
395
|
-
FileField.new(self, how, what)
|
396
|
-
end
|
397
|
-
|
398
|
-
# this is the main method for accessing the file_fields iterator. It returns a FileFields object
|
399
|
-
#
|
400
|
-
# Typical usage:
|
401
|
-
#
|
402
|
-
# ie.file_fields.each { |f| puts f.to_s } # iterate through all the file fields on the page
|
403
|
-
# ie.file_fields[1].to_s # goto the first file field on the page
|
404
|
-
# ie.file_fields.length # show how many file fields are on the page.
|
405
|
-
def file_fields
|
406
|
-
FileFields.new(self)
|
407
|
-
end
|
408
|
-
|
409
|
-
# This is the main method for accessing a text field. Usually an <input type = text> HTML tag. or a text area - a <textarea> tag
|
410
|
-
# * how - symbol - how we access the field, :index, :id, :name etc
|
411
|
-
# * what - string, integer or regular expression - what we are looking for,
|
412
|
-
#
|
413
|
-
# Valid values for 'how' are listed in the Watir Wiki - http://wiki.openqa.org/display/WTR/Methods+supported+by+Element
|
414
|
-
#
|
415
|
-
# returns a TextField object
|
416
|
-
#
|
417
|
-
# Typical Usage
|
418
|
-
#
|
419
|
-
# ie.text_field(:id, 'user_name') # access the text field with an ID of user_name
|
420
|
-
# ie.text_field(:name, 'address') # access the text field with a name of address
|
421
|
-
# ie.text_field(:index, 2) # access the second text field on the page (1 based, so the first field is accessed with :index,1)
|
422
|
-
# ie.text_field(:xpath, "//textarea[@id='user_name']/") # access the text field with an ID of user_name
|
423
|
-
def text_field(how, what=nil)
|
424
|
-
TextField.new(self, how, what)
|
425
|
-
end
|
426
|
-
|
427
|
-
# this is the method for accessing the text_fields iterator. It returns a Text_Fields object
|
428
|
-
#
|
429
|
-
# Typical usage:
|
430
|
-
#
|
431
|
-
# ie.text_fields.each { |t| puts t.to_s } # iterate through all the text fields on the page
|
432
|
-
# ie.text_fields[1].to_s # goto the first text field on the page
|
433
|
-
# ie.text_fields.length # show how many text field are on the page.
|
434
|
-
def text_fields
|
435
|
-
TextFields.new(self)
|
436
|
-
end
|
437
|
-
|
438
|
-
# This is the main method for accessing a hidden field. Usually an <input type = hidden> HTML tag
|
439
|
-
#
|
440
|
-
# * how - symbol - how we access the hidden field, :index, :id, :name etc
|
441
|
-
# * what - string, integer or regular expression - what we are looking for,
|
442
|
-
#
|
443
|
-
# Valid values for 'how' are listed in the Watir Wiki - http://wiki.openqa.org/display/WTR/Methods+supported+by+Element
|
444
|
-
#
|
445
|
-
# returns a Hidden object
|
446
|
-
#
|
447
|
-
# Typical usage
|
448
|
-
#
|
449
|
-
# ie.hidden(:id, 'session_id') # access the hidden field with an ID of session_id
|
450
|
-
# ie.hidden(:name, 'temp_value') # access the hidden field with a name of temp_value
|
451
|
-
# ie.hidden(:index, 2) # access the second hidden field on the page (1 based, so the first field is accessed with :index,1)
|
452
|
-
# ie.hidden(:xpath, "//input[@type='hidden' and @id='session_value']/") # access the hidden field with an ID of session_id
|
453
|
-
def hidden(how, what=nil)
|
454
|
-
Hidden.new(self, how, what)
|
455
|
-
end
|
456
|
-
|
457
|
-
# this is the method for accessing the hiddens iterator. It returns a Hiddens object
|
458
|
-
#
|
459
|
-
# Typical usage:
|
460
|
-
#
|
461
|
-
# ie.hiddens.each { |t| puts t.to_s } # iterate through all the hidden fields on the page
|
462
|
-
# ie.hiddens[1].to_s # goto the first hidden field on the page
|
463
|
-
# ie.hiddens.length # show how many hidden fields are on the page.
|
464
|
-
def hiddens
|
465
|
-
Hiddens.new(self)
|
466
|
-
end
|
467
|
-
|
468
|
-
# This is the main method for accessing a selection list. Usually a <select> HTML tag.
|
469
|
-
# * how - symbol - how we access the selection list, :index, :id, :name etc
|
470
|
-
# * what - string, integer or regular expression - what we are looking for,
|
471
|
-
#
|
472
|
-
# Valid values for 'how' are listed in the Watir Wiki - http://wiki.openqa.org/display/WTR/Methods+supported+by+Element
|
473
|
-
#
|
474
|
-
# returns a SelectList object
|
475
|
-
#
|
476
|
-
# Typical usage
|
477
|
-
#
|
478
|
-
# ie.select_list(:id, 'currency') # access the select box with an id of currency
|
479
|
-
# ie.select_list(:name, 'country') # access the select box with a name of country
|
480
|
-
# ie.select_list(:name, /n_/) # access the first select box whose name matches n_
|
481
|
-
# ie.select_list(:index, 2) # access the second select box on the page (1 based, so the first field is accessed with :index,1)
|
482
|
-
# ie.select(:xpath, "//select[@id='currency']/") # access the select box with an id of currency
|
483
|
-
def select_list(how, what)
|
484
|
-
SelectList.new(self, how, what)
|
485
|
-
end
|
486
|
-
|
487
|
-
# this is the method for accessing the select lists iterator. Returns a SelectLists object
|
488
|
-
#
|
489
|
-
# Typical usage:
|
490
|
-
#
|
491
|
-
# ie.select_lists.each { |s| puts s.to_s } # iterate through all the select boxes on the page
|
492
|
-
# ie.select_lists[1].to_s # goto the first select boxes on the page
|
493
|
-
# ie.select_lists.length # show how many select boxes are on the page.
|
494
|
-
def select_lists
|
495
|
-
SelectLists.new(self)
|
496
|
-
end
|
497
|
-
|
498
|
-
# This is the main method for accessing a check box. Usually an <input type = checkbox> HTML tag.
|
499
|
-
#
|
500
|
-
# * how - symbol - how we access the check box - :index, :id, :name etc
|
501
|
-
# * what - string, integer or regular expression - what we are looking for,
|
502
|
-
# * value - string - when there are multiple objects with different value attributes, this can be used to find the correct object
|
503
|
-
#
|
504
|
-
# Valid values for 'how' are listed in the Watir Wiki - http://wiki.openqa.org/display/WTR/Methods+supported+by+Element
|
505
|
-
#
|
506
|
-
# returns a CheckBox object
|
507
|
-
#
|
508
|
-
# Typical usage
|
509
|
-
#
|
510
|
-
# ie.checkbox(:id, 'send_email') # access the check box with an id of send_mail
|
511
|
-
# ie.checkbox(:name, 'send_copy') # access the check box with a name of send_copy
|
512
|
-
# ie.checkbox(:name, /n_/) # access the first check box whose name matches n_
|
513
|
-
# ie.checkbox(:index, 2) # access the second check box on the page (1 based, so the first field is accessed with :index,1)
|
514
|
-
#
|
515
|
-
# In many instances, checkboxes on an html page have the same name, but are identified by different values. An example is shown next.
|
516
|
-
#
|
517
|
-
# <input type = checkbox name = email_frequency value = 'daily' > Daily Email
|
518
|
-
# <input type = checkbox name = email_frequency value = 'Weekly'> Weekly Email
|
519
|
-
# <input type = checkbox name = email_frequency value = 'monthly'>Monthly Email
|
520
|
-
#
|
521
|
-
# Watir can access these using the following:
|
522
|
-
#
|
523
|
-
# ie.checkbox(:id, 'day_to_send', 'monday') # access the check box with an id of day_to_send and a value of monday
|
524
|
-
# ie.checkbox(:name,'email_frequency', 'weekly') # access the check box with a name of email_frequency and a value of 'weekly'
|
525
|
-
# ie.checkbox(:xpath, "//input[@name='email_frequency' and @value='daily']/") # access the checkbox with a name of email_frequency and a value of 'daily'
|
526
|
-
def checkbox(how, what, value=nil)
|
527
|
-
CheckBox.new(self, how, what, ["checkbox"], value)
|
528
|
-
end
|
529
|
-
|
530
|
-
# this is the method for accessing the check boxes iterator. Returns a CheckBoxes object
|
531
|
-
#
|
532
|
-
# Typical usage:
|
533
|
-
#
|
534
|
-
# ie.checkboxes.each { |c| puts c.to_s } # iterate through all the check boxes on the page
|
535
|
-
# ie.checkboxes[1].to_s # goto the first check box on the page
|
536
|
-
# ie.checkboxes.length # show how many check boxes are on the page.
|
537
|
-
def checkboxes
|
538
|
-
CheckBoxes.new(self)
|
539
|
-
end
|
540
|
-
|
541
|
-
# This is the main method for accessing a radio button. Usually an <input type = radio> HTML tag.
|
542
|
-
# * how - symbol - how we access the radio button, :index, :id, :name etc
|
543
|
-
# * what - string, integer or regular expression - what we are looking for,
|
544
|
-
# * value - string - when there are multiple objects with different value attributes, this can be used to find the correct object
|
545
|
-
#
|
546
|
-
# Valid values for 'how' are listed in the Watir Wiki - http://wiki.openqa.org/display/WTR/Methods+supported+by+Element
|
547
|
-
#
|
548
|
-
# returns a Radio object
|
549
|
-
#
|
550
|
-
# Typical usage
|
551
|
-
#
|
552
|
-
# ie.radio(:id, 'send_email') # access the radio button with an id of currency
|
553
|
-
# ie.radio(:name, 'send_copy') # access the radio button with a name of country
|
554
|
-
# ie.radio(:name, /n_/) # access the first radio button whose name matches n_
|
555
|
-
# ie.radio(:index, 2) # access the second radio button on the page (1 based, so the first field is accessed with :index,1)
|
556
|
-
#
|
557
|
-
# In many instances, radio buttons on an html page have the same name, but are identified by different values. An example is shown next.
|
558
|
-
#
|
559
|
-
# <input type="radio" name="email_frequency" value="daily">Daily Email</input>
|
560
|
-
# <input type="radio" name="email_frequency" value="weekly">Weekly Email</input>
|
561
|
-
# <input type="radio" name="email_frequency" value="monthly">Monthly Email</input>
|
562
|
-
#
|
563
|
-
# Watir can access these using the following:
|
564
|
-
#
|
565
|
-
# ie.radio(:id, 'day_to_send', 'monday') # access the radio button with an id of day_to_send and a value of monday
|
566
|
-
# ie.radio(:name,'email_frequency', 'weekly') # access the radio button with a name of email_frequency and a value of 'weekly'
|
567
|
-
# ie.radio(:xpath, "//input[@name='email_frequency' and @value='daily']/") # access the radio button with a name of email_frequency and a value of 'daily'
|
568
|
-
def radio(how, what, value=nil)
|
569
|
-
Radio.new(self, how, what, ["radio"], value)
|
570
|
-
end
|
571
|
-
|
572
|
-
# This is the method for accessing the radio buttons iterator. Returns a Radios object
|
573
|
-
#
|
574
|
-
# Typical usage:
|
575
|
-
#
|
576
|
-
# ie.radios.each { |r| puts r.to_s } # iterate through all the radio buttons on the page
|
577
|
-
# ie.radios[1].to_s # goto the first radio button on the page
|
578
|
-
# ie.radios.length # show how many radio buttons are on the page.
|
579
|
-
#
|
580
|
-
def radios
|
581
|
-
Radios.new(self)
|
582
|
-
end
|
583
|
-
|
584
|
-
# This is the main method for accessing a link.
|
585
|
-
# * how - symbol - how we access the link, :index, :id, :name, :title, :text, :url
|
586
|
-
# * what - string, integer or regular expression - what we are looking for,
|
587
|
-
#
|
588
|
-
# Valid values for 'how' are listed in the Watir Wiki - http://wiki.openqa.org/display/WTR/Methods+supported+by+Element
|
589
|
-
#
|
590
|
-
# returns a Link object
|
591
|
-
#
|
592
|
-
# Typical Usage
|
593
|
-
#
|
594
|
-
# ie.link(:url, /login/) # access the first link whose url matches login. We can use a string in place of the regular expression
|
595
|
-
# # but the complete path must be used, ie.link(:url, 'http://myserver.com/my_path/login.asp')
|
596
|
-
# ie.link(:index,2) # access the second link on the page
|
597
|
-
# ie.link(:title, "Picture") # access a link using the tool tip
|
598
|
-
# ie.link(:text, 'Click Me') # access the link that has Click Me as its text
|
599
|
-
# ie.link(:xpath, "//a[contains(.,'Click Me')]/") # access the link with Click Me as its text
|
600
|
-
def link(how, what=nil)
|
601
|
-
Link.new(self, how, what)
|
602
|
-
end
|
603
|
-
|
604
|
-
# This is the main method for accessing the links collection. Returns a Links object
|
605
|
-
#
|
606
|
-
# Typical usage:
|
607
|
-
#
|
608
|
-
# ie.links.each { |l| puts l.to_s } # iterate through all the links on the page
|
609
|
-
# ie.links[1].to_s # goto the first link on the page
|
610
|
-
# ie.links.length # show how many links are on the page.
|
611
|
-
#
|
612
|
-
def links
|
613
|
-
Links.new(self)
|
614
|
-
end
|
615
|
-
|
616
|
-
# This is the main method for accessing li tags - http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/map.asp?frame=true
|
617
|
-
# * how - symbol - how we access the li,
|
618
|
-
# * what - string, integer or regular expression - what we are looking for,
|
619
|
-
#
|
620
|
-
# Valid values for 'how' are listed in the Watir Wiki - http://wiki.openqa.org/display/WTR/Methods+supported+by+Element
|
621
|
-
#
|
622
|
-
# returns a li object
|
623
|
-
#
|
624
|
-
# Typical Usage
|
625
|
-
#
|
626
|
-
# ie.li(:id, /list/) # access the first li that matches list.
|
627
|
-
# ie.li(:index,2) # access the second li on the page
|
628
|
-
# ie.li(:title, "A Picture") # access a li using the tooltip text. See http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/title_1.asp?frame=true
|
629
|
-
#
|
630
|
-
def li(how, what)
|
631
|
-
return Li.new(self, how, what)
|
632
|
-
end
|
633
|
-
|
634
|
-
# this is the main method for accessing the lis iterator.
|
635
|
-
#
|
636
|
-
# Returns a lis object
|
637
|
-
#
|
638
|
-
# Typical usage:
|
639
|
-
#
|
640
|
-
# ie.lis.each { |s| puts s.to_s } # iterate through all the lis on the page
|
641
|
-
# ie.lis[1].to_s # goto the first li on the page
|
642
|
-
# ie.lis.length # show how many lis are on the page.
|
643
|
-
#
|
644
|
-
def lis
|
645
|
-
return Lis.new(self)
|
646
|
-
end
|
647
|
-
|
648
|
-
|
649
|
-
# This is the main method for accessing map tags - http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/map.asp?frame=true
|
650
|
-
# * how - symbol - how we access the map,
|
651
|
-
# * what - string, integer or regular expression - what we are looking for,
|
652
|
-
#
|
653
|
-
# Valid values for 'how' are listed in the Watir Wiki - http://wiki.openqa.org/display/WTR/Methods+supported+by+Element
|
654
|
-
#
|
655
|
-
# returns a map object
|
656
|
-
#
|
657
|
-
# Typical Usage
|
658
|
-
#
|
659
|
-
# ie.map(:id, /list/) # access the first map that matches list.
|
660
|
-
# ie.map(:index,2) # access the second map on the page
|
661
|
-
# ie.map(:title, "A Picture") # access a map using the tooltip text. See http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/title_1.asp?frame=true
|
662
|
-
#
|
663
|
-
def map(how, what)
|
664
|
-
return Map.new(self, how, what)
|
665
|
-
end
|
666
|
-
|
667
|
-
# this is the main method for accessing the maps iterator.
|
668
|
-
#
|
669
|
-
# Returns a maps object
|
670
|
-
#
|
671
|
-
# Typical usage:
|
672
|
-
#
|
673
|
-
# ie.maps.each { |s| puts s.to_s } # iterate through all the maps on the page
|
674
|
-
# ie.maps[1].to_s # goto the first map on the page
|
675
|
-
# ie.maps.length # show how many maps are on the page.
|
676
|
-
#
|
677
|
-
def maps
|
678
|
-
return Maps.new(self)
|
679
|
-
end
|
680
|
-
|
681
|
-
# This is the main method for accessing area tags - http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/area.asp?frame=true
|
682
|
-
# * how - symbol - how we access the area
|
683
|
-
# * what - string, integer or regular expression - what we are looking for,
|
684
|
-
#
|
685
|
-
# Valid values for 'how' are listed in the Watir Wiki - http://wiki.openqa.org/display/WTR/Methods+supported+by+Element
|
686
|
-
#
|
687
|
-
# returns a area object
|
688
|
-
#
|
689
|
-
# Typical Usage
|
690
|
-
#
|
691
|
-
# ie.area(:id, /list/) # access the first area that matches list.
|
692
|
-
# ie.area(:index,2) # access the second area on the page
|
693
|
-
# ie.area(:title, "A Picture") # access a area using the tooltip text. See http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/title_1.asp?frame=true
|
694
|
-
#
|
695
|
-
def area(how, what)
|
696
|
-
return Area.new(self, how, what)
|
697
|
-
end
|
698
|
-
|
699
|
-
# this is the main method for accessing the areas iterator.
|
700
|
-
#
|
701
|
-
# Returns a areas object
|
702
|
-
#
|
703
|
-
# Typical usage:
|
704
|
-
#
|
705
|
-
# ie.areas.each { |s| puts s.to_s } # iterate through all the areas on the page
|
706
|
-
# ie.areas[1].to_s # goto the first area on the page
|
707
|
-
# ie.areas.length # show how many areas are on the page.
|
708
|
-
#
|
709
|
-
def areas
|
710
|
-
return Areas.new(self)
|
711
|
-
end
|
712
|
-
|
713
|
-
# This is the main method for accessing images - normally an <img src="image.gif"> HTML tag.
|
714
|
-
# * how - symbol - how we access the image, :index, :id, :name, :src, :title or :alt are supported
|
715
|
-
# * what - string, integer or regular expression - what we are looking for,
|
716
|
-
#
|
717
|
-
# Valid values for 'how' are listed in the Watir Wiki - http://wiki.openqa.org/display/WTR/Methods+supported+by+Element
|
718
|
-
#
|
719
|
-
# returns an Image object
|
720
|
-
#
|
721
|
-
# Typical Usage
|
722
|
-
#
|
723
|
-
# ie.image(:src, /myPic/) # access the first image that matches myPic. We can use a string in place of the regular expression
|
724
|
-
# # but the complete path must be used, ie.image(:src, 'http://myserver.com/my_path/my_image.jpg')
|
725
|
-
# ie.image(:index,2) # access the second image on the page
|
726
|
-
# ie.image(:alt, "A Picture") # access an image using the alt text
|
727
|
-
# ie.image(:xpath, "//img[@alt='A Picture']/") # access an image using the alt text
|
728
|
-
#
|
729
|
-
def image(how,what=nil)
|
730
|
-
Image.new(self, how, what)
|
731
|
-
end
|
732
|
-
|
733
|
-
# This is the main method for accessing the images collection. Returns an Images object
|
734
|
-
#
|
735
|
-
# Typical usage:
|
736
|
-
#
|
737
|
-
# ie.images.each { |i| puts i.to_s } # iterate through all the images on the page
|
738
|
-
# ie.images[1].to_s # goto the first image on the page
|
739
|
-
# ie.images.length # show how many images are on the page.
|
740
|
-
#
|
741
|
-
def images
|
742
|
-
Images.new(self)
|
743
|
-
end
|
744
|
-
|
745
|
-
# This is the main method for accessing JavaScript popups.
|
746
|
-
# returns a PopUp object
|
747
|
-
def popup # BUG this should not be on the container object!
|
748
|
-
PopUp.new(self)
|
749
|
-
end
|
750
|
-
|
751
|
-
# This is the main method for accessing divs. http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/div.asp?frame=true
|
752
|
-
# * how - symbol - how we access the div
|
753
|
-
# * what - string, integer, regular expression or xpath query - what we are looking for,
|
754
|
-
#
|
755
|
-
# Valid values for 'how' are listed in the Watir Wiki - http://wiki.openqa.org/display/WTR/Methods+supported+by+Element
|
756
|
-
#
|
757
|
-
# returns an Div object
|
758
|
-
#
|
759
|
-
# Typical Usage
|
760
|
-
#
|
761
|
-
# ie.div(:id, /list/) # access the first div that matches list.
|
762
|
-
# ie.div(:index,2) # access the second div on the page
|
763
|
-
# ie.div(:title, "A Picture") # access a div using the tooltip text. See http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/title_1.asp?frame=true
|
764
|
-
# ie.div(:xpath, "//div[@id='list']/") # access the first div whose id is 'list'
|
765
|
-
#
|
766
|
-
def div(how, what=nil)
|
767
|
-
Div.new(self, how, what)
|
768
|
-
end
|
769
|
-
|
770
|
-
# this is the main method for accessing the divs iterator. Returns a Divs collection
|
771
|
-
#
|
772
|
-
# Typical usage:
|
773
|
-
#
|
774
|
-
# ie.divs.each { |d| puts d.to_s } # iterate through all the divs on the page
|
775
|
-
# ie.divs[1].to_s # goto the first div on the page
|
776
|
-
# ie.divs.length # show how many divs are on the page.
|
777
|
-
#
|
778
|
-
def divs
|
779
|
-
Divs.new(self)
|
780
|
-
end
|
781
|
-
|
782
|
-
# This is the main method for accessing span tags - http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/span.asp?frame=true
|
783
|
-
# * how - symbol - how we access the span,
|
784
|
-
# * what - string, integer or regular expression - what we are looking for,
|
785
|
-
#
|
786
|
-
# Valid values for 'how' are listed in the Watir Wiki - http://wiki.openqa.org/display/WTR/Methods+supported+by+Element
|
787
|
-
#
|
788
|
-
# returns a Span object
|
789
|
-
#
|
790
|
-
# Typical Usage
|
791
|
-
#
|
792
|
-
# ie.span(:id, /list/) # access the first span that matches list.
|
793
|
-
# ie.span(:index,2) # access the second span on the page
|
794
|
-
# ie.span(:title, "A Picture") # access a span using the tooltip text. See http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/title_1.asp?frame=true
|
795
|
-
#
|
796
|
-
def span(how, what=nil)
|
797
|
-
Span.new(self, how, what)
|
798
|
-
end
|
799
|
-
|
800
|
-
# this is the main method for accessing the spans iterator.
|
801
|
-
#
|
802
|
-
# Returns a Spans object
|
803
|
-
#
|
804
|
-
# Typical usage:
|
805
|
-
#
|
806
|
-
# ie.spans.each { |s| puts s.to_s } # iterate through all the spans on the page
|
807
|
-
# ie.spans[1].to_s # goto the first span on the page
|
808
|
-
# ie.spans.length # show how many spans are on the page.
|
809
|
-
#
|
810
|
-
def spans
|
811
|
-
Spans.new(self)
|
812
|
-
end
|
813
|
-
|
814
|
-
# This is the main method for accessing p tags - http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/p.asp?frame=true
|
815
|
-
# * how - symbol - how we access the p,
|
816
|
-
# * what - string, integer or regular expression - what we are looking for,
|
817
|
-
#
|
818
|
-
# Valid values for 'how' are listed in the Watir Wiki - http://wiki.openqa.org/display/WTR/Methods+supported+by+Element
|
819
|
-
#
|
820
|
-
# returns a P object
|
821
|
-
#
|
822
|
-
# Typical Usage
|
823
|
-
#
|
824
|
-
# ie.p(:id, /list/) # access the first p tag that matches list.
|
825
|
-
# ie.p(:index,2) # access the second p tag on the page
|
826
|
-
# ie.p(:title, "A Picture") # access a p tag using the tooltip text. See http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/title_1.asp?frame=true
|
827
|
-
#
|
828
|
-
def p(how, what=nil)
|
829
|
-
P.new(self, how, what)
|
830
|
-
end
|
831
|
-
|
832
|
-
# this is the main method for accessing the ps iterator.
|
833
|
-
#
|
834
|
-
# Returns a Ps object
|
835
|
-
#
|
836
|
-
# Typical usage:
|
837
|
-
#
|
838
|
-
# ie.ps.each { |p| puts p.to_s } # iterate through all the p tags on the page
|
839
|
-
# ie.ps[1].to_s # goto the first p tag on the page
|
840
|
-
# ie.ps.length # show how many p tags are on the page.
|
841
|
-
#
|
842
|
-
def ps
|
843
|
-
Ps.new(self)
|
844
|
-
end
|
845
|
-
|
846
|
-
# This is the main method for accessing pre tags - http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/pre.asp?frame=true
|
847
|
-
# * how - symbol - how we access the pre, valid values are
|
848
|
-
# :index - finds the item using its index
|
849
|
-
# :id - finds the item using its id attribute
|
850
|
-
# :name - finds the item using its name attribute
|
851
|
-
# * what - string, integer or re, what we are looking for,
|
852
|
-
#
|
853
|
-
# returns a Pre object
|
854
|
-
#
|
855
|
-
# Typical Usage
|
856
|
-
#
|
857
|
-
# ie.pre(:id, /list/) # access the first pre tag that matches list.
|
858
|
-
# ie.pre(:index,2) # access the second pre tag on the page
|
859
|
-
# ie.pre(:title, "A Picture") # access a pre tag using the tooltip text. See http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/title_1.asp?frame=true
|
860
|
-
#
|
861
|
-
def pre(how, what=nil)
|
862
|
-
Pre.new(self, how, what)
|
863
|
-
end
|
864
|
-
|
865
|
-
# this is the main method for accessing the ps iterator.
|
866
|
-
#
|
867
|
-
# Returns a Pres object
|
868
|
-
#
|
869
|
-
# Typical usage:
|
870
|
-
#
|
871
|
-
# ie.pres.each { |pre| puts pre.to_s } # iterate through all the pre tags on the page
|
872
|
-
# ie.pres[1].to_s # goto the first pre tag on the page
|
873
|
-
# ie.pres.length # show how many pre tags are on the page.
|
874
|
-
#
|
875
|
-
def pres
|
876
|
-
Pres.new(self)
|
877
|
-
end
|
878
|
-
|
879
|
-
# This is the main method for accessing labels. http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/label.asp?frame=true
|
880
|
-
# * how - symbol - how we access the label,
|
881
|
-
# * what - string, integer or regular expression - what we are looking for,
|
882
|
-
#
|
883
|
-
# Valid values for 'how' are listed in the Watir Wiki - http://wiki.openqa.org/display/WTR/Methods+supported+by+Element
|
884
|
-
#
|
885
|
-
# returns a Label object
|
886
|
-
#
|
887
|
-
# Typical Usage
|
888
|
-
#
|
889
|
-
# ie.label(:id, /list/) # access the first span that matches list.
|
890
|
-
# ie.label(:index,2) # access the second label on the page
|
891
|
-
# ie.label(:for, "text_1") # access a the label that is associated with the object that has an id of text_1
|
892
|
-
#
|
893
|
-
def label(how, what=nil)
|
894
|
-
Label.new(self, how, what)
|
895
|
-
end
|
896
|
-
|
897
|
-
# this is the main method for accessing the labels iterator. It returns a Labels object
|
898
|
-
#
|
899
|
-
# Returns a Labels object
|
900
|
-
#
|
901
|
-
# Typical usage:
|
902
|
-
#
|
903
|
-
# ie.labels.each { |l| puts l.to_s } # iterate through all the labels on the page
|
904
|
-
# ie.labels[1].to_s # goto the first label on the page
|
905
|
-
# ie.labels.length # show how many labels are on the page.
|
906
|
-
#
|
907
|
-
def labels
|
908
|
-
Labels.new(self)
|
909
|
-
end
|
910
|
-
|
911
|
-
#--
|
912
|
-
#
|
913
|
-
# Searching for Page Elements
|
914
|
-
# Not for external consumption
|
915
|
-
#
|
916
|
-
#++
|
917
|
-
def ole_inner_elements
|
918
|
-
return document.body.all
|
919
|
-
end
|
920
|
-
private :ole_inner_elements
|
921
|
-
|
922
|
-
# This method shows the available objects on the current page.
|
923
|
-
# This is usually only used for debugging or writing new test scripts.
|
924
|
-
# This is a nice feature to help find out what HTML objects are on a page
|
925
|
-
# when developing a test case using Watir.
|
926
|
-
def show_all_objects
|
927
|
-
puts "-----------Objects in page -------------"
|
928
|
-
doc = document
|
929
|
-
s = ""
|
930
|
-
props = ["name", "id", "value", "alt", "src"]
|
931
|
-
doc.all.each do |n|
|
932
|
-
begin
|
933
|
-
s += n.invoke("type").to_s.ljust(16)
|
934
|
-
rescue
|
935
|
-
next
|
936
|
-
end
|
937
|
-
props.each do |prop|
|
938
|
-
begin
|
939
|
-
p = n.invoke(prop)
|
940
|
-
s += " " + "#{prop}=#{p}".to_s.ljust(18)
|
941
|
-
rescue
|
942
|
-
# this object probably doesnt have this property
|
943
|
-
end
|
944
|
-
end
|
945
|
-
s += "\n"
|
946
|
-
end
|
947
|
-
puts s
|
948
|
-
end
|
949
|
-
|
950
|
-
#
|
951
|
-
# Locator Methods
|
952
|
-
#
|
953
|
-
|
954
|
-
# Returns the specified ole object for input elements on a web page.
|
955
|
-
#
|
956
|
-
# This method is used internally by Watir and should not be used externally. It cannot be marked as private because of the way mixins and inheritance work in watir
|
957
|
-
#
|
958
|
-
# * how - symbol - the way we look for the object. Supported values are
|
959
|
-
# - :name
|
960
|
-
# - :id
|
961
|
-
# - :index
|
962
|
-
# - :value etc
|
963
|
-
# * what - string that we are looking for, ex. the name, or id tag attribute or index of the object we are looking for.
|
964
|
-
# * types - what object types we will look at.
|
965
|
-
# * value - used for objects that have one name, but many values. ex. radio lists and checkboxes
|
966
|
-
def locate_input_element(how, what, types, value=nil)
|
967
|
-
elements = nil
|
968
|
-
# Searching through all elements returned by ole_inner_elements
|
969
|
-
# is *significantly* slower than IE's getElementById() and
|
970
|
-
# getElementsByName() calls when how is :id or :name. However
|
971
|
-
# IE doesn't match Regexps, so first we make sure what is a String.
|
972
|
-
# In addition, IE's getElementById() will also return an element
|
973
|
-
# where the :name matches, so we will only return the results of
|
974
|
-
# getElementById() if the matching element actually HAS a matching
|
975
|
-
# :id.
|
976
|
-
begin
|
977
|
-
if what.class == String # Only use fast calls with String what.
|
978
|
-
if how == :id
|
979
|
-
element = document.getElementById(what)
|
980
|
-
# Return if our fast match really HAS a matching :id
|
981
|
-
return element if element.nil? or element.invoke('id') == what
|
982
|
-
elsif how == :name
|
983
|
-
elements = document.getElementsByName(what)
|
984
|
-
end
|
985
|
-
end
|
986
|
-
rescue
|
987
|
-
end
|
988
|
-
# Use slow methods if the faster methods didn't match
|
989
|
-
elements = ole_inner_elements if elements.nil?
|
990
|
-
|
991
|
-
how = :value if how == :caption
|
992
|
-
how = :class_name if how == :class
|
993
|
-
what = what.to_i if how == :index
|
994
|
-
value = value.to_s if value unless value.class == String
|
995
|
-
log "getting object - how is #{how} what is #{what} types = #{types} value = #{value}"
|
996
|
-
|
997
|
-
object_index = 1
|
998
|
-
elements.each do |object|
|
999
|
-
element = Element.new(object)
|
1000
|
-
if types.include?(element.type)
|
1001
|
-
if how == :index
|
1002
|
-
attribute = object_index
|
1003
|
-
else
|
1004
|
-
begin
|
1005
|
-
attribute = element.send(how)
|
1006
|
-
rescue NoMethodError
|
1007
|
-
raise MissingWayOfFindingObjectException,
|
1008
|
-
"#{how} is an unknown way of finding an <INPUT> element (#{what})"
|
1009
|
-
end
|
1010
|
-
end
|
1011
|
-
if what.matches(attribute)
|
1012
|
-
if value
|
1013
|
-
if element.value == value
|
1014
|
-
return object
|
1015
|
-
end
|
1016
|
-
else
|
1017
|
-
return object
|
1018
|
-
end
|
1019
|
-
end
|
1020
|
-
object_index += 1
|
1021
|
-
end
|
1022
|
-
end
|
1023
|
-
return nil
|
1024
|
-
end
|
1025
|
-
|
1026
|
-
# returns the ole object for the specified element
|
1027
|
-
def locate_tagged_element(tag, how, what)
|
1028
|
-
locator = TaggedElementLocator.new(self, tag)
|
1029
|
-
locator.set_specifier(how, what)
|
1030
|
-
locator.locate
|
1031
|
-
end
|
1032
|
-
|
1033
|
-
end # module
|
1034
|
-
|
1035
|
-
class TaggedElementLocator
|
1036
|
-
include Watir
|
1037
|
-
include Watir::Exception
|
1038
|
-
|
1039
|
-
def initialize(container, tag)
|
1040
|
-
@container = container
|
1041
|
-
@tag = tag
|
1042
|
-
end
|
1043
|
-
|
1044
|
-
def set_specifier(how, what)
|
1045
|
-
if how.class == Hash and what.nil?
|
1046
|
-
specifiers = how
|
1047
|
-
else
|
1048
|
-
specifiers = {how => what}
|
1049
|
-
end
|
1050
|
-
|
1051
|
-
@specifiers = {:index => 1} # default if not specified
|
1052
|
-
|
1053
|
-
specifiers.each do |how, what|
|
1054
|
-
what = what.to_i if how == :index
|
1055
|
-
how = :href if how == :url
|
1056
|
-
how = :class_name if how == :class
|
1057
|
-
|
1058
|
-
@specifiers[how] = what
|
1059
|
-
end
|
1060
|
-
|
1061
|
-
end
|
1062
|
-
|
1063
|
-
def each_element tag
|
1064
|
-
@container.document.getElementsByTagName(tag).each do |ole_element|
|
1065
|
-
yield Element.new(ole_element)
|
1066
|
-
end
|
1067
|
-
end
|
1068
|
-
|
1069
|
-
def locate
|
1070
|
-
index_target = @specifiers[:index]
|
1071
|
-
|
1072
|
-
count = 0
|
1073
|
-
each_element(@tag) do |element|
|
1074
|
-
|
1075
|
-
catch :next_element do
|
1076
|
-
@specifiers.each do |how, what|
|
1077
|
-
next if how == :index
|
1078
|
-
unless match? element, how, what
|
1079
|
-
throw :next_element
|
1080
|
-
end
|
1081
|
-
end
|
1082
|
-
count += 1
|
1083
|
-
unless index_target == count
|
1084
|
-
throw :next_element
|
1085
|
-
end
|
1086
|
-
return element.ole_object
|
1087
|
-
end
|
1088
|
-
|
1089
|
-
end # elements
|
1090
|
-
nil
|
1091
|
-
end
|
1092
|
-
|
1093
|
-
def match?(element, how, what)
|
1094
|
-
begin
|
1095
|
-
method = element.method(how)
|
1096
|
-
rescue NameError
|
1097
|
-
raise MissingWayOfFindingObjectException,
|
1098
|
-
"#{how} is an unknown way of finding a <#{@tag}> element (#{what})"
|
1099
|
-
end
|
1100
|
-
case method.arity
|
1101
|
-
when 0
|
1102
|
-
what.matches element.send(how)
|
1103
|
-
when 1
|
1104
|
-
element.send(how, what)
|
1105
|
-
else
|
1106
|
-
raise MissingWayOfFindingObjectException,
|
1107
|
-
"#{how} is an unknown way of finding a <#{@tag}> element (#{what})"
|
1108
|
-
end
|
1109
|
-
end
|
1110
|
-
|
1111
|
-
end
|
1112
|
-
|
1113
|
-
# A PageContainer contains an HTML Document. In other words, it is a
|
1114
|
-
# JavaScript Window.
|
1115
|
-
module PageContainer
|
1116
|
-
include Watir::Exception
|
1117
|
-
|
1118
|
-
# This method checks the currently displayed page for http errors, 404, 500 etc
|
1119
|
-
# It gets called internally by the wait method, so a user does not need to call it explicitly
|
1120
|
-
|
1121
|
-
def check_for_http_error
|
1122
|
-
# check for IE7
|
1123
|
-
n = self.document.invoke('parentWindow').navigator.appVersion
|
1124
|
-
m=/MSIE\s(.*?);/.match( n )
|
1125
|
-
if m and m[1] =='7.0'
|
1126
|
-
if m=/HTTP (\d\d\d.*)/.match( self.title )
|
1127
|
-
raise NavigationException, m[1]
|
1128
|
-
end
|
1129
|
-
else
|
1130
|
-
# assume its IE6
|
1131
|
-
url = self.document.url
|
1132
|
-
if /shdoclc.dll/.match(url)
|
1133
|
-
m = /id=IEText.*?>(.*?)</i.match(self.html)
|
1134
|
-
raise NavigationException, m[1] if m
|
1135
|
-
end
|
1136
|
-
end
|
1137
|
-
false
|
1138
|
-
end
|
1139
|
-
|
1140
|
-
# The HTML Page
|
1141
|
-
def page
|
1142
|
-
document.documentelement
|
1143
|
-
end
|
1144
|
-
private :page
|
1145
|
-
|
1146
|
-
# The HTML of the current page
|
1147
|
-
def html
|
1148
|
-
page.outerhtml
|
1149
|
-
end
|
1150
|
-
|
1151
|
-
# The url of the page object.
|
1152
|
-
def url
|
1153
|
-
page.document.location.href
|
1154
|
-
end
|
1155
|
-
|
1156
|
-
# The text of the current page
|
1157
|
-
def text
|
1158
|
-
page.innertext.strip
|
1159
|
-
end
|
1160
|
-
|
1161
|
-
def eval_in_spawned_process(command)
|
1162
|
-
command.strip!
|
1163
|
-
load_path_code = _code_that_copies_readonly_array($LOAD_PATH, '$LOAD_PATH')
|
1164
|
-
ruby_code = "require 'watir'; "
|
1165
|
-
# ruby_code = "$HIDE_IE = #{$HIDE_IE};" # This prevents attaching to a window from setting it visible. However modal dialogs cannot be attached to when not visible.
|
1166
|
-
ruby_code << "pc = #{attach_command}; " # pc = page container
|
1167
|
-
# IDEA: consider changing this to not use instance_eval (it makes the code hard to understand)
|
1168
|
-
ruby_code << "pc.instance_eval(#{command.inspect})"
|
1169
|
-
exec_string = "start rubyw -e #{(load_path_code + '; ' + ruby_code).inspect}"
|
1170
|
-
system(exec_string)
|
1171
|
-
end
|
1172
|
-
|
1173
|
-
def set_container container
|
1174
|
-
@container = container
|
1175
|
-
@page_container = self
|
1176
|
-
end
|
1177
|
-
|
1178
|
-
# This method is used to display the available html frames that Internet Explorer currently has loaded.
|
1179
|
-
# This method is usually only used for debugging test scripts.
|
1180
|
-
def show_frames
|
1181
|
-
if allFrames = document.frames
|
1182
|
-
count = allFrames.length
|
1183
|
-
puts "there are #{count} frames"
|
1184
|
-
for i in 0..count-1 do
|
1185
|
-
begin
|
1186
|
-
fname = allFrames[i.to_s].name.to_s
|
1187
|
-
puts "frame index: #{i + 1} name: #{fname}"
|
1188
|
-
rescue => e
|
1189
|
-
puts "frame index: #{i + 1} Access Denied, see http://wiki.openqa.org/display/WTR/FAQ#access-denied" if e.to_s.match(/Access is denied/)
|
1190
|
-
end
|
1191
|
-
end
|
1192
|
-
else
|
1193
|
-
puts "no frames"
|
1194
|
-
end
|
1195
|
-
end
|
1196
|
-
|
1197
|
-
# Search the current page for specified text or regexp.
|
1198
|
-
# Returns the index if the specified text was found.
|
1199
|
-
# Returns matchdata object if the specified regexp was found.
|
1200
|
-
#
|
1201
|
-
# *Deprecated*
|
1202
|
-
# Instead use
|
1203
|
-
# IE#text.include? target
|
1204
|
-
# or
|
1205
|
-
# IE#text.match target
|
1206
|
-
def contains_text(target)
|
1207
|
-
if target.kind_of? Regexp
|
1208
|
-
self.text.match(target)
|
1209
|
-
elsif target.kind_of? String
|
1210
|
-
self.text.index(target)
|
1211
|
-
else
|
1212
|
-
raise ArgumentError, "Argument #{target} should be a string or regexp."
|
1213
|
-
end
|
1214
|
-
end
|
1215
|
-
|
1216
|
-
end # module
|
1217
|
-
|
1218
|
-
=begin rdoc
|
1219
|
-
This is Watir, Web Application Testing In Ruby
|
1220
|
-
http://wtr.rubyforge.org
|
1221
|
-
|
1222
|
-
Version "$Revision: 1234 $"
|
1223
|
-
|
1224
|
-
Example:
|
1225
|
-
|
1226
|
-
# Load the Watir library.
|
1227
|
-
require "watir"
|
1228
|
-
|
1229
|
-
# Go to the page you want to test.
|
1230
|
-
ie = Watir::IE.start("http://myserver/mypage")
|
1231
|
-
|
1232
|
-
# Enter "Paul" in a text input field named "username".
|
1233
|
-
ie.text_field(:name, "username").set("Paul")
|
1234
|
-
|
1235
|
-
# Enter "Ruby Co" in the text input field whose "id" is "company_ID".
|
1236
|
-
ie.text_field(:id, "company_ID").set("Ruby Co")
|
1237
|
-
|
1238
|
-
# Click on a link that includes the word "green".
|
1239
|
-
ie.link(:text, /green/)
|
1240
|
-
|
1241
|
-
# Click button that is labelled "Cancel".
|
1242
|
-
ie.button(:value, "Cancel").click
|
1243
|
-
|
1244
|
-
The Watir::IE class allows your test to read and interact with HTML
|
1245
|
-
elements on a page, including their attributes and contents.
|
1246
|
-
The class includes many methods for accessing HTML elements, including the
|
1247
|
-
following:
|
1248
|
-
|
1249
|
-
#button:: <input> tags with type=button, submit, image or reset
|
1250
|
-
#check_box:: <input> tags with type=checkbox
|
1251
|
-
#div:: <div> tags
|
1252
|
-
#form:: <form> tags
|
1253
|
-
#frame:: frames, including both the <frame> elements and the
|
1254
|
-
corresponding pages.
|
1255
|
-
#hidden:: <input> tags with type=hidden
|
1256
|
-
#image:: <img> tags
|
1257
|
-
#label:: <label> tags (including "for" attribute)
|
1258
|
-
#link:: <a> (anchor) tags
|
1259
|
-
#p:: <p> (paragraph) tags
|
1260
|
-
#radio:: <input> tags with the type=radio; known as radio buttons
|
1261
|
-
#select_list:: <select> tags, known as drop-downs or drop-down lists
|
1262
|
-
#span:: <span> tags
|
1263
|
-
#table:: <table> tags, including +row+ and +cell+ methods for accessing
|
1264
|
-
nested elements.
|
1265
|
-
#text_field <input> tags with the type=text (single-line), type=textarea
|
1266
|
-
(multi-line), and type=password
|
1267
|
-
#map:: <map> tags
|
1268
|
-
#area:: <area> tags
|
1269
|
-
#li:: <li> tags
|
1270
|
-
|
1271
|
-
In general, there are several ways to identify a specific object. WATIR's
|
1272
|
-
syntax is in the form (how, what), where "how" is a means of identifying
|
1273
|
-
the object, and "what" is the specific string or regular expression
|
1274
|
-
that WATIR will seek, as shown in the examples above. Available "how"
|
1275
|
-
options depend upon the type of object, but here are a few examples:
|
1276
|
-
|
1277
|
-
How Description
|
1278
|
-
============ ===============================================================
|
1279
|
-
:id Used to find an object that has an "id=" attribute. Since each
|
1280
|
-
id should be unique, according to the XHTML specification,
|
1281
|
-
this is recommended as the most reliable method to find an
|
1282
|
-
object.
|
1283
|
-
:name Used to find an object that has a "name=" attribute. This is
|
1284
|
-
useful for older versions of HTML, but "name" is deprecated
|
1285
|
-
in XHTML.
|
1286
|
-
:value Used to find a text field with a given default value, or a
|
1287
|
-
button with a given caption
|
1288
|
-
:index Used to find the nth object of the specified type on a page.
|
1289
|
-
For example, button(:index, 2) finds the second button.
|
1290
|
-
Current versions of WATIR use 1-based indexing, but future
|
1291
|
-
versions will use 0-based indexing.
|
1292
|
-
:xpath Uses xpath (see separate doc)
|
1293
|
-
|
1294
|
-
Note that the XHTML specification requires that tags and their attributes be
|
1295
|
-
in lower case. WATIR doesn't enforce this; WATIR will find tags and
|
1296
|
-
attributes whether they're in upper, lower, or mixed case. This is either
|
1297
|
-
a bug or a feature.
|
1298
|
-
|
1299
|
-
WATIR uses Microsoft's Document Object Model (DOM) as implemented by Internet
|
1300
|
-
Explorer. For further information on Internet Explorer and on the DOM, go to
|
1301
|
-
the following Web pages:
|
1302
|
-
|
1303
|
-
http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/webbrowser/webbrowser.asp
|
1304
|
-
http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/overview/overview.asp
|
1305
|
-
|
1306
|
-
WATIR supports command-line options:
|
1307
|
-
|
1308
|
-
-b (background) Run Internet Explorer invisibly
|
1309
|
-
-f (fast) By default, WATIR types slowly and pauses briefly between
|
1310
|
-
actions. This switch removes the delays and sets WATIR
|
1311
|
-
to run at full speed. The set_fast_speed method of the
|
1312
|
-
IE object performs the same function; set_slow_speed
|
1313
|
-
returns WATIR to its default behaviour.
|
1314
|
-
=end
|
1315
|
-
class IE
|
1316
|
-
include Watir::Exception
|
1317
|
-
include Container
|
1318
|
-
include PageContainer
|
1319
|
-
|
1320
|
-
def self.quit
|
1321
|
-
end
|
1322
|
-
|
1323
|
-
# Maximum number of seconds to wait when attaching to a window
|
1324
|
-
def self.reset_attach_timeout
|
1325
|
-
@@attach_timeout = 2.0
|
1326
|
-
end
|
1327
|
-
reset_attach_timeout
|
1328
|
-
def self.attach_timeout
|
1329
|
-
@@attach_timeout
|
1330
|
-
end
|
1331
|
-
def self.attach_timeout=(timeout)
|
1332
|
-
@@attach_timeout = timeout
|
1333
|
-
end
|
1334
|
-
|
1335
|
-
# The revision number (according to Subversion)
|
1336
|
-
REVISION_STRING = '$Revision: 1234 $'
|
1337
|
-
REVISION_STRING.scan(/Revision: (\d*)/)
|
1338
|
-
REVISION = $1 or 'unknown'
|
1339
|
-
|
1340
|
-
# The Release number
|
1341
|
-
VERSION_SHORT = '1.5.2'
|
1342
|
-
VERSION = VERSION_SHORT + '.' + REVISION
|
1343
|
-
|
1344
|
-
# Used internally to determine when IE has finished loading a page
|
1345
|
-
READYSTATE_COMPLETE = 4
|
1346
|
-
|
1347
|
-
# TODO: the following constants should be able to be specified by object (not class)
|
1348
|
-
|
1349
|
-
# The delay when entering text on a web page when speed = :slow.
|
1350
|
-
DEFAULT_TYPING_SPEED = 0.08
|
1351
|
-
|
1352
|
-
# The default time we wait after a page has loaded when speed = :slow.
|
1353
|
-
DEFAULT_SLEEP_TIME = 0.1
|
1354
|
-
|
1355
|
-
# The default color for highlighting objects as they are accessed.
|
1356
|
-
HIGHLIGHT_COLOR = 'yellow'
|
1357
|
-
|
1358
|
-
# IE inserts some element whose tagName is empty and just acts as block level element
|
1359
|
-
# Probably some IE method of cleaning things
|
1360
|
-
# To pass the same to REXML we need to give some name to empty tagName
|
1361
|
-
EMPTY_TAG_NAME = "DUMMY"
|
1362
|
-
|
1363
|
-
# The time, in seconds, it took for the new page to load after executing the
|
1364
|
-
# the last command
|
1365
|
-
attr_reader :down_load_time
|
1366
|
-
|
1367
|
-
# Whether the speed is :fast or :slow
|
1368
|
-
attr_reader :speed
|
1369
|
-
|
1370
|
-
# the OLE Internet Explorer object
|
1371
|
-
attr_accessor :ie
|
1372
|
-
|
1373
|
-
# access to the logger object
|
1374
|
-
attr_accessor :logger
|
1375
|
-
|
1376
|
-
# this contains the list of unique urls that have been visited
|
1377
|
-
attr_reader :url_list
|
1378
|
-
|
1379
|
-
# Create a new IE window. Works just like IE.new in Watir 1.4.
|
1380
|
-
def self.new_window
|
1381
|
-
ie = new true
|
1382
|
-
ie._new_window_init
|
1383
|
-
ie
|
1384
|
-
end
|
1385
|
-
|
1386
|
-
# Create an IE browser.
|
1387
|
-
def initialize suppress_new_window=nil
|
1388
|
-
_new_window_init unless suppress_new_window
|
1389
|
-
end
|
1390
|
-
|
1391
|
-
def _new_window_init
|
1392
|
-
create_browser_window
|
1393
|
-
set_defaults
|
1394
|
-
goto 'about:blank' # this avoids numerous problems caused by lack of a document
|
1395
|
-
end
|
1396
|
-
|
1397
|
-
# Create a new IE Window, starting at the specified url.
|
1398
|
-
# If no url is given, start empty.
|
1399
|
-
def self.start url=nil
|
1400
|
-
start_window url
|
1401
|
-
end
|
1402
|
-
|
1403
|
-
# Create a new IE window, starting at the specified url.
|
1404
|
-
# If no url is given, start empty. Works like IE.start in Watir 1.4.
|
1405
|
-
def self.start_window url=nil
|
1406
|
-
ie = new_window
|
1407
|
-
ie.goto url if url
|
1408
|
-
ie
|
1409
|
-
end
|
1410
|
-
|
1411
|
-
# Create a new IE window in a new process.
|
1412
|
-
# This method will not work when
|
1413
|
-
# Watir/Ruby is run under a service (instead of a user).
|
1414
|
-
def self.new_process
|
1415
|
-
ie = new true
|
1416
|
-
ie._new_process_init
|
1417
|
-
ie
|
1418
|
-
end
|
1419
|
-
|
1420
|
-
def _new_process_init
|
1421
|
-
iep = Process.start
|
1422
|
-
@ie = iep.window
|
1423
|
-
@process_id = iep.process_id
|
1424
|
-
set_defaults
|
1425
|
-
goto 'about:blank'
|
1426
|
-
end
|
1427
|
-
|
1428
|
-
# Create a new IE window in a new process, starting at the specified URL.
|
1429
|
-
# Same as IE.start.
|
1430
|
-
def self.start_process url=nil
|
1431
|
-
ie = new_process
|
1432
|
-
ie.goto url if url
|
1433
|
-
ie
|
1434
|
-
end
|
1435
|
-
|
1436
|
-
# Return a Watir::IE object for an existing IE window. Window can be
|
1437
|
-
# referenced by url, title, or window handle.
|
1438
|
-
# Second argument can be either a string or a regular expression in the
|
1439
|
-
# case of of :url or :title.
|
1440
|
-
# IE.attach(:url, 'http://www.google.com')
|
1441
|
-
# IE.attach(:title, 'Google')
|
1442
|
-
# IE.attach(:hwnd, 528140)
|
1443
|
-
# This method will not work when
|
1444
|
-
# Watir/Ruby is run under a service (instead of a user).
|
1445
|
-
def self.attach how, what
|
1446
|
-
ie = new true # don't create window
|
1447
|
-
ie._attach_init(how, what)
|
1448
|
-
ie
|
1449
|
-
end
|
1450
|
-
|
1451
|
-
# this method is used internally to attach to an existing window
|
1452
|
-
def _attach_init how, what
|
1453
|
-
attach_browser_window how, what
|
1454
|
-
set_defaults
|
1455
|
-
wait
|
1456
|
-
end
|
1457
|
-
|
1458
|
-
# Return an IE object that wraps the given window, typically obtained from
|
1459
|
-
# Shell.Application.windows.
|
1460
|
-
def self.bind window
|
1461
|
-
ie = new true
|
1462
|
-
ie.ie = window
|
1463
|
-
ie.set_defaults
|
1464
|
-
ie
|
1465
|
-
end
|
1466
|
-
|
1467
|
-
def create_browser_window
|
1468
|
-
@ie = WIN32OLE.new('InternetExplorer.Application')
|
1469
|
-
end
|
1470
|
-
private :create_browser_window
|
1471
|
-
|
1472
|
-
def set_defaults
|
1473
|
-
self.visible = ! $HIDE_IE
|
1474
|
-
@ole_object = nil
|
1475
|
-
@page_container = self
|
1476
|
-
@error_checkers = []
|
1477
|
-
@activeObjectHighLightColor = HIGHLIGHT_COLOR
|
1478
|
-
|
1479
|
-
if $FAST_SPEED
|
1480
|
-
set_fast_speed
|
1481
|
-
else
|
1482
|
-
set_slow_speed
|
1483
|
-
end
|
1484
|
-
|
1485
|
-
@logger = DefaultLogger.new
|
1486
|
-
@url_list = []
|
1487
|
-
end
|
1488
|
-
|
1489
|
-
def speed= how_fast
|
1490
|
-
case how_fast
|
1491
|
-
when :fast : set_fast_speed
|
1492
|
-
when :slow : set_slow_speed
|
1493
|
-
else
|
1494
|
-
raise ArgumentError, "Invalid speed: #{how_fast}"
|
1495
|
-
end
|
1496
|
-
end
|
1497
|
-
|
1498
|
-
# deprecated: use speed = :fast instead
|
1499
|
-
def set_fast_speed
|
1500
|
-
@typingspeed = 0
|
1501
|
-
@defaultSleepTime = 0.01
|
1502
|
-
@speed = :fast
|
1503
|
-
end
|
1504
|
-
|
1505
|
-
# deprecated: use speed = :slow instead
|
1506
|
-
def set_slow_speed
|
1507
|
-
@typingspeed = DEFAULT_TYPING_SPEED
|
1508
|
-
@defaultSleepTime = DEFAULT_SLEEP_TIME
|
1509
|
-
@speed = :slow
|
1510
|
-
end
|
1511
|
-
|
1512
|
-
def visible
|
1513
|
-
@ie.visible
|
1514
|
-
end
|
1515
|
-
def visible=(boolean)
|
1516
|
-
@ie.visible = boolean if boolean != @ie.visible
|
1517
|
-
end
|
1518
|
-
|
1519
|
-
# Yields successively to each IE window on the current desktop. Takes a block.
|
1520
|
-
# This method will not work when
|
1521
|
-
# Watir/Ruby is run under a service (instead of a user).
|
1522
|
-
# Yields to the window and its hwnd.
|
1523
|
-
def self.each
|
1524
|
-
shell = WIN32OLE.new('Shell.Application')
|
1525
|
-
shell.Windows.each do |window|
|
1526
|
-
next unless (window.path =~ /Internet Explorer/ rescue false)
|
1527
|
-
next unless (hwnd = window.hwnd rescue false)
|
1528
|
-
ie = IE.bind(window)
|
1529
|
-
ie.hwnd = hwnd
|
1530
|
-
yield ie
|
1531
|
-
end
|
1532
|
-
end
|
1533
|
-
|
1534
|
-
# return internet explorer instance as specified. if none is found,
|
1535
|
-
# return nil.
|
1536
|
-
# arguments:
|
1537
|
-
# :url, url -- the URL of the IE browser window
|
1538
|
-
# :title, title -- the title of the browser page
|
1539
|
-
# :hwnd, hwnd -- the window handle of the browser window.
|
1540
|
-
# This method will not work when
|
1541
|
-
# Watir/Ruby is run under a service (instead of a user).
|
1542
|
-
def self.find(how, what)
|
1543
|
-
ie_ole = IE._find(how, what)
|
1544
|
-
IE.bind ie_ole if ie_ole
|
1545
|
-
end
|
1546
|
-
|
1547
|
-
def self._find(how, what)
|
1548
|
-
ieTemp = nil
|
1549
|
-
IE.each do |ie|
|
1550
|
-
window = ie.ie
|
1551
|
-
|
1552
|
-
case how
|
1553
|
-
when :url
|
1554
|
-
ieTemp = window if (what.matches(window.locationURL))
|
1555
|
-
when :title
|
1556
|
-
# normal windows explorer shells do not have document
|
1557
|
-
# note window.document will fail for "new" browsers
|
1558
|
-
begin
|
1559
|
-
title = window.locationname
|
1560
|
-
title = window.document.title
|
1561
|
-
rescue WIN32OLERuntimeError
|
1562
|
-
end
|
1563
|
-
ieTemp = window if what.matches(title)
|
1564
|
-
when :hwnd
|
1565
|
-
begin
|
1566
|
-
ieTemp = window if what == window.HWND
|
1567
|
-
rescue WIN32OLERuntimeError
|
1568
|
-
end
|
1569
|
-
else
|
1570
|
-
raise ArgumentError
|
1571
|
-
end
|
1572
|
-
end
|
1573
|
-
return ieTemp
|
1574
|
-
end
|
1575
|
-
|
1576
|
-
def attach_browser_window how, what
|
1577
|
-
log "Seeking Window with #{how}: #{what}"
|
1578
|
-
ieTemp = nil
|
1579
|
-
begin
|
1580
|
-
Watir::until_with_timeout do
|
1581
|
-
ieTemp = IE._find how, what
|
1582
|
-
end
|
1583
|
-
rescue TimeOutException
|
1584
|
-
raise NoMatchingWindowFoundException,
|
1585
|
-
"Unable to locate a window with #{how} of #{what}"
|
1586
|
-
end
|
1587
|
-
@ie = ieTemp
|
1588
|
-
end
|
1589
|
-
private :attach_browser_window
|
1590
|
-
|
1591
|
-
# Return the current window handle
|
1592
|
-
def hwnd
|
1593
|
-
raise "Not attached to a browser" if @ie.nil?
|
1594
|
-
@hwnd ||= @ie.hwnd
|
1595
|
-
end
|
1596
|
-
attr_writer :hwnd
|
1597
|
-
|
1598
|
-
include Watir::Win32
|
1599
|
-
|
1600
|
-
# Are we attached to an open browser?
|
1601
|
-
def exists?
|
1602
|
-
return false if @closing
|
1603
|
-
begin
|
1604
|
-
@ie.name =~ /Internet Explorer/
|
1605
|
-
rescue WIN32OLERuntimeError
|
1606
|
-
false
|
1607
|
-
end
|
1608
|
-
end
|
1609
|
-
alias :exist? :exists?
|
1610
|
-
|
1611
|
-
# deprecated: use logger= instead
|
1612
|
-
def set_logger(logger)
|
1613
|
-
@logger = logger
|
1614
|
-
end
|
1615
|
-
|
1616
|
-
def log(what)
|
1617
|
-
@logger.debug(what) if @logger
|
1618
|
-
end
|
1619
|
-
|
1620
|
-
#
|
1621
|
-
# Accessing data outside the document
|
1622
|
-
#
|
1623
|
-
|
1624
|
-
# Return the title of the document
|
1625
|
-
def title
|
1626
|
-
@ie.document.title
|
1627
|
-
end
|
1628
|
-
|
1629
|
-
# Return the status of the window, typically from the status bar at the bottom.
|
1630
|
-
def status
|
1631
|
-
raise NoStatusBarException if !@ie.statusBar
|
1632
|
-
return @ie.statusText
|
1633
|
-
end
|
1634
|
-
|
1635
|
-
#
|
1636
|
-
# Navigation
|
1637
|
-
#
|
1638
|
-
|
1639
|
-
# Navigate to the specified URL.
|
1640
|
-
# * url - string - the URL to navigate to
|
1641
|
-
def goto(url)
|
1642
|
-
@ie.navigate(url)
|
1643
|
-
wait
|
1644
|
-
return @down_load_time
|
1645
|
-
end
|
1646
|
-
|
1647
|
-
# Go to the previous page - the same as clicking the browsers back button
|
1648
|
-
# an WIN32OLERuntimeError exception is raised if the browser cant go back
|
1649
|
-
def back
|
1650
|
-
@ie.GoBack
|
1651
|
-
wait
|
1652
|
-
end
|
1653
|
-
|
1654
|
-
# Go to the next page - the same as clicking the browsers forward button
|
1655
|
-
# an WIN32OLERuntimeError exception is raised if the browser cant go forward
|
1656
|
-
def forward
|
1657
|
-
@ie.GoForward
|
1658
|
-
wait
|
1659
|
-
end
|
1660
|
-
|
1661
|
-
# Refresh the current page - the same as clicking the browsers refresh button
|
1662
|
-
# an WIN32OLERuntimeError exception is raised if the browser cant refresh
|
1663
|
-
def refresh
|
1664
|
-
@ie.refresh2(3)
|
1665
|
-
wait
|
1666
|
-
end
|
1667
|
-
|
1668
|
-
# clear the list of urls that we have visited
|
1669
|
-
def clear_url_list
|
1670
|
-
@url_list.clear
|
1671
|
-
end
|
1672
|
-
|
1673
|
-
# Closes the Browser
|
1674
|
-
def close
|
1675
|
-
@closing = true
|
1676
|
-
@ie.quit
|
1677
|
-
end
|
1678
|
-
|
1679
|
-
# Maximize the window (expands to fill the screen)
|
1680
|
-
def maximize
|
1681
|
-
set_window_state :SW_MAXIMIZE
|
1682
|
-
end
|
1683
|
-
|
1684
|
-
# Minimize the window (appears as icon on taskbar)
|
1685
|
-
def minimize
|
1686
|
-
set_window_state :SW_MINIMIZE
|
1687
|
-
end
|
1688
|
-
|
1689
|
-
# Restore the window (after minimizing or maximizing)
|
1690
|
-
def restore
|
1691
|
-
set_window_state :SW_RESTORE
|
1692
|
-
end
|
1693
|
-
|
1694
|
-
# Make the window come to the front
|
1695
|
-
def bring_to_front
|
1696
|
-
autoit.WinActivate title, ''
|
1697
|
-
end
|
1698
|
-
|
1699
|
-
def front?
|
1700
|
-
1 == autoit.WinActive(title, '')
|
1701
|
-
end
|
1702
|
-
|
1703
|
-
private
|
1704
|
-
def set_window_state(state)
|
1705
|
-
autoit.WinSetState title, '', autoit.send(state)
|
1706
|
-
end
|
1707
|
-
def autoit
|
1708
|
-
Watir::autoit
|
1709
|
-
end
|
1710
|
-
public
|
1711
|
-
|
1712
|
-
# Send key events to IE window.
|
1713
|
-
# See http://www.autoitscript.com/autoit3/docs/appendix/SendKeys.htm
|
1714
|
-
# for complete documentation on keys supported and syntax.
|
1715
|
-
def send_keys(key_string)
|
1716
|
-
autoit.WinActivate title
|
1717
|
-
autoit.Send key_string
|
1718
|
-
end
|
1719
|
-
|
1720
|
-
def dir
|
1721
|
-
return File.expand_path(File.dirname(__FILE__))
|
1722
|
-
end
|
1723
|
-
|
1724
|
-
#
|
1725
|
-
# Document and Document Data
|
1726
|
-
#
|
1727
|
-
|
1728
|
-
# Return the current document
|
1729
|
-
def document
|
1730
|
-
return @ie.document
|
1731
|
-
end
|
1732
|
-
|
1733
|
-
# returns the current url, as displayed in the address bar of the browser
|
1734
|
-
def url
|
1735
|
-
return @ie.LocationURL
|
1736
|
-
end
|
1737
|
-
|
1738
|
-
#
|
1739
|
-
# Synchronization
|
1740
|
-
#
|
1741
|
-
include Watir::Utils
|
1742
|
-
|
1743
|
-
# Block execution until the page has loaded.
|
1744
|
-
# =nodoc
|
1745
|
-
# Note: This code needs to be prepared for the ie object to be closed at
|
1746
|
-
# any moment!
|
1747
|
-
def wait(no_sleep=false)
|
1748
|
-
@rexmlDomobject = nil
|
1749
|
-
@down_load_time = 0.0
|
1750
|
-
a_moment = 0.2 # seconds
|
1751
|
-
start_load_time = Time.now
|
1752
125
|
|
1753
|
-
begin
|
1754
|
-
while @ie.busy # XXX need to add time out
|
1755
|
-
sleep a_moment
|
1756
|
-
end
|
1757
|
-
until @ie.readyState == READYSTATE_COMPLETE do
|
1758
|
-
sleep a_moment
|
1759
|
-
end
|
1760
|
-
sleep a_moment
|
1761
|
-
until @ie.document do
|
1762
|
-
sleep a_moment
|
1763
|
-
end
|
1764
|
-
|
1765
|
-
documents_to_wait_for = [@ie.document]
|
1766
|
-
|
1767
|
-
rescue WIN32OLERuntimeError # IE window must have been closed
|
1768
|
-
@down_load_time = Time.now - start_load_time
|
1769
|
-
sleep @defaultSleepTime unless no_sleep
|
1770
|
-
return @down_load_time
|
1771
|
-
end
|
1772
126
|
|
1773
|
-
while doc = documents_to_wait_for.shift
|
1774
|
-
begin
|
1775
|
-
until doc.readyState == "complete" do
|
1776
|
-
sleep a_moment
|
1777
|
-
end
|
1778
|
-
@url_list << doc.url unless @url_list.include?(doc.url)
|
1779
|
-
doc.frames.length.times do |n|
|
1780
|
-
begin
|
1781
|
-
documents_to_wait_for << doc.frames[n.to_s].document
|
1782
|
-
rescue WIN32OLERuntimeError
|
1783
|
-
end
|
1784
|
-
end
|
1785
|
-
rescue WIN32OLERuntimeError
|
1786
|
-
end
|
1787
|
-
end
|
1788
|
-
|
1789
|
-
@down_load_time = Time.now - start_load_time
|
1790
|
-
run_error_checks
|
1791
|
-
sleep @defaultSleepTime unless no_sleep
|
1792
|
-
@down_load_time
|
1793
|
-
end
|
1794
|
-
|
1795
|
-
# Error checkers
|
1796
|
-
|
1797
|
-
# this method runs the predefined error checks
|
1798
|
-
def run_error_checks
|
1799
|
-
@error_checkers.each { |e| e.call(self) }
|
1800
|
-
end
|
1801
|
-
|
1802
|
-
# this method is used to add an error checker that gets executed on every page load
|
1803
|
-
# * checker Proc Object, that contains the code to be run
|
1804
|
-
def add_checker(checker)
|
1805
|
-
@error_checkers << checker
|
1806
|
-
end
|
1807
|
-
|
1808
|
-
# this allows a checker to be disabled
|
1809
|
-
# * checker Proc Object, the checker that is to be disabled
|
1810
|
-
def disable_checker(checker)
|
1811
|
-
@error_checkers.delete(checker)
|
1812
|
-
end
|
1813
|
-
|
1814
|
-
#
|
1815
|
-
# Show me state
|
1816
|
-
#
|
1817
|
-
|
1818
|
-
# Show all forms displays all the forms that are on a web page.
|
1819
|
-
def show_forms
|
1820
|
-
if allForms = document.forms
|
1821
|
-
count = allForms.length
|
1822
|
-
puts "There are #{count} forms"
|
1823
|
-
for i in 0..count-1 do
|
1824
|
-
wrapped = FormWrapper.new(allForms.item(i))
|
1825
|
-
puts "Form name: #{wrapped.name}"
|
1826
|
-
puts " id: #{wrapped.id}"
|
1827
|
-
puts " method: #{wrapped.method}"
|
1828
|
-
puts " action: #{wrapped.action}"
|
1829
|
-
end
|
1830
|
-
else
|
1831
|
-
puts "No forms"
|
1832
|
-
end
|
1833
|
-
end
|
1834
|
-
|
1835
|
-
# this method shows all the images availble in the document
|
1836
|
-
def show_images
|
1837
|
-
doc = document
|
1838
|
-
index = 1
|
1839
|
-
doc.images.each do |l|
|
1840
|
-
puts "image: name: #{l.name}"
|
1841
|
-
puts " id: #{l.invoke("id")}"
|
1842
|
-
puts " src: #{l.src}"
|
1843
|
-
puts " index: #{index}"
|
1844
|
-
index += 1
|
1845
|
-
end
|
1846
|
-
end
|
1847
|
-
|
1848
|
-
# this method shows all the links availble in the document
|
1849
|
-
def show_links
|
1850
|
-
props = ["name", "id", "href"]
|
1851
|
-
print_sizes = [12, 12, 60]
|
1852
|
-
doc = document
|
1853
|
-
index = 0
|
1854
|
-
text_size = 60
|
1855
|
-
# draw the table header
|
1856
|
-
s = "index".ljust(6)
|
1857
|
-
props.each_with_index do |p, i|
|
1858
|
-
s += p.ljust(print_sizes[i])
|
1859
|
-
end
|
1860
|
-
s += "text/src".ljust(text_size)
|
1861
|
-
s += "\n"
|
1862
|
-
|
1863
|
-
# now get the details of the links
|
1864
|
-
doc.links.each do |n|
|
1865
|
-
index += 1
|
1866
|
-
s = s + index.to_s.ljust(6)
|
1867
|
-
props.each_with_index do |prop, i|
|
1868
|
-
printsize = print_sizes[i]
|
1869
|
-
begin
|
1870
|
-
p = n.invoke(prop)
|
1871
|
-
temp_var = "#{p}".to_s.ljust(printsize)
|
1872
|
-
rescue
|
1873
|
-
# this object probably doesnt have this property
|
1874
|
-
temp_var = "".to_s.ljust(printsize)
|
1875
|
-
end
|
1876
|
-
s += temp_var
|
1877
|
-
end
|
1878
|
-
s += n.innerText
|
1879
|
-
if n.getElementsByTagName("IMG").length > 0
|
1880
|
-
s += " / " + n.getElementsByTagName("IMG")[0.to_s].src
|
1881
|
-
end
|
1882
|
-
s += "\n"
|
1883
|
-
end
|
1884
|
-
puts s
|
1885
|
-
end
|
1886
|
-
|
1887
|
-
# this method shows the name, id etc of the object that is currently active - ie the element that has focus
|
1888
|
-
# its mostly used in irb when creating a script
|
1889
|
-
def show_active
|
1890
|
-
s = ""
|
1891
|
-
|
1892
|
-
current = document.activeElement
|
1893
|
-
begin
|
1894
|
-
s += current.invoke("type").to_s.ljust(16)
|
1895
|
-
rescue
|
1896
|
-
end
|
1897
|
-
props = ["name", "id", "value", "alt", "src", "innerText", "href"]
|
1898
|
-
props.each do |prop|
|
1899
|
-
begin
|
1900
|
-
p = current.invoke(prop)
|
1901
|
-
s += " " + "#{prop}=#{p}".to_s.ljust(18)
|
1902
|
-
rescue
|
1903
|
-
#this object probably doesnt have this property
|
1904
|
-
end
|
1905
|
-
end
|
1906
|
-
s += "\n"
|
1907
|
-
end
|
1908
|
-
|
1909
|
-
# this method shows all the divs availble in the document
|
1910
|
-
def show_divs
|
1911
|
-
divs = document.getElementsByTagName("DIV")
|
1912
|
-
puts "Found #{divs.length} div tags"
|
1913
|
-
index = 1
|
1914
|
-
divs.each do |d|
|
1915
|
-
puts "#{index} id=#{d.invoke('id')} class=#{d.invoke("className")}"
|
1916
|
-
index += 1
|
1917
|
-
end
|
1918
|
-
end
|
1919
|
-
|
1920
|
-
# this method is used to show all the tables that are available
|
1921
|
-
def show_tables
|
1922
|
-
tables = document.getElementsByTagName("TABLE")
|
1923
|
-
puts "Found #{tables.length} tables"
|
1924
|
-
index = 1
|
1925
|
-
tables.each do |d|
|
1926
|
-
puts "#{index} id=#{d.invoke('id')} rows=#{d.rows.length} columns=#{begin d.rows["0"].cells.length; rescue; end}"
|
1927
|
-
index += 1
|
1928
|
-
end
|
1929
|
-
end
|
1930
|
-
|
1931
|
-
def show_pres
|
1932
|
-
pres = document.getElementsByTagName("PRE")
|
1933
|
-
puts "Found #{ pres.length } pre tags"
|
1934
|
-
index = 1
|
1935
|
-
pres.each do |d|
|
1936
|
-
puts "#{index} id=#{d.invoke('id')} class=#{d.invoke("className")}"
|
1937
|
-
index+=1
|
1938
|
-
end
|
1939
|
-
end
|
1940
|
-
|
1941
|
-
# this method shows all the spans availble in the document
|
1942
|
-
def show_spans
|
1943
|
-
spans = document.getElementsByTagName("SPAN")
|
1944
|
-
puts "Found #{spans.length} span tags"
|
1945
|
-
index = 1
|
1946
|
-
spans.each do |d|
|
1947
|
-
puts "#{index} id=#{d.invoke('id')} class=#{d.invoke("className")}"
|
1948
|
-
index += 1
|
1949
|
-
end
|
1950
|
-
end
|
1951
|
-
|
1952
|
-
def show_labels
|
1953
|
-
labels = document.getElementsByTagName("LABEL")
|
1954
|
-
puts "Found #{labels.length} label tags"
|
1955
|
-
index = 1
|
1956
|
-
labels.each do |d|
|
1957
|
-
puts "#{index} text=#{d.invoke('innerText')} class=#{d.invoke("className")} for=#{d.invoke("htmlFor")}"
|
1958
|
-
index += 1
|
1959
|
-
end
|
1960
|
-
end
|
1961
|
-
|
1962
|
-
# Gives focus to the frame
|
1963
|
-
def focus
|
1964
|
-
document.activeElement.blur
|
1965
|
-
document.focus
|
1966
|
-
end
|
1967
|
-
|
1968
|
-
#
|
1969
|
-
# Functions written for using xpath for getting the elements.
|
1970
|
-
#
|
1971
|
-
|
1972
|
-
# Get the Rexml object.
|
1973
|
-
def rexml_document_object
|
1974
|
-
#puts "Value of rexmlDomobject is : #{@rexmlDomobject}"
|
1975
|
-
if @rexmlDomobject == nil
|
1976
|
-
create_rexml_document_object
|
1977
|
-
end
|
1978
|
-
return @rexmlDomobject
|
1979
|
-
end
|
1980
|
-
|
1981
|
-
# Create the Rexml object if it is nil. This method is private so can be called only
|
1982
|
-
# from rexml_document_object method.
|
1983
|
-
def create_rexml_document_object
|
1984
|
-
# Use our modified rexml libraries
|
1985
|
-
require 'rexml/document'
|
1986
|
-
unless REXML::Version >= '3.1.4'
|
1987
|
-
raise "Requires REXML version of at least 3.1.4. Actual: #{REXML::Version}"
|
1988
|
-
end
|
1989
|
-
if @rexmlDomobject == nil
|
1990
|
-
htmlSource ="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<HTML>\n"
|
1991
|
-
htmlSource = html_source(document.body,htmlSource," ")
|
1992
|
-
htmlSource += "\n</HTML>\n"
|
1993
|
-
# Angrez: Resolving Jira issue WTR-114
|
1994
|
-
htmlSource = htmlSource.gsub(/ /, ' ')
|
1995
|
-
begin
|
1996
|
-
@rexmlDomobject = REXML::Document.new(htmlSource)
|
1997
|
-
rescue => e
|
1998
|
-
output_rexml_document("error.xml", htmlSource)
|
1999
|
-
raise e
|
2000
|
-
end
|
2001
|
-
end
|
2002
|
-
end
|
2003
|
-
private :create_rexml_document_object
|
2004
|
-
|
2005
|
-
def output_rexml_document(name, text)
|
2006
|
-
file = File.open(name,"w")
|
2007
|
-
file.print(text)
|
2008
|
-
file.close
|
2009
|
-
end
|
2010
|
-
private :output_rexml_document
|
2011
|
-
|
2012
|
-
#Function Tokenizes the tag line and returns array of tokens.
|
2013
|
-
#Token could be either tagName or "=" or attribute name or attribute value
|
2014
|
-
#Attribute value could be either quoted string or single word
|
2015
|
-
def tokenize_tagline(outerHtml)
|
2016
|
-
outerHtml = outerHtml.gsub(/\n|\r/," ")
|
2017
|
-
#removing "< symbol", opening of current tag
|
2018
|
-
outerHtml =~ /^\s*<(.*)$/
|
2019
|
-
outerHtml = $1
|
2020
|
-
tokens = Array.new
|
2021
|
-
i = startOffset = 0
|
2022
|
-
length = outerHtml.length
|
2023
|
-
#puts outerHtml
|
2024
|
-
parsingValue = false
|
2025
|
-
while i < length do
|
2026
|
-
i +=1 while (i < length && outerHtml[i,1] =~ /\s/)
|
2027
|
-
next if i == length
|
2028
|
-
currentToken = outerHtml[i,1]
|
2029
|
-
|
2030
|
-
#Either current tag has been closed or user has not closed the tag >
|
2031
|
-
# and we have received the opening of next element
|
2032
|
-
break if currentToken =~ /<|>/
|
2033
|
-
|
2034
|
-
#parse quoted value
|
2035
|
-
if(currentToken == "\"" || currentToken == "'")
|
2036
|
-
parsingValue = false
|
2037
|
-
quote = currentToken
|
2038
|
-
startOffset = i
|
2039
|
-
i += 1
|
2040
|
-
i += 1 while (i < length && (outerHtml[i,1] != quote || outerHtml[i-1,1] == "\\"))
|
2041
|
-
if i == length
|
2042
|
-
tokens.push quote + outerHtml[startOffset..i-1]
|
2043
|
-
else
|
2044
|
-
tokens.push outerHtml[startOffset..i]
|
2045
|
-
end
|
2046
|
-
elsif currentToken == "="
|
2047
|
-
tokens.push "="
|
2048
|
-
parsingValue = true
|
2049
|
-
else
|
2050
|
-
startOffset = i
|
2051
|
-
i += 1 while (i < length && !(outerHtml[i,1] =~ /\s|=|<|>/)) if !parsingValue
|
2052
|
-
i += 1 while (i < length && !(outerHtml[i,1] =~ /\s|<|>/)) if parsingValue
|
2053
|
-
parsingValue = false
|
2054
|
-
i -= 1
|
2055
|
-
tokens.push outerHtml[startOffset..i]
|
2056
|
-
end
|
2057
|
-
i += 1
|
2058
|
-
end
|
2059
|
-
return tokens
|
2060
|
-
end
|
2061
|
-
private :tokenize_tagline
|
2062
|
-
|
2063
|
-
# This function get and clean all the attributes of the tag.
|
2064
|
-
def all_tag_attributes(outerHtml)
|
2065
|
-
tokens = tokenize_tagline(outerHtml)
|
2066
|
-
#puts tokens
|
2067
|
-
tagLine = ""
|
2068
|
-
count = 1
|
2069
|
-
tokensLength = tokens.length
|
2070
|
-
expectedEqualityOP= false
|
2071
|
-
while count < tokensLength do
|
2072
|
-
if expectedEqualityOP == false
|
2073
|
-
#print Attribute Name
|
2074
|
-
# If attribute name is valid. Refer: http://www.w3.org/TR/REC-xml/#NT-Name
|
2075
|
-
if tokens[count] =~ /^(\w|_|:)(.*)$/
|
2076
|
-
tagLine += " #{tokens[count]}"
|
2077
|
-
expectedEqualityOP = true
|
2078
|
-
end
|
2079
|
-
elsif tokens[count] == "="
|
2080
|
-
count += 1
|
2081
|
-
if count == tokensLength
|
2082
|
-
tagLine += "=\"\""
|
2083
|
-
elsif(tokens[count][0,1] == "\"" || tokens[count][0,1] == "'")
|
2084
|
-
tagLine += "=#{tokens[count]}"
|
2085
|
-
else
|
2086
|
-
tagLine += "=\"#{tokens[count]}\""
|
2087
|
-
end
|
2088
|
-
expectedEqualityOP = false
|
2089
|
-
else
|
2090
|
-
#Opps! equality was expected but its not there.
|
2091
|
-
#Set value same as the attribute name e.g. selected="selected"
|
2092
|
-
tagLine += "=\"#{tokens[count-1]}\""
|
2093
|
-
expectedEqualityOP = false
|
2094
|
-
next
|
2095
|
-
end
|
2096
|
-
count += 1
|
2097
|
-
end
|
2098
|
-
tagLine += "=\"#{tokens[count-1]}\" " if expectedEqualityOP == true
|
2099
|
-
#puts tagLine
|
2100
|
-
return tagLine
|
2101
|
-
end
|
2102
|
-
private :all_tag_attributes
|
2103
|
-
|
2104
|
-
# This function is used to escape the characters that are not valid XML data.
|
2105
|
-
def xml_escape(str)
|
2106
|
-
str = str.gsub(/&/,'&')
|
2107
|
-
str = str.gsub(/</,'<')
|
2108
|
-
str = str.gsub(/>/,'>')
|
2109
|
-
str = str.gsub(/"/, '"')
|
2110
|
-
str
|
2111
|
-
end
|
2112
|
-
private :xml_escape
|
2113
|
-
|
2114
|
-
# Returns HTML Source
|
2115
|
-
# Traverse the DOM tree rooted at body element
|
2116
|
-
# and generate the HTML source.
|
2117
|
-
# element: Represent Current element
|
2118
|
-
# htmlString:HTML Source
|
2119
|
-
# spaces:(Used for debugging). Helps in indentation
|
2120
|
-
def html_source(element, htmlString, spaceString)
|
2121
|
-
begin
|
2122
|
-
tagLine = ""
|
2123
|
-
outerHtml = ""
|
2124
|
-
tagName = ""
|
2125
|
-
begin
|
2126
|
-
tagName = element.tagName.downcase
|
2127
|
-
tagName = EMPTY_TAG_NAME if tagName == ""
|
2128
|
-
# If tag is a mismatched tag.
|
2129
|
-
if !(tagName =~ /^(\w|_|:)(.*)$/)
|
2130
|
-
return htmlString
|
2131
|
-
end
|
2132
|
-
rescue
|
2133
|
-
#handling text nodes
|
2134
|
-
htmlString += xml_escape(element.toString)
|
2135
|
-
return htmlString
|
2136
|
-
end
|
2137
|
-
#puts tagName
|
2138
|
-
#Skip comment and script tag
|
2139
|
-
if tagName =~ /^!/ || tagName== "script" || tagName =="style"
|
2140
|
-
return htmlString
|
2141
|
-
end
|
2142
|
-
#tagLine += spaceString
|
2143
|
-
outerHtml = all_tag_attributes(element.outerHtml) if tagName != EMPTY_TAG_NAME
|
2144
|
-
tagLine += "<#{tagName} #{outerHtml}"
|
2145
|
-
|
2146
|
-
canHaveChildren = element.canHaveChildren
|
2147
|
-
if canHaveChildren
|
2148
|
-
tagLine += ">"
|
2149
|
-
else
|
2150
|
-
tagLine += "/>" #self closing tag
|
2151
|
-
end
|
2152
|
-
#spaceString += spaceString
|
2153
|
-
htmlString += tagLine
|
2154
|
-
childElements = element.childnodes
|
2155
|
-
childElements.each do |child|
|
2156
|
-
htmlString = html_source(child,htmlString,spaceString)
|
2157
|
-
end
|
2158
|
-
if canHaveChildren
|
2159
|
-
#tagLine += spaceString
|
2160
|
-
tagLine ="</" + tagName + ">"
|
2161
|
-
htmlString += tagLine
|
2162
|
-
end
|
2163
|
-
return htmlString
|
2164
|
-
rescue => e
|
2165
|
-
puts e.to_s
|
2166
|
-
end
|
2167
|
-
return htmlString
|
2168
|
-
end
|
2169
|
-
private :html_source
|
2170
|
-
|
2171
|
-
# return the first element that matches the xpath
|
2172
|
-
def element_by_xpath(xpath)
|
2173
|
-
temp = elements_by_xpath(xpath)
|
2174
|
-
temp = temp[0] if temp
|
2175
|
-
return temp
|
2176
|
-
end
|
2177
|
-
|
2178
|
-
# execute xpath and return an array of elements
|
2179
|
-
def elements_by_xpath(xpath)
|
2180
|
-
doc = rexml_document_object
|
2181
|
-
modifiedXpath = ""
|
2182
|
-
selectedElements = Array.new
|
2183
|
-
doc.elements.each(xpath) do |element|
|
2184
|
-
modifiedXpath = element.xpath # element = a REXML element
|
2185
|
-
# puts "modified xpath: #{modifiedXpath}"
|
2186
|
-
# puts "text: #{element.text}"
|
2187
|
-
# puts "class: #{element.attributes['class']}"
|
2188
|
-
# require 'breakpoint'; breakpoint
|
2189
|
-
temp = element_by_absolute_xpath(modifiedXpath) # temp = a DOM/COM element
|
2190
|
-
selectedElements << temp if temp != nil
|
2191
|
-
end
|
2192
|
-
#puts selectedElements.length
|
2193
|
-
if selectedElements.length == 0
|
2194
|
-
return nil
|
2195
|
-
else
|
2196
|
-
return selectedElements
|
2197
|
-
end
|
2198
|
-
end
|
2199
|
-
|
2200
|
-
# Method that iterates over IE DOM object and get the elements for the given
|
2201
|
-
# xpath.
|
2202
|
-
def element_by_absolute_xpath(xpath)
|
2203
|
-
curElem = nil
|
2204
|
-
|
2205
|
-
#puts "Hello; Given xpath is : #{xpath}"
|
2206
|
-
doc = document
|
2207
|
-
curElem = doc.getElementsByTagName("body")["0"]
|
2208
|
-
xpath =~ /^.*\/body\[?\d*\]?\/(.*)/
|
2209
|
-
xpath = $1
|
2210
|
-
|
2211
|
-
if xpath == nil
|
2212
|
-
puts "Function Requires absolute XPath."
|
2213
|
-
return
|
2214
|
-
end
|
2215
|
-
|
2216
|
-
arr = xpath.split(/\//)
|
2217
|
-
return nil if arr.length == 0
|
2218
|
-
|
2219
|
-
lastTagName = arr[arr.length-1].to_s.upcase
|
2220
|
-
|
2221
|
-
# lastTagName is like tagName[number] or just tagName. For the first case we need to
|
2222
|
-
# separate tagName and number.
|
2223
|
-
lastTagName =~ /(\w*)\[?\d*\]?/
|
2224
|
-
lastTagName = $1
|
2225
|
-
#puts lastTagName
|
2226
|
-
|
2227
|
-
for element in arr do
|
2228
|
-
element =~ /(\w*)\[?(\d*)\]?/
|
2229
|
-
tagname = $1
|
2230
|
-
tagname = tagname.upcase
|
2231
|
-
|
2232
|
-
if $2 != nil && $2 != ""
|
2233
|
-
index = $2
|
2234
|
-
index = "#{index}".to_i - 1
|
2235
|
-
else
|
2236
|
-
index = 0
|
2237
|
-
end
|
2238
|
-
|
2239
|
-
#puts "#{element} #{tagname} #{index}"
|
2240
|
-
allElemns = curElem.childnodes
|
2241
|
-
if allElemns == nil || allElemns.length == 0
|
2242
|
-
puts "#{element} is null"
|
2243
|
-
next # Go to next element
|
2244
|
-
end
|
2245
|
-
|
2246
|
-
#puts "Current element is : #{curElem.tagName}"
|
2247
|
-
allElemns.each do |child|
|
2248
|
-
gotIt = false
|
2249
|
-
begin
|
2250
|
-
curTag = child.tagName
|
2251
|
-
curTag = EMPTY_TAG_NAME if curTag == ""
|
2252
|
-
rescue
|
2253
|
-
next
|
2254
|
-
end
|
2255
|
-
#puts child.tagName
|
2256
|
-
if curTag == tagname
|
2257
|
-
index-=1
|
2258
|
-
if index < 0
|
2259
|
-
curElem = child
|
2260
|
-
break
|
2261
|
-
end
|
2262
|
-
end
|
2263
|
-
end
|
2264
|
-
|
2265
|
-
#puts "Node selected at index #{index.to_s} : #{curElem.tagName}"
|
2266
|
-
end
|
2267
|
-
begin
|
2268
|
-
if curElem.tagName == lastTagName
|
2269
|
-
#puts curElem.tagName
|
2270
|
-
return curElem
|
2271
|
-
else
|
2272
|
-
return nil
|
2273
|
-
end
|
2274
|
-
rescue
|
2275
|
-
return nil
|
2276
|
-
end
|
2277
|
-
end
|
2278
|
-
private :element_by_absolute_xpath
|
2279
|
-
|
2280
|
-
def attach_command
|
2281
|
-
"Watir::IE.attach(:hwnd, #{hwnd})"
|
2282
|
-
end
|
2283
|
-
|
2284
|
-
|
2285
|
-
end # class IE
|
2286
|
-
|
2287
|
-
#
|
2288
|
-
# MOVETO: watir/popup.rb
|
2289
|
-
# Module Watir::Popup
|
2290
|
-
#
|
2291
|
-
|
2292
|
-
# POPUP object
|
2293
|
-
class PopUp
|
2294
|
-
def initialize(container)
|
2295
|
-
@container = container
|
2296
|
-
@page_container = container.page_container
|
2297
|
-
end
|
2298
|
-
|
2299
|
-
def button(caption)
|
2300
|
-
return JSButton.new(@container.getIE.hwnd, caption)
|
2301
|
-
end
|
2302
|
-
end
|
2303
|
-
|
2304
|
-
class JSButton
|
2305
|
-
def initialize(hWnd, caption)
|
2306
|
-
@hWnd = hWnd
|
2307
|
-
@caption = caption
|
2308
|
-
end
|
2309
|
-
|
2310
|
-
def startClicker(waitTime=3)
|
2311
|
-
clicker = WinClicker.new
|
2312
|
-
clicker.clickJSDialog_Thread
|
2313
|
-
# clickerThread = Thread.new(@caption) {
|
2314
|
-
# sleep waitTime
|
2315
|
-
# puts "After the wait time in startClicker"
|
2316
|
-
# clickWindowsButton_hwnd(hwnd, buttonCaption)
|
2317
|
-
#}
|
2318
|
-
end
|
2319
|
-
end
|
2320
|
-
|
2321
|
-
# Base class for html elements.
|
2322
|
-
# This is not a class that users would normally access.
|
2323
|
-
class Element # Wrapper
|
2324
|
-
include Watir::Exception
|
2325
|
-
include Container # presumes @container is defined
|
2326
|
-
attr_accessor :container
|
2327
|
-
|
2328
|
-
# number of spaces that separate the property from the value in the to_s method
|
2329
|
-
TO_S_SIZE = 14
|
2330
|
-
|
2331
|
-
# ole_object - the ole object for the element being wrapped
|
2332
|
-
def initialize(ole_object)
|
2333
|
-
@o = ole_object
|
2334
|
-
@original_color = nil
|
2335
|
-
end
|
2336
|
-
|
2337
|
-
# Return the ole object, allowing any methods of the DOM that Watir doesn't support to be used.
|
2338
|
-
def ole_object # BUG: should use an attribute reader and rename the instance variable
|
2339
|
-
return @o
|
2340
|
-
end
|
2341
|
-
def ole_object=(o)
|
2342
|
-
@o = o
|
2343
|
-
end
|
2344
|
-
|
2345
|
-
private
|
2346
|
-
def self.def_wrap(ruby_method_name, ole_method_name=nil)
|
2347
|
-
ole_method_name = ruby_method_name unless ole_method_name
|
2348
|
-
class_eval "def #{ruby_method_name}
|
2349
|
-
assert_exists
|
2350
|
-
ole_object.invoke('#{ole_method_name}')
|
2351
|
-
end"
|
2352
|
-
end
|
2353
|
-
def self.def_wrap_guard(method_name)
|
2354
|
-
class_eval "def #{method_name}
|
2355
|
-
assert_exists
|
2356
|
-
begin
|
2357
|
-
ole_object.invoke('#{method_name}')
|
2358
|
-
rescue
|
2359
|
-
''
|
2360
|
-
end
|
2361
|
-
end"
|
2362
|
-
end
|
2363
|
-
|
2364
|
-
public
|
2365
|
-
def assert_exists
|
2366
|
-
locate if defined?(locate)
|
2367
|
-
unless ole_object
|
2368
|
-
raise UnknownObjectException.new("Unable to locate object, using #{@how} and #{@what}")
|
2369
|
-
end
|
2370
|
-
end
|
2371
|
-
def assert_enabled
|
2372
|
-
unless enabled?
|
2373
|
-
raise ObjectDisabledException, "object #{@how} and #{@what} is disabled"
|
2374
|
-
end
|
2375
|
-
end
|
2376
|
-
|
2377
|
-
# return the name of the element (as defined in html)
|
2378
|
-
def_wrap_guard :name
|
2379
|
-
# return the id of the element
|
2380
|
-
def_wrap_guard :id
|
2381
|
-
# return whether the element is disabled
|
2382
|
-
def_wrap :disabled
|
2383
|
-
alias disabled? disabled
|
2384
|
-
# return the value of the element
|
2385
|
-
def_wrap_guard :value
|
2386
|
-
# return the title of the element
|
2387
|
-
def_wrap_guard :title
|
2388
|
-
# return the style of the element
|
2389
|
-
def_wrap_guard :style
|
2390
|
-
|
2391
|
-
def_wrap_guard :alt
|
2392
|
-
def_wrap_guard :src
|
2393
|
-
|
2394
|
-
# return the type of the element
|
2395
|
-
def_wrap_guard :type # input elements only
|
2396
|
-
# return the url the link points to
|
2397
|
-
def_wrap :href # link only
|
2398
|
-
# return the ID of the control that this label is associated with
|
2399
|
-
def_wrap :for, :htmlFor # label only
|
2400
|
-
# return the class name of the element
|
2401
|
-
# raise an ObjectNotFound exception if the object cannot be found
|
2402
|
-
def_wrap :class_name, :className
|
2403
|
-
# return the unique COM number for the element
|
2404
|
-
def_wrap :unique_number, :uniqueNumber
|
2405
|
-
# Return the outer html of the object - see http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/outerhtml.asp?frame=true
|
2406
|
-
def_wrap :html, :outerHTML
|
2407
|
-
|
2408
|
-
# return the text before the element
|
2409
|
-
def before_text # label only
|
2410
|
-
assert_exists
|
2411
|
-
begin
|
2412
|
-
ole_object.getAdjacentText("afterEnd").strip
|
2413
|
-
rescue
|
2414
|
-
''
|
2415
|
-
end
|
2416
|
-
end
|
2417
|
-
|
2418
|
-
# return the text after the element
|
2419
|
-
def after_text # label only
|
2420
|
-
assert_exists
|
2421
|
-
begin
|
2422
|
-
ole_object.getAdjacentText("beforeBegin").strip
|
2423
|
-
rescue
|
2424
|
-
''
|
2425
|
-
end
|
2426
|
-
end
|
2427
|
-
|
2428
|
-
# Return the innerText of the object
|
2429
|
-
# Raise an ObjectNotFound exception if the object cannot be found
|
2430
|
-
def text
|
2431
|
-
assert_exists
|
2432
|
-
return ole_object.innerText.strip
|
2433
|
-
end
|
2434
|
-
|
2435
|
-
def ole_inner_elements
|
2436
|
-
assert_exists
|
2437
|
-
return ole_object.all
|
2438
|
-
end
|
2439
|
-
private :ole_inner_elements
|
2440
|
-
|
2441
|
-
def document
|
2442
|
-
assert_exists
|
2443
|
-
return ole_object
|
2444
|
-
end
|
2445
|
-
|
2446
|
-
# Return the element immediately containing self.
|
2447
|
-
def parent
|
2448
|
-
assert_exists
|
2449
|
-
result = Element.new(ole_object.parentelement)
|
2450
|
-
result.set_container self
|
2451
|
-
result
|
2452
|
-
end
|
2453
|
-
|
2454
|
-
include Comparable
|
2455
|
-
def <=> other
|
2456
|
-
assert_exists
|
2457
|
-
other.assert_exists
|
2458
|
-
ole_object.sourceindex <=> other.ole_object.sourceindex
|
2459
|
-
end
|
2460
|
-
|
2461
|
-
# Return true if self is contained earlier in the html than other.
|
2462
|
-
alias :before? :<
|
2463
|
-
# Return true if self is contained later in the html than other.
|
2464
|
-
alias :after? :>
|
2465
|
-
|
2466
|
-
def typingspeed
|
2467
|
-
@container.typingspeed
|
2468
|
-
end
|
2469
|
-
|
2470
|
-
def activeObjectHighLightColor
|
2471
|
-
@container.activeObjectHighLightColor
|
2472
|
-
end
|
2473
|
-
|
2474
|
-
# Return an array with many of the properties, in a format to be used by the to_s method
|
2475
|
-
def string_creator
|
2476
|
-
n = []
|
2477
|
-
n << "type:".ljust(TO_S_SIZE) + self.type
|
2478
|
-
n << "id:".ljust(TO_S_SIZE) + self.id.to_s
|
2479
|
-
n << "name:".ljust(TO_S_SIZE) + self.name.to_s
|
2480
|
-
n << "value:".ljust(TO_S_SIZE) + self.value.to_s
|
2481
|
-
n << "disabled:".ljust(TO_S_SIZE) + self.disabled.to_s
|
2482
|
-
return n
|
2483
|
-
end
|
2484
|
-
private :string_creator
|
2485
|
-
|
2486
|
-
# Display basic details about the object. Sample output for a button is shown.
|
2487
|
-
# Raises UnknownObjectException if the object is not found.
|
2488
|
-
# name b4
|
2489
|
-
# type button
|
2490
|
-
# id b5
|
2491
|
-
# value Disabled Button
|
2492
|
-
# disabled true
|
2493
|
-
def to_s
|
2494
|
-
assert_exists
|
2495
|
-
return string_creator.join("\n")
|
2496
|
-
end
|
2497
|
-
|
2498
|
-
# This method is responsible for setting and clearing the colored highlighting on the currently active element.
|
2499
|
-
# use :set to set the highlight
|
2500
|
-
# :clear to clear the highlight
|
2501
|
-
# TODO: Make this two methods: set_highlight & clear_highlight
|
2502
|
-
# TODO: Remove begin/rescue blocks
|
2503
|
-
def highlight(set_or_clear)
|
2504
|
-
if set_or_clear == :set
|
2505
|
-
begin
|
2506
|
-
@original_color ||= style.backgroundColor
|
2507
|
-
style.backgroundColor = @container.activeObjectHighLightColor
|
2508
|
-
rescue
|
2509
|
-
@original_color = nil
|
2510
|
-
end
|
2511
|
-
else # BUG: assumes is :clear, but could actually be anything
|
2512
|
-
begin
|
2513
|
-
style.backgroundColor = @original_color unless @original_color == nil
|
2514
|
-
rescue
|
2515
|
-
# we could be here for a number of reasons...
|
2516
|
-
# e.g. page may have reloaded and the reference is no longer valid
|
2517
|
-
ensure
|
2518
|
-
@original_color = nil
|
2519
|
-
end
|
2520
|
-
end
|
2521
|
-
end
|
2522
|
-
private :highlight
|
2523
|
-
|
2524
|
-
# This method clicks the active element.
|
2525
|
-
# raises: UnknownObjectException if the object is not found
|
2526
|
-
# ObjectDisabledException if the object is currently disabled
|
2527
|
-
def click
|
2528
|
-
click!
|
2529
|
-
@container.wait
|
2530
|
-
end
|
2531
|
-
|
2532
|
-
def click_no_wait
|
2533
|
-
assert_enabled
|
2534
|
-
|
2535
|
-
highlight(:set)
|
2536
|
-
object = "#{self.class}.new(self, :unique_number, #{self.unique_number})"
|
2537
|
-
@page_container.eval_in_spawned_process(object + ".click!")
|
2538
|
-
highlight(:clear)
|
2539
|
-
end
|
2540
|
-
|
2541
|
-
def click!
|
2542
|
-
assert_enabled
|
2543
|
-
|
2544
|
-
highlight(:set)
|
2545
|
-
ole_object.click
|
2546
|
-
highlight(:clear)
|
2547
|
-
end
|
2548
|
-
|
2549
|
-
# Flash the element the specified number of times.
|
2550
|
-
# Defaults to 10 flashes.
|
2551
|
-
def flash number=10
|
2552
|
-
assert_exists
|
2553
|
-
number.times do
|
2554
|
-
highlight(:set)
|
2555
|
-
sleep 0.05
|
2556
|
-
highlight(:clear)
|
2557
|
-
sleep 0.05
|
2558
|
-
end
|
2559
|
-
nil
|
2560
|
-
end
|
2561
|
-
|
2562
|
-
# Executes a user defined "fireEvent" for objects with JavaScript events tied to them such as DHTML menus.
|
2563
|
-
# usage: allows a generic way to fire javascript events on page objects such as "onMouseOver", "onClick", etc.
|
2564
|
-
# raises: UnknownObjectException if the object is not found
|
2565
|
-
# ObjectDisabledException if the object is currently disabled
|
2566
|
-
def fire_event(event)
|
2567
|
-
assert_enabled
|
2568
|
-
|
2569
|
-
highlight(:set)
|
2570
|
-
ole_object.fireEvent(event)
|
2571
|
-
@container.wait
|
2572
|
-
highlight(:clear)
|
2573
|
-
end
|
2574
|
-
|
2575
|
-
# This method sets focus on the active element.
|
2576
|
-
# raises: UnknownObjectException if the object is not found
|
2577
|
-
# ObjectDisabledException if the object is currently disabled
|
2578
|
-
def focus
|
2579
|
-
assert_enabled
|
2580
|
-
ole_object.focus
|
2581
|
-
end
|
2582
|
-
|
2583
|
-
# Returns whether this element actually exists.
|
2584
|
-
def exists?
|
2585
|
-
begin
|
2586
|
-
locate if defined?(locate)
|
2587
|
-
rescue WIN32OLERuntimeError
|
2588
|
-
@o = nil
|
2589
|
-
end
|
2590
|
-
@o ? true: false
|
2591
|
-
end
|
2592
|
-
alias :exist? :exists?
|
2593
|
-
|
2594
|
-
# Returns true if the element is enabled, false if it isn't.
|
2595
|
-
# raises: UnknownObjectException if the object is not found
|
2596
|
-
def enabled?
|
2597
|
-
assert_exists
|
2598
|
-
return ! disabled
|
2599
|
-
end
|
2600
|
-
|
2601
|
-
# Get attribute value for any attribute of the element.
|
2602
|
-
# Returns null if attribute doesn't exist.
|
2603
|
-
def attribute_value(attribute_name)
|
2604
|
-
assert_exists
|
2605
|
-
return ole_object.getAttribute(attribute_name)
|
2606
|
-
end
|
2607
|
-
|
2608
|
-
end
|
2609
|
-
|
2610
|
-
class ElementMapper # Still to be used
|
2611
|
-
include Container
|
2612
|
-
|
2613
|
-
def initialize wrapper_class, container, how, what
|
2614
|
-
@wrapper_class = wrapper_class
|
2615
|
-
set_container
|
2616
|
-
@how = how
|
2617
|
-
@what = what
|
2618
|
-
end
|
2619
|
-
|
2620
|
-
def method_missing method, *args
|
2621
|
-
locate
|
2622
|
-
@wrapper_class.new(@o).send(method, *args)
|
2623
|
-
end
|
2624
|
-
end
|
2625
|
-
|
2626
|
-
class Frame
|
2627
|
-
include Container
|
2628
|
-
include PageContainer
|
2629
|
-
|
2630
|
-
# Find the frame denoted by how and what in the container and return its ole_object
|
2631
|
-
def locate
|
2632
|
-
how = @how
|
2633
|
-
what = @what
|
2634
|
-
frames = @container.document.frames
|
2635
|
-
target = nil
|
2636
|
-
|
2637
|
-
for i in 0..(frames.length - 1)
|
2638
|
-
this_frame = frames.item(i)
|
2639
|
-
case how
|
2640
|
-
when :index
|
2641
|
-
index = i + 1
|
2642
|
-
return this_frame if index == what
|
2643
|
-
when :name
|
2644
|
-
begin
|
2645
|
-
return this_frame if what.matches(this_frame.name)
|
2646
|
-
rescue # access denied?
|
2647
|
-
end
|
2648
|
-
when :id
|
2649
|
-
# We assume that pages contain frames or iframes, but not both.
|
2650
|
-
this_frame_tag = @container.document.getElementsByTagName("FRAME").item(i)
|
2651
|
-
return this_frame if this_frame_tag and what.matches(this_frame_tag.invoke("id"))
|
2652
|
-
this_iframe_tag = @container.document.getElementsByTagName("IFRAME").item(i)
|
2653
|
-
return this_frame if this_iframe_tag and what.matches(this_iframe_tag.invoke("id"))
|
2654
|
-
when :src
|
2655
|
-
this_frame_tag = @container.document.getElementsByTagName("FRAME").item(i)
|
2656
|
-
return this_frame if this_frame_tag and what.matches(this_frame_tag.src)
|
2657
|
-
this_iframe_tag = @container.document.getElementsByTagName("IFRAME").item(i)
|
2658
|
-
return this_frame if this_iframe_tag and what.matches(this_iframe_tag.src)
|
2659
|
-
else
|
2660
|
-
raise ArgumentError, "Argument #{how} not supported"
|
2661
|
-
end
|
2662
|
-
end
|
2663
|
-
|
2664
|
-
raise UnknownFrameException, "Unable to locate a frame with #{how.to_s} #{what}"
|
2665
|
-
end
|
2666
|
-
|
2667
|
-
def initialize(container, how, what)
|
2668
|
-
set_container container
|
2669
|
-
@how = how
|
2670
|
-
@what = what
|
2671
|
-
@o = locate
|
2672
|
-
copy_test_config container
|
2673
|
-
end
|
2674
|
-
|
2675
|
-
def document
|
2676
|
-
@o.document
|
2677
|
-
end
|
2678
|
-
|
2679
|
-
def attach_command
|
2680
|
-
@container.page_container.attach_command + ".frame(#{@how.inspect}, #{@what.inspect})"
|
2681
|
-
end
|
2682
|
-
|
2683
|
-
end
|
2684
|
-
|
2685
|
-
class ModalDialog
|
2686
|
-
include Container
|
2687
|
-
include PageContainer
|
2688
|
-
include Win32
|
2689
|
-
|
2690
|
-
# Return the current window handle
|
2691
|
-
attr_reader :hwnd
|
2692
|
-
|
2693
|
-
def find_modal_from_window
|
2694
|
-
# Use handle of our parent window to see if we have any currently
|
2695
|
-
# enabled popup.
|
2696
|
-
hwnd = @container.hwnd
|
2697
|
-
hwnd_modal = 0
|
2698
|
-
begin
|
2699
|
-
Watir::until_with_timeout do
|
2700
|
-
hwnd_modal, arr = GetWindow.call(hwnd, GW_ENABLEDPOPUP) # GW_ENABLEDPOPUP = 6
|
2701
|
-
hwnd_modal > 0
|
2702
|
-
end
|
2703
|
-
rescue TimeOutException
|
2704
|
-
return nil
|
2705
|
-
end
|
2706
|
-
if hwnd_modal == hwnd || hwnd_modal == 0
|
2707
|
-
hwnd_modal = nil
|
2708
|
-
end
|
2709
|
-
@hwnd = hwnd_modal
|
2710
|
-
end
|
2711
|
-
private :find_modal_from_window
|
2712
|
-
|
2713
|
-
def locate
|
2714
|
-
how = @how
|
2715
|
-
what = @what
|
2716
|
-
|
2717
|
-
case how
|
2718
|
-
when nil
|
2719
|
-
unless find_modal_from_window
|
2720
|
-
raise NoMatchingWindowFoundException,
|
2721
|
-
"Modal Dialog not found. Timeout = #{Watir::IE.attach_timeout}"
|
2722
|
-
end
|
2723
|
-
when :title
|
2724
|
-
case what.class.to_s
|
2725
|
-
# TODO: re-write like WET's so we can select on regular expressions too.
|
2726
|
-
when "String"
|
2727
|
-
begin
|
2728
|
-
Watir::until_with_timeout do
|
2729
|
-
title = "#{what} -- Web Page Dialog"
|
2730
|
-
@hwnd, arr = FindWindowEx.call(0, 0, nil, title)
|
2731
|
-
@hwnd > 0
|
2732
|
-
end
|
2733
|
-
rescue TimeOutException
|
2734
|
-
raise NoMatchingWindowFoundException,
|
2735
|
-
"Modal Dialog with title #{what} not found. Timeout = #{Watir::IE.attach_timeout}"
|
2736
|
-
end
|
2737
|
-
else
|
2738
|
-
raise ArgumentError, "Title value must be String"
|
2739
|
-
end
|
2740
|
-
else
|
2741
|
-
raise ArgumentError, "Only null and :title methods are supported"
|
2742
|
-
end
|
2743
|
-
|
2744
|
-
intUnknown = 0
|
2745
|
-
begin
|
2746
|
-
Watir::until_with_timeout do
|
2747
|
-
intPointer = " " * 4 # will contain the int value of the IUnknown*
|
2748
|
-
GetUnknown.call(@hwnd, intPointer)
|
2749
|
-
intArray = intPointer.unpack('L')
|
2750
|
-
intUnknown = intArray.first
|
2751
|
-
intUnknown > 0
|
2752
|
-
end
|
2753
|
-
rescue TimeOutException => e
|
2754
|
-
raise NoMatchingWindowFoundException,
|
2755
|
-
"Unable to attach to Modal Window #{what.inspect} after #{e.duration} seconds."
|
2756
|
-
end
|
2757
|
-
|
2758
|
-
copy_test_config @parent_container
|
2759
|
-
@document = WIN32OLE.connect_unknown(intUnknown)
|
2760
|
-
end
|
2761
|
-
|
2762
|
-
def initialize(container, how, what=nil)
|
2763
|
-
set_container container
|
2764
|
-
@how = how
|
2765
|
-
@what = what
|
2766
|
-
@parent_container = container
|
2767
|
-
# locate our modal dialog's Document object and save it
|
2768
|
-
begin
|
2769
|
-
locate
|
2770
|
-
rescue NoMethodError => e
|
2771
|
-
message =
|
2772
|
-
"IE#modal_dialog not supported with the current version of Ruby (#{RUBY_VERSION}).\n" +
|
2773
|
-
"See http://jira.openqa.org/browse/WTR-2 for details.\n" +
|
2774
|
-
e.message
|
2775
|
-
raise NoMethodError.new(message)
|
2776
|
-
end
|
2777
|
-
end
|
2778
|
-
|
2779
|
-
def document
|
2780
|
-
@document
|
2781
|
-
end
|
2782
|
-
|
2783
|
-
# Return the title of the document
|
2784
|
-
def title
|
2785
|
-
document.title
|
2786
|
-
end
|
2787
|
-
|
2788
|
-
def close
|
2789
|
-
document.parentWindow.close
|
2790
|
-
end
|
2791
|
-
|
2792
|
-
def attach_command
|
2793
|
-
"Watir::IE.find(:hwnd, #{@container.hwnd}).modal_dialog"
|
2794
|
-
end
|
2795
|
-
|
2796
|
-
def wait(no_sleep=false)
|
2797
|
-
end
|
2798
|
-
|
2799
|
-
# Return true if the modal exists. Mostly this is useful for testing whether
|
2800
|
-
# a modal has closed.
|
2801
|
-
def exists?
|
2802
|
-
Watir::Win32::window_exists? @hwnd
|
2803
|
-
end
|
2804
|
-
alias :exist? :exists?
|
2805
|
-
end
|
2806
|
-
|
2807
|
-
# this class is the super class for the iterator classes (buttons, links, spans etc
|
2808
|
-
# it would normally only be accessed by the iterator methods (spans, links etc) of IE
|
2809
|
-
class ElementCollections
|
2810
|
-
include Enumerable
|
2811
|
-
|
2812
|
-
# Super class for all the iteractor classes
|
2813
|
-
# * container - an instance of an IE object
|
2814
|
-
def initialize(container)
|
2815
|
-
@container = container
|
2816
|
-
@page_container = container.page_container
|
2817
|
-
@length = length # defined by subclasses
|
2818
|
-
|
2819
|
-
# set up the items we want to display when the show method is used
|
2820
|
-
set_show_items
|
2821
|
-
end
|
2822
|
-
|
2823
|
-
private
|
2824
|
-
def set_show_items
|
2825
|
-
@show_attributes = AttributeLengthPairs.new("id", 20)
|
2826
|
-
@show_attributes.add("name", 20)
|
2827
|
-
end
|
2828
|
-
|
2829
|
-
public
|
2830
|
-
def get_length_of_input_objects(object_type)
|
2831
|
-
object_types =
|
2832
|
-
if object_type.kind_of? Array
|
2833
|
-
object_type
|
2834
|
-
else
|
2835
|
-
[object_type]
|
2836
|
-
end
|
2837
|
-
|
2838
|
-
length = 0
|
2839
|
-
objects = @container.document.getElementsByTagName("INPUT")
|
2840
|
-
if objects.length > 0
|
2841
|
-
objects.each do |o|
|
2842
|
-
length += 1 if object_types.include?(o.invoke("type").downcase)
|
2843
|
-
end
|
2844
|
-
end
|
2845
|
-
return length
|
2846
|
-
end
|
2847
|
-
|
2848
|
-
# iterate through each of the elements in the collection in turn
|
2849
|
-
def each
|
2850
|
-
0.upto(@length-1) { |i| yield iterator_object(i) }
|
2851
|
-
end
|
2852
|
-
|
2853
|
-
# allows access to a specific item in the collection
|
2854
|
-
def [](n)
|
2855
|
-
return iterator_object(n-1)
|
2856
|
-
end
|
2857
|
-
|
2858
|
-
# this method is the way to show the objects, normally used from irb
|
2859
|
-
def show
|
2860
|
-
s = "index".ljust(6)
|
2861
|
-
@show_attributes.each do |attribute_length_pair|
|
2862
|
-
s += attribute_length_pair.attribute.ljust(attribute_length_pair.length)
|
2863
|
-
end
|
2864
|
-
|
2865
|
-
index = 1
|
2866
|
-
self.each do |o|
|
2867
|
-
s += "\n"
|
2868
|
-
s += index.to_s.ljust(6)
|
2869
|
-
@show_attributes.each do |attribute_length_pair|
|
2870
|
-
begin
|
2871
|
-
s += eval('o.ole_object.invoke("#{attribute_length_pair.attribute}")').to_s.ljust(attribute_length_pair.length)
|
2872
|
-
rescue => e
|
2873
|
-
s += " ".ljust(attribute_length_pair.length)
|
2874
|
-
end
|
2875
|
-
end
|
2876
|
-
index += 1
|
2877
|
-
end
|
2878
|
-
puts s
|
2879
|
-
end
|
2880
|
-
|
2881
|
-
# this method creates an object of the correct type that the iterators use
|
2882
|
-
private
|
2883
|
-
def iterator_object(i)
|
2884
|
-
element_class.new(@container, :index, i + 1)
|
2885
|
-
end
|
2886
|
-
end
|
2887
|
-
|
2888
|
-
|
2889
|
-
# Forms
|
2890
|
-
|
2891
|
-
module FormAccess
|
2892
|
-
def name
|
2893
|
-
@ole_object.getAttributeNode('name').value
|
2894
|
-
end
|
2895
|
-
def action
|
2896
|
-
@ole_object.action
|
2897
|
-
end
|
2898
|
-
def method
|
2899
|
-
@ole_object.invoke('method')
|
2900
|
-
end
|
2901
|
-
def id
|
2902
|
-
@ole_object.invoke('id')
|
2903
|
-
end
|
2904
|
-
end
|
2905
|
-
|
2906
|
-
# wraps around a form OLE object
|
2907
|
-
class FormWrapper
|
2908
|
-
include FormAccess
|
2909
|
-
def initialize(ole_object)
|
2910
|
-
@ole_object = ole_object
|
2911
|
-
end
|
2912
|
-
end
|
2913
|
-
|
2914
|
-
# Form Factory object
|
2915
|
-
class Form < Element
|
2916
|
-
include FormAccess
|
2917
|
-
include Container
|
2918
|
-
|
2919
|
-
attr_accessor :form
|
2920
|
-
|
2921
|
-
# * container - the containing object, normally an instance of IE
|
2922
|
-
# * how - symbol - how we access the form (:name, :id, :index, :action, :method)
|
2923
|
-
# * what - what we use to access the form
|
2924
|
-
def initialize(container, how, what)
|
2925
|
-
set_container container
|
2926
|
-
@how = how
|
2927
|
-
@what = what
|
2928
|
-
|
2929
|
-
log "Get form how is #{@how} what is #{@what} "
|
2930
|
-
|
2931
|
-
# Get form using xpath.
|
2932
|
-
if @how == :xpath
|
2933
|
-
@ole_object = @container.element_by_xpath(@what)
|
2934
|
-
else
|
2935
|
-
count = 1
|
2936
|
-
doc = @container.document
|
2937
|
-
doc.forms.each do |thisForm|
|
2938
|
-
next unless @ole_object == nil
|
2939
|
-
|
2940
|
-
wrapped = FormWrapper.new(thisForm)
|
2941
|
-
|
2942
|
-
log "form on page, name is " + wrapped.name
|
2943
|
-
|
2944
|
-
@ole_object =
|
2945
|
-
case @how
|
2946
|
-
when :name, :id, :method, :action
|
2947
|
-
@what.matches(wrapped.send(@how)) ? thisForm : nil
|
2948
|
-
when :index
|
2949
|
-
count == @what ? thisForm : nil
|
2950
|
-
else
|
2951
|
-
raise MissingWayOfFindingObjectException, "#{how} is an unknown way of finding a form (#{what})"
|
2952
|
-
end
|
2953
|
-
count = count +1
|
2954
|
-
end
|
2955
|
-
end
|
2956
|
-
super(@ole_object)
|
2957
|
-
|
2958
|
-
copy_test_config container
|
2959
|
-
end
|
2960
|
-
|
2961
|
-
def exists?
|
2962
|
-
@ole_object ? true : false
|
2963
|
-
end
|
2964
|
-
alias :exist? :exists?
|
2965
|
-
|
2966
|
-
# Submit the data -- equivalent to pressing Enter or Return to submit a form.
|
2967
|
-
def submit # XXX use assert_exists
|
2968
|
-
raise UnknownFormException, "Unable to locate a form using #{@how} and #{@what} " if @ole_object == nil
|
2969
|
-
@ole_object.submit
|
2970
|
-
@container.wait
|
2971
|
-
end
|
2972
|
-
|
2973
|
-
def ole_inner_elements # XXX use assert_exists
|
2974
|
-
raise UnknownFormException, "Unable to locate a form using #{@how} and #{@what} " if @ole_object == nil
|
2975
|
-
@ole_object.elements
|
2976
|
-
end
|
2977
|
-
private :ole_inner_elements
|
2978
|
-
|
2979
|
-
def document
|
2980
|
-
return @ole_object
|
2981
|
-
end
|
2982
|
-
|
2983
|
-
def wait(no_sleep=false)
|
2984
|
-
@container.wait(no_sleep)
|
2985
|
-
end
|
2986
|
-
|
2987
|
-
# This method is responsible for setting and clearing the colored highlighting on the specified form.
|
2988
|
-
# use :set to set the highlight
|
2989
|
-
# :clear to clear the highlight
|
2990
|
-
def highlight(set_or_clear, element, count)
|
2991
|
-
|
2992
|
-
if set_or_clear == :set
|
2993
|
-
begin
|
2994
|
-
original_color = element.style.backgroundColor
|
2995
|
-
original_color = "" if original_color==nil
|
2996
|
-
element.style.backgroundColor = activeObjectHighLightColor
|
2997
|
-
rescue => e
|
2998
|
-
puts e
|
2999
|
-
puts e.backtrace.join("\n")
|
3000
|
-
original_color = ""
|
3001
|
-
end
|
3002
|
-
@original_styles[count] = original_color
|
3003
|
-
else
|
3004
|
-
begin
|
3005
|
-
element.style.backgroundColor = @original_styles[ count]
|
3006
|
-
rescue => e
|
3007
|
-
puts e
|
3008
|
-
# we could be here for a number of reasons...
|
3009
|
-
ensure
|
3010
|
-
end
|
3011
|
-
end
|
3012
|
-
end
|
3013
|
-
private :highlight
|
3014
|
-
|
3015
|
-
# causes the object to flash. Normally used in IRB when creating scripts
|
3016
|
-
# Default is 10
|
3017
|
-
def flash number=10
|
3018
|
-
@original_styles = {}
|
3019
|
-
number.times do
|
3020
|
-
count = 0
|
3021
|
-
@ole_object.elements.each do |element|
|
3022
|
-
highlight(:set, element, count)
|
3023
|
-
count += 1
|
3024
|
-
end
|
3025
|
-
sleep 0.05
|
3026
|
-
count = 0
|
3027
|
-
@ole_object.elements.each do |element|
|
3028
|
-
highlight(:clear, element, count)
|
3029
|
-
count += 1
|
3030
|
-
end
|
3031
|
-
sleep 0.05
|
3032
|
-
end
|
3033
|
-
end
|
3034
|
-
|
3035
|
-
end # class Form
|
3036
|
-
|
3037
|
-
# this class contains items that are common between the span, div, and pre objects
|
3038
|
-
# it would not normally be used directly
|
3039
|
-
#
|
3040
|
-
# many of the methods available to this object are inherited from the Element class
|
3041
|
-
#
|
3042
|
-
class NonControlElement < Element
|
3043
|
-
include Watir::Exception
|
3044
|
-
|
3045
|
-
def locate
|
3046
|
-
if @how == :xpath
|
3047
|
-
@o = @container.element_by_xpath(@what)
|
3048
|
-
else
|
3049
|
-
@o = @container.locate_tagged_element(self.class::TAG, @how, @what)
|
3050
|
-
end
|
3051
|
-
end
|
3052
|
-
|
3053
|
-
def initialize(container, how, what)
|
3054
|
-
set_container container
|
3055
|
-
@how = how
|
3056
|
-
@what = what
|
3057
|
-
super nil
|
3058
|
-
end
|
3059
|
-
|
3060
|
-
# this method is used to populate the properties in the to_s method
|
3061
|
-
def span_div_string_creator
|
3062
|
-
n = []
|
3063
|
-
n << "class:".ljust(TO_S_SIZE) + self.class_name
|
3064
|
-
n << "text:".ljust(TO_S_SIZE) + self.text
|
3065
|
-
return n
|
3066
|
-
end
|
3067
|
-
private :span_div_string_creator
|
3068
|
-
|
3069
|
-
# returns the properties of the object in a string
|
3070
|
-
# raises an ObjectNotFound exception if the object cannot be found
|
3071
|
-
def to_s
|
3072
|
-
assert_exists
|
3073
|
-
r = string_creator
|
3074
|
-
r += span_div_string_creator
|
3075
|
-
return r.join("\n")
|
3076
|
-
end
|
3077
|
-
end
|
3078
|
-
|
3079
|
-
class Pre < NonControlElement
|
3080
|
-
TAG = 'PRE'
|
3081
|
-
end
|
3082
|
-
|
3083
|
-
class P < NonControlElement
|
3084
|
-
TAG = 'P'
|
3085
|
-
end
|
3086
|
-
|
3087
|
-
# this class is used to deal with Div tags in the html page. http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/div.asp?frame=true
|
3088
|
-
# It would not normally be created by users
|
3089
|
-
class Div < NonControlElement
|
3090
|
-
TAG = 'DIV'
|
3091
|
-
end
|
3092
|
-
|
3093
|
-
# this class is used to deal with Span tags in the html page. It would not normally be created by users
|
3094
|
-
class Span < NonControlElement
|
3095
|
-
TAG = 'SPAN'
|
3096
|
-
end
|
3097
|
-
|
3098
|
-
# Accesses Label element on the html page - http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/label.asp?frame=true
|
3099
|
-
class Label < NonControlElement
|
3100
|
-
TAG = 'LABEL'
|
3101
|
-
|
3102
|
-
# this method is used to populate the properties in the to_s method
|
3103
|
-
def label_string_creator
|
3104
|
-
n = []
|
3105
|
-
n << "for:".ljust(TO_S_SIZE) + self.for
|
3106
|
-
n << "text:".ljust(TO_S_SIZE) + self.text
|
3107
|
-
return n
|
3108
|
-
end
|
3109
|
-
private :label_string_creator
|
3110
|
-
|
3111
|
-
# returns the properties of the object in a string
|
3112
|
-
# raises an ObjectNotFound exception if the object cannot be found
|
3113
|
-
def to_s
|
3114
|
-
assert_exists
|
3115
|
-
r = string_creator
|
3116
|
-
r += label_string_creator
|
3117
|
-
return r.join("\n")
|
3118
|
-
end
|
3119
|
-
end
|
3120
|
-
|
3121
|
-
class Li < NonControlElement
|
3122
|
-
TAG = 'LI'
|
3123
|
-
end
|
3124
|
-
|
3125
|
-
# This class is used for dealing with tables.
|
3126
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#table method
|
3127
|
-
#
|
3128
|
-
# many of the methods available to this object are inherited from the Element class
|
3129
|
-
#
|
3130
|
-
class Table < Element
|
3131
|
-
include Container
|
3132
|
-
|
3133
|
-
# Returns the table object containing anElement
|
3134
|
-
# * container - an instance of an IE object
|
3135
|
-
# * anElement - a Watir object (TextField, Button, etc.)
|
3136
|
-
def Table.create_from_element(container, anElement)
|
3137
|
-
anElement.locate if defined?(anElement.locate)
|
3138
|
-
o = anElement.ole_object.parentElement
|
3139
|
-
o = o.parentElement until o.tagName == 'TABLE'
|
3140
|
-
new container, :ole_object, o
|
3141
|
-
end
|
3142
|
-
|
3143
|
-
# Returns an initialized instance of a table object
|
3144
|
-
# * container - the container
|
3145
|
-
# * how - symbol - how we access the table
|
3146
|
-
# * what - what we use to access the table - id, name index etc
|
3147
|
-
def initialize(container, how, what)
|
3148
|
-
set_container container
|
3149
|
-
@how = how
|
3150
|
-
@what = what
|
3151
|
-
super nil
|
3152
|
-
end
|
3153
|
-
|
3154
|
-
def locate
|
3155
|
-
if @how == :xpath
|
3156
|
-
@o = @container.element_by_xpath(@what)
|
3157
|
-
elsif @how == :ole_object
|
3158
|
-
@o = @what
|
3159
|
-
else
|
3160
|
-
@o = @container.locate_tagged_element('TABLE', @how, @what)
|
3161
|
-
end
|
3162
|
-
end
|
3163
|
-
|
3164
|
-
# override the highlight method, as if the tables rows are set to have a background color,
|
3165
|
-
# this will override the table background color, and the normal flash method won't work
|
3166
|
-
def highlight(set_or_clear)
|
3167
|
-
|
3168
|
-
if set_or_clear == :set
|
3169
|
-
begin
|
3170
|
-
@original_border = @o.border.to_i
|
3171
|
-
if @o.border.to_i==1
|
3172
|
-
@o.border = 2
|
3173
|
-
else
|
3174
|
-
@o.border = 1
|
3175
|
-
end
|
3176
|
-
rescue
|
3177
|
-
@original_border = nil
|
3178
|
-
end
|
3179
|
-
else
|
3180
|
-
begin
|
3181
|
-
@o.border= @original_border unless @original_border == nil
|
3182
|
-
@original_border = nil
|
3183
|
-
rescue
|
3184
|
-
# we could be here for a number of reasons...
|
3185
|
-
ensure
|
3186
|
-
@original_border = nil
|
3187
|
-
end
|
3188
|
-
end
|
3189
|
-
super
|
3190
|
-
end
|
3191
|
-
|
3192
|
-
# this method is used to populate the properties in the to_s method
|
3193
|
-
def table_string_creator
|
3194
|
-
n = []
|
3195
|
-
n << "rows:".ljust(TO_S_SIZE) + self.row_count.to_s
|
3196
|
-
n << "cols:".ljust(TO_S_SIZE) + self.column_count.to_s
|
3197
|
-
return n
|
3198
|
-
end
|
3199
|
-
private :table_string_creator
|
3200
|
-
|
3201
|
-
# returns the properties of the object in a string
|
3202
|
-
# raises an ObjectNotFound exception if the object cannot be found
|
3203
|
-
def to_s
|
3204
|
-
assert_exists
|
3205
|
-
r = string_creator
|
3206
|
-
r += table_string_creator
|
3207
|
-
return r.join("\n")
|
3208
|
-
end
|
3209
|
-
|
3210
|
-
# iterates through the rows in the table. Yields a TableRow object
|
3211
|
-
def each
|
3212
|
-
assert_exists
|
3213
|
-
1.upto(@o.getElementsByTagName("TR").length) { |i| yield TableRow.new(@container, :ole_object, row(i)) }
|
3214
|
-
end
|
3215
|
-
|
3216
|
-
# Returns a row in the table
|
3217
|
-
# * index - the index of the row
|
3218
|
-
def [](index)
|
3219
|
-
assert_exists
|
3220
|
-
return TableRow.new(@container, :ole_object, row(index))
|
3221
|
-
end
|
3222
|
-
|
3223
|
-
# This method returns the number of rows in the table.
|
3224
|
-
# Raises an UnknownObjectException if the table doesnt exist.
|
3225
|
-
def row_count
|
3226
|
-
assert_exists
|
3227
|
-
#return table_body.children.length
|
3228
|
-
return @o.getElementsByTagName("TR").length
|
3229
|
-
end
|
3230
|
-
|
3231
|
-
# This method returns the number of columns in a row of the table.
|
3232
|
-
# Raises an UnknownObjectException if the table doesn't exist.
|
3233
|
-
# * index - the index of the row
|
3234
|
-
def column_count(index=1)
|
3235
|
-
assert_exists
|
3236
|
-
row(index).cells.length
|
3237
|
-
end
|
3238
|
-
|
3239
|
-
# This method returns the table as a 2 dimensional array. Dont expect too much if there are nested tables, colspan etc.
|
3240
|
-
# Raises an UnknownObjectException if the table doesn't exist.
|
3241
|
-
# http://www.w3.org/TR/html4/struct/tables.html
|
3242
|
-
def to_a
|
3243
|
-
assert_exists
|
3244
|
-
y = []
|
3245
|
-
table_rows = @o.getElementsByTagName("TR")
|
3246
|
-
for row in table_rows
|
3247
|
-
x = []
|
3248
|
-
for td in row.getElementsbyTagName("TD")
|
3249
|
-
x << td.innerText.strip
|
3250
|
-
end
|
3251
|
-
y << x
|
3252
|
-
end
|
3253
|
-
return y
|
3254
|
-
end
|
3255
|
-
|
3256
|
-
def table_body(index=1)
|
3257
|
-
return @o.getElementsByTagName('TBODY')[index]
|
3258
|
-
end
|
3259
|
-
private :table_body
|
3260
|
-
|
3261
|
-
# returns a watir object
|
3262
|
-
def body(how, what)
|
3263
|
-
return TableBody.new(@container, how, what, self)
|
3264
|
-
end
|
3265
|
-
|
3266
|
-
# returns a watir object
|
3267
|
-
def bodies
|
3268
|
-
assert_exists
|
3269
|
-
return TableBodies.new(@container, @o)
|
3270
|
-
end
|
3271
|
-
|
3272
|
-
# returns an ole object
|
3273
|
-
def row(index)
|
3274
|
-
return @o.invoke("rows")[(index-1).to_s]
|
3275
|
-
end
|
3276
|
-
private :row
|
3277
|
-
|
3278
|
-
# Returns an array containing all the text values in the specified column
|
3279
|
-
# Raises an UnknownCellException if the specified column does not exist in every
|
3280
|
-
# Raises an UnknownObjectException if the table doesn't exist.
|
3281
|
-
# row of the table
|
3282
|
-
# * columnnumber - column index to extract values from
|
3283
|
-
def column_values(columnnumber)
|
3284
|
-
|
3285
|
-
return(1..row_count).collect {|idx| self[idx][columnnumber].text}
|
3286
|
-
end
|
3287
|
-
|
3288
|
-
# Returns an array containing all the text values in the specified row
|
3289
|
-
# Raises an UnknownObjectException if the table doesn't exist.
|
3290
|
-
# * rownumber - row index to extract values from
|
3291
|
-
def row_values(rownumber)
|
3292
|
-
return(1..column_count(rownumber)).collect {|idx| self[rownumber][idx].text}
|
3293
|
-
end
|
3294
|
-
|
3295
|
-
end
|
3296
|
-
|
3297
|
-
# this class is a collection of the table body objects that exist in the table
|
3298
|
-
# it wouldnt normally be created by a user, but gets returned by the bodies method of the Table object
|
3299
|
-
# many of the methods available to this object are inherited from the Element class
|
3300
|
-
#
|
3301
|
-
class TableBodies < Element
|
3302
|
-
def initialize(container, parent_table)
|
3303
|
-
set_container container
|
3304
|
-
@o = parent_table # in this case, @o is the parent table
|
3305
|
-
end
|
3306
|
-
|
3307
|
-
# returns the number of TableBodies that exist in the table
|
3308
|
-
def length
|
3309
|
-
assert_exists
|
3310
|
-
return @o.tBodies.length
|
3311
|
-
end
|
3312
|
-
|
3313
|
-
# returns the n'th Body as a Watir TableBody object
|
3314
|
-
def []n
|
3315
|
-
assert_exists
|
3316
|
-
return TableBody.new(@container, :ole_object, ole_table_body_at_index(n))
|
3317
|
-
end
|
3318
|
-
|
3319
|
-
# returns an ole table body
|
3320
|
-
def ole_table_body_at_index(n)
|
3321
|
-
return @o.tBodies[(n-1).to_s]
|
3322
|
-
end
|
3323
|
-
|
3324
|
-
# iterates through each of the TableBodies in the Table. Yields a TableBody object
|
3325
|
-
def each
|
3326
|
-
1.upto(@o.tBodies.length) { |i| yield TableBody.new(@container, :ole_object, ole_table_body_at_index(i)) }
|
3327
|
-
end
|
3328
|
-
|
3329
|
-
end
|
3330
|
-
|
3331
|
-
# this class is a table body
|
3332
|
-
class TableBody < Element
|
3333
|
-
def locate
|
3334
|
-
@o = nil
|
3335
|
-
if @how == :ole_object
|
3336
|
-
@o = @what # in this case, @o is the table body
|
3337
|
-
elsif @how == :index
|
3338
|
-
@o = @parent_table.bodies.ole_table_body_at_index(@what)
|
3339
|
-
end
|
3340
|
-
@rows = []
|
3341
|
-
if @o
|
3342
|
-
@o.rows.each do |oo|
|
3343
|
-
@rows << TableRow.new(@container, :ole_object, oo)
|
3344
|
-
end
|
3345
|
-
end
|
3346
|
-
end
|
3347
|
-
|
3348
|
-
def initialize(container, how, what, parent_table=nil)
|
3349
|
-
set_container container
|
3350
|
-
@how = how
|
3351
|
-
@what = what
|
3352
|
-
@parent_table = parent_table
|
3353
|
-
super nil
|
3354
|
-
end
|
3355
|
-
|
3356
|
-
# returns the specified row as a TableRow object
|
3357
|
-
def [](n)
|
3358
|
-
assert_exists
|
3359
|
-
return @rows[n - 1]
|
3360
|
-
end
|
3361
|
-
|
3362
|
-
# iterates through all the rows in the table body
|
3363
|
-
def each
|
3364
|
-
locate
|
3365
|
-
0.upto(@rows.length - 1) { |i| yield @rows[i] }
|
3366
|
-
end
|
3367
|
-
|
3368
|
-
# returns the number of rows in this table body.
|
3369
|
-
def length
|
3370
|
-
return @rows.length
|
3371
|
-
end
|
3372
|
-
end
|
3373
|
-
|
3374
|
-
|
3375
|
-
# this class is a table row
|
3376
|
-
class TableRow < Element
|
3377
|
-
|
3378
|
-
def locate
|
3379
|
-
@o = nil
|
3380
|
-
if @how == :ole_object
|
3381
|
-
@o = @what
|
3382
|
-
elsif @how == :xpath
|
3383
|
-
@o = @container.element_by_xpath(@what)
|
3384
|
-
else
|
3385
|
-
@o = @container.locate_tagged_element("TR", @how, @what)
|
3386
|
-
end
|
3387
|
-
if @o # cant call the assert_exists here, as an exists? method call will fail
|
3388
|
-
@cells = []
|
3389
|
-
@o.cells.each do |oo|
|
3390
|
-
@cells << TableCell.new(@container, :ole_object, oo)
|
3391
|
-
end
|
3392
|
-
end
|
3393
|
-
end
|
3394
|
-
|
3395
|
-
# Returns an initialized instance of a table row
|
3396
|
-
# * o - the object contained in the row
|
3397
|
-
# * container - an instance of an IE object
|
3398
|
-
# * how - symbol - how we access the row
|
3399
|
-
# * what - what we use to access the row - id, index etc. If how is :ole_object then what is a Internet Explorer Raw Row
|
3400
|
-
def initialize(container, how, what)
|
3401
|
-
set_container container
|
3402
|
-
@how = how
|
3403
|
-
@what = what
|
3404
|
-
super nil
|
3405
|
-
end
|
3406
|
-
|
3407
|
-
# this method iterates through each of the cells in the row. Yields a TableCell object
|
3408
|
-
def each
|
3409
|
-
locate
|
3410
|
-
0.upto(@cells.length-1) { |i| yield @cells[i] }
|
3411
|
-
end
|
3412
|
-
|
3413
|
-
# Returns an element from the row as a TableCell object
|
3414
|
-
def [](index)
|
3415
|
-
assert_exists
|
3416
|
-
raise UnknownCellException, "Unable to locate a cell at index #{index}" if @cells.length < index
|
3417
|
-
return @cells[(index - 1)]
|
3418
|
-
end
|
3419
|
-
|
3420
|
-
# defaults all missing methods to the array of elements, to be able to
|
3421
|
-
# use the row as an array
|
3422
|
-
# def method_missing(aSymbol, *args)
|
3423
|
-
# return @o.send(aSymbol, *args)
|
3424
|
-
# end
|
3425
|
-
|
3426
|
-
def column_count
|
3427
|
-
locate
|
3428
|
-
@cells.length
|
3429
|
-
end
|
3430
|
-
end
|
3431
|
-
|
3432
|
-
# this class is a table cell - when called via the Table object
|
3433
|
-
class TableCell < Element
|
3434
|
-
include Watir::Exception
|
3435
|
-
include Container
|
3436
|
-
|
3437
|
-
def locate
|
3438
|
-
if @how == :xpath
|
3439
|
-
@o = @container.element_by_xpath(@what)
|
3440
|
-
elsif @how == :ole_object
|
3441
|
-
@o = @what
|
3442
|
-
else
|
3443
|
-
@o = @container.locate_tagged_element("TD", @how, @what)
|
3444
|
-
end
|
3445
|
-
end
|
3446
|
-
|
3447
|
-
# Returns an initialized instance of a table cell
|
3448
|
-
# * container - an IE object
|
3449
|
-
# * how - symbol - how we access the cell
|
3450
|
-
# * what - what we use to access the cell - id, name index etc
|
3451
|
-
def initialize(container, how, what)
|
3452
|
-
set_container container
|
3453
|
-
@how = how
|
3454
|
-
@what = what
|
3455
|
-
super nil
|
3456
|
-
end
|
3457
|
-
|
3458
|
-
def ole_inner_elements
|
3459
|
-
locate
|
3460
|
-
return @o.all
|
3461
|
-
end
|
3462
|
-
private :ole_inner_elements
|
3463
|
-
|
3464
|
-
def document
|
3465
|
-
locate
|
3466
|
-
return @o
|
3467
|
-
end
|
3468
|
-
|
3469
|
-
alias to_s text
|
3470
|
-
|
3471
|
-
def colspan
|
3472
|
-
locate
|
3473
|
-
@o.colSpan
|
3474
|
-
end
|
3475
|
-
|
3476
|
-
end
|
3477
|
-
|
3478
|
-
# This class is the means of accessing an image on a page.
|
3479
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#image method
|
3480
|
-
#
|
3481
|
-
# many of the methods available to this object are inherited from the Element class
|
3482
|
-
#
|
3483
|
-
class Image < Element
|
3484
|
-
def initialize(container, how, what)
|
3485
|
-
set_container container
|
3486
|
-
@how = how
|
3487
|
-
@what = what
|
3488
|
-
super nil
|
3489
|
-
end
|
3490
|
-
|
3491
|
-
def locate
|
3492
|
-
if @how == :xpath
|
3493
|
-
@o = @container.element_by_xpath(@what)
|
3494
|
-
else
|
3495
|
-
@o = @container.locate_tagged_element('IMG', @how, @what)
|
3496
|
-
end
|
3497
|
-
end
|
3498
|
-
|
3499
|
-
# this method produces the properties for an image as an array
|
3500
|
-
def image_string_creator
|
3501
|
-
n = []
|
3502
|
-
n << "src:".ljust(TO_S_SIZE) + self.src.to_s
|
3503
|
-
n << "file date:".ljust(TO_S_SIZE) + self.fileCreatedDate.to_s
|
3504
|
-
n << "file size:".ljust(TO_S_SIZE) + self.fileSize.to_s
|
3505
|
-
n << "width:".ljust(TO_S_SIZE) + self.width.to_s
|
3506
|
-
n << "height:".ljust(TO_S_SIZE) + self.height.to_s
|
3507
|
-
n << "alt:".ljust(TO_S_SIZE) + self.alt.to_s
|
3508
|
-
return n
|
3509
|
-
end
|
3510
|
-
private :image_string_creator
|
3511
|
-
|
3512
|
-
# returns a string representation of the object
|
3513
|
-
def to_s
|
3514
|
-
assert_exists
|
3515
|
-
r = string_creator
|
3516
|
-
r += image_string_creator
|
3517
|
-
return r.join("\n")
|
3518
|
-
end
|
3519
|
-
|
3520
|
-
# this method returns the file created date of the image
|
3521
|
-
def fileCreatedDate
|
3522
|
-
assert_exists
|
3523
|
-
return @o.invoke("fileCreatedDate")
|
3524
|
-
end
|
3525
|
-
|
3526
|
-
# this method returns the filesize of the image
|
3527
|
-
def fileSize
|
3528
|
-
assert_exists
|
3529
|
-
return @o.invoke("fileSize").to_s
|
3530
|
-
end
|
3531
|
-
|
3532
|
-
# returns the width in pixels of the image, as a string
|
3533
|
-
def width
|
3534
|
-
assert_exists
|
3535
|
-
return @o.invoke("width").to_s
|
3536
|
-
end
|
3537
|
-
|
3538
|
-
# returns the height in pixels of the image, as a string
|
3539
|
-
def height
|
3540
|
-
assert_exists
|
3541
|
-
return @o.invoke("height").to_s
|
3542
|
-
end
|
3543
|
-
|
3544
|
-
# This method attempts to find out if the image was actually loaded by the web browser.
|
3545
|
-
# If the image was not loaded, the browser is unable to determine some of the properties.
|
3546
|
-
# We look for these missing properties to see if the image is really there or not.
|
3547
|
-
# If the Disk cache is full (tools menu -> Internet options -> Temporary Internet Files), it may produce incorrect responses.
|
3548
|
-
def hasLoaded?
|
3549
|
-
locate
|
3550
|
-
raise UnknownObjectException, "Unable to locate image using #{@how} and #{@what}" if @o == nil
|
3551
|
-
return false if @o.fileCreatedDate == "" and @o.fileSize.to_i == -1
|
3552
|
-
return true
|
3553
|
-
end
|
3554
|
-
|
3555
|
-
# this method highlights the image (in fact it adds or removes a border around the image)
|
3556
|
-
# * set_or_clear - symbol - :set to set the border, :clear to remove it
|
3557
|
-
def highlight(set_or_clear)
|
3558
|
-
if set_or_clear == :set
|
3559
|
-
begin
|
3560
|
-
@original_border = @o.border
|
3561
|
-
@o.border = 1
|
3562
|
-
rescue
|
3563
|
-
@original_border = nil
|
3564
|
-
end
|
3565
|
-
else
|
3566
|
-
begin
|
3567
|
-
@o.border = @original_border
|
3568
|
-
@original_border = nil
|
3569
|
-
rescue
|
3570
|
-
# we could be here for a number of reasons...
|
3571
|
-
ensure
|
3572
|
-
@original_border = nil
|
3573
|
-
end
|
3574
|
-
end
|
3575
|
-
end
|
3576
|
-
private :highlight
|
3577
|
-
|
3578
|
-
# This method saves the image to the file path that is given. The
|
3579
|
-
# path must be in windows format (c:\\dirname\\somename.gif). This method
|
3580
|
-
# will not overwrite a previously existing image. If an image already
|
3581
|
-
# exists at the given path then a dialog will be displayed prompting
|
3582
|
-
# for overwrite.
|
3583
|
-
# Raises a WatirException if AutoIt is not correctly installed
|
3584
|
-
# path - directory path and file name of where image should be saved
|
3585
|
-
def save(path)
|
3586
|
-
require 'watir/windowhelper'
|
3587
|
-
WindowHelper.check_autoit_installed
|
3588
|
-
@container.goto(src)
|
3589
|
-
begin
|
3590
|
-
thrd = fill_save_image_dialog(path)
|
3591
|
-
@container.document.execCommand("SaveAs")
|
3592
|
-
thrd.join(5)
|
3593
|
-
ensure
|
3594
|
-
@container.back
|
3595
|
-
end
|
3596
|
-
end
|
3597
|
-
|
3598
|
-
def fill_save_image_dialog(path)
|
3599
|
-
Thread.new do
|
3600
|
-
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\"")
|
3601
|
-
end
|
3602
|
-
end
|
3603
|
-
private :fill_save_image_dialog
|
3604
|
-
end
|
3605
|
-
|
3606
|
-
|
3607
|
-
# This class is the means of accessing a link on a page
|
3608
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#link method
|
3609
|
-
# many of the methods available to this object are inherited from the Element class
|
3610
|
-
#
|
3611
|
-
class Link < Element
|
3612
|
-
# Returns an initialized instance of a link object
|
3613
|
-
# * container - an instance of a container
|
3614
|
-
# * how - symbol - how we access the link
|
3615
|
-
# * what - what we use to access the link, text, url, index etc
|
3616
|
-
def initialize(container, how, what)
|
3617
|
-
set_container container
|
3618
|
-
@how = how
|
3619
|
-
@what = what
|
3620
|
-
super(nil)
|
3621
|
-
end
|
3622
|
-
|
3623
|
-
def locate
|
3624
|
-
if @how == :xpath
|
3625
|
-
@o = @container.element_by_xpath(@what)
|
3626
|
-
else
|
3627
|
-
begin
|
3628
|
-
@o = @container.locate_tagged_element('A', @how, @what)
|
3629
|
-
rescue UnknownObjectException
|
3630
|
-
@o = nil
|
3631
|
-
end
|
3632
|
-
end
|
3633
|
-
end
|
3634
|
-
|
3635
|
-
# if an image is used as part of the link, this will return true
|
3636
|
-
def link_has_image
|
3637
|
-
assert_exists
|
3638
|
-
return true if @o.getElementsByTagName("IMG").length > 0
|
3639
|
-
return false
|
3640
|
-
end
|
3641
|
-
|
3642
|
-
# this method returns the src of an image, if an image is used as part of the link
|
3643
|
-
def src # BUG?
|
3644
|
-
assert_exists
|
3645
|
-
if @o.getElementsByTagName("IMG").length > 0
|
3646
|
-
return @o.getElementsByTagName("IMG")[0.to_s].src
|
3647
|
-
else
|
3648
|
-
return ""
|
3649
|
-
end
|
3650
|
-
end
|
3651
|
-
|
3652
|
-
def link_string_creator
|
3653
|
-
n = []
|
3654
|
-
n << "href:".ljust(TO_S_SIZE) + self.href
|
3655
|
-
n << "inner text:".ljust(TO_S_SIZE) + self.text
|
3656
|
-
n << "img src:".ljust(TO_S_SIZE) + self.src if self.link_has_image
|
3657
|
-
return n
|
3658
|
-
end
|
3659
|
-
|
3660
|
-
# returns a textual description of the link
|
3661
|
-
def to_s
|
3662
|
-
assert_exists
|
3663
|
-
r = string_creator
|
3664
|
-
r = r + link_string_creator
|
3665
|
-
return r.join("\n")
|
3666
|
-
end
|
3667
|
-
end
|
3668
|
-
|
3669
|
-
class InputElement < Element
|
3670
|
-
def locate
|
3671
|
-
if @how == :xpath
|
3672
|
-
@o = @container.element_by_xpath(@what)
|
3673
|
-
elsif @how == :ole_object
|
3674
|
-
@o = @what
|
3675
|
-
else
|
3676
|
-
@o = @container.locate_input_element(@how, @what, self.class::INPUT_TYPES)
|
3677
|
-
end
|
3678
|
-
end
|
3679
|
-
def initialize(container, how, what)
|
3680
|
-
set_container container
|
3681
|
-
@how = how
|
3682
|
-
@what = what
|
3683
|
-
super(nil)
|
3684
|
-
end
|
3685
|
-
end
|
3686
|
-
|
3687
|
-
# This class is the way in which select boxes are manipulated.
|
3688
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#select_list method
|
3689
|
-
class SelectList < InputElement
|
3690
|
-
INPUT_TYPES = ["select-one", "select-multiple"]
|
3691
|
-
|
3692
|
-
attr_accessor :o
|
3693
|
-
|
3694
|
-
# This method clears the selected items in the select box
|
3695
|
-
def clearSelection
|
3696
|
-
assert_exists
|
3697
|
-
highlight(:set)
|
3698
|
-
wait = false
|
3699
|
-
@o.each do |selectBoxItem|
|
3700
|
-
if selectBoxItem.selected
|
3701
|
-
selectBoxItem.selected = false
|
3702
|
-
wait = true
|
3703
|
-
end
|
3704
|
-
end
|
3705
|
-
@container.wait if wait
|
3706
|
-
highlight(:clear)
|
3707
|
-
end
|
3708
|
-
# private :clearSelection
|
3709
|
-
|
3710
|
-
# This method selects an item, or items in a select box, by text.
|
3711
|
-
# Raises NoValueFoundException if the specified value is not found.
|
3712
|
-
# * item - the thing to select, string or reg exp
|
3713
|
-
def select(item)
|
3714
|
-
select_item_in_select_list(:text, item)
|
3715
|
-
end
|
3716
|
-
alias :set :select
|
3717
|
-
|
3718
|
-
# Selects an item, or items in a select box, by value.
|
3719
|
-
# Raises NoValueFoundException if the specified value is not found.
|
3720
|
-
# * item - the value of the thing to select, string, reg exp or an array of string and reg exps
|
3721
|
-
def select_value(item)
|
3722
|
-
select_item_in_select_list(:value, item)
|
3723
|
-
end
|
3724
|
-
|
3725
|
-
# BUG: Should be private
|
3726
|
-
# Selects something from the select box
|
3727
|
-
# * name - symbol :value or :text - how we find an item in the select box
|
3728
|
-
# * item - string or reg exp - what we are looking for
|
3729
|
-
def select_item_in_select_list(attribute, value)
|
3730
|
-
assert_exists
|
3731
|
-
highlight(:set)
|
3732
|
-
doBreak = false
|
3733
|
-
@container.log "Setting box #{@o.name} to #{attribute} #{value} "
|
3734
|
-
@o.each do |option| # items in the list
|
3735
|
-
if value.matches(option.invoke(attribute.to_s))
|
3736
|
-
if option.selected
|
3737
|
-
doBreak = true
|
3738
|
-
break
|
3739
|
-
else
|
3740
|
-
option.selected = true
|
3741
|
-
@o.fireEvent("onChange")
|
3742
|
-
@container.wait
|
3743
|
-
doBreak = true
|
3744
|
-
break
|
3745
|
-
end
|
3746
|
-
end
|
3747
|
-
end
|
3748
|
-
unless doBreak
|
3749
|
-
raise NoValueFoundException,
|
3750
|
-
"No option with #{attribute.to_s} of #{value} in this select element"
|
3751
|
-
end
|
3752
|
-
highlight(:clear)
|
3753
|
-
end
|
3754
|
-
|
3755
|
-
# Returns all the items in the select list as an array.
|
3756
|
-
# An empty array is returned if the select box has no contents.
|
3757
|
-
# Raises UnknownObjectException if the select box is not found
|
3758
|
-
def getAllContents # BUG: camel_case.rb
|
3759
|
-
assert_exists
|
3760
|
-
@container.log "There are #{@o.length} items"
|
3761
|
-
returnArray = []
|
3762
|
-
@o.each { |thisItem| returnArray << thisItem.text }
|
3763
|
-
return returnArray
|
3764
|
-
end
|
3765
|
-
|
3766
|
-
# Returns the selected items as an array.
|
3767
|
-
# Raises UnknownObjectException if the select box is not found.
|
3768
|
-
def getSelectedItems
|
3769
|
-
assert_exists
|
3770
|
-
returnArray = []
|
3771
|
-
@container.log "There are #{@o.length} items"
|
3772
|
-
@o.each do |thisItem|
|
3773
|
-
if thisItem.selected
|
3774
|
-
@container.log "Item (#{thisItem.text}) is selected"
|
3775
|
-
returnArray << thisItem.text
|
3776
|
-
end
|
3777
|
-
end
|
3778
|
-
return returnArray
|
3779
|
-
end
|
3780
|
-
|
3781
|
-
# Does the SelectList include the specified option (text)?
|
3782
|
-
def includes? text
|
3783
|
-
getAllContents.include? text
|
3784
|
-
end
|
3785
|
-
|
3786
|
-
# Is the specified option (text) selected? Raises exception of option does not exist.
|
3787
|
-
def selected? text
|
3788
|
-
unless includes? text
|
3789
|
-
raise UnknownObjectException, "Option #{text} not found."
|
3790
|
-
end
|
3791
|
-
getSelectedItems.include? text
|
3792
|
-
end
|
3793
|
-
|
3794
|
-
def option(attribute, value)
|
3795
|
-
assert_exists
|
3796
|
-
Option.new(self, attribute, value)
|
3797
|
-
end
|
3798
|
-
end
|
3799
|
-
|
3800
|
-
module OptionAccess
|
3801
|
-
def text
|
3802
|
-
@option.text
|
3803
|
-
end
|
3804
|
-
def value
|
3805
|
-
@option.value
|
3806
|
-
end
|
3807
|
-
def selected
|
3808
|
-
@option.selected
|
3809
|
-
end
|
3810
|
-
end
|
3811
|
-
|
3812
|
-
class OptionWrapper
|
3813
|
-
include OptionAccess
|
3814
|
-
def initialize(option)
|
3815
|
-
@option = option
|
3816
|
-
end
|
3817
|
-
end
|
3818
|
-
|
3819
|
-
# An item in a select list
|
3820
|
-
class Option
|
3821
|
-
include OptionAccess
|
3822
|
-
include Watir::Exception
|
3823
|
-
def initialize(select_list, attribute, value)
|
3824
|
-
@select_list = select_list
|
3825
|
-
@how = attribute
|
3826
|
-
@what = value
|
3827
|
-
@option = nil
|
3828
|
-
|
3829
|
-
unless [:text, :value].include? attribute
|
3830
|
-
raise MissingWayOfFindingObjectException,
|
3831
|
-
"Option does not support attribute #{@how}"
|
3832
|
-
end
|
3833
|
-
@select_list.o.each do |option| # items in the list
|
3834
|
-
if value.matches(option.invoke(attribute.to_s))
|
3835
|
-
@option = option
|
3836
|
-
break
|
3837
|
-
end
|
3838
|
-
end
|
3839
|
-
|
3840
|
-
end
|
3841
|
-
def assert_exists
|
3842
|
-
unless @option
|
3843
|
-
raise UnknownObjectException,
|
3844
|
-
"Unable to locate an option using #{@how} and #{@what}"
|
3845
|
-
end
|
3846
|
-
end
|
3847
|
-
private :assert_exists
|
3848
|
-
def select
|
3849
|
-
assert_exists
|
3850
|
-
@select_list.select_item_in_select_list(@how, @what)
|
3851
|
-
end
|
3852
|
-
end
|
3853
|
-
|
3854
|
-
# This is the main class for accessing buttons.
|
3855
|
-
# Normally a user would not need to create this object as it is
|
3856
|
-
# returned by the Watir::Container#button method
|
3857
|
-
class Button < InputElement
|
3858
|
-
INPUT_TYPES = ["button", "submit", "image", "reset"]
|
3859
|
-
end
|
3860
|
-
|
3861
|
-
# This class is the main class for Text Fields
|
3862
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#text_field method
|
3863
|
-
class TextField < InputElement
|
3864
|
-
INPUT_TYPES = ["text", "password", "textarea"]
|
3865
|
-
|
3866
|
-
def_wrap_guard :size
|
3867
|
-
def_wrap_guard :maxlength
|
3868
|
-
|
3869
|
-
# Returns true or false if the text field is read only.
|
3870
|
-
# Raises UnknownObjectException if the object can't be found.
|
3871
|
-
def_wrap :readonly?, :readOnly
|
3872
|
-
|
3873
|
-
def text_string_creator
|
3874
|
-
n = []
|
3875
|
-
n << "length:".ljust(TO_S_SIZE) + self.size.to_s
|
3876
|
-
n << "max length:".ljust(TO_S_SIZE) + self.maxlength.to_s
|
3877
|
-
n << "read only:".ljust(TO_S_SIZE) + self.readonly?.to_s
|
3878
|
-
|
3879
|
-
return n
|
3880
|
-
end
|
3881
|
-
private :text_string_creator
|
3882
|
-
|
3883
|
-
def to_s
|
3884
|
-
assert_exists
|
3885
|
-
r = string_creator
|
3886
|
-
r += text_string_creator
|
3887
|
-
return r.join("\n")
|
3888
|
-
end
|
3889
|
-
|
3890
|
-
def assert_not_readonly
|
3891
|
-
raise ObjectReadOnlyException, "Textfield #{@how} and #{@what} is read only." if self.readonly?
|
3892
|
-
end
|
3893
|
-
|
3894
|
-
# This method returns true or false if the text field contents is either a string match
|
3895
|
-
# or a regular expression match to the supplied value.
|
3896
|
-
# Raises UnknownObjectException if the object can't be found
|
3897
|
-
# * containsThis - string or reg exp - the text to verify
|
3898
|
-
def verify_contains(containsThis) # FIXME: verify_contains should have same name and semantics as IE#contains_text (prolly make this work for all elements)
|
3899
|
-
assert_exists
|
3900
|
-
if containsThis.kind_of? String
|
3901
|
-
return true if self.value == containsThis
|
3902
|
-
elsif containsThis.kind_of? Regexp
|
3903
|
-
return true if self.value.match(containsThis) != nil
|
3904
|
-
end
|
3905
|
-
return false
|
3906
|
-
end
|
3907
|
-
|
3908
|
-
# this method is used to drag the entire contents of the text field to another text field
|
3909
|
-
# 19 Jan 2005 - It is added as prototype functionality, and may change
|
3910
|
-
# * destination_how - symbol, :id, :name how we identify the drop target
|
3911
|
-
# * destination_what - string or regular expression, the name, id, etc of the text field that will be the drop target
|
3912
|
-
def dragContentsTo(destination_how, destination_what)
|
3913
|
-
assert_exists
|
3914
|
-
destination = @container.text_field(destination_how, destination_what)
|
3915
|
-
raise UnknownObjectException, "Unable to locate destination using #{destination_how } and #{destination_what } " if destination.exists? == false
|
3916
|
-
|
3917
|
-
@o.focus
|
3918
|
-
@o.select
|
3919
|
-
value = self.value
|
3920
|
-
|
3921
|
-
@o.fireEvent("onSelect")
|
3922
|
-
@o.fireEvent("ondragstart")
|
3923
|
-
@o.fireEvent("ondrag")
|
3924
|
-
destination.fireEvent("onDragEnter")
|
3925
|
-
destination.fireEvent("onDragOver")
|
3926
|
-
destination.fireEvent("ondrop")
|
3927
|
-
|
3928
|
-
@o.fireEvent("ondragend")
|
3929
|
-
destination.value = destination.value + value.to_s
|
3930
|
-
self.value = ""
|
3931
|
-
end
|
3932
|
-
|
3933
|
-
# This method clears the contents of the text box.
|
3934
|
-
# Raises UnknownObjectException if the object can't be found
|
3935
|
-
# Raises ObjectDisabledException if the object is disabled
|
3936
|
-
# Raises ObjectReadOnlyException if the object is read only
|
3937
|
-
def clear
|
3938
|
-
assert_enabled
|
3939
|
-
assert_not_readonly
|
3940
|
-
|
3941
|
-
highlight(:set)
|
3942
|
-
|
3943
|
-
@o.scrollIntoView
|
3944
|
-
@o.focus
|
3945
|
-
@o.select
|
3946
|
-
@o.fireEvent("onSelect")
|
3947
|
-
@o.value = ""
|
3948
|
-
@o.fireEvent("onKeyPress")
|
3949
|
-
@o.fireEvent("onChange")
|
3950
|
-
@container.wait
|
3951
|
-
highlight(:clear)
|
3952
|
-
end
|
3953
|
-
|
3954
|
-
# This method appens the supplied text to the contents of the text box.
|
3955
|
-
# Raises UnknownObjectException if the object cant be found
|
3956
|
-
# Raises ObjectDisabledException if the object is disabled
|
3957
|
-
# Raises ObjectReadOnlyException if the object is read only
|
3958
|
-
# * setThis - string - the text to append
|
3959
|
-
def append(setThis)
|
3960
|
-
assert_enabled
|
3961
|
-
assert_not_readonly
|
3962
|
-
|
3963
|
-
highlight(:set)
|
3964
|
-
@o.scrollIntoView
|
3965
|
-
@o.focus
|
3966
|
-
doKeyPress(setThis)
|
3967
|
-
highlight(:clear)
|
3968
|
-
end
|
3969
|
-
|
3970
|
-
# This method sets the contents of the text box to the supplied text
|
3971
|
-
# Raises UnknownObjectException if the object cant be found
|
3972
|
-
# Raises ObjectDisabledException if the object is disabled
|
3973
|
-
# Raises ObjectReadOnlyException if the object is read only
|
3974
|
-
# * setThis - string - the text to set
|
3975
|
-
def set(setThis)
|
3976
|
-
assert_enabled
|
3977
|
-
assert_not_readonly
|
3978
|
-
|
3979
|
-
highlight(:set)
|
3980
|
-
@o.scrollIntoView
|
3981
|
-
@o.focus
|
3982
|
-
@o.select
|
3983
|
-
@o.fireEvent("onSelect")
|
3984
|
-
@o.value = ""
|
3985
|
-
@o.fireEvent("onKeyPress")
|
3986
|
-
doKeyPress(setThis)
|
3987
|
-
highlight(:clear)
|
3988
|
-
@o.fireEvent("onChange")
|
3989
|
-
@o.fireEvent("onBlur")
|
3990
|
-
end
|
3991
|
-
|
3992
|
-
# 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
|
3993
|
-
# it is preffered to use the set method.
|
3994
|
-
def value=(v)
|
3995
|
-
assert_exists
|
3996
|
-
@o.value = v.to_s
|
3997
|
-
end
|
3998
|
-
|
3999
|
-
# This method is used internally by setText and appendText
|
4000
|
-
# It should not be used externally.
|
4001
|
-
# * value - string - The string to enter into the text field
|
4002
|
-
def doKeyPress(value)
|
4003
|
-
begin
|
4004
|
-
maxLength = @o.maxLength
|
4005
|
-
if value.length > maxLength
|
4006
|
-
original_value = value
|
4007
|
-
value = original_value[0 .. maxLength-1 ]
|
4008
|
-
@container.log " Supplied string is #{original_value.length} chars, which exceeds the max length (#{maxLength}) of the field. Using value: #{value}"
|
4009
|
-
end
|
4010
|
-
rescue WIN32OLERuntimeError => e
|
4011
|
-
# probably a text area - so it doesnt have a max Length
|
4012
|
-
raise e unless /unknown property or method .*?maxLength/.match( e.message )
|
4013
|
-
maxLength = -1
|
4014
|
-
end
|
4015
|
-
for i in 0 .. value.length-1
|
4016
|
-
sleep @container.typingspeed
|
4017
|
-
c = value[i,1]
|
4018
|
-
#@container.log " adding c.chr " + c
|
4019
|
-
@o.value = @o.value.to_s + c
|
4020
|
-
@o.fireEvent("onKeyDown")
|
4021
|
-
@o.fireEvent("onKeyPress")
|
4022
|
-
@o.fireEvent("onKeyUp")
|
4023
|
-
end
|
4024
|
-
|
4025
|
-
end
|
4026
|
-
private :doKeyPress
|
4027
|
-
end
|
4028
|
-
|
4029
|
-
# this class can be used to access hidden field objects
|
4030
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#hidden method
|
4031
|
-
class Hidden < TextField
|
4032
|
-
INPUT_TYPES = ["hidden"]
|
4033
|
-
|
4034
|
-
# set is overriden in this class, as there is no way to set focus to a hidden field
|
4035
|
-
def set(n)
|
4036
|
-
self.value = n
|
4037
|
-
end
|
4038
|
-
|
4039
|
-
# override the append method, so that focus isnt set to the hidden object
|
4040
|
-
def append(n)
|
4041
|
-
self.value = self.value.to_s + n.to_s
|
4042
|
-
end
|
4043
|
-
|
4044
|
-
# override the clear method, so that focus isnt set to the hidden object
|
4045
|
-
def clear
|
4046
|
-
self.value = ""
|
4047
|
-
end
|
4048
|
-
|
4049
|
-
# this method will do nothing, as you cant set focus to a hidden field
|
4050
|
-
def focus
|
4051
|
-
end
|
4052
|
-
|
4053
|
-
end
|
4054
|
-
|
4055
|
-
# This class is the class for fields that accept file uploads
|
4056
|
-
# Windows dialog is opened and handled in this case by autoit
|
4057
|
-
# launching into a new process.
|
4058
|
-
class FileField < InputElement
|
4059
|
-
INPUT_TYPES = ["file"]
|
4060
|
-
|
4061
|
-
# set the file location in the Choose file dialog in a new process
|
4062
|
-
# will raise a Watir Exception if AutoIt is not correctly installed
|
4063
|
-
def set(setPath)
|
4064
|
-
assert_exists
|
4065
|
-
require 'watir/windowhelper'
|
4066
|
-
WindowHelper.check_autoit_installed
|
4067
|
-
begin
|
4068
|
-
thrd = Thread.new do
|
4069
|
-
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\"")
|
4070
|
-
end
|
4071
|
-
thrd.join(1)
|
4072
|
-
rescue
|
4073
|
-
raise Watir::Exception::WatirException, "Problem accessing Choose file dialog"
|
4074
|
-
end
|
4075
|
-
click
|
4076
|
-
end
|
4077
|
-
end
|
4078
|
-
|
4079
|
-
# This class is the class for radio buttons and check boxes.
|
4080
|
-
# It contains methods common to both.
|
4081
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#checkbox or Watir::Container#radio methods
|
4082
|
-
#
|
4083
|
-
# most of the methods available to this element are inherited from the Element class
|
4084
|
-
#
|
4085
|
-
class RadioCheckCommon < Element
|
4086
|
-
def locate
|
4087
|
-
if @how == :xpath
|
4088
|
-
@o = @container.element_by_xpath(@what)
|
4089
|
-
else
|
4090
|
-
@o = @container.locate_input_element(@how, @what, @type, @value)
|
4091
|
-
end
|
4092
|
-
end
|
4093
|
-
def initialize(container, how, what, type, value=nil)
|
4094
|
-
set_container container
|
4095
|
-
@how = how
|
4096
|
-
@what = what
|
4097
|
-
@type = type
|
4098
|
-
@value = value
|
4099
|
-
super(nil)
|
4100
|
-
end
|
4101
|
-
|
4102
|
-
# BUG: rename me
|
4103
|
-
# This method determines if a radio button or check box is set.
|
4104
|
-
# Returns true is set/checked or false if not set/checked.
|
4105
|
-
# Raises UnknownObjectException if its unable to locate an object.
|
4106
|
-
def isSet?
|
4107
|
-
assert_exists
|
4108
|
-
return @o.checked
|
4109
|
-
end
|
4110
|
-
alias getState isSet?
|
4111
|
-
alias checked? isSet?
|
4112
|
-
|
4113
|
-
# This method clears a radio button or check box. Note, with radio buttons one of them will almost always be set.
|
4114
|
-
# Returns true if set or false if not set.
|
4115
|
-
# Raises UnknownObjectException if its unable to locate an object
|
4116
|
-
# ObjectDisabledException IF THE OBJECT IS DISABLED
|
4117
|
-
def clear
|
4118
|
-
assert_enabled
|
4119
|
-
highlight(:set)
|
4120
|
-
set_clear_item(false)
|
4121
|
-
highlight(:clear)
|
4122
|
-
end
|
4123
|
-
|
4124
|
-
# This method sets the radio list item or check box.
|
4125
|
-
# Raises UnknownObjectException if it's unable to locate an object
|
4126
|
-
# ObjectDisabledException if the object is disabled
|
4127
|
-
def set
|
4128
|
-
assert_enabled
|
4129
|
-
highlight(:set)
|
4130
|
-
set_clear_item(true)
|
4131
|
-
highlight(:clear)
|
4132
|
-
end
|
4133
|
-
|
4134
|
-
# This method is the common code for setting or clearing checkboxes and radio.
|
4135
|
-
def set_clear_item(set)
|
4136
|
-
@o.checked = set
|
4137
|
-
@o.fireEvent("onClick")
|
4138
|
-
@container.wait
|
4139
|
-
end
|
4140
|
-
private :set_clear_item
|
4141
|
-
|
4142
|
-
end
|
4143
|
-
|
4144
|
-
#--
|
4145
|
-
# this class makes the docs better
|
4146
|
-
#++
|
4147
|
-
# This class is the watir representation of a radio button.
|
4148
|
-
class Radio < RadioCheckCommon
|
4149
|
-
end
|
4150
|
-
|
4151
|
-
# This class is the watir representation of a check box.
|
4152
|
-
class CheckBox < RadioCheckCommon
|
4153
|
-
|
4154
|
-
# With no arguments supplied, sets the check box.
|
4155
|
-
# If the optional value is supplied, the checkbox is set, when its true and
|
4156
|
-
# cleared when its false
|
4157
|
-
# Raises UnknownObjectException if it's unable to locate an object
|
4158
|
-
# ObjectDisabledException if the object is disabled
|
4159
|
-
def set(value=true)
|
4160
|
-
assert_enabled
|
4161
|
-
highlight :set
|
4162
|
-
unless @o.checked == value
|
4163
|
-
set_clear_item value
|
4164
|
-
end
|
4165
|
-
highlight :clear
|
4166
|
-
end
|
4167
|
-
|
4168
|
-
# Clears a check box.
|
4169
|
-
# Raises UnknownObjectException if its unable to locate an object
|
4170
|
-
# ObjectDisabledException if the object is disabled
|
4171
|
-
def clear
|
4172
|
-
set false
|
4173
|
-
end
|
4174
|
-
|
4175
|
-
end
|
4176
|
-
|
4177
|
-
#--
|
4178
|
-
# These classes are not for public consumption, so we switch off rdoc
|
4179
|
-
|
4180
|
-
|
4181
|
-
# presumes element_class or element_tag is defined
|
4182
|
-
# for subclasses of ElementCollections
|
4183
|
-
module CommonCollection
|
4184
|
-
def element_tag
|
4185
|
-
element_class::TAG
|
4186
|
-
end
|
4187
|
-
def length
|
4188
|
-
@container.document.getElementsByTagName(element_tag).length
|
4189
|
-
end
|
4190
|
-
end
|
4191
|
-
|
4192
|
-
# This class is used as part of the .show method of the iterators class
|
4193
|
-
# it would not normally be used by a user
|
4194
|
-
class AttributeLengthPairs
|
4195
|
-
|
4196
|
-
# This class is used as part of the .show method of the iterators class
|
4197
|
-
# it would not normally be used by a user
|
4198
|
-
class AttributeLengthHolder
|
4199
|
-
attr_accessor :attribute
|
4200
|
-
attr_accessor :length
|
4201
|
-
|
4202
|
-
def initialize(attrib, length)
|
4203
|
-
@attribute = attrib
|
4204
|
-
@length = length
|
4205
|
-
end
|
4206
|
-
end
|
4207
|
-
|
4208
|
-
def initialize(attrib=nil, length=nil)
|
4209
|
-
@attr=[]
|
4210
|
-
add(attrib, length) if attrib
|
4211
|
-
@index_counter = 0
|
4212
|
-
end
|
4213
|
-
|
4214
|
-
# BUG: Untested. (Null implementation passes all tests.)
|
4215
|
-
def add(attrib, length)
|
4216
|
-
@attr << AttributeLengthHolder.new(attrib, length)
|
4217
|
-
end
|
4218
|
-
|
4219
|
-
def delete(attrib)
|
4220
|
-
item_to_delete = nil
|
4221
|
-
@attr.each_with_index do |e,i|
|
4222
|
-
item_to_delete = i if e.attribute == attrib
|
4223
|
-
end
|
4224
|
-
@attr.delete_at(item_to_delete) unless item_to_delete == nil
|
4225
|
-
end
|
4226
|
-
|
4227
|
-
def next
|
4228
|
-
temp = @attr[@index_counter]
|
4229
|
-
@index_counter += 1
|
4230
|
-
return temp
|
4231
|
-
end
|
4232
|
-
|
4233
|
-
def each
|
4234
|
-
0.upto(@attr.length-1) { |i | yield @attr[i] }
|
4235
|
-
end
|
4236
|
-
end
|
4237
|
-
|
4238
|
-
# resume rdoc
|
4239
|
-
#++
|
4240
|
-
|
4241
|
-
# this class accesses the buttons in the document as a collection
|
4242
|
-
# it would normally only be accessed by the Watir::Container#buttons method
|
4243
|
-
class Buttons < ElementCollections
|
4244
|
-
def element_class; Button; end
|
4245
|
-
def length
|
4246
|
-
get_length_of_input_objects(["button", "submit", "image"])
|
4247
|
-
end
|
4248
|
-
|
4249
|
-
private
|
4250
|
-
def set_show_items
|
4251
|
-
super
|
4252
|
-
@show_attributes.add("disabled", 9)
|
4253
|
-
@show_attributes.add("value", 20)
|
4254
|
-
end
|
4255
|
-
end
|
4256
|
-
|
4257
|
-
# this class accesses the file fields in the document as a collection
|
4258
|
-
# normal access is via the Container#file_fields method
|
4259
|
-
class FileFields < ElementCollections
|
4260
|
-
def element_class; FileField; end
|
4261
|
-
def length
|
4262
|
-
get_length_of_input_objects(["file"])
|
4263
|
-
end
|
4264
|
-
|
4265
|
-
private
|
4266
|
-
def set_show_items
|
4267
|
-
super
|
4268
|
-
@show_attributes.add("disabled", 9)
|
4269
|
-
@show_attributes.add("value", 20)
|
4270
|
-
end
|
4271
|
-
end
|
4272
|
-
|
4273
|
-
# this class accesses the check boxes in the document as a collection
|
4274
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#checkboxes method
|
4275
|
-
class CheckBoxes < ElementCollections
|
4276
|
-
def element_class; CheckBox; end
|
4277
|
-
def length
|
4278
|
-
get_length_of_input_objects("checkbox")
|
4279
|
-
end
|
4280
|
-
|
4281
|
-
private
|
4282
|
-
def iterator_object(i)
|
4283
|
-
@container.checkbox(:index, i + 1)
|
4284
|
-
end
|
4285
|
-
end
|
4286
|
-
|
4287
|
-
# this class accesses the radio buttons in the document as a collection
|
4288
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#radios method
|
4289
|
-
class Radios < ElementCollections
|
4290
|
-
def element_class; Radio; end
|
4291
|
-
def length
|
4292
|
-
get_length_of_input_objects("radio")
|
4293
|
-
end
|
4294
|
-
|
4295
|
-
private
|
4296
|
-
def iterator_object(i)
|
4297
|
-
@container.radio(:index, i + 1)
|
4298
|
-
end
|
4299
|
-
end
|
4300
|
-
|
4301
|
-
# this class accesses the select boxes in the document as a collection
|
4302
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#select_lists method
|
4303
|
-
class SelectLists < ElementCollections
|
4304
|
-
include CommonCollection
|
4305
|
-
def element_class; SelectList; end
|
4306
|
-
def element_tag; 'SELECT'; end
|
4307
|
-
end
|
4308
|
-
|
4309
|
-
# this class accesses the links in the document as a collection
|
4310
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#links method
|
4311
|
-
class Links < ElementCollections
|
4312
|
-
include CommonCollection
|
4313
|
-
def element_class; Link; end
|
4314
|
-
def element_tag; 'A'; end
|
4315
|
-
|
4316
|
-
private
|
4317
|
-
def set_show_items
|
4318
|
-
super
|
4319
|
-
@show_attributes.add("href", 60)
|
4320
|
-
@show_attributes.add("innerText", 60)
|
4321
|
-
end
|
4322
|
-
end
|
4323
|
-
|
4324
|
-
class Lis < ElementCollections
|
4325
|
-
include Watir::CommonCollection
|
4326
|
-
def element_class; Li; end
|
4327
|
-
|
4328
|
-
def set_show_items
|
4329
|
-
super
|
4330
|
-
@show_attributes.delete( "name")
|
4331
|
-
@show_attributes.add( "className" , 20)
|
4332
|
-
end
|
4333
|
-
end
|
4334
|
-
|
4335
|
-
class Map < NonControlElement
|
4336
|
-
TAG = 'MAP'
|
4337
|
-
end
|
4338
|
-
|
4339
|
-
class Area < NonControlElement
|
4340
|
-
TAG = 'AREA'
|
4341
|
-
end
|
4342
|
-
|
4343
|
-
# this class accesses the maps in the document as a collection
|
4344
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#maps method
|
4345
|
-
class Maps < ElementCollections
|
4346
|
-
include CommonCollection
|
4347
|
-
def element_class; Map; end
|
4348
|
-
def element_tag; 'MAP'; end
|
4349
|
-
end
|
4350
|
-
|
4351
|
-
|
4352
|
-
# this class accesses the areas in the document as a collection
|
4353
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#areas method
|
4354
|
-
class Areas < ElementCollections
|
4355
|
-
include CommonCollection
|
4356
|
-
def element_class; Area; end
|
4357
|
-
def element_tag; 'AREA'; end
|
4358
|
-
end
|
4359
|
-
|
4360
|
-
# this class accesses the imnages in the document as a collection
|
4361
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#images method
|
4362
|
-
class Images < ElementCollections
|
4363
|
-
def element_class; Image; end
|
4364
|
-
def length
|
4365
|
-
@container.document.images.length
|
4366
|
-
end
|
4367
|
-
|
4368
|
-
private
|
4369
|
-
def set_show_items
|
4370
|
-
super
|
4371
|
-
@show_attributes.add("src", 60)
|
4372
|
-
@show_attributes.add("alt", 30)
|
4373
|
-
end
|
4374
|
-
end
|
4375
|
-
|
4376
|
-
# this class accesses the text fields in the document as a collection
|
4377
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#text_fields method
|
4378
|
-
class TextFields < ElementCollections
|
4379
|
-
def element_class; TextField; end
|
4380
|
-
def length
|
4381
|
-
# text areas are also included in the TextFields, but we need to get them seperately
|
4382
|
-
get_length_of_input_objects(["text", "password"]) +
|
4383
|
-
@container.document.getElementsByTagName("textarea").length
|
4384
|
-
end
|
4385
|
-
end
|
4386
|
-
|
4387
|
-
# this class accesses the hidden fields in the document as a collection
|
4388
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#hiddens method
|
4389
|
-
class Hiddens < ElementCollections
|
4390
|
-
def element_class; Hidden; end
|
4391
|
-
def length
|
4392
|
-
get_length_of_input_objects("hidden")
|
4393
|
-
end
|
4394
|
-
end
|
4395
|
-
|
4396
|
-
# this class accesses the text fields in the document as a collection
|
4397
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#tables method
|
4398
|
-
class Tables < ElementCollections
|
4399
|
-
include CommonCollection
|
4400
|
-
def element_class; Table; end
|
4401
|
-
def element_tag; 'TABLE'; end
|
4402
|
-
|
4403
|
-
private
|
4404
|
-
def set_show_items
|
4405
|
-
super
|
4406
|
-
@show_attributes.delete("name")
|
4407
|
-
end
|
4408
|
-
end
|
4409
|
-
# this class accesses the table rows in the document as a collection
|
4410
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#rows method
|
4411
|
-
class TableRows < ElementCollections
|
4412
|
-
include CommonCollection
|
4413
|
-
def element_class; TableRow; end
|
4414
|
-
def element_tag; 'TR'; end
|
4415
|
-
end
|
4416
|
-
# this class accesses the table cells in the document as a collection
|
4417
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#cells method
|
4418
|
-
class TableCells < ElementCollections
|
4419
|
-
include CommonCollection
|
4420
|
-
def element_class; TableCell; end
|
4421
|
-
def element_tag; 'TD'; end
|
4422
|
-
end
|
4423
|
-
# this class accesses the labels in the document as a collection
|
4424
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#labels method
|
4425
|
-
class Labels < ElementCollections
|
4426
|
-
include CommonCollection
|
4427
|
-
def element_class; Label; end
|
4428
|
-
def element_tag; 'LABEL'; end
|
4429
|
-
|
4430
|
-
private
|
4431
|
-
def set_show_items
|
4432
|
-
super
|
4433
|
-
@show_attributes.add("htmlFor", 20)
|
4434
|
-
end
|
4435
|
-
end
|
4436
|
-
|
4437
|
-
# this class accesses the pre tags in the document as a collection
|
4438
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#pres method
|
4439
|
-
class Pres < ElementCollections
|
4440
|
-
include CommonCollection
|
4441
|
-
def element_class; Pre; end
|
4442
|
-
|
4443
|
-
private
|
4444
|
-
def set_show_items
|
4445
|
-
super
|
4446
|
-
@show_attributes.delete("name")
|
4447
|
-
@show_attributes.add("className", 20)
|
4448
|
-
end
|
4449
|
-
end
|
4450
|
-
|
4451
|
-
# this class accesses the p tags in the document as a collection
|
4452
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#ps method
|
4453
|
-
class Ps < ElementCollections
|
4454
|
-
include CommonCollection
|
4455
|
-
def element_class; P; end
|
4456
|
-
|
4457
|
-
private
|
4458
|
-
def set_show_items
|
4459
|
-
super
|
4460
|
-
@show_attributes.delete("name")
|
4461
|
-
@show_attributes.add("className", 20)
|
4462
|
-
end
|
4463
|
-
|
4464
|
-
end
|
4465
|
-
# this class accesses the spans in the document as a collection
|
4466
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#spans method
|
4467
|
-
class Spans < ElementCollections
|
4468
|
-
include CommonCollection
|
4469
|
-
def element_class; Span; end
|
4470
|
-
|
4471
|
-
private
|
4472
|
-
def set_show_items
|
4473
|
-
super
|
4474
|
-
@show_attributes.delete("name")
|
4475
|
-
@show_attributes.add("className", 20)
|
4476
|
-
end
|
4477
|
-
end
|
4478
|
-
|
4479
|
-
# this class accesses the divs in the document as a collection
|
4480
|
-
# Normally a user would not need to create this object as it is returned by the Watir::Container#divs method
|
4481
|
-
class Divs < ElementCollections
|
4482
|
-
include CommonCollection
|
4483
|
-
def element_class; Div; end
|
4484
|
-
|
4485
|
-
private
|
4486
|
-
def set_show_items
|
4487
|
-
super
|
4488
|
-
@show_attributes.delete("name")
|
4489
|
-
@show_attributes.add("className", 20)
|
4490
|
-
end
|
4491
|
-
end
|
4492
|
-
|
4493
127
|
# Move to Watir::Utils
|
4494
128
|
|
4495
129
|
@@autoit = nil
|
@@ -4520,4 +154,4 @@ def _code_that_copies_readonly_array(array, name)
|
|
4520
154
|
end
|
4521
155
|
|
4522
156
|
require 'watir/camel_case'
|
4523
|
-
require 'watir/elements'
|
157
|
+
require 'watir/bonus-elements'
|