watir 1.8.1 → 1.9.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +10 -0
- data/VERSION +1 -1
- data/lib/watir/container.rb +7 -2
- data/lib/watir/core.rb +4 -0
- data/lib/watir/dialogs/file_upload.rb +36 -0
- data/lib/watir/dialogs/javascript.rb +47 -0
- data/lib/watir/element.rb +44 -4
- data/lib/watir/frame.rb +15 -2
- data/lib/watir/ie-class.rb +42 -18
- data/lib/watir/ie.rb +3 -6
- data/lib/watir/image.rb +5 -4
- data/lib/watir/input_elements.rb +40 -89
- data/lib/watir/modal_dialog.rb +6 -0
- data/lib/watir/module.rb +0 -23
- data/lib/watir/win32.rb +4 -0
- data/lib/watir/win32ole.rb +5 -2
- data/lib/watir/win32ole/1.8.7/win32ole.so +0 -0
- data/rakefile.rb +2 -1
- data/unittests/click_no_wait_test.rb +4 -2
- data/unittests/close_all_test.rb +1 -1
- data/unittests/dialog_test.rb +22 -38
- data/unittests/filefield_xpath_test.rb +4 -1
- data/unittests/form_test.rb +1 -0
- data/unittests/frame_test.rb +17 -1
- data/unittests/html/ie_9.html +6 -0
- data/unittests/html/iframe.html +3 -0
- data/unittests/ie9_test.rb +16 -0
- data/unittests/images_test.rb +1 -1
- data/unittests/minmax_test.rb +16 -9
- data/unittests/no_wait_test.rb +10 -4
- data/unittests/setup.rb +0 -13
- data/unittests/version_test.rb +15 -0
- data/unittests/win32ole_so_test.rb +35 -0
- data/unittests/windows/send_keys_test.rb +0 -6
- data/watir.gemspec +6 -4
- metadata +67 -38
- data/lib/watir/AutoItX.chm +0 -0
- data/lib/watir/AutoItX3.dll +0 -0
- data/lib/watir/WindowHelper.rb +0 -49
- data/lib/watir/clickJSDialog.rb +0 -19
- data/lib/watir/dialog.rb +0 -46
- data/lib/watir/popup.rb +0 -30
- data/lib/watir/setFileDialog.rb +0 -16
- data/lib/watir/win32ole/win32ole.so +0 -0
- data/lib/watir/winClicker.rb +0 -460
- data/unittests/other/WindowLogonExample.rb +0 -28
- data/unittests/other/WindowLogonExtra.rb +0 -7
- data/unittests/other/jscriptExtraAlert.rb +0 -7
- data/unittests/other/jscriptExtraConfirmCancel.rb +0 -7
- data/unittests/other/jscriptExtraConfirmOk.rb +0 -7
- data/unittests/other/jscriptPushButton.rb +0 -6
- data/unittests/other/jscript_test.rb +0 -63
- data/unittests/popups_test.rb +0 -41
data/watir.gemspec
CHANGED
@@ -2,10 +2,9 @@ require 'watir-rdoc'
|
|
2
2
|
|
3
3
|
$__watir_source_patterns = [
|
4
4
|
'CHANGES', 'rakefile.rb', 'VERSION', "README.rdoc", 'watir.gemspec', 'watir-rdoc.rb', 'LICENSE',
|
5
|
-
'lib/watir/*.rb', 'lib/watir/
|
6
|
-
'unittests/*.rb', 'unittests/html/*.html', 'unittests/html/images/*.*',
|
5
|
+
'lib/watir/*.rb', 'lib/watir/dialogs/*.rb', 'unittests/*.rb', 'unittests/html/*.html', 'unittests/html/images/*.*',
|
7
6
|
'unittests/other/*.rb', 'unittests/testcase/*.rb', 'unittests/windows/*.rb',
|
8
|
-
'lib/watir/IEDialog/Release/IEDialog.dll', 'lib/watir/win32ole/win32ole.so',
|
7
|
+
'lib/watir/IEDialog/Release/IEDialog.dll', 'lib/watir/win32ole/1.8.7/win32ole.so',
|
9
8
|
'lib/watir/contrib/*.rb'] +
|
10
9
|
$WATIR_EXTRA_RDOC_FILES
|
11
10
|
|
@@ -31,6 +30,7 @@ spec = Gem::Specification.new do |s|
|
|
31
30
|
s.homepage = 'http://www.watir.com/'
|
32
31
|
|
33
32
|
s.platform = Gem::Platform::RUBY
|
33
|
+
s.required_ruby_version = '>= 1.8.7'
|
34
34
|
s.requirements << 'Microsoft Windows running Internet Explorer 5.5 or later.'
|
35
35
|
s.require_path = 'lib'
|
36
36
|
|
@@ -39,6 +39,8 @@ spec = Gem::Specification.new do |s|
|
|
39
39
|
s.add_dependency 'commonwatir', '= ' + version
|
40
40
|
s.add_dependency 'firewatir', '= ' + version
|
41
41
|
s.add_dependency 'nokogiri'
|
42
|
+
s.add_dependency 'ffi', '~>1.0'
|
43
|
+
s.add_dependency 'rautomation', '~>0.5'
|
42
44
|
|
43
45
|
s.has_rdoc = true
|
44
46
|
s.rdoc_options += $WATIR_RDOC_OPTIONS
|
@@ -54,4 +56,4 @@ spec = Gem::Specification.new do |s|
|
|
54
56
|
}
|
55
57
|
}.flatten
|
56
58
|
|
57
|
-
end
|
59
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: watir
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 15424167
|
5
|
+
prerelease: 6
|
6
6
|
segments:
|
7
7
|
- 1
|
8
|
-
-
|
8
|
+
- 9
|
9
|
+
- 0
|
10
|
+
- rc
|
9
11
|
- 1
|
10
|
-
version: 1.
|
12
|
+
version: 1.9.0.rc1
|
11
13
|
platform: ruby
|
12
14
|
authors:
|
13
15
|
- Bret Pettichord
|
@@ -15,8 +17,7 @@ autorequire:
|
|
15
17
|
bindir: bin
|
16
18
|
cert_chain: []
|
17
19
|
|
18
|
-
date: 2011-
|
19
|
-
default_executable:
|
20
|
+
date: 2011-06-05 00:00:00 Z
|
20
21
|
dependencies:
|
21
22
|
- !ruby/object:Gem::Dependency
|
22
23
|
name: win32-process
|
@@ -58,12 +59,14 @@ dependencies:
|
|
58
59
|
requirements:
|
59
60
|
- - "="
|
60
61
|
- !ruby/object:Gem::Version
|
61
|
-
hash:
|
62
|
+
hash: 15424167
|
62
63
|
segments:
|
63
64
|
- 1
|
64
|
-
-
|
65
|
+
- 9
|
66
|
+
- 0
|
67
|
+
- rc
|
65
68
|
- 1
|
66
|
-
version: 1.
|
69
|
+
version: 1.9.0.rc1
|
67
70
|
type: :runtime
|
68
71
|
version_requirements: *id003
|
69
72
|
- !ruby/object:Gem::Dependency
|
@@ -74,12 +77,14 @@ dependencies:
|
|
74
77
|
requirements:
|
75
78
|
- - "="
|
76
79
|
- !ruby/object:Gem::Version
|
77
|
-
hash:
|
80
|
+
hash: 15424167
|
78
81
|
segments:
|
79
82
|
- 1
|
80
|
-
-
|
83
|
+
- 9
|
84
|
+
- 0
|
85
|
+
- rc
|
81
86
|
- 1
|
82
|
-
version: 1.
|
87
|
+
version: 1.9.0.rc1
|
83
88
|
type: :runtime
|
84
89
|
version_requirements: *id004
|
85
90
|
- !ruby/object:Gem::Dependency
|
@@ -96,6 +101,36 @@ dependencies:
|
|
96
101
|
version: "0"
|
97
102
|
type: :runtime
|
98
103
|
version_requirements: *id005
|
104
|
+
- !ruby/object:Gem::Dependency
|
105
|
+
name: ffi
|
106
|
+
prerelease: false
|
107
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
108
|
+
none: false
|
109
|
+
requirements:
|
110
|
+
- - ~>
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
hash: 15
|
113
|
+
segments:
|
114
|
+
- 1
|
115
|
+
- 0
|
116
|
+
version: "1.0"
|
117
|
+
type: :runtime
|
118
|
+
version_requirements: *id006
|
119
|
+
- !ruby/object:Gem::Dependency
|
120
|
+
name: rautomation
|
121
|
+
prerelease: false
|
122
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
123
|
+
none: false
|
124
|
+
requirements:
|
125
|
+
- - ~>
|
126
|
+
- !ruby/object:Gem::Version
|
127
|
+
hash: 1
|
128
|
+
segments:
|
129
|
+
- 0
|
130
|
+
- 5
|
131
|
+
version: "0.5"
|
132
|
+
type: :runtime
|
133
|
+
version_requirements: *id007
|
99
134
|
description: " WATIR is \"Web Application Testing in Ruby\". Watir (pronounced water) is a free,\n open-source functional testing tool for automating browser-based tests of web applications.\n It works with applications written in any language.\n Watir drives the Internet Explorer browser the same way an end user would.\n It clicks links, fills in forms, presses buttons.\n Watir also checks results, such as whether expected text appears on the\n page, or whether a control is enabled.\n Watir can test web applications written in any language.\n Watir is a Ruby library that works with Internet Explorer on Windows.\n"
|
100
135
|
email: watir-general@groups.google.com
|
101
136
|
executables:
|
@@ -113,13 +148,11 @@ files:
|
|
113
148
|
- watir-rdoc.rb
|
114
149
|
- LICENSE
|
115
150
|
- lib/watir/camel_case.rb
|
116
|
-
- lib/watir/clickJSDialog.rb
|
117
151
|
- lib/watir/close_all.rb
|
118
152
|
- lib/watir/collections.rb
|
119
153
|
- lib/watir/container.rb
|
120
154
|
- lib/watir/cookiemanager.rb
|
121
155
|
- lib/watir/core.rb
|
122
|
-
- lib/watir/dialog.rb
|
123
156
|
- lib/watir/element.rb
|
124
157
|
- lib/watir/element_collections.rb
|
125
158
|
- lib/watir/form.rb
|
@@ -138,17 +171,13 @@ files:
|
|
138
171
|
- lib/watir/module.rb
|
139
172
|
- lib/watir/non_control_elements.rb
|
140
173
|
- lib/watir/page-container.rb
|
141
|
-
- lib/watir/popup.rb
|
142
174
|
- lib/watir/process.rb
|
143
175
|
- lib/watir/screen_capture.rb
|
144
|
-
- lib/watir/setFileDialog.rb
|
145
176
|
- lib/watir/table.rb
|
146
177
|
- lib/watir/win32.rb
|
147
178
|
- lib/watir/win32ole.rb
|
148
|
-
- lib/watir/
|
149
|
-
- lib/watir/
|
150
|
-
- lib/watir/AutoItX3.dll
|
151
|
-
- lib/watir/AutoItX.chm
|
179
|
+
- lib/watir/dialogs/file_upload.rb
|
180
|
+
- lib/watir/dialogs/javascript.rb
|
152
181
|
- unittests/all_tests.rb
|
153
182
|
- unittests/buttons_xpath_test.rb
|
154
183
|
- unittests/checkbox_test.rb
|
@@ -171,6 +200,7 @@ files:
|
|
171
200
|
- unittests/form_xpath_test.rb
|
172
201
|
- unittests/frame_test.rb
|
173
202
|
- unittests/google_form_test.rb
|
203
|
+
- unittests/ie9_test.rb
|
174
204
|
- unittests/ie_exists_test.rb
|
175
205
|
- unittests/ie_mock.rb
|
176
206
|
- unittests/ie_test.rb
|
@@ -189,7 +219,6 @@ files:
|
|
189
219
|
- unittests/pagecontainstext_test.rb
|
190
220
|
- unittests/parent_child_test.rb
|
191
221
|
- unittests/perf_test.rb
|
192
|
-
- unittests/popups_test.rb
|
193
222
|
- unittests/pre_test.rb
|
194
223
|
- unittests/radios_test.rb
|
195
224
|
- unittests/radios_xpath_test.rb
|
@@ -208,6 +237,8 @@ files:
|
|
208
237
|
- unittests/textfields_test.rb
|
209
238
|
- unittests/textfields_xpath_test.rb
|
210
239
|
- unittests/textfield_for_ch_char_test.rb
|
240
|
+
- unittests/version_test.rb
|
241
|
+
- unittests/win32ole_so_test.rb
|
211
242
|
- unittests/window_tests.rb
|
212
243
|
- unittests/xpath_tests.rb
|
213
244
|
- unittests/html/blankpage.html
|
@@ -228,6 +259,8 @@ files:
|
|
228
259
|
- unittests/html/frame_links.html
|
229
260
|
- unittests/html/frame_multi.html
|
230
261
|
- unittests/html/google_india.html
|
262
|
+
- unittests/html/ie_9.html
|
263
|
+
- unittests/html/iframe.html
|
231
264
|
- unittests/html/iframeTest.html
|
232
265
|
- unittests/html/iframeTest1.html
|
233
266
|
- unittests/html/iframeTest2.html
|
@@ -275,19 +308,12 @@ files:
|
|
275
308
|
- unittests/html/images/square.jpg
|
276
309
|
- unittests/html/images/triangle.jpg
|
277
310
|
- unittests/other/all_tests_concurrent.rb
|
278
|
-
- unittests/other/jscriptExtraAlert.rb
|
279
|
-
- unittests/other/jscriptExtraConfirmCancel.rb
|
280
|
-
- unittests/other/jscriptExtraConfirmOk.rb
|
281
|
-
- unittests/other/jscriptPushButton.rb
|
282
|
-
- unittests/other/jscript_test.rb
|
283
311
|
- unittests/other/navigate_exception_test.rb
|
284
312
|
- unittests/other/rexml_unit_test.rb
|
285
313
|
- unittests/other/screen_capture_test.rb
|
286
314
|
- unittests/other/testcase_method_order_test.rb
|
287
315
|
- unittests/other/testcase_verify_test.rb
|
288
316
|
- unittests/other/wait_until_test.rb
|
289
|
-
- unittests/other/WindowLogonExample.rb
|
290
|
-
- unittests/other/WindowLogonExtra.rb
|
291
317
|
- unittests/windows/attach_to_existing_window_test.rb
|
292
318
|
- unittests/windows/attach_to_new_window_test.rb
|
293
319
|
- unittests/windows/close_window_test.rb
|
@@ -300,12 +326,11 @@ files:
|
|
300
326
|
- unittests/windows/open_close_test.rb
|
301
327
|
- unittests/windows/send_keys_test.rb
|
302
328
|
- lib/watir/IEDialog/Release/IEDialog.dll
|
303
|
-
- lib/watir/win32ole/win32ole.so
|
329
|
+
- lib/watir/win32ole/1.8.7/win32ole.so
|
304
330
|
- lib/watir/contrib/enabled_popup.rb
|
305
331
|
- lib/watir/contrib/ie-new-process.rb
|
306
332
|
- lib/watir/contrib/page_checker.rb
|
307
333
|
- bin/watir-console
|
308
|
-
has_rdoc: true
|
309
334
|
homepage: http://www.watir.com/
|
310
335
|
licenses: []
|
311
336
|
|
@@ -326,23 +351,27 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
326
351
|
requirements:
|
327
352
|
- - ">="
|
328
353
|
- !ruby/object:Gem::Version
|
329
|
-
hash:
|
354
|
+
hash: 57
|
330
355
|
segments:
|
331
|
-
-
|
332
|
-
|
356
|
+
- 1
|
357
|
+
- 8
|
358
|
+
- 7
|
359
|
+
version: 1.8.7
|
333
360
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
334
361
|
none: false
|
335
362
|
requirements:
|
336
|
-
- - "
|
363
|
+
- - ">"
|
337
364
|
- !ruby/object:Gem::Version
|
338
|
-
hash:
|
365
|
+
hash: 25
|
339
366
|
segments:
|
340
|
-
-
|
341
|
-
|
367
|
+
- 1
|
368
|
+
- 3
|
369
|
+
- 1
|
370
|
+
version: 1.3.1
|
342
371
|
requirements:
|
343
372
|
- Microsoft Windows running Internet Explorer 5.5 or later.
|
344
373
|
rubyforge_project: Watir
|
345
|
-
rubygems_version: 1.
|
374
|
+
rubygems_version: 1.7.2
|
346
375
|
signing_key:
|
347
376
|
specification_version: 3
|
348
377
|
summary: Automated testing tool for web applications.
|
data/lib/watir/AutoItX.chm
DELETED
Binary file
|
data/lib/watir/AutoItX3.dll
DELETED
Binary file
|
data/lib/watir/WindowHelper.rb
DELETED
@@ -1,49 +0,0 @@
|
|
1
|
-
require 'watir/win32ole'
|
2
|
-
require 'watir/ie' # for Watir.autoit
|
3
|
-
|
4
|
-
class WindowHelper
|
5
|
-
@@ie_window_name = "Windows Internet Explorer"
|
6
|
-
def initialize()
|
7
|
-
@autoit = Watir.autoit
|
8
|
-
end
|
9
|
-
|
10
|
-
def push_alert_button
|
11
|
-
@autoit.WinWait @@ie_window_name, ""
|
12
|
-
@autoit.Send "{ENTER}"
|
13
|
-
end
|
14
|
-
|
15
|
-
def push_confirm_button_ok
|
16
|
-
@autoit.WinWait @@ie_window_name, ""
|
17
|
-
@autoit.Send "{ENTER}"
|
18
|
-
end
|
19
|
-
|
20
|
-
def push_confirm_button_cancel
|
21
|
-
@autoit.WinWait @@ie_window_name, ""
|
22
|
-
@autoit.Send "{ESCAPE}"
|
23
|
-
end
|
24
|
-
|
25
|
-
def push_security_alert_yes
|
26
|
-
@autoit.WinWait "Security Alert", ""
|
27
|
-
@autoit.Send "{TAB}"
|
28
|
-
@autoit.Send "{TAB}"
|
29
|
-
@autoit.Send "{SPACE}"
|
30
|
-
end
|
31
|
-
|
32
|
-
def logon(title,name = 'john doe',password = 'john doe')
|
33
|
-
@autoit.WinWait title, ""
|
34
|
-
@autoit.Send name
|
35
|
-
@autoit.Send "{TAB}"
|
36
|
-
@autoit.Send password
|
37
|
-
@autoit.Send "{ENTER}"
|
38
|
-
end
|
39
|
-
|
40
|
-
def WindowHelper.check_autoit_installed
|
41
|
-
begin
|
42
|
-
Watir.autoit
|
43
|
-
rescue
|
44
|
-
raise Watir::Exception::WatirException, "The AutoIt dll must be correctly registered for this feature to work properly"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
|
data/lib/watir/clickJSDialog.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# clickJSDialog.rb
|
3
|
-
#
|
4
|
-
#
|
5
|
-
# This file contains the JS clicker when it runs as a separate process
|
6
|
-
|
7
|
-
$LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
8
|
-
puts $LOAD_PATH
|
9
|
-
require 'watir/winClicker'
|
10
|
-
|
11
|
-
button = "OK"
|
12
|
-
button = ARGV[0] unless ARGV[0] == nil
|
13
|
-
sleepTime = 0
|
14
|
-
sleepTime = ARGV[1] unless ARGV[1] == nil
|
15
|
-
|
16
|
-
|
17
|
-
clicker= WinClicker.new
|
18
|
-
result = clicker.clickJavaScriptDialog( button )
|
19
|
-
clicker = nil
|
data/lib/watir/dialog.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
require 'watir/ie'
|
2
|
-
# TODO: move this file to watir/contrib
|
3
|
-
|
4
|
-
module Watir
|
5
|
-
|
6
|
-
class Dialog
|
7
|
-
WindowName = 'Windows Internet Explorer'
|
8
|
-
def button(name)
|
9
|
-
DialogButton.new(name)
|
10
|
-
end
|
11
|
-
def close
|
12
|
-
# TODO: register autoit before use
|
13
|
-
autoit = WIN32OLE.new('AutoItX3.Control')
|
14
|
-
autoit.WinClose WindowName, ""
|
15
|
-
end
|
16
|
-
def exists?
|
17
|
-
# TODO: register autoit before use
|
18
|
-
autoit = WIN32OLE.new('AutoItX3.Control')
|
19
|
-
found = autoit.WinWait(WindowName, "", 1)
|
20
|
-
return found == 1
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def dialog
|
25
|
-
Dialog.new
|
26
|
-
end
|
27
|
-
|
28
|
-
class DialogButton
|
29
|
-
def initialize(name)
|
30
|
-
@name = name
|
31
|
-
end
|
32
|
-
def click
|
33
|
-
# TODO: register autoit before use
|
34
|
-
autoit = WIN32OLE.new('AutoItX3.Control')
|
35
|
-
autoit.WinWait Dialog::WindowName, "", 1
|
36
|
-
name_pattern = Regexp.new "^#{@name}$"
|
37
|
-
unless name_pattern =~ autoit.WinGetText(Dialog::WindowName, "")
|
38
|
-
raise Watir::Exception::UnknownObjectException
|
39
|
-
end
|
40
|
-
autoit.Send "{ENTER}"
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|
45
|
-
|
46
|
-
|
data/lib/watir/popup.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
module Watir
|
2
|
-
# POPUP object
|
3
|
-
class PopUp
|
4
|
-
def initialize(container)
|
5
|
-
@container = container
|
6
|
-
@page_container = container.page_container
|
7
|
-
end
|
8
|
-
|
9
|
-
def button(caption)
|
10
|
-
return JSButton.new(@container.getIE.hwnd, caption)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
class JSButton
|
15
|
-
def initialize(hWnd, caption)
|
16
|
-
@hWnd = hWnd
|
17
|
-
@caption = caption
|
18
|
-
end
|
19
|
-
|
20
|
-
def startClicker(waitTime=3)
|
21
|
-
clicker = WinClicker.new
|
22
|
-
clicker.clickJSDialog_Thread
|
23
|
-
# clickerThread = Thread.new(@caption) {
|
24
|
-
# sleep waitTime
|
25
|
-
# puts "After the wait time in startClicker"
|
26
|
-
# clickWindowsButton_hwnd(hwnd, buttonCaption)
|
27
|
-
#}
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
data/lib/watir/setFileDialog.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
#
|
2
|
-
# setFileDialog.rb
|
3
|
-
#
|
4
|
-
#
|
5
|
-
# This file contains the file dialog when it runs as a separate process
|
6
|
-
|
7
|
-
$LOAD_PATH << File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
8
|
-
puts $LOAD_PATH
|
9
|
-
require 'watir/winClicker'
|
10
|
-
|
11
|
-
filepath = "invalid path passed to setFileDialog.rb"
|
12
|
-
filepath = ARGV[0] unless ARGV[0] == nil
|
13
|
-
|
14
|
-
clicker= WinClicker.new
|
15
|
-
clicker.setFileRequesterFileName(filepath)
|
16
|
-
clicker = nil
|
Binary file
|
data/lib/watir/winClicker.rb
DELETED
@@ -1,460 +0,0 @@
|
|
1
|
-
=begin rdoc
|
2
|
-
This is Watir's window clicker helper class, uses Win32 api
|
3
|
-
calls to access buttons and windows.
|
4
|
-
|
5
|
-
Typical usage:
|
6
|
-
# include this file in your script
|
7
|
-
require "watir/winClicker.rb"
|
8
|
-
|
9
|
-
# create a new instance of WinClicker and use it
|
10
|
-
wc = WinClicker.new
|
11
|
-
wc.clickWindowsButton("My Window", "Click Me", 30)
|
12
|
-
|
13
|
-
=end
|
14
|
-
|
15
|
-
#
|
16
|
-
# class to click javascript dialog boxes, file requester dialogs etc
|
17
|
-
require 'dl/import'
|
18
|
-
require 'dl/struct'
|
19
|
-
require "timeout"
|
20
|
-
require 'Win32API'
|
21
|
-
|
22
|
-
class WinClicker
|
23
|
-
|
24
|
-
WM_CLOSE = 0x0010
|
25
|
-
WM_KEYDOWN = 0x0100
|
26
|
-
WM_KEYUP = 0x0101
|
27
|
-
WM_CHAR = 0x0102
|
28
|
-
BM_CLICK = 0x00F5
|
29
|
-
WM_COMMAND = 0x0111
|
30
|
-
WM_SETTEXT = 0x000C
|
31
|
-
WM_GETTEXT = 0x000D
|
32
|
-
|
33
|
-
HWND_TOP = 0
|
34
|
-
HWND_BOTTOM = 1
|
35
|
-
HWND_TOPMOST = -1
|
36
|
-
HWND_NOTOPMOST = -2
|
37
|
-
|
38
|
-
SWP_SHOWWINDOW = 0x40
|
39
|
-
SWP_NOSIZE = 1
|
40
|
-
SWP_NOMOVE = 2
|
41
|
-
|
42
|
-
TRUE_1 = 1
|
43
|
-
|
44
|
-
# these are constants for commonly used windows windows
|
45
|
-
WINCLASS_DIALOG = "32770"
|
46
|
-
|
47
|
-
# these are the most used methods
|
48
|
-
|
49
|
-
def initialize
|
50
|
-
@User32 = DL.dlopen("user32")
|
51
|
-
# we must determine the path we are in
|
52
|
-
@path_to_clicker = '"' + File.expand_path(File.dirname(__FILE__)) + '"'
|
53
|
-
end
|
54
|
-
|
55
|
-
|
56
|
-
# The system function passes command to the command interpreter, which executes the string as an operating-system command
|
57
|
-
# http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore98/html/_crt_system.2c_._wsystem.asp
|
58
|
-
# using win32api
|
59
|
-
def winsystem(command)
|
60
|
-
pid = Win32API.new("crtdll", "system", ['P'], 'L').Call(command)
|
61
|
-
end
|
62
|
-
|
63
|
-
# returns the short path version of a long path
|
64
|
-
# 8.3 style
|
65
|
-
def getShortFileName(longName)
|
66
|
-
size = 255
|
67
|
-
buffer = " " * 255
|
68
|
-
returnSize = Win32API.new("kernel32" , "GetShortPathNameA" , 'ppl' , 'L').Call(longName , buffer , size )
|
69
|
-
a = ""
|
70
|
-
a = a + buffer[0...returnSize]
|
71
|
-
return a
|
72
|
-
end
|
73
|
-
|
74
|
-
# Set the first edit box in the Choose file dialog to textToSet
|
75
|
-
# we may need to play with the default try count. 3 is a reasonably safe value.
|
76
|
-
def setFileRequesterFileName( textToSet, tryCount = 3 )
|
77
|
-
for i in (1..tryCount)
|
78
|
-
# first set the Choose File Window to be active
|
79
|
-
hWnd = getWindowHandle("Choose file" )
|
80
|
-
if hWnd != -1
|
81
|
-
makeWindowActive(hWnd)
|
82
|
-
setTextValueForFileNameField( hWnd , textToSet)
|
83
|
-
clickWindowsButton_hwnd(hWnd, "&Open")
|
84
|
-
return true
|
85
|
-
end
|
86
|
-
end
|
87
|
-
return false
|
88
|
-
end
|
89
|
-
|
90
|
-
# fire off setting the file name for the Choose file dialog
|
91
|
-
# in a new process
|
92
|
-
def setFileRequesterFileName_newProcess ( textToSet )
|
93
|
-
myapp = "rubyw #{@path_to_clicker}/setFileDialog.rb #{textToSet}"
|
94
|
-
# first argument to system call is a window title, in this case blank ""
|
95
|
-
winsystem( "start \"\" #{myapp}" )
|
96
|
-
end
|
97
|
-
|
98
|
-
# Return the text value from the first combo box
|
99
|
-
# on the Choose file dialog or nil if not found
|
100
|
-
def getFileRequesterFileName()
|
101
|
-
# first set the Choose File Window to be active
|
102
|
-
hWnd = getWindowHandle("Choose file" )
|
103
|
-
if hWnd != -1
|
104
|
-
makeWindowActive(hWnd)
|
105
|
-
return getTextValueForFileNameField( hWnd )
|
106
|
-
else
|
107
|
-
return nil
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
# Click on a dialog with title of "Internet Explorer"
|
112
|
-
# Default button to click is "OK"
|
113
|
-
# parenthWnd not used
|
114
|
-
def clickJavaScriptDialog(button="OK" , parenthWnd = -1)
|
115
|
-
clickWindowsButton("Internet Explorer" , button )
|
116
|
-
end
|
117
|
-
|
118
|
-
# Calls system to launch a new process to click on the button
|
119
|
-
# defaults to "OK" button
|
120
|
-
def clickJSDialog_NewProcess(button = "OK" )
|
121
|
-
myapp = "rubyw #{@path_to_clicker}/clickJSDialog.rb #{button}"
|
122
|
-
log "Starting win clicker in a new process. Looking for button #{button}"
|
123
|
-
log "Starting app: #{myapp}"
|
124
|
-
# first argument to system call is a window title, in this case blank ""
|
125
|
-
winsystem( "start \"\" #{myapp}" )
|
126
|
-
end
|
127
|
-
|
128
|
-
|
129
|
-
# as a thread
|
130
|
-
def clickJSDialog_Thread(button = "OK" )
|
131
|
-
sleep 3
|
132
|
-
n = 0
|
133
|
-
while n < 3
|
134
|
-
sleep 1
|
135
|
-
clickWindowsButton("Internet Explorer" , button )
|
136
|
-
n=n+1
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
# Looks for a window titled "Security Alert", clicks
|
141
|
-
# on Yes button
|
142
|
-
def clearSecurityAlertBox
|
143
|
-
clickWindowsButton("Security Alert" , "&Yes" )
|
144
|
-
end
|
145
|
-
alias :clear_security_alert :clearSecurityAlertBox
|
146
|
-
|
147
|
-
# Returns the parent handle for the given child handle
|
148
|
-
def getParent (childhWnd )
|
149
|
-
# pass a hWnd into this function and it will return the parent hWnd
|
150
|
-
getParentWindow = @User32['GetParent' , 'II' ]
|
151
|
-
a , b = getParentWindow.call(childhWnd )
|
152
|
-
return a
|
153
|
-
end
|
154
|
-
alias :get_parent :getParent
|
155
|
-
|
156
|
-
def with_dl_callback(type, prc)
|
157
|
-
callback = DL.callback(type, &prc)
|
158
|
-
error = nil
|
159
|
-
begin
|
160
|
-
yield callback
|
161
|
-
ensure
|
162
|
-
DL.remove_callback(callback)
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
# Enumerates open windows and
|
167
|
-
# returns a window handle from a given title and window class
|
168
|
-
# Window class and title are matched regexes
|
169
|
-
def getWindowHandle(title, winclass = "" )
|
170
|
-
enum_windows = @User32['EnumWindows', 'IPL']
|
171
|
-
get_class_name = @User32['GetClassName', 'ILpI']
|
172
|
-
get_caption_length = @User32['GetWindowTextLengthA' ,'LI' ] # format here - return value type (Long) followed by parameter types - int in this case - see http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/~checkout~/ruby/ext/dl/doc/dl.txt?
|
173
|
-
get_caption = @User32['GetWindowTextA', 'iLsL' ]
|
174
|
-
|
175
|
-
len = 32
|
176
|
-
buff = " " * len
|
177
|
-
classMatch = false
|
178
|
-
|
179
|
-
bContinueEnum = -1 # Windows "true" to continue enum_windows.
|
180
|
-
found_hwnd = -1
|
181
|
-
|
182
|
-
enum_windows_proc = lambda {|hwnd,lparam|
|
183
|
-
sleep 0.05
|
184
|
-
r,rs = get_class_name.call(hwnd, buff, buff.size)
|
185
|
-
|
186
|
-
if winclass != "" then
|
187
|
-
if /#{winclass}/ =~ rs[1].to_s
|
188
|
-
classMatch = true
|
189
|
-
end
|
190
|
-
else
|
191
|
-
classMatch = true
|
192
|
-
end
|
193
|
-
|
194
|
-
if classMatch ==true
|
195
|
-
textLength, a = get_caption_length.call(hwnd)
|
196
|
-
captionBuffer = " " * (textLength+1)
|
197
|
-
t , textCaption = get_caption.call(hwnd, captionBuffer , textLength+1)
|
198
|
-
if /#{title}/ =~ textCaption[1].to_s
|
199
|
-
found_hwnd = hwnd
|
200
|
-
bContinueEnum = 0 # False, discontinue enum_windows
|
201
|
-
end
|
202
|
-
bContinueEnum
|
203
|
-
else
|
204
|
-
bContinueEnum
|
205
|
-
end
|
206
|
-
}
|
207
|
-
with_dl_callback('ILL',enum_windows_proc) do |callback|
|
208
|
-
r,rs = enum_windows.call(callback, 0)
|
209
|
-
end
|
210
|
-
return found_hwnd
|
211
|
-
end
|
212
|
-
alias :get_window_handle :getWindowHandle
|
213
|
-
|
214
|
-
# Call SwitchToThisWindow win32api which will
|
215
|
-
# The SwitchToThisWindow function is called to switch focus to a specified window
|
216
|
-
# and bring it to the foreground
|
217
|
-
def makeWindowActive (hWnd)
|
218
|
-
switch_to_window = @User32['SwitchToThisWindow' , 'pLI' ]
|
219
|
-
# set it to be the one with focus
|
220
|
-
switch_to_window.call(hWnd , 1)
|
221
|
-
end
|
222
|
-
alias :make_window_active :makeWindowActive
|
223
|
-
|
224
|
-
# Posts a message to the handle passed in to click
|
225
|
-
def clickButtonWithHandle(buttonhWnd)
|
226
|
-
post_message = @User32['PostMessage', 'ILILL']
|
227
|
-
r,rs = post_message.call(buttonhWnd, BM_CLICK, 0, 0)
|
228
|
-
end
|
229
|
-
alias :click_button_with_handle :clickButtonWithHandle
|
230
|
-
|
231
|
-
# Based on the parent window handle passed in,
|
232
|
-
# click on the button with the given caption.
|
233
|
-
def clickWindowsButton_hwnd (hwnd , buttonCaption )
|
234
|
-
makeWindowActive(hwnd)
|
235
|
-
d = getChildHandle( hwnd , buttonCaption )
|
236
|
-
if d != -1
|
237
|
-
makeWindowActive(hwnd)
|
238
|
-
clickButtonWithHandle(d)
|
239
|
-
else
|
240
|
-
return false
|
241
|
-
end
|
242
|
-
return true
|
243
|
-
end
|
244
|
-
alias :click_windows_button_hwnd :clickWindowsButton_hwnd
|
245
|
-
|
246
|
-
# this clicks the button with the name in the window with the caption. It keeps looking for the button until
|
247
|
-
# until the timeout expires
|
248
|
-
def clickWindowsButton (windowCaption , buttonCaption , maxWaitTime=30 )
|
249
|
-
sleep 1
|
250
|
-
hwnd = -1
|
251
|
-
begin
|
252
|
-
timeout(maxWaitTime) do
|
253
|
-
hwnd = getWindowHandle(windowCaption)
|
254
|
-
while hwnd == -1
|
255
|
-
hwnd = getWindowHandle(windowCaption)
|
256
|
-
sleep 0.5
|
257
|
-
end
|
258
|
-
makeWindowActive(hwnd)
|
259
|
-
end
|
260
|
-
rescue Timeout::Error
|
261
|
-
return false
|
262
|
-
rescue => e
|
263
|
-
raise e
|
264
|
-
end
|
265
|
-
if hwnd != -1
|
266
|
-
makeWindowActive(hwnd)
|
267
|
-
else
|
268
|
-
end
|
269
|
-
d = getChildHandle( hwnd , buttonCaption )
|
270
|
-
if d != -1
|
271
|
-
makeWindowActive(hwnd)
|
272
|
-
clickButtonWithHandle(d)
|
273
|
-
else
|
274
|
-
return false
|
275
|
-
end
|
276
|
-
return true
|
277
|
-
end
|
278
|
-
alias :click_windows_button :clickWindowsButton
|
279
|
-
|
280
|
-
# Enumerate through children of the parent hwnd, pass back
|
281
|
-
# the handle for the control with the given caption
|
282
|
-
# the caption is compared as a regex
|
283
|
-
def getChildHandle ( hWnd , childCaption )
|
284
|
-
enum_childWindows = @User32['EnumChildWindows' , 'IIPL' ]
|
285
|
-
get_caption_length = @User32['GetWindowTextLengthA' ,'LI' ] # format here - return value type (Long) followed by parameter types - int in this case - see http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/~checkout~/ruby/ext/dl/doc/dl.txt?
|
286
|
-
get_caption = @User32['GetWindowTextA', 'iLsL' ]
|
287
|
-
match_hwnd = -1 # hWnd of handle matching childCaption
|
288
|
-
buff = " " * 16
|
289
|
-
get_class_name = @User32['GetClassName', 'ILpI']
|
290
|
-
|
291
|
-
bContinueEnum = -1
|
292
|
-
enum_childWindowsProc = lambda {|chwnd,lparam|
|
293
|
-
r,rs = get_class_name.call(chwnd, buff, buff.size)
|
294
|
-
textLength, a = get_caption_length.call(chwnd)
|
295
|
-
captionBuffer = " " * (textLength+1)
|
296
|
-
|
297
|
-
t , textCaption = get_caption.call(chwnd, captionBuffer , textLength+1)
|
298
|
-
if /#{childCaption}/ =~ textCaption[1].to_s then
|
299
|
-
match_hwnd = chwnd
|
300
|
-
bContinueEnum = 0 # Windows "false" to discontinue enum_childWindow
|
301
|
-
end
|
302
|
-
bContinueEnum
|
303
|
-
}
|
304
|
-
with_dl_callback('ILL',enum_childWindowsProc) do |callback|
|
305
|
-
r = enum_childWindows.call(hWnd, callback ,0)
|
306
|
-
end
|
307
|
-
return match_hwnd
|
308
|
-
end
|
309
|
-
alias :get_chwnd :getChildHandle
|
310
|
-
|
311
|
-
# Convenience method to return Static text for
|
312
|
-
# children of the window with the given caption
|
313
|
-
def getStaticText(caption)
|
314
|
-
return getStaticTextFromWindow(caption, -1)
|
315
|
-
end
|
316
|
-
alias :get_static_text :getStaticText
|
317
|
-
|
318
|
-
# Convenience method to return Static text for
|
319
|
-
# children of the window handle
|
320
|
-
def getStaticText_hWnd (hWnd)
|
321
|
-
return getStaticTextFromWindow("" , hWnd)
|
322
|
-
end
|
323
|
-
alias :get_static_text_hwnd :getStaticText_hWnd
|
324
|
-
|
325
|
-
# Return text as an array from child controls of the window
|
326
|
-
# given as either a handle or with the given caption
|
327
|
-
# that have a class type of Static
|
328
|
-
def getStaticTextFromWindow( windowCaption , hWnd)
|
329
|
-
enum_childWindows = @User32['EnumChildWindows' , 'IIPL' ]
|
330
|
-
get_caption_length = @User32['GetWindowTextLengthA' ,'LI' ] # format here - return value type (Long) followed by parameter types - int in this case - see http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/~checkout~/ruby/ext/dl/doc/dl.txt?
|
331
|
-
get_caption = @User32['GetWindowTextA', 'iLsL' ]
|
332
|
-
|
333
|
-
staticText = []
|
334
|
-
buff = " " * 16
|
335
|
-
get_class_name = @User32['GetClassName', 'ILpI']
|
336
|
-
|
337
|
-
if hWnd == -1
|
338
|
-
hWnd = getWindowHandle(windowCaption)
|
339
|
-
end
|
340
|
-
|
341
|
-
if hWnd == -1
|
342
|
-
return staticText
|
343
|
-
end
|
344
|
-
|
345
|
-
bContinueEnum = -1
|
346
|
-
enum_childWindows_proc = lambda {|hWnd,lparam|
|
347
|
-
r,rs = get_class_name.call(hWnd, buff, buff.size)
|
348
|
-
if rs[1].to_s == "Static" # there must be a better way of detecting this
|
349
|
-
textLength, a = get_caption_length.call(hWnd)
|
350
|
-
captionBuffer = " " * (textLength+1)
|
351
|
-
t , textCaption = get_caption.call(hWnd, captionBuffer , textLength+1)
|
352
|
-
staticText << textCaption[1].to_s
|
353
|
-
end
|
354
|
-
bContinueEnum
|
355
|
-
}
|
356
|
-
with_dl_callback('ILL',enum_childWindows_proc) do |callback|
|
357
|
-
r = enum_childWindows.call(hWnd, callback ,0)
|
358
|
-
end
|
359
|
-
return staticText
|
360
|
-
end
|
361
|
-
alias :get_static_text_from_window :getStaticTextFromWindow
|
362
|
-
|
363
|
-
# returns the handle (or -1 if its not found) of the
|
364
|
-
# nth control of this class in the parent window specified
|
365
|
-
# by the window handle
|
366
|
-
def getHandleOfControl (hWnd , controlClass, position )
|
367
|
-
enum_childWindows = @User32['EnumChildWindows' , 'IIPL' ]
|
368
|
-
get_caption_length = @User32['GetWindowTextLengthA' ,'LI' ] # format here - return value type (Long) followed by parameter types - int in this case - see http://www.ruby-lang.org/cgi-bin/cvsweb.cgi/~checkout~/ruby/ext/dl/doc/dl.txt?
|
369
|
-
get_caption = @User32['GetWindowTextA', 'iLsL' ]
|
370
|
-
control_hWnd = []
|
371
|
-
buff = " " * 16
|
372
|
-
get_class_name = @User32['GetClassName', 'ILpI']
|
373
|
-
|
374
|
-
bContinueEnum = -1
|
375
|
-
enum_childWindows_proc = lambda {|hWnd,lparam|
|
376
|
-
r,rs = get_class_name.call(hWnd, buff, buff.size)
|
377
|
-
if rs[1].to_s == controlClass # there must be a better way of detecting this
|
378
|
-
control_hWnd << hWnd
|
379
|
-
end
|
380
|
-
bContinueEnum
|
381
|
-
}
|
382
|
-
with_dl_callback('ILL',enum_childWindows_proc) do |callback|
|
383
|
-
r = enum_childWindows.call(hWnd, callback ,0)
|
384
|
-
end
|
385
|
-
controlHwnd = control_hWnd[position]
|
386
|
-
if controlHwnd == nil then
|
387
|
-
controlHwnd = -1
|
388
|
-
end
|
389
|
-
return controlHwnd
|
390
|
-
end
|
391
|
-
alias :get_handle_of_ctrl :getHandleOfControl
|
392
|
-
|
393
|
-
# Call set text on the given window handle
|
394
|
-
def setComboBoxText(hWnd , textToSet)
|
395
|
-
set_text(hWnd, textToSet)
|
396
|
-
end
|
397
|
-
alias :set_combo_txt :setComboBoxText
|
398
|
-
|
399
|
-
# Call set text on the given window handle
|
400
|
-
def setTextBoxText(hWnd , textToSet)
|
401
|
-
set_text(hWnd, textToSet)
|
402
|
-
end
|
403
|
-
alias :set_textbox_txt :setTextBoxText
|
404
|
-
|
405
|
-
# Private method to set text called by the two methods above
|
406
|
-
def set_text(hWnd, textToSet)
|
407
|
-
send_message = @User32['SendMessage', 'ILISS']
|
408
|
-
r ,rs = send_message.call(hWnd , WM_SETTEXT ,'',textToSet)
|
409
|
-
end
|
410
|
-
private :set_text
|
411
|
-
|
412
|
-
# Get the text in the handle for the given control
|
413
|
-
def getControlText(hWnd)
|
414
|
-
buff = " " * 256
|
415
|
-
send_message = @User32['SendMessage', 'ILIIS']
|
416
|
-
r ,rs = send_message.call(hWnd , WM_GETTEXT , 256 , buff )
|
417
|
-
return buff.to_s
|
418
|
-
end
|
419
|
-
alias :get_ctrl_txt :getControlText
|
420
|
-
|
421
|
-
# get the title for the specified hwnd
|
422
|
-
def getWindowTitle(hWnd)
|
423
|
-
buff = " " * 256
|
424
|
-
getWindowText = @User32['GetWindowText' , 'ILSI']
|
425
|
-
r , rs = getWindowText.call( hWnd , buff , 256 )
|
426
|
-
return buff.to_s
|
427
|
-
end
|
428
|
-
alias :get_win_title :getWindowTitle
|
429
|
-
|
430
|
-
# Get the text in the first combo box
|
431
|
-
# file requester methods returns nil on failure to
|
432
|
-
# locate the 1st combobox
|
433
|
-
def getTextValueForFileNameField(parenthWnd)
|
434
|
-
f = getHandleOfControl(parenthWnd, "ComboBox", 1)
|
435
|
-
if f == -1 then
|
436
|
-
# unable to find the first combobox
|
437
|
-
return nil
|
438
|
-
else
|
439
|
-
# we have the control and now
|
440
|
-
# can send it some messages
|
441
|
-
return getWinText(f )
|
442
|
-
end
|
443
|
-
end
|
444
|
-
alias :get_file_name :getTextValueForFileNameField
|
445
|
-
|
446
|
-
# this sets the filename field to text to set
|
447
|
-
def setTextValueForFileNameField( parenthWnd , textToSet )
|
448
|
-
# get the handle of the nth control that is an Edit box
|
449
|
-
f = getHandleOfControl(parenthWnd, "Edit" , 0 )
|
450
|
-
if f == -1 then
|
451
|
-
# unable to get a handle on the first edit control
|
452
|
-
return false
|
453
|
-
else
|
454
|
-
# we found the control and can now send it some messages
|
455
|
-
setComboBoxText(f , textToSet)
|
456
|
-
return true
|
457
|
-
end
|
458
|
-
end
|
459
|
-
alias :set_file_name :setTextValueForFileNameField
|
460
|
-
end
|