watir 1.4.1

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.
Files changed (98) hide show
  1. data/readme.rb +211 -0
  2. data/unittests/WindowLogonExample.rb +30 -0
  3. data/unittests/WindowLogonExtra.rb +7 -0
  4. data/unittests/all_tests.rb +10 -0
  5. data/unittests/all_tests_concurrent.rb +57 -0
  6. data/unittests/attachToExistingWindow_test.rb +40 -0
  7. data/unittests/buttons_test.rb +131 -0
  8. data/unittests/checkbox_test.rb +149 -0
  9. data/unittests/core_tests.rb +9 -0
  10. data/unittests/css_test.rb +60 -0
  11. data/unittests/div_test.rb +179 -0
  12. data/unittests/errorchecker_test.rb +29 -0
  13. data/unittests/filefield_test.rb +35 -0
  14. data/unittests/form_test.rb +279 -0
  15. data/unittests/frame_test.rb +141 -0
  16. data/unittests/html/blankpage.html +12 -0
  17. data/unittests/html/buttons1.html +40 -0
  18. data/unittests/html/checkboxes1.html +69 -0
  19. data/unittests/html/complex_table.html +36 -0
  20. data/unittests/html/cssTest.html +42 -0
  21. data/unittests/html/div.html +105 -0
  22. data/unittests/html/fileupload.html +45 -0
  23. data/unittests/html/formTest1.html +39 -0
  24. data/unittests/html/forms2.html +45 -0
  25. data/unittests/html/forms3.html +132 -0
  26. data/unittests/html/forms4.html +27 -0
  27. data/unittests/html/frame_buttons.html +4 -0
  28. data/unittests/html/frame_links.html +4 -0
  29. data/unittests/html/frame_multi.html +5 -0
  30. data/unittests/html/iframeTest.html +13 -0
  31. data/unittests/html/iframeTest1.html +7 -0
  32. data/unittests/html/iframeTest2.html +6 -0
  33. data/unittests/html/images/1.gif +0 -0
  34. data/unittests/html/images/2.GIF +0 -0
  35. data/unittests/html/images/3.GIF +0 -0
  36. data/unittests/html/images/button.jpg +0 -0
  37. data/unittests/html/images/circle.jpg +0 -0
  38. data/unittests/html/images/minus.GIF +0 -0
  39. data/unittests/html/images/originaltriangle.jpg +0 -0
  40. data/unittests/html/images/plus.gif +0 -0
  41. data/unittests/html/images/square.jpg +0 -0
  42. data/unittests/html/images/triangle.jpg +0 -0
  43. data/unittests/html/images1.html +52 -0
  44. data/unittests/html/javascriptevents.html +39 -0
  45. data/unittests/html/link_pass.html +11 -0
  46. data/unittests/html/links1.html +37 -0
  47. data/unittests/html/links2.html +11 -0
  48. data/unittests/html/nestedFrames.html +6 -0
  49. data/unittests/html/pass.html +10 -0
  50. data/unittests/html/popups1.html +60 -0
  51. data/unittests/html/radioButtons1.html +71 -0
  52. data/unittests/html/select_tealeaf.html +54 -0
  53. data/unittests/html/selectboxes1.html +55 -0
  54. data/unittests/html/simple_table.html +26 -0
  55. data/unittests/html/simple_table_buttons.html +104 -0
  56. data/unittests/html/simple_table_columns.html +76 -0
  57. data/unittests/html/table1.html +142 -0
  58. data/unittests/html/textarea.html +30 -0
  59. data/unittests/html/textfields1.html +87 -0
  60. data/unittests/html/textsearch.html +44 -0
  61. data/unittests/ie_mock.rb +93 -0
  62. data/unittests/ie_test.rb +50 -0
  63. data/unittests/images_test.rb +179 -0
  64. data/unittests/iostring.rb +30 -0
  65. data/unittests/iostring_test.rb +48 -0
  66. data/unittests/js_events_test.rb +77 -0
  67. data/unittests/jscriptExtraAlert.rb +6 -0
  68. data/unittests/jscriptExtraConfirmCancel.rb +7 -0
  69. data/unittests/jscriptExtraConfirmOk.rb +7 -0
  70. data/unittests/jscriptPushButton.rb +5 -0
  71. data/unittests/jscript_test.rb +57 -0
  72. data/unittests/links_test.rb +169 -0
  73. data/unittests/minmax_test.rb +31 -0
  74. data/unittests/navigate_test.rb +56 -0
  75. data/unittests/non_core_tests.rb +9 -0
  76. data/unittests/pagecontainstext_test.rb +49 -0
  77. data/unittests/popups_test.rb +44 -0
  78. data/unittests/radios_test.rb +164 -0
  79. data/unittests/screen_capture_test.rb +53 -0
  80. data/unittests/selectbox_test.rb +197 -0
  81. data/unittests/send_keys_test.rb +29 -0
  82. data/unittests/setup.rb +47 -0
  83. data/unittests/table_test.rb +306 -0
  84. data/unittests/textAreafields_test.rb +81 -0
  85. data/unittests/textfields_test.rb +239 -0
  86. data/watir.rb +3744 -0
  87. data/watir/AutoItX3.dll +0 -0
  88. data/watir/WindowHelper.rb +47 -0
  89. data/watir/camel_case.rb +37 -0
  90. data/watir/clickJSDialog.rb +19 -0
  91. data/watir/cookiemanager.rb +53 -0
  92. data/watir/exceptions.rb +60 -0
  93. data/watir/screen_capture.rb +115 -0
  94. data/watir/setFileDialog.rb +16 -0
  95. data/watir/testUnitAddons.rb +47 -0
  96. data/watir/watir_simple.rb +475 -0
  97. data/watir/winClicker.rb +505 -0
  98. metadata +152 -0
@@ -0,0 +1,239 @@
1
+ # feature tests for Text Fields
2
+ # revision: $Revision: 1.31 $
3
+
4
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..') if $0 == __FILE__
5
+ require 'unittests/setup'
6
+
7
+ class TC_Fields < Test::Unit::TestCase
8
+ include Watir
9
+
10
+ def setup()
11
+ $ie.goto($htmlRoot + "textfields1.html")
12
+ end
13
+
14
+ def test_text_field_exists
15
+ assert($ie.text_field(:name, "text1").exists?)
16
+ assert_false($ie.text_field(:name, "missing").exists?)
17
+
18
+ assert($ie.text_field(:id, "text2").exists?)
19
+ assert_false($ie.text_field(:id, "alsomissing").exists?)
20
+
21
+ assert($ie.text_field(:beforeText , "This Text After").exists? )
22
+ assert($ie.text_field(:afterText , "This Text Before").exists? )
23
+
24
+ assert($ie.text_field(:beforeText , /after/i).exists? )
25
+ assert($ie.text_field(:afterText , /before/i).exists? )
26
+ end
27
+
28
+ def test_text_field_dragContentsTo
29
+ $ie.text_field(:name, "text1").dragContentsTo(:id, "text2")
30
+ assert_equal($ie.text_field(:name, "text1").getContents, "" )
31
+ assert_equal($ie.text_field(:id, "text2").getContents, "goodbye allHello World" )
32
+ end
33
+
34
+ def test_text_field_VerifyContents
35
+ assert($ie.text_field(:name, "text1").verify_contains("Hello World") )
36
+ assert($ie.text_field(:name, "text1").verify_contains(/Hello\sW/ ) )
37
+ assert_false($ie.text_field(:name, "text1").verify_contains("Ruby") )
38
+ assert_false($ie.text_field(:name, "text1").verify_contains(/R/) )
39
+ assert_raises(UnknownObjectException , "UnknownObjectException was supposed to be thrown" ) { $ie.text_field(:name, "NoName").verify_contains("No field to get a value of") }
40
+
41
+ assert($ie.text_field(:id, "text2").verify_contains("goodbye all") )
42
+ assert_raises(UnknownObjectException , "UnknownObjectException was supposed to be thrown" ) { $ie.text_field(:id, "noID").verify_contains("No field to get a value of") }
43
+
44
+ end
45
+
46
+ def test_text_field_enabled
47
+ assert_false($ie.text_field(:name, "disabled").enabled? )
48
+ assert($ie.text_field(:name, "text1").enabled? )
49
+ assert($ie.text_field(:id, "text2").enabled? )
50
+ end
51
+
52
+ def test_text_field_readOnly
53
+ assert_false($ie.text_field(:name, "disabled").readonly? )
54
+ assert($ie.text_field(:name, "readOnly").readonly? )
55
+ assert($ie.text_field(:id, "readOnly2").readonly? )
56
+ end
57
+
58
+ def test_text_field_getContents()
59
+ assert_raises(UnknownObjectException , "ObjectReadOnlyException was supposed to be thrown" ) { $ie.text_field(:name, "missing_field").append("Some Text") }
60
+ assert_equal( "Hello World" , $ie.text_field(:name, "text1").getContents )
61
+ end
62
+
63
+ def test_TextField_to_s
64
+ expected = [build_to_s_regex("type", "text"),
65
+ build_to_s_regex("id", ""),
66
+ build_to_s_regex("name", "text1"),
67
+ build_to_s_regex("value", "Hello World"),
68
+ build_to_s_regex("disabled", "false"),
69
+ build_to_s_regex("length", "20"),
70
+ build_to_s_regex("max length", "2147483647"),
71
+ build_to_s_regex("read only", "false")]
72
+ items = $ie.text_field(:index, 1).to_s.split(/\n/)
73
+ expected.each_with_index{|regex, x| assert(regex =~ items[x]) }
74
+ expected[1] = build_to_s_regex("id", "text2")
75
+ expected[2] = build_to_s_regex("name", "")
76
+ expected[3] = build_to_s_regex("value", "goodbye all")
77
+ items = $ie.text_field(:index, 2).to_s.split(/\n/)
78
+ expected.each_with_index{|regex, x| assert(regex =~ items[x]) }
79
+ assert_raises(UnknownObjectException , "UnknownObjectException was supposed to be thrown" ) { $ie.text_field(:index, 999 ).to_s}
80
+ end
81
+
82
+ def build_to_s_regex(lhs, rhs)
83
+ Regexp.new("^#{lhs}: +#{rhs}$")
84
+ end
85
+
86
+ def test_text_field_Append
87
+ assert_raises(ObjectReadOnlyException , "ObjectReadOnlyException was supposed to be thrown" ) { $ie.text_field(:id, "readOnly2").append("Some Text") }
88
+ assert_raises(ObjectDisabledException , "ObjectDisabledException was supposed to be thrown" ) { $ie.text_field(:name, "disabled").append("Some Text") }
89
+ assert_raises(UnknownObjectException , "UnknownObjectException was supposed to be thrown" ) { $ie.text_field(:name, "missing_field").append("Some Text") }
90
+
91
+ $ie.text_field(:name, "text1").append(" Some Text")
92
+ assert_equal( "Hello World Some Text" , $ie.text_field(:name, "text1").getContents )
93
+
94
+ # may need this to see that it really happened
95
+ #puts "press return to continue"
96
+ #gets
97
+
98
+ end
99
+
100
+
101
+ def test_text_field_Clear
102
+ assert_raises(ObjectReadOnlyException , "ObjectReadOnlyException was supposed to be thrown" ) { $ie.text_field(:id, "readOnly2").append("Some Text") }
103
+ assert_raises(ObjectDisabledException , "ObjectReadOnlyException was supposed to be thrown" ) { $ie.text_field(:name, "disabled").append("Some Text") }
104
+ assert_raises(UnknownObjectException , "ObjectReadOnlyException was supposed to be thrown" ) { $ie.text_field(:name, "missing_field").append("Some Text") }
105
+
106
+ $ie.text_field(:name, "text1").clear()
107
+ assert_equal( "" , $ie.text_field(:name, "text1").getContents )
108
+
109
+ # may need this to see that it really happened
110
+ #puts "press return to continue"
111
+ #gets
112
+
113
+ end
114
+
115
+ def test_text_field_Set
116
+ assert_raises(ObjectReadOnlyException , "ObjectReadOnlyException was supposed to be thrown" ) { $ie.text_field(:id, "readOnly2").append("Some Text") }
117
+ assert_raises(ObjectDisabledException , "ObjectReadOnlyException was supposed to be thrown" ) { $ie.text_field(:name, "disabled").append("Some Text") }
118
+ assert_raises(UnknownObjectException , "ObjectReadOnlyException was supposed to be thrown" ) { $ie.text_field(:name, "missing_field").append("Some Text") }
119
+
120
+ $ie.text_field(:name, "text1").set("watir IE Controller")
121
+ assert_equal( "watir IE Controller" , $ie.text_field(:name, "text1").getContents )
122
+
123
+ # may need this to see that it really happened
124
+ #puts "press return to continue"
125
+ #gets
126
+ end
127
+
128
+ def test_text_field_properties
129
+
130
+ assert_raises(UnknownObjectException , "UnknownObjectException was supposed to be thrown" ) { $ie.text_field(:index, 199).value}
131
+ assert_raises(UnknownObjectException , "UnknownObjectException was supposed to be thrown" ) { $ie.text_field(:index, 199).name }
132
+ assert_raises(UnknownObjectException , "UnknownObjectException was supposed to be thrown" ) { $ie.text_field(:index, 199).id }
133
+ assert_raises(UnknownObjectException , "UnknownObjectException was supposed to be thrown" ) { $ie.text_field(:index, 199).disabled }
134
+ assert_raises(UnknownObjectException , "UnknownObjectException was supposed to be thrown" ) { $ie.text_field(:index, 199).type }
135
+
136
+ assert_equal( "Hello World" , $ie.text_field(:index, 1).value )
137
+ assert_equal( "text" , $ie.text_field(:index, 1).type)
138
+ assert_equal( "text1" , $ie.text_field(:index, 1).name )
139
+ assert_equal( "" , $ie.text_field(:index, 1).id )
140
+ assert_equal( false , $ie.text_field(:index, 1).disabled )
141
+
142
+ assert_equal( "" , $ie.text_field(:index, 2).name )
143
+ assert_equal( "text2" , $ie.text_field(:index, 2).id )
144
+
145
+ assert( $ie.text_field(:index, 3).disabled )
146
+
147
+ assert_equal( "This used to test :afterText" , $ie.text_field(:name, "aftertest" ).title )
148
+ assert_equal( "" , $ie.text_field(:index, 1 ).title )
149
+
150
+
151
+ end
152
+
153
+ def test_text_field_iterators
154
+
155
+ assert_equal( 12 , $ie.text_fields.length )
156
+
157
+ # watir is 1 based, so this is the first text field
158
+ assert_equal( "Hello World" , $ie.text_fields[1].value )
159
+ assert_equal( "text1" , $ie.text_fields[1].name )
160
+
161
+ assert_equal( "password" , $ie.text_fields[ $ie.text_fields.length ].type)
162
+
163
+
164
+ index = 1
165
+ $ie.text_fields.each do |t|
166
+ assert_equal( $ie.text_field(:index, index).value, t.value )
167
+ assert_equal( $ie.text_field(:index, index).id, t.id )
168
+ assert_equal( $ie.text_field(:index, index).name, t.name )
169
+ index +=1
170
+ end
171
+ assert_equal( index-1, $ie.text_fields.length)
172
+
173
+ end
174
+
175
+ def test_JS_Events
176
+ $ie.text_field(:name , 'events_tester').set('p')
177
+
178
+ # the following line has an extra keypress at the begining, as we mimic the delete key being pressed
179
+ assert_equal( "keypresskeydownkeypresskeyup" , $ie.text_field(:name , 'events_text').value.gsub("\r\n" , "") )
180
+ $ie.button(:value , "Clear Events Box").click
181
+ $ie.text_field(:name , 'events_tester').set('ab')
182
+
183
+ # the following line has an extra keypress at the begining, as we mimic the delete key being pressed
184
+ assert_equal( "keypresskeydownkeypresskeyupkeydownkeypresskeyup" , $ie.text_field(:name , 'events_text').value.gsub("\r\n" , "") )
185
+
186
+ end
187
+
188
+ def test_password
189
+
190
+ $ie.text_field(:name , "password1").set("secret")
191
+ assert( 'secret' , $ie.text_field(:name , "password1").value )
192
+
193
+ $ie.text_field(:id , "password1").set("top_secret")
194
+ assert( 'top_secret' , $ie.text_field(:id, "password1").value )
195
+ end
196
+
197
+ def test_labels_iterator
198
+
199
+ assert_equal(3, $ie.labels.length)
200
+ assert_equal('Label For this Field' , $ie.labels[1].innerText.strip )
201
+ assert_equal('Password With ID ( the text here is a label for it )' , $ie.labels[3].innerText )
202
+
203
+ count=0
204
+ $ie.labels.each do |l|
205
+ count +=1
206
+ end
207
+ assert_equal(count, $ie.labels.length)
208
+
209
+
210
+ end
211
+
212
+ def test_label_properties
213
+ assert_raises(UnknownObjectException ) { $ie.label(:index,20).innerText }
214
+ assert_raises(UnknownObjectException ) { $ie.label(:index,20).for }
215
+ assert_raises(UnknownObjectException ) { $ie.label(:index,20).name }
216
+ assert_raises(UnknownObjectException ) { $ie.label(:index,20).type }
217
+ assert_raises(UnknownObjectException ) { $ie.label(:index,20).id }
218
+
219
+ assert_false( $ie.label(:index,10).exists? )
220
+ assert_false( $ie.label(:id,'missing').exists? )
221
+ assert( $ie.label(:index,1).exists? )
222
+
223
+
224
+ assert_equal( "" , $ie.label(:index,1).id )
225
+ assert_false( $ie.label(:index,1).disabled )
226
+ assert( $ie.label(:index,1).enabled?)
227
+
228
+
229
+ assert_equal( "label2" , $ie.label(:index,2).id )
230
+ assert_equal( "Label" , $ie.label(:index,2).type )
231
+
232
+ assert_equal( "Password With ID ( the text here is a label for it )" , $ie.label(:index,3).innerText)
233
+ assert_equal( "password1" , $ie.label(:index,3).for)
234
+ end
235
+
236
+
237
+
238
+
239
+ end
@@ -0,0 +1,3744 @@
1
+ =begin
2
+ license
3
+ ---------------------------------------------------------------------------
4
+ Copyright (c) 2004-2005, Paul Rogers and Bret Pettichord
5
+ All rights reserved.
6
+
7
+ Redistribution and use in source and binary forms, with or without
8
+ modification, are permitted provided that the following conditions are met:
9
+
10
+ 1. Redistributions of source code must retain the above copyright notice,
11
+ this list of conditions and the following disclaimer.
12
+
13
+ 2. Redistributions in binary form must reproduce the above copyright
14
+ notice, this list of conditions and the following disclaimer in the
15
+ documentation and/or other materials provided with the distribution.
16
+
17
+ 3. Neither the names Paul Rogers, Bret Pettichord nor the names of contributors to
18
+ this software may be used to endorse or promote products derived from this
19
+ software without specific prior written permission.
20
+
21
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
22
+ IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
25
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
28
+ OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29
+ WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
30
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
31
+ ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
+ --------------------------------------------------------------------------
33
+ (based on BSD Open Source License)
34
+ =end
35
+
36
+ # This is Watir, Web Application Testing In Ruby
37
+ # Home page is http://wtr.rubyforge.org
38
+ #
39
+ # Version "$Revision: 1.211.2.2 $"
40
+ #
41
+ # Typical usage:
42
+ # # include the controller
43
+ # require "watir"
44
+ # # go to the page you want to test
45
+ # ie = Watir::IE.start("http://myserver/mypage")
46
+ # # enter "Paul" into an input field named "username"
47
+ # ie.text_field(:name, "username").set("Paul")
48
+ # # enter "Ruby Co" into input field with id "company_ID"
49
+ # ie.text_field(:id ,"company_ID").set("Ruby Co")
50
+ # # click button that has a caption of "Cancel"
51
+ # ie.button(:value, "Cancel").click
52
+ #
53
+ # The ways that are available to identify an html object depend upon the object type, but include
54
+ # :id used for an object that has an ID attribute -- this is the best way!
55
+ # :name used for an object that has a name attribute.
56
+ # :value value of text fields, captions of buttons
57
+ # :index finds the nth object of the specified type - eg button(:index , 2) finds the second button. This is 1 based. <br>
58
+ # :beforeText finds the object immeditaley before the specified text. Doesnt work if the text is in a table cell
59
+ # :afterText finds the object immeditaley after the specified text. Doesnt work if the text is in a table cell
60
+ #
61
+
62
+
63
+ # These 2 web sites provide info on Internet Explorer and on the DOM as implemented by Internet Explorer
64
+ # http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/webbrowser/webbrowser.asp
65
+ # http://msdn.microsoft.com/library/default.asp?url=/workshop/browser/overview/overview.asp
66
+
67
+ # command line options:
68
+ #
69
+ # -b (background) Run Internet Explorer invisible
70
+ # -f (fast) Run tests fast
71
+ # -x (spinner) Add a spinner that displays when pages are waiting to be loaded.
72
+
73
+ require 'win32ole'
74
+ require 'logger'
75
+ require 'watir/winClicker'
76
+ require 'watir/exceptions'
77
+
78
+ class String
79
+ def matches (x)
80
+ return self == x
81
+ end
82
+ end
83
+
84
+ class Regexp
85
+ def matches (x)
86
+ return self.match(x)
87
+ end
88
+ end
89
+
90
+ # ARGV needs to be deleted to enable the Test::Unit functionality that grabs
91
+ # the remaining ARGV as a filter on what tests to run.
92
+ # Note: this means that watir must be require'd BEFORE test/unit.
93
+ def command_line_flag(switch)
94
+ setting = ARGV.include?(switch)
95
+ ARGV.delete(switch)
96
+ return setting
97
+ end
98
+
99
+ # Constant to make Internet explorer minimisez. -b stands for background
100
+ $HIDE_IE = command_line_flag('-b')
101
+
102
+ # Constant to enable/disable the spinner
103
+ $ENABLE_SPINNER = command_line_flag('-x')
104
+
105
+ # Constant to set fast speed
106
+ $FAST_SPEED = command_line_flag('-f')
107
+
108
+ # Eat the -s command line switch (deprecated)
109
+ command_line_flag('-s')
110
+
111
+ module Watir
112
+ include Watir::Exception
113
+
114
+ # BUG: this won't work right until the null objects are pulled out
115
+ def exists?
116
+ begin
117
+ yield
118
+ true
119
+ rescue
120
+ false
121
+ end
122
+ end
123
+
124
+ class WatirLogger < Logger
125
+ def initialize( filName , logsToKeep, maxLogSize )
126
+ super( filName , logsToKeep, maxLogSize )
127
+ self.level = Logger::DEBUG
128
+ self.datetime_format = "%d-%b-%Y %H:%M:%S"
129
+ self.debug("Watir starting")
130
+ end
131
+ end
132
+
133
+ class DefaultLogger < Logger
134
+ def initialize()
135
+ super(STDERR)
136
+ self.level = Logger::WARN
137
+ self.datetime_format = "%d-%b-%Y %H:%M:%S"
138
+ self.info "Log started"
139
+ end
140
+ end
141
+
142
+ # This class displays the spinner object that appears in the console when a page is being loaded
143
+ class Spinner
144
+
145
+ def initialize(enabled = true)
146
+ @s = [ "\b/" , "\b|" , "\b\\" , "\b-"]
147
+ @i=0
148
+ @enabled = enabled
149
+ end
150
+
151
+ # reverse the direction of spinning
152
+ def reverse
153
+ @s.reverse!
154
+ end
155
+
156
+ def spin
157
+ print self.next if @enabled
158
+ end
159
+
160
+ # get the next character to display
161
+ def next
162
+ @i=@i+1
163
+ @i=0 if @i>@s.length-1
164
+ return @s[@i]
165
+ end
166
+ end
167
+
168
+ # This module contains the factory methods that are used to access most html objects
169
+ #
170
+ # For example, to access a button on a web page that has the following html
171
+ # <input type = button name= 'b1' value='Click Me' onClick='javascript:doSomething()'>
172
+ #
173
+ # the following watir code could be used
174
+ #
175
+ # ie.button(:name, 'b1').click
176
+ #
177
+ # or
178
+ #
179
+ # ie.button(:value, 'Click Me').to_s
180
+ #
181
+ # there are many methods available to the Button object
182
+ #
183
+ # Is includable for classes that have @ieController, document and document.body
184
+ module SupportsSubElements
185
+ include Watir::Exception
186
+
187
+ # this method returns the real Internet Explorer object, allowing access to objects, properties and methods that Watir doesnot support
188
+ def ie
189
+ return @ieController
190
+ end
191
+
192
+ # write the specified string to the log, assuming a logger has been setup using IE#set_logger
193
+ def log ( what )
194
+ @ieController.logger.debug( what ) if @logger
195
+ end
196
+
197
+ # this method causes Watir to wait until Internet Explorer has finished the action
198
+ def wait( noSleep = false )
199
+ @ieController.wait( noSleep )
200
+ end
201
+
202
+ def process_default(default_attribute, how, what)
203
+ if what == nil
204
+ what = how
205
+ how = default_attribute
206
+ end
207
+ return how, what
208
+ end
209
+ private :process_default
210
+
211
+ # this method is the main way of accessing a frame
212
+ # * how - how the frame is accessed. This can also just be the name of the frame
213
+ # * what - what we want to access.
214
+ #
215
+ # Typical usage:
216
+ #
217
+ # ie.frame(:index, 1)
218
+ # ie.frame(:name , 'main_frame')
219
+ # ie.frame('main_frame') # in this case, just a name is supplied
220
+ def frame(how, what=nil)
221
+ how, what = process_default :name, how, what
222
+ return Frame.new(self, how, what)
223
+ end
224
+
225
+ # this method is used to access a form.
226
+ # available ways of accessing it are, :index , :name, :id, :method, :action
227
+ # * how - symbol - WHat mecahnism we use to find the form, one of the above. NOTE if what is not supplied this parameter is the NAME of the form
228
+ # * what - String - the text associated with the symbol
229
+ def form(how, what=nil)
230
+ how, what = process_default :name, how, what
231
+ return Form.new(self, how, what)
232
+ end
233
+
234
+ # This method is used to get a table from the page.
235
+ # :index (1 based counting)and :id are supported.
236
+ # NOTE :name is not supported, as the table tag does not have a name attribute. It is not part of the DOM.
237
+ # :index can be used when there are multiple tables on a page.
238
+ # The first form can be accessed with :index 1, the second :index 2, etc.
239
+ # * how - symbol - the way we look for the table. Supported values are
240
+ # - :id
241
+ # - :index
242
+ # * what - string the thing we are looking for, ex. id or index of the object we are looking for
243
+ def table( how, what )
244
+ return Table.new( self , how, what)
245
+ end
246
+
247
+ # this is the main method for accessing the tables iterator. It returns a Tables object
248
+ #
249
+ # Typical usage:
250
+ #
251
+ # ie.tables.each { |t| puts t.to_s } # iterate through all the tables on the page
252
+ # ie.tables[1].to_s # goto the first table on the page
253
+ # ie.tables.length # show how many tables are on the page. Tables that are nested will be included in this
254
+ def tables()
255
+ return Tables.new(self)
256
+ end
257
+
258
+ # this method accesses a table cell.
259
+ # how - symbol - how we access the cell, :id is supported
260
+ #
261
+ # returns a TableCell Object
262
+ def cell( how, what )
263
+ return TableCell.new( self, how, what)
264
+ end
265
+
266
+ # this method accesses a table row.
267
+ # how - symbol - how we access the row, :id is supported
268
+ #
269
+ # returns a TableRow object
270
+ def row( how, what )
271
+ return TableRow.new( self, how, what)
272
+ end
273
+
274
+ # This is the main method for accessing a button. Often declared as an <input type = submit> tag.
275
+ # * how - symbol - how we access the button
276
+ # * what - string, int or re , what we are looking for,
277
+ # Returns a Button object.
278
+ #
279
+ # Valid values for 'how' are
280
+ #
281
+ # :index - find the item using the index in the container ( a container can be a document, a TableCell, a Span, a Div or a P
282
+ # index is 1 based
283
+ # :name - find the item using the name attribute
284
+ # :id - find the item using the id attribute
285
+ # :value - find the item using the value attribute ( in this case the button caption)
286
+ # :caption - same as value
287
+ # :beforeText - finds the item immediately before the specified text
288
+ # :afterText - finds the item immediately after the specified text
289
+ #
290
+ # Typical Usage
291
+ #
292
+ # ie.button(:id, 'b_1') # access the button with an ID of b_1
293
+ # ie.button(:name, 'verify_data') # access the button with a name of verify_data
294
+ # ie.button(:value, 'Login') # access the button with a value (the text displayed on the button) of Login
295
+ # ie.button(:caption, 'Login') # same as above
296
+ # ie.button(:value, /Log/) # access the button that has text matching /Log/
297
+ # ie.button(:index, 2) # access the second button on the page ( 1 based, so the first button is accessed with :index,1)
298
+ #
299
+ # if only a single parameter is supplied, then :value is used
300
+ #
301
+ # ie.button('Click Me') # access the button with a value of Click Me
302
+ def button(how, what=nil)
303
+ how, what = process_default :value, how, what
304
+ return Button.new(self, how, what)
305
+ end
306
+
307
+ # this is the main method for accessing the buttons iterator. It returns a Buttons object
308
+ #
309
+ # Typical usage:
310
+ #
311
+ # ie.buttons.each { |b| puts b.to_s } # iterate through all the buttons on the page
312
+ # ie.buttons[1].to_s # goto the first button on the page
313
+ # ie.buttons.length # show how many buttons are on the page.
314
+ def buttons()
315
+ return Buttons.new(self)
316
+ end
317
+
318
+
319
+ # This is the main method for accessing a file field. Usually an <input type = file> HTML tag.
320
+ # * how - symbol - how we access the field , :index, :id, :name etc
321
+ # * what - string, int or re , what we are looking for,
322
+ #
323
+ # returns a FileField object
324
+ #
325
+ # Typical Usage
326
+ #
327
+ # ie.file_field(:id, 'up_1') # access the file upload field with an ID of up_1
328
+ # ie.file_field(:name, 'upload') # access the file upload field with a name of upload
329
+ # ie.file_field(:index, 2) # access the second file upload on the page ( 1 based, so the first field is accessed with :index,1)
330
+ #
331
+ def file_field(how , what)
332
+ return FileField.new(self , how, what)
333
+ end
334
+
335
+ # this is the main method for accessing the file_fields iterator. It returns a FileFields object
336
+ #
337
+ # Typical usage:
338
+ #
339
+ # ie.file_fields.each { |f| puts f.to_s } # iterate through all the file fields on the page
340
+ # ie.file_fields[1].to_s # goto the first file field on the page
341
+ # ie.file_fields.length # show how many file fields are on the page.
342
+ def file_fields()
343
+ return FileFields.new(self)
344
+ end
345
+
346
+ # This is the main method for accessing a text field. Usually an <input type = text> HTML tag. or a text area - a <textarea> tag
347
+ # * how - symbol - how we access the field , :index, :id, :name etc
348
+ # * what - string, int or re , what we are looking for,
349
+ #
350
+ # returns a TextField object
351
+ #
352
+ # Valid values for 'how' are
353
+ #
354
+ # :index - find the item using the index in the container ( a container can be a document, a TableCell, a Span, a Div or a P
355
+ # index is 1 based
356
+ # :name - find the item using the name attribute
357
+ # :id - find the item using the id attribute
358
+ # :beforeText - finds the item immediately before the specified text
359
+ # :afterText - finds the item immediately after the specified text
360
+ #
361
+ # Typical Usage
362
+ #
363
+ # ie.text_field(:id, 'user_name') # access the text field with an ID of user_name
364
+ # ie.text_field(:name, 'address') # access the text field with a name of address
365
+ # ie.text_field(:index, 2) # access the second text field on the page ( 1 based, so the first field is accessed with :index,1)
366
+ def text_field(how , what=nil)
367
+ return TextField.new(self, how, what)
368
+ end
369
+
370
+ # this is the method for accessing the text_fields iterator. It returns a Text_Fields object
371
+ #
372
+ # Typical usage:
373
+ #
374
+ # ie.text_fields.each { |t| puts t.to_s } # iterate through all the text fields on the page
375
+ # ie.text_fields[1].to_s # goto the first text field on the page
376
+ # ie.text_fields.length # show how many text field are on the page.
377
+ def text_fields
378
+ return TextFields.new(self)
379
+ end
380
+
381
+ # This is the main method for accessing a hidden field. Usually an <input type = hidden> HTML tag
382
+ # * how - symbol - how we access the field , :index, :id, :name etc
383
+ # * what - string, int or re , what we are looking for,
384
+ #
385
+ # returns a Hidden object
386
+ #
387
+ # Typical usage
388
+ #
389
+ # ie.hidden(:id, 'session_id') # access the hidden field with an ID of session_id
390
+ # ie.hidden(:name, 'temp_value') # access the hidden field with a name of temp_value
391
+ # ie.hidden(:index, 2) # access the second hidden field on the page ( 1 based, so the first field is accessed with :index,1)
392
+ def hidden( how, what )
393
+ return Hidden.new(self, how, what)
394
+ end
395
+
396
+ # this is the method for accessing the hiddens iterator. It returns a Hiddens object
397
+ #
398
+ # Typical usage:
399
+ #
400
+ # ie.hiddens.each { |t| puts t.to_s } # iterate through all the hidden fields on the page
401
+ # ie.hiddens[1].to_s # goto the first hidden field on the page
402
+ # ie.hiddens.length # show how many hidden fields are on the page.
403
+ def hiddens
404
+ return Hiddens.new(self)
405
+ end
406
+
407
+ # This is the main method for accessing a selection list. Usually a <select> HTML tag.
408
+ # * how - symbol - how we access the selection list , :index, :id, :name etc
409
+ # * what - string, int or re , what we are looking for,
410
+ #
411
+ # returns a SelectList object
412
+ #
413
+ # Valid values for 'how' are
414
+ #
415
+ # :index - find the item using the index in the container ( a container can be a document, a TableCell, a Span, a Div or a P
416
+ # index is 1 based
417
+ # :name - find the item using the name attribute
418
+ # :id - find the item using the id attribute
419
+ # :beforeText - finds the item immediately before the specified text
420
+ # :afterText - finds the item immediately after the specified text
421
+ #
422
+ # Typical usage
423
+ #
424
+ # ie.select_list(:id, 'currency') # access the select box with an id of currency
425
+ # ie.select_list(:name, 'country') # access the select box with a name of country
426
+ # ie.select_list(:name, /n_/ ) # access the first select box whose name matches n_
427
+ # ie.select_list(:index, 2) # access the second select box on the page ( 1 based, so the first field is accessed with :index,1)
428
+ def select_list(how , what=nil)
429
+ return SelectList.new(self, how, what)
430
+ end
431
+
432
+ # this is the method for accessing the select lists iterator. Returns a SelectLists object
433
+ #
434
+ # Typical usage:
435
+ #
436
+ # ie.select_lists.each { |s| puts s.to_s } # iterate through all the select boxes on the page
437
+ # ie.select_lists[1].to_s # goto the first select boxes on the page
438
+ # ie.select_lists.length # show how many select boxes are on the page.
439
+ def select_lists()
440
+ return SelectLists.new(self)
441
+ end
442
+
443
+ # This is the main method for accessing a check box. Usually an <input type = checkbox> HTML tag.
444
+ #
445
+ # * how - symbol - how we access the check box , :index, :id, :name etc
446
+ # * what - string, int or re , what we are looking for,
447
+ # * value - string - when there are multiple objects with different value attributes, this can be used to find the correct object
448
+ #
449
+ # returns a CheckBox object
450
+ #
451
+ # Valid values for 'how' are
452
+ #
453
+ # :index - find the item using the index in the container ( a container can be a document, a TableCell, a Span, a Div or a P
454
+ # index is 1 based
455
+ # :name - find the item using the name attribute
456
+ # :id - find the item using the id attribute
457
+ # :beforeText - finds the item immediately before the specified text
458
+ # :afterText - finds the item immediately after the specified text
459
+ #
460
+ # Typical usage
461
+ #
462
+ # ie.checkbox(:id, 'send_email') # access the check box with an id of send_mail
463
+ # ie.checkbox(:name, 'send_copy') # access the check box with a name of send_copy
464
+ # ie.checkbox(:name, /n_/ ) # access the first check box whose name matches n_
465
+ # ie.checkbox(:index, 2) # access the second check box on the page ( 1 based, so the first field is accessed with :index,1)
466
+ #
467
+ # In many instances, checkboxes on an html page have the same name, but are identified by different values. An example is shown next.
468
+ #
469
+ # <input type = checkbox name = email_frequency value = 'daily' > Daily Email
470
+ # <input type = checkbox name = email_frequency value = 'Weekly'> Weekly Email
471
+ # <input type = checkbox name = email_frequency value = 'monthly'>Monthly Email
472
+ #
473
+ # Watir can access these using the following:
474
+ #
475
+ # ie.checkbox(:id, 'day_to_send' , 'monday' ) # access the check box with an id of day_to_send and a value of monday
476
+ # ie.checkbox(:name ,'email_frequency', 'weekly') # access the check box with a name of email_frequency and a value of 'weekly'
477
+ def checkbox(how, what=nil ,value=nil)
478
+ return CheckBox.new(self, how, what, ["checkbox"], value)
479
+ end
480
+
481
+ # this is the method for accessing the check boxes iterator. Returns a CheckBoxes object
482
+ #
483
+ # Typical usage:
484
+ #
485
+ # ie.checkboxes.each { |c| puts c.to_s } # iterate through all the check boxes on the page
486
+ # ie.checkboxes[1].to_s # goto the first check box on the page
487
+ # ie.checkboxes.length # show how many check boxes are on the page.
488
+ def checkboxes
489
+ return CheckBoxes.new(self)
490
+ end
491
+
492
+ # This is the main method for accessing a radio button. Usually an <input type = radio> HTML tag.
493
+ # * how - symbol - how we access the radio button, :index, :id, :name etc
494
+ # * what - string, int or regexp , what we are looking for,
495
+ # * value - string - when there are multiple objects with different value attributes, this can be used to find the correct object
496
+ #
497
+ # returns a Radio object
498
+ #
499
+ # Valid values for 'how' are
500
+ #
501
+ # :index - find the item using the index in the container ( a container can be a document, a TableCell, a Span, a Div or a P
502
+ # index is 1 based
503
+ # :name - find the item using the name attribute
504
+ # :id - find the item using the id attribute
505
+ # :beforeText - finds the item immediately before the specified text
506
+ # :afterText - finds the item immediately after the specified text
507
+ #
508
+ # Typical usage
509
+ #
510
+ # ie.radio(:id, 'send_email') # access the radio button with an id of currency
511
+ # ie.radio(:name, 'send_copy') # access the radio button with a name of country
512
+ # ie.radio(:name, /n_/ ) # access the first radio button whose name matches n_
513
+ # ie.radio(:index, 2) # access the second radio button on the page ( 1 based, so the first field is accessed with :index,1)
514
+ #
515
+ # In many instances, radio buttons on an html page have the same name, but are identified by different values. An example is shown next.
516
+ #
517
+ # <input type = radio name = email_frequency value = 'daily' > Daily Email
518
+ # <input type = radio name = email_frequency value = 'Weekly'> Weekly Email
519
+ # <input type = radio name = email_frequency value = 'monthly'>Monthly Email
520
+ #
521
+ # Watir can access these using the following:
522
+ #
523
+ # ie.radio(:id, 'day_to_send' , 'monday' ) # access the radio button with an id of day_to_send and a value of monday
524
+ # ie.radio(:name ,'email_frequency', 'weekly') # access the radio button with a name of email_frequency and a value of 'weekly'
525
+ #
526
+ def radio(how, what=nil, value=nil)
527
+ return Radio.new(self, how, what, ["radio"], value)
528
+ end
529
+
530
+ # This is the method for accessing the radio buttons iterator. Returns a Radios object
531
+ #
532
+ # Typical usage:
533
+ #
534
+ # ie.radios.each { |r| puts r.to_s } # iterate through all the radio buttons on the page
535
+ # ie.radios[1].to_s # goto the first radio button on the page
536
+ # ie.radios.length # show how many radio buttons are on the page.
537
+ #
538
+ def radios
539
+ return Radios.new(self)
540
+ end
541
+
542
+ # This is the main method for accessing a link.
543
+ # * how - symbol - how we access the link, :index, :id, :name , :beforetext, :afterText, :title , :text , :url
544
+ # * what - string, int or re , what we are looking for
545
+ #
546
+ # returns a Link object
547
+ #
548
+ # Valid values for 'how' are
549
+ #
550
+ # :index - find the item using the index in the container ( a container can be a document, a TableCell, a Span, a Div or a P
551
+ # index is 1 based
552
+ # :name - find the item using the name attribute
553
+ # :id - find the item using the id attribute
554
+ # :beforeText - finds the item immediately before the specified text
555
+ # :afterText - finds the item immediately after the specified text
556
+ # :url - finds the link based on the url. This must be the full path to the link, so is best used with a regular expression
557
+ # :text - finds a link using the innerText of the link, ie the Text that is displayed to the user
558
+ # :title - finds the item using the tool tip text
559
+ #
560
+ # Typical Usage
561
+ #
562
+ # ie.link(:url, /login/) # access the first link whose url matches login. We can use a string in place of the regular expression
563
+ # # but the complete path must be used, ie.link(:url, 'http://myserver.com/my_path/login.asp')
564
+ # ie.link(:index,2) # access the second link on the page
565
+ # ie.link(:title , "Picture") # access a link using the tool tip
566
+ # ie.link(:text, 'Click Me') # access the link that has Click Me as its text
567
+ # ie.link(:afterText, 'Click->') # access the link that immediately follows the text Click->
568
+ #
569
+ def link(how, what=nil)
570
+ return Link.new(self, how, what)
571
+ end
572
+
573
+ # This is the main method for accessing the links collection. Returns a Links object
574
+ #
575
+ # Typical usage:
576
+ #
577
+ # ie.links.each { |l| puts l.to_s } # iterate through all the links on the page
578
+ # ie.links[1].to_s # goto the first link on the page
579
+ # ie.links.length # show how many links are on the page.
580
+ #
581
+ def links
582
+ return Links.new(self)
583
+ end
584
+
585
+ # This is the main method for accessing images - normally an <img src="image.gif"> HTML tag.
586
+ # * how - symbol - how we access the image, :index, :id, :name , :src or :alt are supported
587
+ # * what - string, int or re , what we are looking for,
588
+ #
589
+ # returns an Image object
590
+ #
591
+ # Valid values for 'how' are
592
+ #
593
+ # :index - find the item using the index in the container ( a container can be a document, a TableCell, a Span, a Div or a P
594
+ # index is 1 based
595
+ # :name - find the item using the name attribute
596
+ # :id - find the item using the id attribute
597
+ # :alt - finds the item using the tool tip text
598
+ # :src - finds the item using the src tag. This must be the fully qualified name, so is best used with a regular expression
599
+ #
600
+ # Typical Usage
601
+ #
602
+ # ie.image(:src, /myPic/) # access the first image that matches myPic. We can use a string in place of the regular expression
603
+ # # but the complete path must be used, ie.image(:src, 'http://myserver.com/my_path/my_image.jpg')
604
+ # ie.image(:index,2) # access the second image on the page
605
+ # ie.image(:alt , "A Picture") # access an image using the alt text
606
+ #
607
+ def image( how , what=nil)
608
+ return Image.new(self, how, what)
609
+ end
610
+
611
+ # This is the main method for accessing the images collection. Returns an Images object
612
+ #
613
+ # Typical usage:
614
+ #
615
+ # ie.images.each { |i| puts i.to_s } # iterate through all the images on the page
616
+ # ie.images[1].to_s # goto the first image on the page
617
+ # ie.images.length # show how many images are on the page.
618
+ #
619
+ def images
620
+ return Images.new(self)
621
+ end
622
+
623
+ # This is the main method for accessing JavaScript popups.
624
+ # returns a PopUp object
625
+ def popup
626
+ return PopUp.new(self )
627
+ end
628
+
629
+ # This is the main method for accessing divs. http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/div.asp?frame=true
630
+ # * how - symbol - how we access the div, :index, :id, :title
631
+ # * what - string, integer or re , what we are looking for,
632
+ #
633
+ # returns an Div object
634
+ #
635
+ # Typical Usage
636
+ #
637
+ # ie.div(:id, /list/) # access the first div that matches list.
638
+ # ie.div(:index,2) # access the second div on the page
639
+ # 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
640
+ #
641
+ def div(how, what)
642
+ return Div.new(self, how, what)
643
+ end
644
+
645
+ # this is the main method for accessing the divs iterator. Returns a Divs object
646
+ #
647
+ # Typical usage:
648
+ #
649
+ # ie.divs.each { |d| puts d.to_s } # iterate through all the divs on the page
650
+ # ie.divs[1].to_s # goto the first div on the page
651
+ # ie.divs.length # show how many divs are on the page.
652
+ #
653
+ def divs
654
+ return Divs.new(self)
655
+ end
656
+
657
+ # This is the main method for accessing span tags - http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/span.asp?frame=true
658
+ # * how - symbol - how we access the span, :index, :id, :name
659
+ # * what - string, integer or re , what we are looking for,
660
+ #
661
+ # returns a Span object
662
+ #
663
+ # Typical Usage
664
+ #
665
+ # ie.span(:id, /list/) # access the first span that matches list.
666
+ # ie.span(:index,2) # access the second span on the page
667
+ # 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
668
+ #
669
+ def span(how , what)
670
+ return Span.new(self, how, what)
671
+ end
672
+
673
+ # this is the main method for accessing the spans iterator.
674
+ #
675
+ # Returns a Spans object
676
+ #
677
+ # Typical usage:
678
+ #
679
+ # ie.spans.each { |s| puts s.to_s } # iterate through all the spans on the page
680
+ # ie.spans[1].to_s # goto the first span on the page
681
+ # ie.spans.length # show how many spans are on the page.
682
+ #
683
+ def spans
684
+ return Spans.new(self)
685
+ end
686
+
687
+ # This is the main method for accessing p tags - http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/p.asp?frame=true
688
+ # * how - symbol - how we access the p, :index, :id, :name
689
+ # * what - string, integer or re , what we are looking for,
690
+ #
691
+ # returns a P object
692
+ #
693
+ # Typical Usage
694
+ #
695
+ # ie.p(:id, /list/) # access the first p tag that matches list.
696
+ # ie.p(:index,2) # access the second p tag on the page
697
+ # 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
698
+ #
699
+ def p(how, what)
700
+ return P.new(self , how , what)
701
+ end
702
+
703
+ # this is the main method for accessing the ps iterator.
704
+ #
705
+ # Returns a Ps object
706
+ #
707
+ # Typical usage:
708
+ #
709
+ # ie.ps.each { |p| puts p.to_s } # iterate through all the p tags on the page
710
+ # ie.ps[1].to_s # goto the first p tag on the page
711
+ # ie.ps.length # show how many p tags are on the page.
712
+ #
713
+ def ps
714
+ return Ps.new(self)
715
+ end
716
+
717
+ # This is the main method for accessing labels. http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/label.asp?frame=true
718
+ # * how - symbol - how we access the label, :index, :id, :for
719
+ # * what - string, integer or re , what we are looking for,
720
+ #
721
+ # returns a Label object
722
+ #
723
+ # Typical Usage
724
+ #
725
+ # ie.label(:id, /list/) # access the first span that matches list.
726
+ # ie.label(:index,2) # access the second label on the page
727
+ # ie.label(:for, "text_1") # access a the label that is associated with the object that has an id of text_1
728
+ #
729
+ def label(how, what)
730
+ return Label.new(self, how, what)
731
+ end
732
+
733
+ # this is the main method for accessing the labels iterator. It returns a Labels object
734
+ #
735
+ # Returns a Labels object
736
+ #
737
+ # Typical usage:
738
+ #
739
+ # ie.labels.each { |l| puts l.to_s } # iterate through all the labels on the page
740
+ # ie.labels[1].to_s # goto the first label on the page
741
+ # ie.labels.length # show how many labels are on the page.
742
+ #
743
+ def labels()
744
+ return Labels.new(self)
745
+ end
746
+
747
+ #--
748
+ #
749
+ # Searching for Page Elements
750
+ # Not for external consumption
751
+ #
752
+ #++
753
+ def getContainerContents()
754
+ return document.body.all
755
+ end
756
+ private :getContainerContents
757
+
758
+ # this method is used internally by Watir and should not be used externally.
759
+ # It cannot be marked as private because of the way mixins and inheritance work in watir.
760
+ # BUG: This looks wrong: Not everything that includes SupportsSubElements has a document.body!
761
+ def getContainer()
762
+ return document.body
763
+ end
764
+
765
+ # This is the main method for finding objects on a web page.
766
+ #
767
+ # 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
768
+ #
769
+ # * how - symbol - the way we look for the object. Supported values are
770
+ # - :name
771
+ # - :id
772
+ # - :index
773
+ # - :value etc
774
+ # * what - string that we are looking for, ex. the name, or id tag attribute or index of the object we are looking for.
775
+ # * types - what object types we will look at. Only used when index is specified as the how.
776
+ # * value - used for objects that have one name, but many values. ex. radio lists and checkboxes
777
+ def getObject(how, what, types, value=nil)
778
+ container = getContainerContents # XXX actually this returns a collection object (not a container)
779
+ how = :value if how == :caption
780
+ log "getting object - how is #{how} what is #{what} types = #{types} value = #{value}"
781
+
782
+ o = nil
783
+ if how == :index
784
+ index = what.to_i
785
+ log" getting object #{types.to_s} at index( #{index}"
786
+
787
+ objectIndex = 1
788
+ container.each do | thisObject |
789
+ begin
790
+ this_type = thisObject.invoke("type")
791
+ rescue
792
+ this_type = nil
793
+ end
794
+ if types.include?(this_type)
795
+ if objectIndex == index
796
+ o = thisObject
797
+ break
798
+ end
799
+ objectIndex += 1
800
+ end
801
+ end
802
+ return o
803
+
804
+ else
805
+ container.each do |object|
806
+ next unless o == nil
807
+
808
+ begin
809
+ case how
810
+ when :id
811
+ attribute = object.invoke("id")
812
+ when :name
813
+ attribute = object.invoke("name")
814
+ when :value
815
+ attribute = object.value
816
+ when :alt
817
+ attribute = object.alt
818
+ when :src
819
+ attribute = object.src
820
+ when :beforeText
821
+ attribute = object.getAdjacentText("afterEnd").strip
822
+ when :afterText
823
+ attribute = object.getAdjacentText("beforeBegin").strip
824
+ else
825
+ next
826
+ end
827
+
828
+ if what.matches(attribute) && types.include?(object.invoke("type"))
829
+ if value
830
+ log "checking value supplied #{value} ( #{value.class}) actual #{object.value} ( #{object.value.class})"
831
+ if object.value.to_s == value.to_s
832
+ o = object
833
+ end
834
+ else # no value
835
+ o = object
836
+ end
837
+ end
838
+
839
+ rescue => e
840
+ log 'IE#getObject error ' + e.to_s
841
+ end
842
+
843
+ end
844
+ end
845
+
846
+ return o
847
+ end
848
+
849
+ # This method is used iternally by Watir and should not be used externally. It cannot be marked as private because of the way mixins and inheritance work in watir
850
+ #
851
+ # this method finds the specified image
852
+ # * how - symbol - how to look
853
+ # * what - string or regexp - what to look ofr
854
+ def getImage( how, what )
855
+
856
+ doc = document
857
+ count = 1
858
+ images = doc.all.tags("IMG")
859
+ o=nil
860
+ images.each do |img|
861
+
862
+ #puts "Image on page: src = #{img.src}"
863
+
864
+ next unless o == nil
865
+ if how == :index
866
+ o = img if count == what.to_i
867
+ else
868
+ case how
869
+
870
+ when :src
871
+ attribute = img.src
872
+ when :name
873
+ attribute = img.name
874
+ when :id
875
+ attribute = img.invoke("id")
876
+ when :alt
877
+ attribute = img.invoke("alt")
878
+ else
879
+ next
880
+ end
881
+
882
+ o = img if what.matches(attribute)
883
+ end
884
+ count +=1
885
+ end # do
886
+ return o
887
+
888
+ end
889
+
890
+ # This method is used iternally by Watir and should not be used externally. It cannot be marked as private because of the way mixins and inheritance work in watir
891
+ #
892
+ # This method gets a link from the document. This is a hyperlink, generally declared in the <a href="http://testsite">test site</a> HTML tag.
893
+ # * how - symbol - how we get the link Supported types are:
894
+ # :index - the link at position x , 1 based
895
+ # :url - get the link that has a url that matches. A regular expression match is performed
896
+ # :text - get link based on the supplied text. uses either a string or regular expression match
897
+ # * what - depends on how - an integer for index, a string or regexp for url and text
898
+ def getLink( how, what )
899
+ links = document.all.tags("A")
900
+
901
+ # Guard ensures watir won't crash if somehow the list of links is nil
902
+ if (links == nil)
903
+ raise UnknownObjectException, "Unknown Object in getLink: attempted to click a link when no links present"
904
+ end
905
+
906
+ link = nil
907
+ case how
908
+ when :index
909
+ begin
910
+ link = links[ (what-1).to_s ]
911
+ rescue
912
+ link=nil
913
+ end
914
+
915
+ when :url
916
+ links.each do |thisLink|
917
+ if what.matches(thisLink.href)
918
+ link = thisLink if link == nil
919
+ end
920
+ end
921
+
922
+ when :text
923
+ links.each do |thisLink|
924
+ if what.matches(thisLink.innerText.strip)
925
+ link = thisLink if link == nil
926
+ end
927
+ end
928
+
929
+ when :id
930
+ links.each do |thisLink|
931
+ if what.matches(thisLink.invoke("id"))
932
+ link = thisLink if link == nil
933
+ end
934
+ end
935
+ when :name
936
+ links.each do |thisLink|
937
+ if what.matches(thisLink.invoke("name"))
938
+ link = thisLink if link == nil
939
+ end
940
+ end
941
+
942
+ when :title
943
+ links.each do |thisLink|
944
+ if what.matches(thisLink.invoke("title"))
945
+ link = thisLink if link == nil
946
+ end
947
+ end
948
+
949
+ when :beforeText
950
+ links.each do |thisLink|
951
+ if what.matches(thisLink.getAdjacentText("afterEnd").strip)
952
+ link = thisLink if link == nil
953
+ end
954
+ end
955
+
956
+ when :afterText
957
+ links.each do |thisLink|
958
+ if what.matches(thisLink.getAdjacentText("beforeBegin").strip)
959
+ link = thisLink if link == nil
960
+ end
961
+ end
962
+ else
963
+ raise MissingWayOfFindingObjectException, "#{how.inspect} is an unknown way of finding a link ( #{what} )"
964
+ end
965
+
966
+ # if no link found, link will be a nil. This is OK. Actions taken on links (e.g. "click") should rescue
967
+ # the nil-related exceptions and provide useful information to the user.
968
+ return link
969
+
970
+ end
971
+
972
+ # This method is used iternally by Watir and should not be used externally. It cannot be marked as private because of the way mixins and inheritance work in watir
973
+ #
974
+ # This method gets a table row or cell
975
+ # * how - symbol - how we get the link row or cell types are:
976
+ # id
977
+ # * what - a string or regexp
978
+ def getTablePart( part , how , what )
979
+ doc = document
980
+ parts = doc.all.tags( part )
981
+ n = nil
982
+ parts.each do | p |
983
+ next unless n==nil
984
+ if what.matches( p.invoke("id") )
985
+ n = p
986
+ end
987
+ end
988
+ return n
989
+ end
990
+
991
+ # This method is used iternally by Watir and should not be used externally. It cannot be marked as private because of the way mixins and inheritance work in watir
992
+ #
993
+ # this method is used to get elements like SPAN or DIV
994
+ def getNonControlObject(part , how, what )
995
+
996
+ doc = document
997
+ parts = doc.all.tags( part )
998
+ n = nil
999
+ case how
1000
+ when :id
1001
+ attribute = "id"
1002
+ when :name
1003
+ attribute = "name"
1004
+ when :title
1005
+ attribute = "title"
1006
+ when :for # only applies to labels
1007
+ attribute = "htmlFor"
1008
+ end
1009
+
1010
+ if attribute
1011
+ parts.each do | p |
1012
+ next unless n==nil
1013
+ n = p if what.matches( p.invoke(attribute) )
1014
+ end
1015
+ elsif how == :index
1016
+ count = 1
1017
+ parts.each do | p |
1018
+ next unless n==nil
1019
+ n = p if what == count
1020
+ count +=1
1021
+ end
1022
+ else
1023
+ raise MissingWayOfFindingObjectException, "unknown way of finding a #{ part} ( {what} )"
1024
+ end
1025
+ return n
1026
+
1027
+ end
1028
+
1029
+ end
1030
+
1031
+
1032
+ # This class is the main Internet Explorer Controller
1033
+ # An instance of this must be created to access Internet Explorer.
1034
+ class IE
1035
+ include Watir::Exception
1036
+ include SupportsSubElements
1037
+
1038
+ # The revision number ( according to CVS )
1039
+ REVISION = "$Revision: 1.211.2.2 $"
1040
+
1041
+ # the Release number
1042
+ VERSION = "1.4.1"
1043
+
1044
+ # Used internally to determine when IE has finished loading a page
1045
+ READYSTATE_COMPLETE = 4
1046
+
1047
+ # The default delay when entering text on a web page.
1048
+ DEFAULT_TYPING_SPEED = 0.08
1049
+
1050
+ # The default time we wait after a page has loaded.
1051
+ DEFAULT_SLEEP_TIME = 0.1
1052
+
1053
+ # The default color for highlighting objects as they are accessed.
1054
+ DEFAULT_HIGHLIGHT_COLOR = "yellow"
1055
+
1056
+ # This is used to change the typing speed when entering text on a page.
1057
+ attr_accessor :typingspeed
1058
+
1059
+ # This is used to change how long after a page has finished loading that we wait for.
1060
+ attr_accessor :defaultSleepTime
1061
+
1062
+ # The color we want to use for the active object. This can be any valid web-friendly color.
1063
+ attr_accessor :activeObjectHighLightColor
1064
+
1065
+ # use this to switch the spinner on and off
1066
+ attr_accessor :enable_spinner
1067
+
1068
+ # use this to get the time for the last page download
1069
+ attr_reader :down_load_time
1070
+
1071
+ # When a new window is created it is stored in newWindow
1072
+ attr_accessor :newWindow
1073
+
1074
+ # Use this to gain access to the 'raw' internet explorer object.
1075
+ attr_reader :ie
1076
+
1077
+ # access to the logger object
1078
+ attr_accessor :logger
1079
+
1080
+
1081
+ # this contains the list of unique urls that have been visited
1082
+ attr_reader :url_list
1083
+
1084
+ def initialize(suppress_new_window=nil)
1085
+ unless suppress_new_window
1086
+ create_browser_window
1087
+ set_defaults
1088
+ end
1089
+ end
1090
+
1091
+ # Create a new IE Window, starting at the specified url.
1092
+ # If no url is given, start empty.
1093
+ def IE.start( url = nil )
1094
+ ie = new
1095
+ ie.goto(url) if url
1096
+ return ie
1097
+ end
1098
+
1099
+ # Attach to an existing IE window, either by url or title.
1100
+ # IE.attach(:url, 'http://www.google.com')
1101
+ # IE.attach(:title, 'Google')
1102
+ def IE.attach(how, what)
1103
+ ie = new(true) # don't create window
1104
+ ie.attach_init(how, what)
1105
+ return ie
1106
+ end
1107
+
1108
+ # this method is used internally to attach to an existing window
1109
+ # dont make private
1110
+ def attach_init( how, what )
1111
+ attach_browser_window(how, what)
1112
+ set_defaults
1113
+ wait
1114
+ end
1115
+
1116
+ def set_defaults
1117
+ @form = nil
1118
+
1119
+ @enable_spinner = $ENABLE_SPINNER
1120
+ @error_checkers= []
1121
+
1122
+ @ie.visible = ! $HIDE_IE
1123
+ @activeObjectHighLightColor = DEFAULT_HIGHLIGHT_COLOR
1124
+ if $FAST_SPEED
1125
+ set_fast_speed
1126
+ else
1127
+ set_slow_speed
1128
+ end
1129
+
1130
+ @logger = DefaultLogger.new()
1131
+
1132
+ @url_list = []
1133
+
1134
+ # add an error checker for http navigation errors, such as 404, 500 etc
1135
+ navigation_checker=Proc.new{ |ie|
1136
+ if ie.document.frames.length > 1
1137
+ 1.upto ie.document.frames.length do |i|
1138
+ check_for_http_error(ie.frame(:index, i) )
1139
+ end
1140
+ else
1141
+ check_for_http_error(ie)
1142
+ end
1143
+ }
1144
+
1145
+ add_checker( navigation_checker )
1146
+
1147
+ end
1148
+ private :set_defaults
1149
+
1150
+ # This method checks the currently displayed page for http errors, 404, 500 etc
1151
+ # It gets called internally by the wait method, so a user does not need to call it explicitly
1152
+ def check_for_http_error(ie)
1153
+ url=ie.document.url
1154
+ #puts "url is " + url
1155
+ if /shdoclc.dll/.match(url)
1156
+ #puts "Match on shdoclc.dll"
1157
+ m = /id=IEText.*?>(.*?)</i.match(ie.html)
1158
+ if m
1159
+ #puts "Error is #{m[1]}"
1160
+ raise NavigationException , m[1]
1161
+ end
1162
+ end
1163
+ end
1164
+
1165
+ def set_fast_speed
1166
+ @typingspeed = 0
1167
+ @defaultSleepTime = 0.01
1168
+ end
1169
+
1170
+ def set_slow_speed
1171
+ @typingspeed = DEFAULT_TYPING_SPEED
1172
+ @defaultSleepTime = DEFAULT_SLEEP_TIME
1173
+ end
1174
+
1175
+ def create_browser_window
1176
+ @ie = WIN32OLE.new('InternetExplorer.Application')
1177
+ end
1178
+ private :create_browser_window
1179
+
1180
+ def attach_browser_window( how, what )
1181
+ log "Seeking Window with #{how}: #{ what }"
1182
+ shell = WIN32OLE.new("Shell.Application")
1183
+ appWindows = shell.Windows()
1184
+
1185
+ ieTemp = nil
1186
+ appWindows.each do |aWin|
1187
+ log "Found a window: #{aWin}. "
1188
+
1189
+ case how
1190
+ when :url
1191
+ log " url is: #{aWin.locationURL}\n"
1192
+ ieTemp = aWin if (what.matches(aWin.locationURL) )
1193
+ when :title
1194
+ # normal windows explorer shells do not have document
1195
+ title = nil
1196
+ begin
1197
+ title = aWin.document.title
1198
+ rescue WIN32OLERuntimeError
1199
+ end
1200
+ ieTemp = aWin if (what.matches( title ) )
1201
+ else
1202
+ raise ArgumentError
1203
+ end
1204
+ end
1205
+
1206
+ #if it can not find window
1207
+ if ieTemp == nil
1208
+ raise NoMatchingWindowFoundException,
1209
+ "Unable to locate a window with #{ how} of #{what}"
1210
+ end
1211
+ @ie = ieTemp
1212
+ end
1213
+ private :attach_browser_window
1214
+
1215
+ # deprecated: use logger= instead
1216
+ def set_logger( logger )
1217
+ @logger = logger
1218
+ end
1219
+
1220
+ def log ( what )
1221
+ @logger.debug( what ) if @logger
1222
+ end
1223
+
1224
+ # Deprecated: Use IE#ie instead
1225
+ # This method returns the Internet Explorer object.
1226
+ # Methods, properties, etc. that the IE object does not support can be accessed.
1227
+ def getIE()
1228
+ return @ie
1229
+ end
1230
+
1231
+ #
1232
+ # Accessing data outside the document
1233
+ #
1234
+
1235
+ # Return the title of the window
1236
+ def title
1237
+ @ie.document.title
1238
+ end
1239
+
1240
+ # Return the status of the window, typically from the status bar at the bottom.
1241
+ def status
1242
+ raise NoStatusBarException if !@ie.statusBar
1243
+ return @ie.statusText()
1244
+ end
1245
+
1246
+ #
1247
+ # Navigation
1248
+ #
1249
+
1250
+ # Navigate to the specified URL.
1251
+ # * url - string - the URL to navigate to
1252
+ def goto( url )
1253
+ @ie.navigate(url)
1254
+ wait()
1255
+ sleep 0.2
1256
+ return @down_load_time
1257
+ end
1258
+
1259
+ # Go to the previous page - the same as clicking the browsers back button
1260
+ # an WIN32OLERuntimeError exception is raised if the browser cant go back
1261
+ def back
1262
+ @ie.GoBack()
1263
+ wait
1264
+ end
1265
+
1266
+ # Go to the next page - the same as clicking the browsers forward button
1267
+ # an WIN32OLERuntimeError exception is raised if the browser cant go forward
1268
+ def forward
1269
+ @ie.GoForward()
1270
+ wait
1271
+ end
1272
+
1273
+ # Refresh the current page - the same as clicking the browsers refresh button
1274
+ # an WIN32OLERuntimeError exception is raised if the browser cant refresh
1275
+ def refresh
1276
+ @ie.refresh2(3)
1277
+ wait
1278
+ end
1279
+
1280
+ # clear the list of urls that we have visited
1281
+ def clear_url_list
1282
+ @url_list.clear
1283
+ end
1284
+
1285
+ # Closes the Browser
1286
+ def close
1287
+ @ie.quit
1288
+ end
1289
+
1290
+ # Maximize the window (expands to fill the screen)
1291
+ def maximize; set_window_state (:SW_MAXIMIZE); end
1292
+
1293
+ # Minimize the window (appears as icon on taskbar)
1294
+ def minimize; set_window_state (:SW_MINIMIZE); end
1295
+
1296
+ # Restore the window (after minimizing or maximizing)
1297
+ def restore; set_window_state (:SW_RESTORE); end
1298
+
1299
+ # Make the window come to the front
1300
+ def bring_to_front
1301
+ autoit = WIN32OLE.new('AutoItX3.Control')
1302
+ autoit.WinActivate title, ''
1303
+ end
1304
+
1305
+ def front?
1306
+ autoit = WIN32OLE.new('AutoItX3.Control')
1307
+ 1 == autoit.WinActive(title, '')
1308
+ end
1309
+
1310
+ def set_window_state (state)
1311
+ autoit = WIN32OLE.new('AutoItX3.Control')
1312
+ autoit.WinSetState title, '', autoit.send(state)
1313
+ end
1314
+ private :set_window_state
1315
+
1316
+ # Send key events to IE window.
1317
+ # See http://www.autoitscript.com/autoit3/docs/appendix/SendKeys.htm
1318
+ # for complete documentation on keys supported and syntax.
1319
+ def send_keys (key_string)
1320
+ autoit = WIN32OLE.new 'AutoItX3.Control'
1321
+ autoit.WinActivate title
1322
+ autoit.Send key_string
1323
+ end
1324
+
1325
+ # used by the popup code only
1326
+ def dir
1327
+ return File.expand_path(File.dirname(__FILE__))
1328
+ end
1329
+
1330
+ #
1331
+ # Document and Document Data
1332
+ #
1333
+
1334
+ # Return the current document
1335
+ def document
1336
+ return @ie.document
1337
+ end
1338
+
1339
+ # returns the current url, as displayed in the address bar of the browser
1340
+ def url
1341
+ return @ie.LocationURL
1342
+ end
1343
+
1344
+ # Search the current page for specified text or regexp.
1345
+ # Returns true if the specified text was found.
1346
+ # Returns matchdata object if the specified regexp was found.
1347
+ # * text - string or regular expression - the string to look for
1348
+ def contains_text(text)
1349
+ returnValue = false
1350
+ retryCount = 0
1351
+ begin
1352
+ retryCount += 1
1353
+ returnValue =
1354
+ if text.kind_of? Regexp
1355
+ document.body.innerText.match(text)
1356
+ elsif text.kind_of? String
1357
+ document.body.innerText.index(text)
1358
+ else
1359
+ raise MissingWayOfFindingObjectException
1360
+ end
1361
+ rescue MissingWayOfFindingObjectException => e
1362
+ raise e
1363
+ rescue
1364
+ retry if retryCount < 2
1365
+ end
1366
+ return returnValue
1367
+ end
1368
+
1369
+ #
1370
+ # Synchronization
1371
+ #
1372
+
1373
+ # This method is used internally to cause an execution to stop until the page has loaded in Internet Explorer.
1374
+ def wait( noSleep = false )
1375
+ begin
1376
+ @down_load_time=0
1377
+ pageLoadStart = Time.now
1378
+ @pageHasReloaded= false
1379
+
1380
+ s= Spinner.new(@enable_spinner)
1381
+ while @ie.busy
1382
+ @pageHasReloaded = true
1383
+ sleep 0.02
1384
+ s.spin
1385
+ end
1386
+ s.reverse
1387
+
1388
+ log "wait: readystate=" + @ie.readyState.to_s
1389
+ until @ie.readyState == READYSTATE_COMPLETE
1390
+ @pageHasReloaded = true
1391
+ sleep 0.02
1392
+ s.spin
1393
+ end
1394
+ sleep 0.02
1395
+
1396
+ until @ie.document.readyState == "complete"
1397
+ sleep 0.02
1398
+ s.spin
1399
+ end
1400
+
1401
+
1402
+ if @ie.document.frames.length > 1
1403
+ begin
1404
+ 0.upto @ie.document.frames.length-1 do |i|
1405
+ until @ie.document.frames[i.to_s].document.readyState == "complete"
1406
+ sleep 0.02
1407
+ s.spin
1408
+ end
1409
+ @url_list << @ie.document.frames[i.to_s].document.url unless url_list.include?(@ie.document.frames[i.to_s].document.url)
1410
+ end
1411
+ rescue=>e
1412
+ @logger.warn 'frame error in wait' + e.to_s + "\n" + e.backtrace.join("\n")
1413
+ end
1414
+ else
1415
+ @url_list << @ie.document.url unless @url_list.include?(@ie.document.url)
1416
+ end
1417
+ @down_load_time = Time.now - pageLoadStart
1418
+
1419
+ run_error_checks
1420
+
1421
+ print "\b" unless @enable_spinner == false
1422
+
1423
+ s=nil
1424
+ rescue WIN32OLERuntimeError => e
1425
+ @logger.info "runtime error in wait: #{e}\n#{e.backtrace.join("\\\n")}"
1426
+ end
1427
+ sleep 0.01
1428
+ sleep @defaultSleepTime unless noSleep == true
1429
+ end
1430
+
1431
+ # Error checkers
1432
+
1433
+ # this method runs the predefined error checks
1434
+ def run_error_checks
1435
+ @error_checkers.each do |e|
1436
+ e.call(self)
1437
+ end
1438
+ end
1439
+
1440
+ # this method is used to add an error checker that gets executed on every page load
1441
+ # * checker Proc Object, that contains the code to be run
1442
+ def add_checker( checker)
1443
+ @error_checkers << checker
1444
+ end
1445
+
1446
+ # this allows a checker to be disabled
1447
+ # * checker Proc Object, the checker that is to be disabled
1448
+ def disable_checker( checker )
1449
+ @error_checkers.delete(checker)
1450
+ end
1451
+
1452
+ # The HTML of the current page
1453
+ def html
1454
+ return document.body.outerHTML
1455
+ end
1456
+
1457
+ # The text of the current document
1458
+ def text
1459
+ return document.body.innerText.strip
1460
+ end
1461
+
1462
+ #
1463
+ # Show me state
1464
+ #
1465
+
1466
+ # This method is used to display the available html frames that Internet Explorer currently has loaded.
1467
+ # This method is usually only used for debugging test scripts.
1468
+ def show_frames
1469
+ if allFrames = document.frames
1470
+ count = allFrames.length
1471
+ puts "there are #{count} frames"
1472
+ for i in 0..count-1 do
1473
+ begin
1474
+ fname = allFrames[i.to_s].name.to_s
1475
+ puts "frame index: #{i+1} name: #{fname}"
1476
+ rescue => e
1477
+ puts "frame index: #{i+1} --Access Denied--" if e.to_s.match(/Access is denied/)
1478
+ end
1479
+ end
1480
+ else
1481
+ puts "no frames"
1482
+ end
1483
+ end
1484
+
1485
+ # Show all forms displays all the forms that are on a web page.
1486
+ def show_forms
1487
+ if allForms = document.forms
1488
+ count = allForms.length
1489
+ puts "There are #{count} forms"
1490
+ for i in 0..count-1 do
1491
+ wrapped = FormWrapper.new(allForms.item(i))
1492
+ puts "Form name: #{wrapped.name}"
1493
+ puts " id: #{wrapped.id}"
1494
+ puts " method: #{wrapped.method}"
1495
+ puts " action: #{wrapped.action}"
1496
+ end
1497
+ else
1498
+ puts "No forms"
1499
+ end
1500
+ end
1501
+
1502
+ # this method shows all the images availble in the document
1503
+ def show_images
1504
+ doc = document
1505
+ index=1
1506
+ doc.images.each do |l|
1507
+ puts "image: name: #{l.name}"
1508
+ puts " id: #{l.invoke("id")}"
1509
+ puts " src: #{l.src}"
1510
+ puts " index: #{index}"
1511
+ index+=1
1512
+ end
1513
+ end
1514
+
1515
+ # this method shows all the links availble in the document
1516
+ def show_links
1517
+
1518
+ props= ["name" ,"id" , "href" ]
1519
+ print_sizes= [12 , 12, 60]
1520
+ doc = document
1521
+ index=0
1522
+ text_size = 60
1523
+ # draw the table header
1524
+ s = "index".ljust(6)
1525
+ props.each_with_index do |p,i|
1526
+ s=s+ p.ljust(print_sizes[i])
1527
+ end
1528
+ s=s + "text/src".ljust(text_size)
1529
+ s=s+"\n"
1530
+
1531
+ # now get the details of the links
1532
+ doc.links.each do |n|
1533
+ index+=1
1534
+ s = s + index.to_s.ljust(6)
1535
+ props.each_with_index do |prop,i|
1536
+ printsize=print_sizes[i]
1537
+ begin
1538
+ p = n.invoke(prop)
1539
+ temp_var = "#{p}".to_s.ljust(printsize)
1540
+ rescue
1541
+ # this object probably doesnt have this property
1542
+ temp_var = "".to_s.ljust(printsize)
1543
+ end
1544
+ s =s+ temp_var
1545
+ end
1546
+ s=s+ n.innerText
1547
+ if n.getElementsByTagName("IMG").length > 0
1548
+ s=s+ " / " + n.getElementsByTagName("IMG")[0.to_s].src
1549
+ end
1550
+ s=s+"\n"
1551
+ end
1552
+ puts s
1553
+ end
1554
+
1555
+ # this method shows the name, id etc of the object that is currently active - ie the element that has focus
1556
+ # its mostly used in irb when creating a script
1557
+ def show_active
1558
+ s = ""
1559
+
1560
+ current = document.activeElement
1561
+ begin
1562
+ s=s+current.invoke("type").to_s.ljust(16)
1563
+ rescue
1564
+ end
1565
+ props=["name", "id", "value", "alt", "src", "innerText", "href"]
1566
+ props.each do |prop|
1567
+ begin
1568
+ p = current.invoke(prop)
1569
+ s =s+ " " + "#{prop}=#{p}".to_s.ljust(18)
1570
+ rescue
1571
+ #this object probably doesnt have this property
1572
+ end
1573
+ end
1574
+ s=s+"\n"
1575
+ end
1576
+
1577
+ # This method shows the available objects on the current page.
1578
+ # This is usually only used for debugging or writing new test scripts.
1579
+ # This is a nice feature to help find out what HTML objects are on a page
1580
+ # when developing a test case using Watir.
1581
+ def show_all_objects
1582
+ puts "-----------Objects in page -------------"
1583
+ doc = document
1584
+ s = ""
1585
+ props=["name" ,"id" , "value" , "alt" , "src"]
1586
+ doc.all.each do |n|
1587
+ begin
1588
+ s=s+n.invoke("type").to_s.ljust(16)
1589
+ rescue
1590
+ next
1591
+ end
1592
+ props.each do |prop|
1593
+ begin
1594
+ p = n.invoke(prop)
1595
+ s =s+ " " + "#{prop}=#{p}".to_s.ljust(18)
1596
+ rescue
1597
+ # this object probably doesnt have this property
1598
+ end
1599
+ end
1600
+ s=s+"\n"
1601
+ end
1602
+ puts s+"\n\n\n"
1603
+ end
1604
+
1605
+ # this method shows all the divs availble in the document
1606
+ def show_divs
1607
+ divs = document.getElementsByTagName("DIV")
1608
+ puts "Found #{divs.length} div tags"
1609
+ index=1
1610
+ divs.each do |d|
1611
+ puts "#{index} id=#{d.invoke('id')} class=#{d.invoke("className")}"
1612
+ index+=1
1613
+ end
1614
+ end
1615
+
1616
+ # this method is used to show all the tables that are available
1617
+ def show_tables
1618
+ tables = document.getElementsByTagName("TABLE")
1619
+ puts "Found #{tables.length} tables"
1620
+ index=1
1621
+ tables.each do |d|
1622
+ puts "#{index} id=#{d.invoke('id')} rows=#{d.rows.length} columns=#{d.rows["0"].cells.length }"
1623
+ index+=1
1624
+ end
1625
+ end
1626
+
1627
+ # this method shows all the spans availble in the document
1628
+ def show_spans
1629
+ spans = document.getElementsByTagName("SPAN")
1630
+ puts "Found #{spans.length} span tags"
1631
+ index=1
1632
+ spans.each do |d|
1633
+ puts "#{index} id=#{d.invoke('id')} class=#{d.invoke("className")}"
1634
+ index+=1
1635
+ end
1636
+ end
1637
+
1638
+ def show_labels
1639
+ labels = document.getElementsByTagName("LABEL")
1640
+ puts "Found #{labels.length} label tags"
1641
+ index=1
1642
+ labels.each do |d|
1643
+ puts "#{index} text=#{d.invoke('innerText')} class=#{d.invoke("className")} for=#{d.invoke("htmlFor")}"
1644
+ index+=1
1645
+ end
1646
+ end
1647
+
1648
+ #
1649
+ # This method gives focus to the frame
1650
+ # It may be removed and become part of the frame object
1651
+ def focus
1652
+ document.activeElement.blur
1653
+ document.focus
1654
+ end
1655
+
1656
+ end # class IE
1657
+
1658
+ #
1659
+ # MOVETO: watir/popup.rb
1660
+ # Module Watir::Popup
1661
+ #
1662
+
1663
+ # POPUP object
1664
+ class PopUp
1665
+ def initialize( ieController )
1666
+ @ieController = ieController
1667
+ end
1668
+
1669
+ def button( caption )
1670
+ return JSButton.new( @ieController.getIE.hwnd , caption )
1671
+ end
1672
+ end
1673
+
1674
+ class JSButton
1675
+ def initialize( hWnd , caption )
1676
+ @hWnd = hWnd
1677
+ @caption = caption
1678
+ end
1679
+
1680
+ def startClicker( waitTime = 3 )
1681
+ clicker = WinClicker.new
1682
+ clicker.clickJSDialog_Thread
1683
+ # clickerThread = Thread.new( @caption ) {
1684
+ # sleep waitTime
1685
+ # puts "After the wait time in startClicker"
1686
+ # clickWindowsButton_hwnd(hwnd , buttonCaption )
1687
+ #}
1688
+ end
1689
+ end
1690
+
1691
+ #
1692
+ # Module Watir::Control or Watir::BrowserDriver
1693
+ #
1694
+
1695
+ class Frame < IE
1696
+
1697
+ def initialize(container, how, what)
1698
+ @container = container
1699
+ @frame = nil
1700
+
1701
+ frames = @container.document.frames
1702
+
1703
+ for i in 0 .. frames.length-1
1704
+ next unless @frame == nil
1705
+ this_frame = frames.item(i)
1706
+ if how == :index
1707
+ if i+1 == what
1708
+ @frame = this_frame
1709
+ end
1710
+ elsif how == :name
1711
+ begin
1712
+ if what.matches(this_frame.name)
1713
+ @frame = this_frame
1714
+ end
1715
+ rescue # access denied?
1716
+ end
1717
+ elsif how == :id
1718
+ # BUG: Won't work for IFRAMES
1719
+ if what.matches(@container.document.getElementsByTagName("FRAME").item(i).invoke("id"))
1720
+ @frame = this_frame
1721
+ end
1722
+ else
1723
+ raise ArgumentError, "Argument #{how} not supported"
1724
+ end
1725
+ end
1726
+
1727
+ unless @frame
1728
+ raise UnknownFrameException , "Unable to locate a frame with name #{ what} "
1729
+ end
1730
+
1731
+ @typingspeed = container.typingspeed
1732
+ @activeObjectHighLightColor = container.activeObjectHighLightColor
1733
+ end
1734
+
1735
+ def ie
1736
+ return @frame
1737
+ end
1738
+
1739
+ def document
1740
+ @frame.document
1741
+ end
1742
+
1743
+ def wait(no_sleep = false)
1744
+ @container.wait(no_sleep)
1745
+ end
1746
+ end
1747
+
1748
+
1749
+ # Forms
1750
+
1751
+ module FormAccess
1752
+ def name
1753
+ @form.getAttributeNode('name').value
1754
+ end
1755
+ def action
1756
+ @form.action
1757
+ end
1758
+ def method
1759
+ @form.invoke('method')
1760
+ end
1761
+ def id
1762
+ @form.invoke("id").to_s
1763
+ end
1764
+ end
1765
+
1766
+ # wraps around a form OLE object
1767
+ class FormWrapper
1768
+ include FormAccess
1769
+ def initialize ( ole_object )
1770
+ @form = ole_object
1771
+ end
1772
+ end
1773
+
1774
+ # Form Factory object
1775
+ class Form < IE
1776
+ include FormAccess
1777
+
1778
+ attr_accessor :form
1779
+
1780
+
1781
+ # * container - the containing object, normally an instance of IE
1782
+ # * how - symbol - how we access the form (:name, :id, :index, :action, :method)
1783
+ # * what - what we use to access the form
1784
+ def initialize( container, how, what )
1785
+ @container = container
1786
+ @formHow = how
1787
+ @formName = what
1788
+
1789
+ log "Get form formHow is #{@formHow} formName is #{@formName} "
1790
+ count = 1
1791
+ doc = @container.document
1792
+ doc.forms.each do |thisForm|
1793
+ next unless @form == nil
1794
+
1795
+ wrapped = FormWrapper.new(thisForm)
1796
+
1797
+ log "form on page, name is " + wrapped.name
1798
+
1799
+ @form =
1800
+ case @formHow
1801
+ when :name
1802
+ wrapped.name == @formName ? thisForm : nil
1803
+ when :id
1804
+ wrapped.id == @formName.to_s ? thisForm : nil
1805
+ when :index
1806
+ count == @formName.to_i ? thisForm : nil
1807
+ when :method
1808
+ wrapped.method.downcase == @formName.downcase ? thisForm : nil
1809
+ when :action
1810
+ @formName.matches(wrapped.action) ? thisForm : nil
1811
+ else
1812
+ raise MissingWayOfFindingObjectException
1813
+ end
1814
+ count = count +1
1815
+ end
1816
+
1817
+ @typingspeed = @container.typingspeed
1818
+ @activeObjectHighLightColor = @container.activeObjectHighLightColor
1819
+ end
1820
+
1821
+ def exists?
1822
+ @form ? true : false
1823
+ end
1824
+
1825
+ # Submit the data -- equivalent to pressing Enter or Return to submit a form.
1826
+ def submit
1827
+ raise UnknownFormException , "Unable to locate a form using #{@formHow} and #{@formName} " if @form == nil
1828
+ @form.submit
1829
+ @container.wait
1830
+ end
1831
+
1832
+ def getContainerContents
1833
+ raise UnknownFormException , "Unable to locate a form using #{@formHow} and #{@formName} " if @form == nil
1834
+ @form.elements.all
1835
+ end
1836
+ private :getContainerContents
1837
+
1838
+ def getContainer
1839
+ return @form
1840
+ end
1841
+
1842
+ def wait(no_sleep = false)
1843
+ @container.wait(no_sleep)
1844
+ end
1845
+
1846
+ # This method is responsible for setting and clearing the colored highlighting on the specified form.
1847
+ # use :set to set the highlight
1848
+ # :clear to clear the highlight
1849
+ def highLight( setOrClear , element , count)
1850
+
1851
+ if setOrClear == :set
1852
+ begin
1853
+ original_color = element.style.backgroundColor
1854
+ original_color = "" if original_color== nil
1855
+ element.style.backgroundColor = activeObjectHighLightColor
1856
+ rescue => e
1857
+ puts e
1858
+ puts e.backtrace.join("\n")
1859
+ original_color = ""
1860
+ end
1861
+ @original_styles[ count ] = original_color
1862
+ else
1863
+ begin
1864
+ element.style.backgroundColor = @original_styles[ count]
1865
+ rescue => e
1866
+ puts e
1867
+ # we could be here for a number of reasons...
1868
+ ensure
1869
+ end
1870
+ end
1871
+ end
1872
+ private :highLight
1873
+
1874
+ # causes the object to flash. Normally used in IRB when creating scripts
1875
+ def flash
1876
+ @original_styles = {}
1877
+ 10.times do
1878
+ count=0
1879
+ @form.elements.each do |element|
1880
+ highLight(:set , element , count)
1881
+ count +=1
1882
+ end
1883
+ sleep 0.05
1884
+ count = 0
1885
+ @form.elements.each do |element|
1886
+ highLight(:clear , element , count)
1887
+ count +=1
1888
+ end
1889
+ sleep 0.05
1890
+ end
1891
+ end
1892
+
1893
+ end # class Form
1894
+
1895
+ # Base class for most elements.
1896
+ # This is not a class that users would normally access.
1897
+ class Element
1898
+ include Watir::Exception
1899
+
1900
+ # number of spaces that seperate the property from the value in the to_s method
1901
+ TO_S_SIZE = 14
1902
+
1903
+ # o - the ole object for the element being wrapped
1904
+ def initialize( o )
1905
+ @o = o
1906
+ @originalColor = nil
1907
+ end
1908
+
1909
+ private
1910
+ def self.def_wrap(method_name)
1911
+ class_eval "def #{method_name}
1912
+ assert_exists
1913
+ @o.invoke('#{method_name}')
1914
+ end"
1915
+ end
1916
+ def self.def_wrap_guard(method_name)
1917
+ class_eval "def #{method_name}
1918
+ assert_exists
1919
+ begin
1920
+ @o.invoke('#{method_name}')
1921
+ rescue
1922
+ ''
1923
+ end
1924
+ end"
1925
+ end
1926
+ def assert_exists
1927
+ unless @o
1928
+ raise UnknownObjectException.new("Unable to locate object, using #{@how} and #{@what}")
1929
+ end
1930
+ end
1931
+ def assert_enabled
1932
+ unless enabled?
1933
+ raise ObjectDisabledException, "object #{@how} and #{@what} is disabled"
1934
+ end
1935
+ end
1936
+
1937
+ public
1938
+ def_wrap_guard :type
1939
+ def_wrap_guard :name
1940
+ def_wrap :id
1941
+ def_wrap :disabled
1942
+ def_wrap_guard :value
1943
+ def_wrap_guard :title
1944
+
1945
+ # returns the Object in its OLE form, allowing any methods of the DOM that Watir doesnt support to be used
1946
+ #--
1947
+ # BUG: should be renamed appropriately and then use an attribute reader
1948
+ #++
1949
+ def getOLEObject
1950
+ return @o
1951
+ end
1952
+
1953
+ # returns the outer html of the object - see http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/outerhtml.asp?frame=true
1954
+ def html
1955
+ assert_exists
1956
+ return @o.outerHTML
1957
+ end
1958
+
1959
+ # Returns an array with many of the properties, in a format to be used by the to_s method
1960
+ def string_creator
1961
+ n = []
1962
+ n << "type:".ljust(TO_S_SIZE) + self.type
1963
+ n << "id:".ljust(TO_S_SIZE) + self.id.to_s
1964
+ n << "name:".ljust(TO_S_SIZE) + self.name.to_s
1965
+ n << "value:".ljust(TO_S_SIZE) + self.value.to_s
1966
+ n << "disabled:".ljust(TO_S_SIZE) + self.disabled.to_s
1967
+ return n
1968
+ end
1969
+
1970
+ # This method displays basic details about the object. Sample output for a button is shown.
1971
+ # Raises UnknownObjectException if the object is not found.
1972
+ # name b4
1973
+ # type button
1974
+ # id b5
1975
+ # value Disabled Button
1976
+ # disabled true
1977
+ def to_s
1978
+ assert_exists
1979
+ return string_creator.join("\n")
1980
+ end
1981
+
1982
+ # This method is responsible for setting and clearing the colored highlighting on the currently active element.
1983
+ # use :set to set the highlight
1984
+ # :clear to clear the highlight
1985
+ def highLight( setOrClear )
1986
+ if setOrClear == :set
1987
+ begin
1988
+ @originalColor = @o.style.backgroundColor
1989
+ @o.style.backgroundColor = @ieController.activeObjectHighLightColor
1990
+ rescue
1991
+ @originalColor = nil
1992
+ end
1993
+ else # BUG: assumes is :clear, but could actually be anything
1994
+ begin
1995
+ @o.style.backgroundColor = @originalColor unless @originalColor == nil
1996
+ rescue
1997
+ # we could be here for a number of reasons...
1998
+ ensure
1999
+ @originalColor = nil
2000
+ end
2001
+ end
2002
+ end
2003
+ private :highLight
2004
+
2005
+ # This method clicks the active element.
2006
+ # raises: UnknownObjectException if the object is not found
2007
+ # ObjectDisabledException if the object is currently disabled
2008
+ def click
2009
+ assert_exists
2010
+ assert_enabled
2011
+
2012
+ highLight(:set)
2013
+ @o.click()
2014
+ @ieController.wait()
2015
+ highLight(:clear)
2016
+ end
2017
+
2018
+ # causes the object to flash. Normally used in IRB when creating scripts
2019
+ def flash
2020
+ assert_exists
2021
+ 10.times do
2022
+ highLight(:set)
2023
+ sleep 0.05
2024
+ highLight(:clear)
2025
+ sleep 0.05
2026
+ end
2027
+ nil
2028
+ end
2029
+
2030
+ # This method executes a user defined "fireEvent" for objects with JavaScript events tied to them such as DHTML menus.
2031
+ # usage: allows a generic way to fire javascript events on page objects such as "onMouseOver", "onClick", etc.
2032
+ # raises: UnknownObjectException if the object is not found
2033
+ # ObjectDisabledException if the object is currently disabled
2034
+ def fireEvent(event)
2035
+ assert_exists
2036
+ assert_enabled
2037
+
2038
+ highLight(:set)
2039
+ @o.fireEvent(event)
2040
+ @ieController.wait()
2041
+ highLight(:clear)
2042
+ end
2043
+ alias fire_event fireEvent
2044
+
2045
+ # This method sets focus on the active element.
2046
+ # raises: UnknownObjectException if the object is not found
2047
+ # ObjectDisabledException if the object is currently disabled
2048
+ def focus()
2049
+ assert_exists
2050
+ assert_enabled
2051
+ @o.focus()
2052
+ end
2053
+
2054
+ # This methods checks to see if the current element actually exists.
2055
+ def exists?
2056
+ @o? true: false
2057
+ end
2058
+
2059
+ # Returns true if the element is enabled, false if it isn't.
2060
+ # raises: UnknownObjectException if the object is not found
2061
+ def enabled?
2062
+ assert_exists
2063
+ return ! @o.invoke("disabled")
2064
+ end
2065
+ end
2066
+
2067
+
2068
+ # this class is the super class for the iterator classes ( buttons, links, spans etc
2069
+ # it would normally only be accessed by the iterator methods ( spans , links etc) of IE
2070
+ class ElementCollections
2071
+ include Enumerable
2072
+
2073
+ # Super class for all the iteractor classes
2074
+ # * ieController - an instance of an IE object
2075
+ def initialize( ieController)
2076
+ @ieController = ieController
2077
+ @length = length() # defined by subclasses
2078
+
2079
+ # set up the items we want to display when the show method s used
2080
+ set_show_items
2081
+ end
2082
+
2083
+ def set_show_items
2084
+ @show_attributes = AttributeLengthPairs.new( "id" , 20)
2085
+ @show_attributes.add( "name" , 20)
2086
+ end
2087
+
2088
+ def get_length_of_input_objects(object_type)
2089
+ object_types =
2090
+ if object_type.kind_of? Array
2091
+ object_type
2092
+ else
2093
+ [ object_type ]
2094
+ end
2095
+
2096
+ length = 0
2097
+ objects = @ieController.getContainer.getElementsByTagName("INPUT")
2098
+ if objects.length > 0
2099
+ objects.each do |o|
2100
+ length += 1 if object_types.include?(o.invoke("type").downcase )
2101
+ end
2102
+ end
2103
+ return length
2104
+ end
2105
+
2106
+ # iterate through each of the elements in the collection in turn
2107
+ def each
2108
+ 0.upto( @length-1 ) { |i | yield iterator_object(i) }
2109
+ end
2110
+
2111
+ # allows access to a specific item in the collection
2112
+ def [](n)
2113
+ return iterator_object(n-1)
2114
+ end
2115
+
2116
+ # this method is the way to show the objects, normally used from irb
2117
+ def show
2118
+ s="index".ljust(6)
2119
+ @show_attributes.each do |attribute_length_pair|
2120
+ s=s + attribute_length_pair.attribute.ljust(attribute_length_pair.length)
2121
+ end
2122
+
2123
+ index = 1
2124
+ self.each do |o|
2125
+ s= s+"\n"
2126
+ s=s + index.to_s.ljust(6)
2127
+ @show_attributes.each do |attribute_length_pair|
2128
+ begin
2129
+ s=s + eval( 'o.getOLEObject.invoke("#{attribute_length_pair.attribute}")').to_s.ljust( attribute_length_pair.length )
2130
+ rescue=>e
2131
+ s=s+ " ".ljust( attribute_length_pair.length )
2132
+ end
2133
+ end
2134
+ index+=1
2135
+ end
2136
+ puts s
2137
+ end
2138
+
2139
+ # this method creates an object of the correct type that the iterators use
2140
+ private
2141
+ def iterator_object(i)
2142
+ element_class.new(@ieController, :index, i+1)
2143
+ end
2144
+ end
2145
+
2146
+ # this class contains items that are common between the span and div objects
2147
+ # it would not normally be used directly
2148
+ #
2149
+ # many of the methods available to this object are inherited from the Element class
2150
+ #
2151
+ class SpanDivCommon < Element
2152
+ include Watir::Exception
2153
+ include SupportsSubElements
2154
+
2155
+ attr_reader :typingspeed
2156
+
2157
+ def initialize( ieController, how , what )
2158
+ @ieController = ieController
2159
+ @how = how
2160
+ @what = what
2161
+ @o = @ieController.getNonControlObject(tag , @how, @what )
2162
+ super( @o )
2163
+ @typingspeed = @ieController.typingspeed
2164
+ @activeObjectHighLightColor = @ieController.activeObjectHighLightColor
2165
+ end
2166
+
2167
+ def getContainerContents()
2168
+ return @o.all
2169
+ end
2170
+ private :getContainerContents
2171
+
2172
+ def getContainer()
2173
+ return @o
2174
+ end
2175
+
2176
+ # this method returns the innerText of the object
2177
+ # raises an ObjectNotFound exception if the object cannot be found
2178
+ def text
2179
+ assert_exists
2180
+ return @o.innerText.strip
2181
+ end
2182
+
2183
+ # returns the class name of the span or div is using
2184
+ # raises an ObjectNotFound exception if the object cannot be found
2185
+ def class_name
2186
+ assert_exists
2187
+ return @o.invoke("className")
2188
+ end
2189
+
2190
+ # this method returns the type of object
2191
+ # raises an ObjectNotFound exception if the object cannot be found
2192
+ def type
2193
+ assert_exists
2194
+ return self.class.name[self.class.name.index("::")+2 .. self.class.name.length ]
2195
+ end
2196
+
2197
+ # this method is used to populate the properties in the to_s method
2198
+ def span_div_string_creator
2199
+ n = []
2200
+ n << "class:".ljust(TO_S_SIZE) + self.class_name
2201
+ n << "text:".ljust(TO_S_SIZE) + self.text
2202
+ return n
2203
+ end
2204
+ private :span_div_string_creator
2205
+
2206
+ # returns the properties of the object in a string
2207
+ # raises an ObjectNotFound exception if the object cannot be found
2208
+ def to_s
2209
+ assert_exists
2210
+ r = string_creator
2211
+ r=r + span_div_string_creator
2212
+ return r.join("\n")
2213
+ end
2214
+ end
2215
+
2216
+ class P < SpanDivCommon
2217
+ TAG = 'P'
2218
+ def tag; TAG; end
2219
+ def self.tag; TAG; end
2220
+ end
2221
+
2222
+ # 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
2223
+ # It would not normally be created by users
2224
+ class Div < SpanDivCommon
2225
+ TAG = 'DIV'
2226
+ def tag; TAG; end
2227
+ def self.tag; TAG; end
2228
+ end
2229
+
2230
+ # this class is used to deal with Span tags in the html page. It would not normally be created by users
2231
+ class Span < SpanDivCommon
2232
+ TAG = 'SPAN'
2233
+ def tag; TAG; end
2234
+ def self.tag; TAG; end
2235
+ end
2236
+
2237
+ # this class is used to access a label object on the html page - http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/label.asp?frame=true
2238
+ #
2239
+ # many of the methods available to this object are inherited from the Element class
2240
+ #
2241
+ class Label < Element
2242
+ def initialize( ieController , how, what)
2243
+ @ieController = ieController
2244
+ @how = how
2245
+ @what = what
2246
+ @o = @ieController.getNonControlObject("LABEL" , @how, @what )
2247
+ super( @o )
2248
+ end
2249
+
2250
+ # return the type of this object
2251
+ def type
2252
+ assert_exists
2253
+ return "Label"
2254
+ end
2255
+
2256
+ # return the ID of the control that this label is associated with
2257
+ def for
2258
+ assert_exists
2259
+ return @o.htmlFor
2260
+ end
2261
+
2262
+ def text
2263
+ assert_exists
2264
+ return @o.innerText.strip
2265
+ end
2266
+ alias innerText :text
2267
+
2268
+ # this method is used to populate the properties in the to_s method
2269
+ def label_string_creator
2270
+ n = []
2271
+ n << "for:".ljust(TO_S_SIZE) + self.for
2272
+ n << "inner text:".ljust(TO_S_SIZE) + self.innerText
2273
+ return n
2274
+ end
2275
+ private :label_string_creator
2276
+
2277
+ # returns the properties of the object in a string
2278
+ # raises an ObjectNotFound exception if the object cannot be found
2279
+ def to_s
2280
+ assert_exists
2281
+ r = string_creator
2282
+ r=r + label_string_creator
2283
+ return r.join("\n")
2284
+ end
2285
+
2286
+ end
2287
+
2288
+ # This class is used for dealing with tables.
2289
+ # Normally a user would not need to create this object as it is returned by the Watir::SupportsSubElements#table method
2290
+ #
2291
+ # many of the methods available to this object are inherited from the Element class
2292
+ #
2293
+ class Table < Element
2294
+
2295
+ # Returns an initialized instance of the table object to wich anElement belongs
2296
+ # * ieController - an instance of an IE object
2297
+ # * anElement - a Watir object (TextField, Button, etc.)
2298
+ def Table.create_from_element(ieController,anElement)
2299
+ o = anElement.getOLEObject.parentElement
2300
+ while(o && o.tagName != 'TABLE')
2301
+ o = o.parentElement
2302
+ end
2303
+ return Table.new(ieController,:from_object,o)
2304
+ end
2305
+
2306
+ # Returns an initialized instance of a table object
2307
+ # * parent - an instance of an IEController ( or a frame etc )
2308
+ # * how - symbol - how we access the table
2309
+ # * what - what we use to access the table - id, name index etc
2310
+ def initialize( parent, how , what )
2311
+ @ieController = parent
2312
+ @how = how
2313
+ @what = what
2314
+
2315
+ table = nil
2316
+
2317
+ if(@how != :from_object) then
2318
+ table=get_table
2319
+ else
2320
+ table = @what
2321
+ end
2322
+
2323
+ parent.log "table - #{@what}, #{@how} Not found " if table == nil
2324
+ @o = table
2325
+ super( @o )
2326
+ end
2327
+
2328
+ # ---
2329
+ # BUG: should be private
2330
+ # +++
2331
+ # this method finds the specified table on the page
2332
+ def get_table
2333
+ allTables = @ieController.document.getElementsByTagName("TABLE")
2334
+ @ieController.log "There are #{ allTables.length } tables"
2335
+ tableIndex = 1
2336
+ table=nil
2337
+ allTables.each do |t|
2338
+ next unless table == nil
2339
+ case @how
2340
+ when :id
2341
+ if @what.matches( t.invoke("id").to_s )
2342
+ table = t
2343
+ end
2344
+ when :index
2345
+ if tableIndex == @what.to_i
2346
+ table = t
2347
+ end
2348
+ end
2349
+ tableIndex = tableIndex + 1
2350
+ end
2351
+ return table
2352
+ end
2353
+
2354
+
2355
+ # override the highlight method, as if the tables rows are set to have a background color,
2356
+ # this will override the table background color, and the normal flsh method wont work
2357
+ def highLight(setOrClear )
2358
+
2359
+ if setOrClear == :set
2360
+ begin
2361
+ @original_border = @o.border.to_i
2362
+ if @o.border.to_i==1
2363
+ @o.border = 2
2364
+ else
2365
+ @o.border=1
2366
+ end
2367
+ rescue
2368
+ @original_border = nil
2369
+ end
2370
+ else
2371
+ begin
2372
+ @o.border= @original_border unless @original_border == nil
2373
+ @original_border = nil
2374
+ rescue
2375
+ # we could be here for a number of reasons...
2376
+ ensure
2377
+ @original_border = nil
2378
+ end
2379
+ end
2380
+ super
2381
+ end
2382
+
2383
+ # this method is used to ppulate the properties in the to_s method
2384
+ def table_string_creator
2385
+ n = []
2386
+ n << "rows:".ljust(TO_S_SIZE) + self.row_count.to_s
2387
+ n << "cols:".ljust(TO_S_SIZE) + self.column_count.to_s
2388
+ return n
2389
+ end
2390
+ private :table_string_creator
2391
+
2392
+ # returns the properties of the object in a string
2393
+ # raises an ObjectNotFound exception if the object cannot be found
2394
+ def to_s
2395
+ assert_exists
2396
+ r = string_creator
2397
+ r=r + table_string_creator
2398
+ return r.join("\n")
2399
+ end
2400
+
2401
+ # iterates through the rows in the table. Yields a TableRow object
2402
+ def each
2403
+ assert_exists
2404
+ 1.upto( @o.getElementsByTagName("TR").length ) { |i | yield TableRow.new(@ieController ,:direct, row(i) ) }
2405
+ end
2406
+
2407
+ # Returns a row in the table
2408
+ # * index - the index of the row
2409
+ def [](index)
2410
+ raise UnknownTableException , "Unable to locate a table using #{@how} and #{@what} " if @o == nil
2411
+ return TableRow.new(@ieController ,:direct, row(index) )
2412
+ end
2413
+
2414
+ # This method returns the number of rows in the table.
2415
+ # Raises an UnknownTableException if the table doesnt exist.
2416
+ def row_count
2417
+ raise UnknownTableException , "Unable to locate a table using #{@how} and #{@what} " if @o == nil
2418
+ #return table_body.children.length
2419
+ return @o.getElementsByTagName("TR").length
2420
+ end
2421
+
2422
+ # This method returns the number of columns in a row of the table.
2423
+ # Raises an UnknownTableException if the table doesn't exist.
2424
+ # * index - the index of the row
2425
+ def column_count(index=1)
2426
+ raise UnknownTableException , "Unable to locate a table using #{@how} and #{@what} " if @o == nil
2427
+ row(index).cells.length
2428
+ end
2429
+
2430
+ # This method returns the table as a 2 dimensional array. Dont expect too much if there are nested tables, colspan etc.
2431
+ # Raises an UnknownTableException if the table doesn't exist.
2432
+ def to_a
2433
+ raise UnknownTableException , "Unable to locate a table using #{@how} and #{@what} " if @o == nil
2434
+ y = []
2435
+ table_rows = @o.getElementsByTagName("TR")
2436
+ for row in table_rows
2437
+ x = []
2438
+ for td in row.getElementsbyTagName("TD")
2439
+ x << td.innerText.strip
2440
+ end
2441
+ y << x
2442
+ end
2443
+ return y
2444
+
2445
+ end
2446
+
2447
+ def table_body(index=1)
2448
+ return @o.getElementsByTagName('TBODY')[index]
2449
+ end
2450
+ private :table_body
2451
+
2452
+ def body( how , what )
2453
+ return TableBody.new( @ieController, how, what , self)
2454
+ end
2455
+
2456
+ def bodies
2457
+ return TableBodies.new(@ieController, :direct , @o)
2458
+ end
2459
+
2460
+ def row(index)
2461
+ return @o.invoke("rows")[(index-1).to_s]
2462
+ end
2463
+ private :row
2464
+
2465
+ # Returns an array containing all the text values in the specified column
2466
+ # Raises an UnknownCellException if the specified column does not exist in every
2467
+ # Raises an UnknownTableException if the table doesn't exist.
2468
+ # row of the table
2469
+ # * columnnumber - column index to extract values from
2470
+ def column_values(columnnumber)
2471
+ return (1..row_count).collect {|idx| self[idx][columnnumber].text}
2472
+ end
2473
+
2474
+ # Returns an array containing all the text values in the specified row
2475
+ # Raises an UnknownTableException if the table doesn't exist.
2476
+ # * rownumber - row index to extract values from
2477
+ def row_values(rownumber)
2478
+ return (1..column_count(rownumber)).collect {|idx| self[rownumber][idx].text}
2479
+ end
2480
+
2481
+ end
2482
+
2483
+
2484
+ # this class is a collection of the table body objects that exist in the table
2485
+ # it wouldnt normally be created by a user, but gets returned by the bodies method of the Table object
2486
+ # many of the methods available to this object are inherited from the Element class
2487
+ #
2488
+ class TableBodies<Element
2489
+ def initialize(ieController, how, what )
2490
+ @ieController = ieController
2491
+ @o= nil
2492
+ if how == :direct
2493
+ @o = what # in this case, @o is the parent table
2494
+ end
2495
+ end
2496
+
2497
+ # returns the number of TableBodies that exist in the table
2498
+ def length
2499
+ assert_exists
2500
+ return @o.tBodies.length
2501
+ end
2502
+
2503
+ # returns the n'th Body as a Watir TableBody object
2504
+ def []n
2505
+ assert_exists
2506
+ return TableBody.new( @ieController , :direct , @o.tBodies[(n-1).to_s] )
2507
+ end
2508
+
2509
+ def get_IE_table_body_at_index( n )
2510
+ return @o.tBodies[(n-1).to_s]
2511
+ end
2512
+
2513
+ # iterates through each of the TableBodies in the Table. Yields a TableBody object
2514
+ def each
2515
+ 0.upto( @o.tBodies.length-1 ) { |i | yield TableBody.new( @ieController , :direct , @o.tBodies[i.to_s] ) }
2516
+ end
2517
+
2518
+ end
2519
+
2520
+
2521
+ # this class is a table body
2522
+ class TableBody<Element
2523
+ def initialize(ieController, how, what, parent_table=nil )
2524
+ @ieController = ieController
2525
+ @o= nil
2526
+ if how == :direct
2527
+ @o = what # in this case, @o is the table body
2528
+ elsif how == :index
2529
+ @o=parent_table.bodies.get_IE_table_body_at_index( what )
2530
+ end
2531
+ @rows = []
2532
+ update_rows
2533
+ super(@o)
2534
+ end
2535
+
2536
+ # This method updates the internal representation of the table. It can be used on dynamic tables to update the watir representation
2537
+ # after the table has changed
2538
+ # BUG: Remove
2539
+ def update_rows
2540
+ if @o
2541
+ @o.rows.each do |oo|
2542
+ @rows << TableRow.new(@ieController, :direct, oo)
2543
+ end
2544
+ end
2545
+ end
2546
+
2547
+ # returns the specified row as a TableRow object
2548
+ def []n
2549
+ assert_exists
2550
+ return TableRow.new( @ieController , :direct , @rows[n-1] )
2551
+ end
2552
+
2553
+ # iterates through all the rows in the table body
2554
+ def each
2555
+ 0.upto( @rows.length-1 ) { |i | yield @rows[i] }
2556
+ end
2557
+
2558
+ # returns the number of rows in this table body.
2559
+ def length
2560
+ return @rows.length
2561
+ end
2562
+ end
2563
+
2564
+
2565
+ # this class is a table row
2566
+ class TableRow < Element
2567
+
2568
+ # Returns an initialized instance of a table row
2569
+ # * o - the object contained in the row
2570
+ # * ieController - an instance of an IE object
2571
+ # * how - symbol - how we access the row
2572
+ # * what - what we use to access the row - id, index etc. If how is :direct then what is a Internet Explorer Raw Row
2573
+ def initialize(ieController , how, what)
2574
+ @ieController = ieController
2575
+ @how = how
2576
+ @what = what
2577
+ @o=nil
2578
+ if how == :direct
2579
+ @o = what
2580
+ else
2581
+ @o = ieController.getTablePart( "TR" , how , what )
2582
+ end
2583
+ update_row_cells
2584
+ super( @o )
2585
+ end
2586
+
2587
+
2588
+ # this method updates the internal list of cells.
2589
+ def update_row_cells
2590
+ if @o # cant call the assert_exists here, as an exists? method call will fail
2591
+ @cells=[]
2592
+ @o.cells.each do |oo|
2593
+ @cells << TableCell.new(@ieController, :direct, oo)
2594
+ end
2595
+ end
2596
+ end
2597
+
2598
+ # this method iterates through each of the cells in the row. Yields a TableCell object
2599
+ def each
2600
+ 0.upto( @cells.length-1 ) { |i | yield @cells[i] }
2601
+ end
2602
+
2603
+ # Returns an element from the row as a TableCell object
2604
+ def [](index)
2605
+ assert_exists
2606
+ raise UnknownCellException , "Unable to locate a cell at index #{index}" if @cells.length < index
2607
+ return @cells[(index-1)]
2608
+ end
2609
+
2610
+ #defaults all missing methods to the array of elements, to be able to
2611
+ # use the row as an array
2612
+ def method_missing(aSymbol,*args)
2613
+ return @o.send(aSymbol,*args)
2614
+ end
2615
+
2616
+ def column_count
2617
+ @cells.length
2618
+ end
2619
+ end
2620
+
2621
+ # this class is a table cell - when called via the Table object
2622
+ class TableCell <Element
2623
+ include Watir::Exception
2624
+ include SupportsSubElements
2625
+
2626
+ attr_reader :typingspeed
2627
+ attr_reader :activeObjectHighLightColor
2628
+
2629
+ # Returns an initialized instance of a table cell
2630
+ # * ieController - an IE object
2631
+ # * how - symbol - how we access the cell
2632
+ # * what - what we use to access the cell - id, name index etc
2633
+ def initialize( ieController, how , what )
2634
+ @ieController = ieController
2635
+ #puts "How = #{how}"
2636
+ if how == :direct
2637
+ @o = what
2638
+ #puts "@o.class=#{@o.class}"
2639
+ else
2640
+ @o = ieController.getTablePart( "TD" , how , what )
2641
+ end
2642
+ super( @o )
2643
+ @how = how
2644
+ @what = what
2645
+ @typingspeed = @ieController.typingspeed
2646
+ @activeObjectHighLightColor = @ieController.activeObjectHighLightColor
2647
+ end
2648
+
2649
+ def getContainerContents
2650
+ return @o.all
2651
+ end
2652
+ private :getContainerContents
2653
+
2654
+ def getContainer
2655
+ return @o
2656
+ end
2657
+
2658
+ def document
2659
+ return @o
2660
+ end
2661
+
2662
+ # returns the contents of the cell as text
2663
+ def text
2664
+ raise UnknownObjectException , "Unable to locate table cell with #{@how} of #{@what}" if @o == nil
2665
+ return @o.innerText.strip
2666
+ end
2667
+ alias to_s text
2668
+
2669
+ def colspan
2670
+ @o.colSpan
2671
+ end
2672
+
2673
+ end
2674
+
2675
+ # This class is the means of accessing an image on a page.
2676
+ # Normally a user would not need to create this object as it is returned by the Watir::SupportsSubElements#image method
2677
+ #
2678
+ # many of the methods available to this object are inherited from the Element class
2679
+ #
2680
+ class Image < Element
2681
+
2682
+ # Returns an initialized instance of a image object
2683
+ # * ieController - an instance of an IEController
2684
+ # * how - symbol - how we access the image
2685
+ # * what - what we use to access the image, name, src, index, id or alt
2686
+ def initialize( ieController, how , what )
2687
+ @ieController = ieController
2688
+ @how = how
2689
+ @what = what
2690
+ @o = @ieController.getImage(@how, @what)
2691
+ super( @o )
2692
+ end
2693
+
2694
+ # this method produces the properties for an image as an array
2695
+ def image_string_creator
2696
+ n = []
2697
+ n << "src:".ljust(TO_S_SIZE) + self.src.to_s
2698
+ n << "file date:".ljust(TO_S_SIZE) + self.fileCreatedDate.to_s
2699
+ n << "file size:".ljust(TO_S_SIZE) + self.fileSize.to_s
2700
+ n << "width:".ljust(TO_S_SIZE) + self.width.to_s
2701
+ n << "height:".ljust(TO_S_SIZE) + self.height.to_s
2702
+ n << "alt:".ljust(TO_S_SIZE) + self.alt.to_s
2703
+ return n
2704
+ end
2705
+ private :image_string_creator
2706
+
2707
+ # returns a string representation of the object
2708
+ def to_s
2709
+ assert_exists
2710
+ r = string_creator
2711
+ r=r + image_string_creator
2712
+ return r.join("\n")
2713
+ end
2714
+
2715
+ def_wrap :src
2716
+
2717
+ # this method returns the file created date of the image
2718
+ def fileCreatedDate
2719
+ assert_exists
2720
+ return @o.invoke("fileCreatedDate")
2721
+ end
2722
+
2723
+ # this method returns the filesize of the image
2724
+ def fileSize
2725
+ assert_exists
2726
+ return @o.invoke("fileSize").to_s
2727
+ end
2728
+
2729
+ # returns the width in pixels of the image, as a string
2730
+ def width
2731
+ assert_exists
2732
+ return @o.invoke("width").to_s
2733
+ end
2734
+
2735
+ # returns the alt text of the image
2736
+ def alt
2737
+ assert_exists
2738
+ return @o.invoke("alt").to_s
2739
+ end
2740
+
2741
+
2742
+ # returns the height in pixels of the image, as a string
2743
+ def height
2744
+ assert_exists
2745
+ return @o.invoke("height").to_s
2746
+ end
2747
+
2748
+ # returns the type of the object - 'image'
2749
+ def type
2750
+ assert_exists
2751
+ return "image"
2752
+ end
2753
+
2754
+ # This method attempts to find out if the image was actually loaded by the web browser.
2755
+ # If the image was not loaded, the browser is unable to determine some of the properties.
2756
+ # We look for these missing properties to see if the image is really there or not.
2757
+ # If the Disk cache is full ( tools menu -> Internet options -> Temporary Internet Files) , it may produce incorrect responses.
2758
+ def hasLoaded?
2759
+ raise UnknownObjectException , "Unable to locate image using #{@how} and #{@what} " if @o==nil
2760
+ return false if @o.fileCreatedDate == "" and @o.fileSize.to_i == -1
2761
+ return true
2762
+ end
2763
+
2764
+ # this method highlights the image ( in fact it adds or removes a border around the image)
2765
+ # * setOrClear - symbol - :set to set the border, :clear to remove it
2766
+ def highLight( setOrClear )
2767
+ if setOrClear == :set
2768
+ begin
2769
+ @original_border = @o.border
2770
+ @o.border = 1
2771
+ rescue
2772
+ @original_border = nil
2773
+ end
2774
+ else
2775
+ begin
2776
+ @o.border = @original_border
2777
+ @original_border = nil
2778
+ rescue
2779
+ # we could be here for a number of reasons...
2780
+ ensure
2781
+ @original_border = nil
2782
+ end
2783
+ end
2784
+ end
2785
+ private :highLight
2786
+
2787
+ # This method saves the image to the file path that is given. The
2788
+ # path must be in windows format (c:\\dirname\\somename.gif). This method
2789
+ # will not overwrite a previously existing image. If an image already
2790
+ # exists at the given path then a dialog will be displayed prompting
2791
+ # for overwrite.
2792
+ # Raises a WatirException if AutoIt is not correctly installed
2793
+ # path - directory path and file name of where image should be saved
2794
+ def save(path)
2795
+ require 'watir/windowhelper'
2796
+ WindowHelper.check_autoit_installed
2797
+ @ieController.goto(src)
2798
+ begin
2799
+ thrd = fill_save_image_dialog(path)
2800
+ @ieController.document.execCommand("SaveAs")
2801
+ thrd.join(5)
2802
+ ensure
2803
+ @ieController.back
2804
+ end
2805
+ end
2806
+
2807
+ def fill_save_image_dialog(path)
2808
+ Thread.new do
2809
+ 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\"")
2810
+ end
2811
+ end
2812
+ private :fill_save_image_dialog
2813
+ end
2814
+
2815
+
2816
+ # This class is the means of accessing a link on a page
2817
+ # Normally a user would not need to create this object as it is returned by the Watir::SupportsSubElements#link method
2818
+ # many of the methods available to this object are inherited from the Element class
2819
+ #
2820
+ class Link < Element
2821
+ # Returns an initialized instance of a link object
2822
+ # * ieController - an instance of an IEController
2823
+ # * how - symbol - how we access the link
2824
+ # * what - what we use to access the link, text, url, index etc
2825
+ def initialize( ieController, how , what )
2826
+ @ieController = ieController
2827
+ @how = how
2828
+ @what = what
2829
+ begin
2830
+ @o = @ieController.getLink( @how, @what )
2831
+ rescue UnknownObjectException
2832
+ @o = nil
2833
+ end
2834
+ super( @o )
2835
+ end
2836
+
2837
+ # returns 'link' as the object type
2838
+ def type
2839
+ assert_exists
2840
+ return "link"
2841
+ end
2842
+
2843
+ # returns the text displayed by the link
2844
+ def innerText
2845
+ assert_exists
2846
+ return @o.innerText.strip
2847
+ end
2848
+ alias text innerText
2849
+
2850
+ # returns the url the link points to
2851
+ def_wrap :href
2852
+
2853
+ # if an image is used as part of the link, this will return true
2854
+ def link_has_image
2855
+ return true if @o.getElementsByTagName("IMG").length > 0
2856
+ return false
2857
+ end
2858
+
2859
+ # this method returns the src of an image, if an image is used as part of the link
2860
+ def src
2861
+ if @o.getElementsByTagName("IMG").length > 0
2862
+ return @o.getElementsByTagName("IMG")[0.to_s].src
2863
+ else
2864
+ return ""
2865
+ end
2866
+ end
2867
+
2868
+ def link_string_creator
2869
+ n = []
2870
+ n << "href:".ljust(TO_S_SIZE) + self.href
2871
+ n << "inner text:".ljust(TO_S_SIZE) + self.innerText
2872
+ n << "img src:".ljust(TO_S_SIZE) + self.src if self.link_has_image
2873
+ return n
2874
+ end
2875
+
2876
+ # returns a textual description of the link
2877
+ def to_s
2878
+ assert_exists
2879
+ r = string_creator
2880
+ r=r + link_string_creator
2881
+ return r.join("\n")
2882
+ end
2883
+ end
2884
+
2885
+ # This class is the way in which select boxes are manipulated.
2886
+ # Normally a user would not need to create this object as it is returned by the Watir::SupportsSubElements#select_list method
2887
+ #
2888
+ # many of the methods available to this object are inherited from the Element class
2889
+ #
2890
+ class SelectList < Element
2891
+ # returns an initialized instance of a SelectList object
2892
+ # * ieController - an instance of an IEController
2893
+ # * how - symbol - how we access the select box
2894
+ # * what - what we use to access the select box, name, id etc
2895
+ def initialize( ieController, how , what )
2896
+ @ieController = ieController
2897
+ @how = how
2898
+ @what = what
2899
+ @o = @ieController.getObject(@how, @what, ["select-one", "select-multiple"])
2900
+ super( @o )
2901
+ end
2902
+
2903
+ attr :o
2904
+
2905
+ # This method clears the selected items in the select box
2906
+ def clearSelection
2907
+ assert_exists
2908
+ highLight( :set)
2909
+ wait = false
2910
+ @o.each do |selectBoxItem|
2911
+ if selectBoxItem.selected
2912
+ selectBoxItem.selected = false
2913
+ wait = true
2914
+ end
2915
+ end
2916
+ @ieController.wait if wait
2917
+ highLight( :clear)
2918
+ end
2919
+ # private :clearSelection
2920
+
2921
+ # This method selects an item, or items in a select box, by text.
2922
+ # Raises NoValueFoundException if the specified value is not found.
2923
+ # * item - the thing to select, string, reg exp or an array of string and reg exps
2924
+ def select( item )
2925
+ select_item_in_select_list( :text , item )
2926
+ end
2927
+
2928
+ # Selects an item, or items in a select box, by value.
2929
+ # Raises NoValueFoundException if the specified value is not found.
2930
+ # * item - the value of the thing to select, string, reg exp or an array of string and reg exps
2931
+ def select_value( item )
2932
+ select_item_in_select_list( :value , item )
2933
+ end
2934
+
2935
+ # BUG: Should be private
2936
+ # Selects something from the select box
2937
+ # * name - symbol :value or :text - how we find an item in the select box
2938
+ # * item - string or reg exp - what we are looking for
2939
+ def select_item_in_select_list( attribute, value )
2940
+ assert_exists
2941
+ highLight( :set )
2942
+ doBreak = false
2943
+ @ieController.log "Setting box #{@o.name} to #{attribute} #{value} "
2944
+ @o.each do |option| # items in the list
2945
+ if value.matches( option.invoke(attribute.to_s))
2946
+ if option.selected
2947
+ doBreak = true
2948
+ break
2949
+ else
2950
+ option.selected = true
2951
+ @o.fireEvent("onChange")
2952
+ @ieController.wait
2953
+ doBreak = true
2954
+ break
2955
+ end
2956
+ end
2957
+ end
2958
+ unless doBreak
2959
+ raise NoValueFoundException,
2960
+ "No option with #{attribute.to_s} of #{value} in this select element"
2961
+ end
2962
+ highLight( :clear )
2963
+ end
2964
+
2965
+ # Returns all the items in the select list as an array.
2966
+ # An empty array is returned if the select box has no contents.
2967
+ # Raises UnknownObjectException if the select box is not found
2968
+ def getAllContents()
2969
+ assert_exists
2970
+ @ieController.log "There are #{@o.length} items"
2971
+ returnArray = []
2972
+ @o.each { |thisItem| returnArray << thisItem.text }
2973
+ return returnArray
2974
+ end
2975
+
2976
+ # Returns the selected items as an array.
2977
+ # Raises UnknownObjectException if the select box is not found.
2978
+ def getSelectedItems
2979
+ assert_exists
2980
+ returnArray = []
2981
+ @ieController.log "There are #{@o.length} items"
2982
+ @o.each do |thisItem|
2983
+ if thisItem.selected
2984
+ @ieController.log "Item ( #{thisItem.text} ) is selected"
2985
+ returnArray << thisItem.text
2986
+ end
2987
+ end
2988
+ return returnArray
2989
+ end
2990
+
2991
+ def option (attribute, value)
2992
+ Option.new(self, attribute, value)
2993
+ end
2994
+ end
2995
+
2996
+ module OptionAccess
2997
+ def text
2998
+ @option.text
2999
+ end
3000
+ def value
3001
+ @option.value
3002
+ end
3003
+ def selected
3004
+ @option.selected
3005
+ end
3006
+ end
3007
+
3008
+ class OptionWrapper
3009
+ include OptionAccess
3010
+ def initialize (option)
3011
+ @option = option
3012
+ end
3013
+ end
3014
+
3015
+ # An item in a select list
3016
+ class Option
3017
+ include OptionAccess
3018
+ include Watir::Exception
3019
+ def initialize (select_list, attribute, value)
3020
+ @select_list = select_list
3021
+ @how = attribute
3022
+ @what = value
3023
+ @option = nil
3024
+
3025
+ unless [:text, :value].include? attribute
3026
+ raise MissingWayOfFindingObjectException,
3027
+ "Option does not support attribute #{@how}"
3028
+ end
3029
+ @select_list.o.each do |option| # items in the list
3030
+ if value.matches( option.invoke(attribute.to_s))
3031
+ @option = option
3032
+ break
3033
+ end
3034
+ end
3035
+
3036
+ end
3037
+ def assert_exists
3038
+ unless @option
3039
+ raise UnknownObjectException,
3040
+ "Unable to locate an option using #{@how} and #{@what}"
3041
+ end
3042
+ end
3043
+ private :assert_exists
3044
+ def select
3045
+ assert_exists
3046
+ @select_list.select_item_in_select_list(@how, @what)
3047
+ end
3048
+ end
3049
+
3050
+ # This is the main class for accessing buttons.
3051
+ # Normally a user would not need to create this object as it is returned by the Watir::SupportsSubElements#button method
3052
+ #
3053
+ # most of the methods available to Button objects are inherited from the Element class
3054
+ #
3055
+ class Button < Element
3056
+ def initialize( ieController, how , what )
3057
+ @ieController = ieController
3058
+ @how = how
3059
+ @what = what
3060
+ if(how == :from_object) then
3061
+ @o = what
3062
+ else
3063
+ @o = @ieController.getObject( @how, @what , object_types)
3064
+ end
3065
+ super( @o )
3066
+ end
3067
+
3068
+ def object_types
3069
+ return ["button" , "submit" , "image" , "reset" ]
3070
+ end
3071
+
3072
+ end
3073
+
3074
+
3075
+ # File dialog
3076
+ class FileField < Element
3077
+ # Create an instance of the file object
3078
+ def initialize( ieController, how , what )
3079
+ @ieController = ieController
3080
+ @how = how
3081
+ @what = what
3082
+ super( @o )
3083
+ @o = @ieController.getObject( @how, @what , ["file"] )
3084
+
3085
+ end
3086
+
3087
+ def set(setPath)
3088
+ assert_exists
3089
+ Thread.new {
3090
+ clicker = WinClicker.new
3091
+ clicker.setFileRequesterFileName_newProcess(setPath)
3092
+ }
3093
+ # may need to experiment with this value. if it takes longer than this
3094
+ # to open the new external Ruby process, the current thread may become
3095
+ # blocked by the file chooser.
3096
+ sleep(1)
3097
+ self.click
3098
+ end
3099
+ end
3100
+
3101
+ # This class is the class for radio buttons and check boxes.
3102
+ # It contains methods common to both.
3103
+ # Normally a user would not need to create this object as it is returned by the Watir::SupportsSubElements#checkbox or Watir::SupportsSubElements#radio methods
3104
+ #
3105
+ # most of the methods available to this element are inherited from the Element class
3106
+ #
3107
+ class RadioCheckCommon < Element
3108
+
3109
+ def initialize( ieController, how , what , type, value=nil )
3110
+ @ieController = ieController
3111
+ @how = how
3112
+ @what = what
3113
+ @type = type
3114
+ @value = value
3115
+ @o = @ieController.getObject(@how, @what, @type, @value)
3116
+ super( @o )
3117
+ end
3118
+
3119
+ # This method determines if a radio button or check box is set.
3120
+ # Returns true is set/checked or false if not set/checked.
3121
+ # Raises UnknownObjectException if its unable to locate an object.
3122
+ def isSet?
3123
+ assert_exists
3124
+ return @o.checked
3125
+ end
3126
+ alias getState isSet?
3127
+ alias checked? isSet?
3128
+
3129
+ # This method clears a radio button or check box. Note, with radio buttons one of them will almost always be set.
3130
+ # Returns true if set or false if not set.
3131
+ # Raises UnknownObjectException if its unable to locate an object
3132
+ # ObjectDisabledException IF THE OBJECT IS DISABLED
3133
+ def clear
3134
+ assert_exists
3135
+ assert_enabled
3136
+ highLight( :set)
3137
+ set_clear_item( false )
3138
+ highLight( :clear )
3139
+ end
3140
+
3141
+ # This method sets the radio list item or check box.
3142
+ # Raises UnknownObjectException if its unable to locate an object
3143
+ # ObjectDisabledException if the object is disabled
3144
+ def set
3145
+ assert_exists
3146
+ assert_enabled
3147
+ highLight( :set)
3148
+ set_clear_item( true )
3149
+ highLight( :clear )
3150
+ end
3151
+
3152
+ # This method is the common code for setting or clearing checkboxes and radio. A user would normalyy not access this, but use Checkbox#set etc
3153
+ def set_clear_item( set )
3154
+ @o.checked = set
3155
+ @o.fireEvent("onClick")
3156
+ @ieController.wait
3157
+ end
3158
+ private :set_clear_item
3159
+
3160
+ end
3161
+
3162
+ #--
3163
+ # this class is only used to change the name of the class that radio buttons use to something more meaningful
3164
+ # and to make the docs better
3165
+ #++
3166
+ # This class is the watir representation of a radio button.
3167
+ class Radio < RadioCheckCommon
3168
+
3169
+ end
3170
+
3171
+
3172
+ # This class is the watir representation of a check box.
3173
+ class CheckBox < RadioCheckCommon
3174
+
3175
+ # This method, with no arguments supplied, sets the check box.
3176
+ # If the optional set_or_clear is supplied, the checkbox is set, when its true and cleared when its false
3177
+ # Raises UnknownObjectException if its unable to locate an object
3178
+ # ObjectDisabledException if the object is disabled
3179
+ def set( set_or_clear=true )
3180
+ assert_exists
3181
+ assert_enabled
3182
+ highLight( :set)
3183
+
3184
+ if set_or_clear == true
3185
+ if @o.checked == false
3186
+ set_clear_item( true )
3187
+ end
3188
+ else
3189
+ self.clear
3190
+ end
3191
+ highLight( :clear )
3192
+ end
3193
+
3194
+ # This method clears a check box.
3195
+ # Returns true if set or false if not set.
3196
+ # Raises UnknownObjectException if its unable to locate an object
3197
+ # ObjectDisabledException if the object is disabled
3198
+ def clear
3199
+ assert_exists
3200
+ assert_enabled
3201
+ highLight( :set)
3202
+ if @o.checked == true
3203
+ set_clear_item( false )
3204
+ end
3205
+ highLight( :clear)
3206
+ end
3207
+
3208
+
3209
+ end
3210
+
3211
+
3212
+ # This class is the main class for Text Fields
3213
+ # Normally a user would not need to create this object as it is returned by the Watir::SupportsSubElements#text_field method
3214
+ #
3215
+ # most of the methods available to this element are inherited from the Element class
3216
+ #
3217
+ class TextField < Element
3218
+
3219
+ def initialize( ieController, how , what )
3220
+ @ieController = ieController
3221
+ @how = how
3222
+ @what = what
3223
+
3224
+ if(how != :from_object) then
3225
+ @o = @ieController.getObject(@how, @what, supported_types)
3226
+ else
3227
+ @o = what
3228
+ end
3229
+ super( @o )
3230
+ end
3231
+
3232
+ def supported_types
3233
+ return ["text" , "password", "textarea"]
3234
+ end
3235
+ private :supported_types
3236
+
3237
+ def size
3238
+ assert_exists
3239
+ begin
3240
+ s=@o.size
3241
+ rescue
3242
+ # TextArea does not support size
3243
+ s=""
3244
+ end
3245
+ return s
3246
+
3247
+ end
3248
+
3249
+ def maxLength
3250
+ assert_exists
3251
+ begin
3252
+ s=@o.maxlength
3253
+ rescue
3254
+ # TextArea does not support maxLength
3255
+ s=""
3256
+ end
3257
+ return s
3258
+ end
3259
+
3260
+ def text_string_creator
3261
+ n = []
3262
+ n << "length:".ljust(TO_S_SIZE) + self.size.to_s
3263
+ n << "max length:".ljust(TO_S_SIZE) + self.maxLength.to_s
3264
+ n << "read only:".ljust(TO_S_SIZE) + self.readonly?.to_s
3265
+
3266
+ return n
3267
+ end
3268
+
3269
+ def to_s
3270
+ assert_exists
3271
+ r = string_creator
3272
+ r=r + text_string_creator
3273
+ return r.join("\n")
3274
+ end
3275
+
3276
+ # This method returns true or false if the text field is read only.
3277
+ # Raises UnknownObjectException if the object can't be found.
3278
+ def readonly?
3279
+ assert_exists
3280
+ return @o.readOnly
3281
+ end
3282
+ alias readOnly? :readonly?
3283
+
3284
+ def assert_not_readonly
3285
+ raise ObjectReadOnlyException , "Textfield #{@how} and #{@what} is read only" if self.readonly?
3286
+ end
3287
+ #--
3288
+ # BUG: rename me
3289
+ #++
3290
+ # This method returns the current contents of the text field as a string.
3291
+ # Raises UnknownObjectException if the object can't be found
3292
+ def getContents()
3293
+ assert_exists
3294
+ return self.value
3295
+ end
3296
+
3297
+ # This method returns true orfalse if the text field contents is either a string match
3298
+ # or a regular expression match to the supplied value.
3299
+ # Raises UnknownObjectException if the object can't be found
3300
+ # * containsThis - string or reg exp - the text to verify
3301
+ def verify_contains( containsThis )
3302
+ assert_exists
3303
+ if containsThis.kind_of? String
3304
+ return true if self.value == containsThis
3305
+ elsif containsThis.kind_of? Regexp
3306
+ return true if self.value.match(containsThis) != nil
3307
+ end
3308
+ return false
3309
+ end
3310
+
3311
+ # this method is used to drag the entire contents of the text field to another text field
3312
+ # 19 Jan 2005 - It is added as prototype functionality, and may change
3313
+ # * destination_how - symbol, :id, :name how we identify the drop target
3314
+ # * destination_what - string or regular expression, the name, id, etc of the text field that will be the drop target
3315
+ def dragContentsTo( destination_how , destination_what)
3316
+ assert_exists
3317
+ destination = @ieController.textField(destination_how , destination_what)
3318
+
3319
+ raise UnknownObjectException , "Unable to locate destination using #{destination_how } and #{destination_what } " if destination.exists? == false
3320
+
3321
+ @o.focus
3322
+ @o.select()
3323
+ value = self.value
3324
+
3325
+ @o.fireEvent("onSelect")
3326
+ @o.fireEvent("ondragstart")
3327
+ @o.fireEvent("ondrag")
3328
+ destination.fireEvent("onDragEnter")
3329
+ destination.fireEvent("onDragOver")
3330
+ destination.fireEvent("ondrop")
3331
+
3332
+ @o.fireEvent("ondragend")
3333
+ destination.value= ( destination.value + value.to_s )
3334
+ self.value = ""
3335
+ end
3336
+
3337
+ # This method clears the contents of the text box.
3338
+ # Raises UnknownObjectException if the object can't be found
3339
+ # Raises ObjectDisabledException if the object is disabled
3340
+ # Raises ObjectReadOnlyException if the object is read only
3341
+ def clear
3342
+ assert_exists
3343
+ assert_enabled
3344
+ assert_not_readonly
3345
+
3346
+ highLight(:set)
3347
+
3348
+ @o.scrollIntoView
3349
+ @o.focus
3350
+ @o.select()
3351
+ @o.fireEvent("onSelect")
3352
+ @o.value = ""
3353
+ @o.fireEvent("onKeyPress")
3354
+ @o.fireEvent("onChange")
3355
+ @ieController.wait()
3356
+ highLight(:clear)
3357
+ end
3358
+
3359
+ # This method appens the supplied text to the contents of the text box.
3360
+ # Raises UnknownObjectException if the object cant be found
3361
+ # Raises ObjectDisabledException if the object is disabled
3362
+ # Raises ObjectReadOnlyException if the object is read only
3363
+ # * setThis - string - the text to append
3364
+ def append( setThis)
3365
+ assert_exists
3366
+ assert_enabled
3367
+ assert_not_readonly
3368
+
3369
+ highLight(:set)
3370
+ @o.scrollIntoView
3371
+ @o.focus
3372
+ doKeyPress( setThis )
3373
+ highLight(:clear)
3374
+ end
3375
+
3376
+ # This method sets the contents of the text box to the supplied text
3377
+ # Raises UnknownObjectException if the object cant be found
3378
+ # Raises ObjectDisabledException if the object is disabled
3379
+ # Raises ObjectReadOnlyException if the object is read only
3380
+ # * setThis - string - the text to set
3381
+ def set( setThis )
3382
+ assert_exists
3383
+ assert_enabled
3384
+ assert_not_readonly
3385
+
3386
+ highLight(:set)
3387
+ @o.scrollIntoView
3388
+ @o.focus
3389
+ @o.select()
3390
+ @o.fireEvent("onSelect")
3391
+ @o.value = ""
3392
+ @o.fireEvent("onKeyPress")
3393
+ doKeyPress( setThis )
3394
+ highLight(:clear)
3395
+ @o.fireEvent("onChange")
3396
+ @o.fireEvent("onBlur")
3397
+ end
3398
+
3399
+ # 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
3400
+ # it is preffered to use the set method.
3401
+ def value=(v)
3402
+ assert_exists
3403
+ @o.value = v.to_s
3404
+ end
3405
+
3406
+ def fire_key_events
3407
+ @o.fireEvent("onKeyDown")
3408
+ @o.fireEvent("onKeyPress")
3409
+ @o.fireEvent("onKeyUp")
3410
+ end
3411
+ private :fire_key_events
3412
+
3413
+ # This method is used internally by setText and appendText
3414
+ # It should not be used externally.
3415
+ # * value - string - The string to enter into the text field
3416
+ def doKeyPress( value )
3417
+ begin
3418
+ maxLength = @o.maxLength
3419
+ if value.length > maxLength
3420
+ value = suppliedValue[0 .. maxLength ]
3421
+ @ieController.log " Supplied string is #{suppliedValue.length} chars, which exceeds the max length (#{maxLength}) of the field. Using value: #{value}"
3422
+ end
3423
+ rescue
3424
+ # probably a text area - so it doesnt have a max Length
3425
+ maxLength = -1
3426
+ end
3427
+ for i in 0 .. value.length-1
3428
+ sleep @ieController.typingspeed # typing speed
3429
+ c = value[i,1]
3430
+ #@ieController.log " adding c.chr " + c #.chr.to_s
3431
+ @o.value = @o.value.to_s + c #c.chr
3432
+ fire_key_events
3433
+ end
3434
+
3435
+ end
3436
+ private :doKeyPress
3437
+ end
3438
+
3439
+ # this class can be used to access hidden field objects
3440
+ # Normally a user would not need to create this object as it is returned by the Watir::SupportsSubElements#hidden method
3441
+ #
3442
+ # most of the methods available to this element are inherited from the Element class
3443
+ #
3444
+ class Hidden < TextField
3445
+
3446
+ def initialize( ieController, how , what )
3447
+ super
3448
+ end
3449
+
3450
+ def supported_types
3451
+ return ["hidden"]
3452
+ end
3453
+
3454
+
3455
+ # set is overriden in this class, as there is no way to set focus to a hidden field
3456
+ def set(n)
3457
+ self.value=n
3458
+ end
3459
+
3460
+ # override the append method, so that focus isnt set to the hidden object
3461
+ def append(n)
3462
+ self.value = self.value.to_s + n.to_s
3463
+ end
3464
+
3465
+ # override the clear method, so that focus isnt set to the hidden object
3466
+ def clear
3467
+ self.value = ""
3468
+ end
3469
+
3470
+ # this method will do nothing, as you cant set focus to a hidden field
3471
+ def focus
3472
+ # do nothing!
3473
+ end
3474
+
3475
+ end
3476
+
3477
+ #--
3478
+ # These classes are not for public consumption, so we switch off rdoc
3479
+
3480
+
3481
+ # presumes element_class or element_tag is defined
3482
+ # for subclasses of ElementCollections
3483
+ module CommonCollection
3484
+ def element_tag
3485
+ element_class.tag
3486
+ end
3487
+ def length
3488
+ @ieController.getContainer.getElementsByTagName(element_tag).length
3489
+ end
3490
+ end
3491
+
3492
+ # This class is used as part of the .show method of the iterators class
3493
+ # it would not normally be used by a user
3494
+ class AttributeLengthPairs
3495
+
3496
+ # This class is used as part of the .show method of the iterators class
3497
+ # it would not normally be used by a user
3498
+ class AttributeLengthHolder
3499
+ attr_accessor :attribute
3500
+ attr_accessor :length
3501
+
3502
+ def initialize( attrib, length)
3503
+ @attribute = attrib
3504
+ @length = length
3505
+ end
3506
+ end
3507
+
3508
+ def initialize( attrib=nil , length=nil)
3509
+ @attr=[]
3510
+ add( attrib , length ) if attrib
3511
+ @index_counter=0
3512
+ end
3513
+
3514
+ # BUG: Untested. (Null implementation passes all tests.)
3515
+ def add( attrib , length)
3516
+ @attr << AttributeLengthHolder.new( attrib , length )
3517
+ end
3518
+
3519
+ def delete(attrib)
3520
+ item_to_delete=nil
3521
+ @attr.each_with_index do |e,i|
3522
+ item_to_delete = i if e.attribute==attrib
3523
+ end
3524
+ @attr.delete_at(item_to_delete ) unless item_to_delete == nil
3525
+ end
3526
+
3527
+ def next
3528
+ temp = @attr[@index_counter]
3529
+ @index_counter +=1
3530
+ return temp
3531
+ end
3532
+
3533
+ def each
3534
+ 0.upto( @attr.length-1 ) { |i | yield @attr[i] }
3535
+ end
3536
+ end
3537
+
3538
+ # resume rdoc
3539
+ #++
3540
+
3541
+
3542
+ # this class accesses the buttons in the document as a collection
3543
+ # it would normally only be accessed by the Watir::SupportsSubElements#buttons method
3544
+ #
3545
+ class Buttons < ElementCollections
3546
+ def element_class; Button; end
3547
+ def length
3548
+ get_length_of_input_objects(["button", "submit", "image"])
3549
+ end
3550
+
3551
+ def set_show_items
3552
+ super
3553
+ @show_attributes.add( "disabled" , 9)
3554
+ @show_attributes.add( "value" , 20)
3555
+ end
3556
+ end
3557
+
3558
+
3559
+ # this class accesses the file fields in the document as a collection
3560
+ # it would normally only be accessed by the Watir::SupportsSubElements#file_fields method
3561
+ #
3562
+ class FileFields< ElementCollections
3563
+ def element_class; FileField; end
3564
+ def length
3565
+ get_length_of_input_objects(["file"])
3566
+ end
3567
+
3568
+ def set_show_items
3569
+ super
3570
+ @show_attributes.add( "disabled" , 9)
3571
+ @show_attributes.add( "value" , 20)
3572
+ end
3573
+ end
3574
+
3575
+
3576
+ # this class accesses the check boxes in the document as a collection
3577
+ # Normally a user would not need to create this object as it is returned by the Watir::SupportsSubElements#checkboxes method
3578
+ #
3579
+ class CheckBoxes < ElementCollections
3580
+ def element_class; CheckBox; end
3581
+ def length
3582
+ get_length_of_input_objects("checkbox")
3583
+ end
3584
+ # this method creates an object of the correct type that the iterators use
3585
+ private
3586
+ def iterator_object(i)
3587
+ @ieController.checkbox(:index, i+1)
3588
+ end
3589
+ end
3590
+
3591
+ # this class accesses the radio buttons in the document as a collection
3592
+ # Normally a user would not need to create this object as it is returned by the Watir::SupportsSubElements#radios method
3593
+ #
3594
+ class Radios < ElementCollections
3595
+ def element_class; Radio; end
3596
+ def length
3597
+ get_length_of_input_objects("radio")
3598
+ end
3599
+ # this method creates an object of the correct type that the iterators use
3600
+ private
3601
+ def iterator_object(i)
3602
+ @ieController.radio(:index, i+1)
3603
+ end
3604
+ end
3605
+
3606
+ # this class accesses the select boxes in the document as a collection
3607
+ # Normally a user would not need to create this object as it is returned by the Watir::SupportsSubElements#select_lists method
3608
+ #
3609
+ class SelectLists < ElementCollections
3610
+ include CommonCollection
3611
+ def element_class; SelectList; end
3612
+ def element_tag; 'SELECT'; end
3613
+ end
3614
+
3615
+ # this class accesses the links in the document as a collection
3616
+ # Normally a user would not need to create this object as it is returned by the Watir::SupportsSubElements#links method
3617
+ #
3618
+ class Links < ElementCollections
3619
+ include CommonCollection
3620
+ def element_class; Link; end
3621
+ def element_tag; 'A'; end
3622
+
3623
+ def set_show_items
3624
+ super
3625
+ @show_attributes.add("href", 60)
3626
+ @show_attributes.add("innerText" , 60)
3627
+ end
3628
+
3629
+ end
3630
+
3631
+ # this class accesses the imnages in the document as a collection
3632
+ # Normally a user would not need to create this object as it is returned by the Watir::SupportsSubElements#images method
3633
+ #
3634
+ class Images < ElementCollections
3635
+ def element_class; Image; end
3636
+ def length
3637
+ @ieController.document.images.length
3638
+ end
3639
+
3640
+ def set_show_items
3641
+ super
3642
+ @show_attributes.add("src", 60)
3643
+ @show_attributes.add("alt", 30)
3644
+ end
3645
+
3646
+ end
3647
+
3648
+ # this class accesses the text fields in the document as a collection
3649
+ # Normally a user would not need to create this object as it is returned by the Watir::SupportsSubElements#text_fields method
3650
+ #
3651
+ class TextFields < ElementCollections
3652
+ def element_class; TextField; end
3653
+ def length
3654
+ # text areas are also included inthe Text_filds, but we need to get them seperately
3655
+ get_length_of_input_objects( ["text" , "password"] ) +
3656
+ @ieController.ie.document.body.getElementsByTagName("textarea").length
3657
+ end
3658
+ end
3659
+
3660
+ # this class accesses the hidden fields in the document as a collection
3661
+ # Normally a user would not need to create this object as it is returned by the Watir::SupportsSubElements#hiddens method
3662
+ class Hiddens < ElementCollections
3663
+ def element_class; Hidden; end
3664
+ def length
3665
+ get_length_of_input_objects("hidden")
3666
+ end
3667
+ end
3668
+
3669
+ # this class accesses the text fields in the document as a collection
3670
+ # Normally a user would not need to create this object as it is returned by the Watir::SupportsSubElements#tables method
3671
+ #
3672
+ class Tables < ElementCollections
3673
+ include CommonCollection
3674
+ def element_class; Table; end
3675
+ def element_tag; 'TABLE'; end
3676
+
3677
+ def set_show_items
3678
+ super
3679
+ @show_attributes.delete( "name")
3680
+ end
3681
+ end
3682
+
3683
+ # this class accesses the labels in the document as a collection
3684
+ # Normally a user would not need to create this object as it is returned by the Watir::SupportsSubElements#labels method
3685
+ #
3686
+ class Labels < ElementCollections
3687
+ include CommonCollection
3688
+ def element_class; Label; end
3689
+ def element_tag; 'LABEL'; end
3690
+
3691
+ def set_show_items
3692
+ super
3693
+ @show_attributes.add("htmlFor", 20)
3694
+ end
3695
+ end
3696
+
3697
+ # this class accesses the p tags in the document as a collection
3698
+ # Normally a user would not need to create this object as it is returned by the Watir::SupportsSubElements#ps method
3699
+ #
3700
+ class Ps < ElementCollections
3701
+ include CommonCollection
3702
+ def element_class; P; end
3703
+
3704
+ def set_show_items
3705
+ super
3706
+ @show_attributes.delete( "name")
3707
+ @show_attributes.add( "className" , 20)
3708
+ end
3709
+
3710
+ end
3711
+
3712
+ # this class accesses the spans in the document as a collection
3713
+ # Normally a user would not need to create this object as it is returned by the Watir::SupportsSubElements#spans method
3714
+ #
3715
+ class Spans < ElementCollections
3716
+ include CommonCollection
3717
+ def element_class; Span; end
3718
+
3719
+ def set_show_items
3720
+ super
3721
+ @show_attributes.delete( "name")
3722
+ @show_attributes.add( "className" , 20)
3723
+ end
3724
+
3725
+ end
3726
+
3727
+ # this class accesses the divs in the document as a collection
3728
+ # Normally a user would not need to create this object as it is returned by the Watir::SupportsSubElements#divs method
3729
+ #
3730
+ class Divs < ElementCollections
3731
+ include CommonCollection
3732
+ def element_class; Div; end
3733
+
3734
+ def set_show_items
3735
+ super
3736
+ @show_attributes.delete( "name")
3737
+ @show_attributes.add( "className" , 20)
3738
+ end
3739
+
3740
+ end
3741
+
3742
+ end
3743
+
3744
+ require 'watir/camel_case'