rautomation 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.rdoc +4 -0
- data/README.rdoc +26 -11
- data/Rakefile +5 -5
- data/VERSION +1 -1
- data/lib/rautomation/adapter/autoit/button.rb +16 -4
- data/lib/rautomation/adapter/autoit/locators.rb +2 -1
- data/lib/rautomation/adapter/autoit/text_field.rb +20 -6
- data/lib/rautomation/adapter/autoit/window.rb +61 -23
- data/lib/rautomation/adapter/ffi/button.rb +15 -4
- data/lib/rautomation/adapter/ffi/constants.rb +1 -4
- data/lib/rautomation/adapter/ffi/functions.rb +8 -3
- data/lib/rautomation/adapter/ffi/locators.rb +8 -2
- data/lib/rautomation/adapter/ffi/text_field.rb +17 -5
- data/lib/rautomation/adapter/ffi/window.rb +58 -21
- data/lib/rautomation/adapter/helper.rb +1 -0
- data/lib/rautomation/button.rb +9 -8
- data/lib/rautomation/text_field.rb +12 -11
- data/lib/rautomation/wait_helper.rb +2 -2
- data/lib/rautomation/window.rb +61 -53
- data/rautomation.gemspec +7 -7
- data/spec/spec_helper.rb +2 -0
- metadata +9 -9
data/History.rdoc
CHANGED
data/README.rdoc
CHANGED
@@ -5,14 +5,14 @@
|
|
5
5
|
|
6
6
|
== DESCRIPTION
|
7
7
|
|
8
|
-
RAutomation
|
8
|
+
RAutomation is a small and easy to use library for helping out to automate windows and their controls
|
9
9
|
for automated testing.
|
10
10
|
|
11
|
-
RAutomation
|
12
|
-
* Easy to use and user-friendly API (inspired by Watir http://www.watir.com)
|
11
|
+
RAutomation provides:
|
12
|
+
* Easy to use and user-friendly API (inspired by Watir http://www.watir.com)
|
13
13
|
* Cross-platform compatibility
|
14
|
-
* Easy extensibility -
|
15
|
-
|
14
|
+
* Easy extensibility - with small scripting effort it's possible to add support for not yet
|
15
|
+
supported platforms or technologies
|
16
16
|
|
17
17
|
== USAGE
|
18
18
|
|
@@ -30,16 +30,17 @@ RAutomation aims to provide:
|
|
30
30
|
button.click
|
31
31
|
|
32
32
|
window2 = RAutomation::Window.new(:title => "Other Title", :adapter => :autoit) # use AutoIt adapter
|
33
|
-
|
33
|
+
# use adapter's (in this case AutoIt's) internal methods not part of the public API directly
|
34
|
+
window2.WinClose("[TITLE:Other Title]")
|
34
35
|
|
35
|
-
|
36
|
+
Check out the documentation for other possible usages!
|
36
37
|
|
37
38
|
== INSTALL
|
38
39
|
|
39
40
|
=== Windows
|
40
41
|
|
41
42
|
1. gem install rautomation
|
42
|
-
2. create
|
43
|
+
2. create script and run it
|
43
44
|
|
44
45
|
Available adapters:
|
45
46
|
* :ffi - uses Windows API directly with FFI (default)
|
@@ -51,18 +52,32 @@ You might need administrative privileges if running for the first time and you h
|
|
51
52
|
=== Linux
|
52
53
|
|
53
54
|
Feel yourself at home on Linux and know how to automate windows and their controls? I would be happy if you'd contact me
|
54
|
-
about that matter - or even better,
|
55
|
+
about that matter - or even better, follow the instructions at "How to create a new adapter?"
|
55
56
|
|
56
57
|
=== OS X
|
57
58
|
|
58
59
|
Feel yourself at home on OS X and know how to automate windows and their controls? I would be happy if you'd contact me
|
59
|
-
about that matter - or even better,
|
60
|
+
about that matter - or even better, follow the instructions at "How to create a new adapter?"
|
60
61
|
|
61
62
|
=== Others
|
62
63
|
|
63
64
|
Feel yourself at home on some operating system not listed in here and know how to automate windows and their controls?
|
64
65
|
Does Ruby also work on that operating system? I would be happy if you'd contact me
|
65
|
-
about that matter - or even better,
|
66
|
+
about that matter - or even better, follow the instructions at "How to create a new adapter?"
|
67
|
+
|
68
|
+
== How to create a new adapter?
|
69
|
+
|
70
|
+
1. Fork the project.
|
71
|
+
2. Create entry point file to lib/rautomation/adapter which should load all adapter specific files.
|
72
|
+
3. Add `autoload` statement into lib/rautomation/adapter/helper.rb for that file.
|
73
|
+
4. Copy button.rb, text_field.rb and window.rb from some of the existing adapter's directory.
|
74
|
+
5. Add spec data for your adapter into spec/spec_helper DATA constant.
|
75
|
+
6. Use environment variable __RAUTOMATION_ADAPTER__ to point to that adapter.
|
76
|
+
7. Start coding and spec-ing.
|
77
|
+
|
78
|
+
Don't forget to fix the documentation for that adapter also!
|
79
|
+
|
80
|
+
In case of any problems, feel free to contact me.
|
66
81
|
|
67
82
|
== Note on Patches/Pull Requests
|
68
83
|
|
data/Rakefile
CHANGED
@@ -6,14 +6,14 @@ begin
|
|
6
6
|
Jeweler::Tasks.new do |gem|
|
7
7
|
gem.name = "rautomation"
|
8
8
|
gem.summary = %Q{Automate windows and their controls through user-friendly API with Ruby}
|
9
|
-
gem.description = %Q{RAutomation
|
9
|
+
gem.description = %Q{RAutomation is a small and easy to use library for helping out to automate windows and their controls
|
10
10
|
for automated testing.
|
11
11
|
|
12
|
-
RAutomation
|
13
|
-
* Easy to use and user-friendly API (inspired by Watir http://www.watir.com)
|
12
|
+
RAutomation provides:
|
13
|
+
* Easy to use and user-friendly API (inspired by Watir http://www.watir.com)
|
14
14
|
* Cross-platform compatibility
|
15
|
-
* Easy extensibility -
|
16
|
-
|
15
|
+
* Easy extensibility - with small scripting effort it's possible to add support for not yet
|
16
|
+
supported platforms or technologies}
|
17
17
|
gem.email = "jarmo.p@gmail.com"
|
18
18
|
gem.homepage = "http://github.com/jarmo/RAutomation"
|
19
19
|
gem.authors = ["Jarmo Pertman"]
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
@@ -5,6 +5,7 @@ module RAutomation
|
|
5
5
|
include WaitHelper
|
6
6
|
include Locators
|
7
7
|
|
8
|
+
# @private
|
8
9
|
# Special-cased locators
|
9
10
|
LOCATORS = {
|
10
11
|
[:class, Regexp] => :regexpclass,
|
@@ -12,13 +13,22 @@ module RAutomation
|
|
12
13
|
:value => :text
|
13
14
|
}
|
14
15
|
|
15
|
-
#
|
16
|
+
# Creates the button object.
|
17
|
+
# @note this method is not meant to be accessed directly, but only through {RAutomation::Window#button}!
|
18
|
+
# @param [RAutomation::Window] window this button belongs to.
|
19
|
+
# @param [Hash] locators for searching the button.
|
20
|
+
# @option locators [String, Regexp] :value Value (text) of the button
|
21
|
+
# @option locators [String, Regexp] :class Internal class name of the button
|
22
|
+
# @option locators [String, Fixnum] :id Internal ID of the button
|
23
|
+
# @option locators [String, Fixnum] :index 0-based index to specify n-th button if all other criteria match
|
24
|
+
# @see RAutomation::Window#button
|
16
25
|
def initialize(window, locators)
|
17
26
|
@window = window
|
18
27
|
extract(locators)
|
19
28
|
end
|
20
29
|
|
21
|
-
|
30
|
+
# @see RAutomation::Button#click
|
31
|
+
def click
|
22
32
|
clicked = false
|
23
33
|
wait_until do
|
24
34
|
@window.activate
|
@@ -31,11 +41,13 @@ module RAutomation
|
|
31
41
|
end
|
32
42
|
end
|
33
43
|
|
34
|
-
|
44
|
+
# @see RAutomation::Button#value
|
45
|
+
def value
|
35
46
|
Window.autoit.ControlGetText(@window.locator_hwnd, "", @locators)
|
36
47
|
end
|
37
48
|
|
38
|
-
|
49
|
+
# @see RAutomation::Button#exists?
|
50
|
+
def exists?
|
39
51
|
not Window.autoit.ControlGetHandle(@window.locator_hwnd, "", @locators).empty?
|
40
52
|
end
|
41
53
|
end
|
@@ -1,11 +1,12 @@
|
|
1
1
|
module RAutomation
|
2
2
|
module Adapter
|
3
3
|
module Autoit
|
4
|
+
# @private
|
4
5
|
module Locators
|
5
6
|
|
6
7
|
private
|
7
8
|
|
8
|
-
def extract(locators)
|
9
|
+
def extract(locators)
|
9
10
|
@locators = "[#{locators.map do |locator, value|
|
10
11
|
locator_key = self.class::LOCATORS[locator] || self.class::LOCATORS[[locator, value.class]]
|
11
12
|
value = value.to_i + 1 if locator == :index # use 0-based indexing
|
@@ -5,19 +5,30 @@ module RAutomation
|
|
5
5
|
include WaitHelper
|
6
6
|
include Locators
|
7
7
|
|
8
|
+
# @private
|
8
9
|
# Special-cased locators
|
9
10
|
LOCATORS = {
|
10
11
|
[:class, Regexp] => :regexpclass,
|
11
|
-
:index => :instance
|
12
|
+
:index => :instance,
|
13
|
+
:value => :text
|
12
14
|
}
|
13
15
|
|
14
|
-
#
|
16
|
+
# Creates the text field object.
|
17
|
+
# @note this method is not meant to be accessed directly, but only through {RAutomation::Window#text_field}!
|
18
|
+
# @param [RAutomation::Window] window this text field belongs to.
|
19
|
+
# @param [Hash] locators for searching the text field.
|
20
|
+
# @option locators [String, Regexp] :class Internal class name of the text field
|
21
|
+
# @option locators [String, Regexp] :value Value (text) of the text field
|
22
|
+
# @option locators [String, Fixnum] :id Internal ID of the text field
|
23
|
+
# @option locators [String, Fixnum] :index 0-based index to specify n-th text field if all other criteria match
|
24
|
+
# @see RAutomation::Window#text_field
|
15
25
|
def initialize(window, locators)
|
16
26
|
@window = window
|
17
27
|
extract(locators)
|
18
28
|
end
|
19
29
|
|
20
|
-
|
30
|
+
# @see RAutomation::TextField#set
|
31
|
+
def set(text)
|
21
32
|
wait_until do
|
22
33
|
@window.activate
|
23
34
|
@window.active? &&
|
@@ -27,15 +38,18 @@ module RAutomation
|
|
27
38
|
end
|
28
39
|
end
|
29
40
|
|
30
|
-
|
41
|
+
# @see RAutomation::TextField#clear
|
42
|
+
def clear
|
31
43
|
set ""
|
32
44
|
end
|
33
45
|
|
34
|
-
|
46
|
+
# @see RAutomation::TextField#value
|
47
|
+
def value
|
35
48
|
Window.autoit.ControlGetText(@window.locator_hwnd, "", @locators)
|
36
49
|
end
|
37
50
|
|
38
|
-
|
51
|
+
# @see RAutomation::TextField#exists?
|
52
|
+
def exists?
|
39
53
|
not Window.autoit.ControlGetHandle(@window.locator_hwnd, "", @locators).empty?
|
40
54
|
end
|
41
55
|
end
|
@@ -6,11 +6,13 @@ module RAutomation
|
|
6
6
|
include Locators
|
7
7
|
|
8
8
|
class << self
|
9
|
-
|
9
|
+
# @private
|
10
|
+
def autoit
|
10
11
|
@@autoit
|
11
12
|
end
|
12
13
|
|
13
|
-
|
14
|
+
# @private
|
15
|
+
def load_autoit
|
14
16
|
@@autoit = WIN32OLE.new('AutoItX3.Control')
|
15
17
|
rescue WIN32OLERuntimeError
|
16
18
|
dll = File.dirname(__FILE__) + "/../../../../ext/AutoItX/AutoItX3.dll"
|
@@ -22,8 +24,10 @@ module RAutomation
|
|
22
24
|
load_autoit
|
23
25
|
@@autoit.AutoItSetOption("WinWaitDelay", 350)
|
24
26
|
|
27
|
+
# Locators of the window.
|
25
28
|
attr_reader :locators
|
26
29
|
|
30
|
+
# @private
|
27
31
|
# Special-cased locators
|
28
32
|
LOCATORS = {
|
29
33
|
[:title, Regexp] => :regexptitle,
|
@@ -31,69 +35,95 @@ module RAutomation
|
|
31
35
|
:hwnd => :handle
|
32
36
|
}
|
33
37
|
|
34
|
-
#
|
38
|
+
# Creates the window object.
|
39
|
+
# @note this method is not meant to be accessed directly, but only through {RAutomation::Window#initialize}!
|
40
|
+
# @param [Hash] locators for searching the window.
|
41
|
+
# @option locators [String, Regexp] :title Title of the window
|
42
|
+
# @option locators [String, Regexp] :text Visible text of the window
|
43
|
+
# @option locators [String, Regexp] :class Internal class name of the window
|
44
|
+
# @option locators [String, Fixnum] :hwnd Window handle in decimal format
|
45
|
+
# @option locators [String, Fixnum] :index 0-based index to specify n-th window if all other criteria match
|
46
|
+
# @see RAutomation::Window#initialize
|
35
47
|
def initialize(locators)
|
36
48
|
@hwnd = locators[:hwnd]
|
37
49
|
@locator_text = locators.delete(:text)
|
38
50
|
extract(locators)
|
39
51
|
end
|
40
52
|
|
41
|
-
#
|
42
|
-
# Searches only for visible windows with having some text at all.
|
43
|
-
|
53
|
+
# Retrieves handle of the window.
|
54
|
+
# @note Searches only for visible windows with having some text at all.
|
55
|
+
# @see RAutomation::Window#hwnd
|
56
|
+
def hwnd
|
44
57
|
@hwnd ||= @@autoit.WinList(@locators, @locator_text).pop.compact.
|
45
58
|
find {|handle| w = self.class.new(:hwnd => handle.hex); w.visible? && !w.text.empty?}.
|
46
59
|
hex rescue nil
|
47
60
|
end
|
48
61
|
|
49
|
-
|
62
|
+
# @see RAutomation::Window#pid
|
63
|
+
def pid
|
64
|
+
@@autoit.WinGetProcess(hwnd)
|
65
|
+
end
|
66
|
+
|
67
|
+
# @see RAutomation::Window#title
|
68
|
+
def title
|
50
69
|
@@autoit.WinGetTitle(locator_hwnd)
|
51
70
|
end
|
52
71
|
|
53
|
-
|
72
|
+
# @see RAutomation::Window#activate
|
73
|
+
def activate
|
54
74
|
@@autoit.WinWait(locator_hwnd, "", 1)
|
55
75
|
@@autoit.WinActivate(locator_hwnd)
|
56
76
|
sleep 1
|
57
77
|
end
|
58
78
|
|
59
|
-
|
79
|
+
# @see RAutomation::Window#active?
|
80
|
+
def active?
|
60
81
|
@@autoit.WinActive(locator_hwnd) == 1
|
61
82
|
end
|
62
83
|
|
63
|
-
|
84
|
+
# @see RAutomation::Window#text
|
85
|
+
def text
|
64
86
|
@@autoit.WinGetText(locator_hwnd)
|
65
87
|
end
|
66
88
|
|
67
|
-
|
89
|
+
# @see RAutomation::Window#exists?
|
90
|
+
def exists?
|
68
91
|
@@autoit.WinExists(locator_hwnd) == 1
|
69
92
|
end
|
70
93
|
|
71
|
-
|
94
|
+
# @see RAutomation::Window#visible?
|
95
|
+
def visible?
|
72
96
|
@@autoit.WinGetState(locator_hwnd) & 2 == 2
|
73
97
|
end
|
74
98
|
|
75
|
-
|
99
|
+
# @see RAutomation::Window#maximize
|
100
|
+
def maximize
|
76
101
|
@@autoit.WinSetState(locator_hwnd, "", @@autoit.SW_MAXIMIZE)
|
77
102
|
sleep 1
|
78
103
|
end
|
79
104
|
|
80
|
-
|
105
|
+
# @see RAutomation::Window#minimize
|
106
|
+
def minimize
|
81
107
|
@@autoit.WinSetState(locator_hwnd, "", @@autoit.SW_MINIMIZE)
|
82
108
|
sleep 1
|
83
109
|
end
|
84
110
|
|
85
|
-
|
111
|
+
# @see RAutomation::Window#minimized?
|
112
|
+
def minimized?
|
86
113
|
@@autoit.WinGetState(locator_hwnd) & 16 == 16
|
87
114
|
end
|
88
115
|
|
89
|
-
|
116
|
+
# @see RAutomation::Window#restore
|
117
|
+
def restore
|
90
118
|
@@autoit.WinSetState(locator_hwnd, "", @@autoit.SW_RESTORE)
|
91
119
|
sleep 1
|
92
120
|
end
|
93
121
|
|
94
|
-
# Activates the
|
122
|
+
# Activates the window and sends keys to it.
|
95
123
|
#
|
96
|
-
# Refer to AutoIt documentation
|
124
|
+
# Refer to AutoIt documentation at http://www.autoitscript.com/autoit3/docs/appendix/SendKeys.htm
|
125
|
+
# for keys syntax.
|
126
|
+
# @see RAutomation::Window#send_keys
|
97
127
|
def send_keys(keys)
|
98
128
|
wait_until do
|
99
129
|
activate
|
@@ -102,24 +132,32 @@ module RAutomation
|
|
102
132
|
@@autoit.Send(keys)
|
103
133
|
end
|
104
134
|
|
105
|
-
|
135
|
+
# @see RAutomation::Window#close
|
136
|
+
def close
|
106
137
|
@@autoit.WinClose(locator_hwnd)
|
107
138
|
@@autoit.WinKill(locator_hwnd)
|
108
139
|
end
|
109
140
|
|
110
|
-
|
141
|
+
# @see Button#initialize
|
142
|
+
# @see RAutomation::Window#button
|
143
|
+
def button(locator)
|
111
144
|
Button.new(self, locator)
|
112
145
|
end
|
113
146
|
|
114
|
-
|
147
|
+
# @see TextField#initialize
|
148
|
+
# @see RAutomation::Window#text_field
|
149
|
+
def text_field(locator)
|
115
150
|
TextField.new(self, locator)
|
116
151
|
end
|
117
152
|
|
118
|
-
|
153
|
+
# Redirects all method calls not part of the public API to the AutoIt directly.
|
154
|
+
# @example execute AutoIt's WinGetTitle function:
|
155
|
+
# RAutomation::Window.new(:hwnd => 123456).WinGetTitle(...)
|
156
|
+
# @see RAutomation::Window#method_missing
|
157
|
+
def method_missing(name, *args)
|
119
158
|
@@autoit.send(name, *args)
|
120
159
|
end
|
121
160
|
|
122
|
-
# Used internally.
|
123
161
|
# @private
|
124
162
|
def locator_hwnd
|
125
163
|
"[HANDLE:#{hwnd.to_i.to_s(16)}]"
|
@@ -5,13 +5,22 @@ module RAutomation
|
|
5
5
|
include WaitHelper
|
6
6
|
include Locators
|
7
7
|
|
8
|
-
#
|
8
|
+
# Creates the button object.
|
9
|
+
# @note this method is not meant to be accessed directly, but only through {RAutomation::Window#button}!
|
10
|
+
# @param [RAutomation::Window] window this button belongs to.
|
11
|
+
# @param [Hash] locators for searching the button.
|
12
|
+
# @option locators [String, Regexp] :value Value (text) of the button
|
13
|
+
# @option locators [String, Regexp] :class Internal class name of the button
|
14
|
+
# @option locators [String, Fixnum] :id Internal ID of the button
|
15
|
+
# @option locators [String, Fixnum] :index 0-based index to specify n-th button if all other criteria match
|
16
|
+
# @see RAutomation::Window#button
|
9
17
|
def initialize(window, locators)
|
10
18
|
@window = window
|
11
19
|
extract(locators)
|
12
20
|
end
|
13
21
|
|
14
|
-
|
22
|
+
# @see RAutomation::Button#click
|
23
|
+
def click
|
15
24
|
clicked = false
|
16
25
|
wait_until do
|
17
26
|
hwnd = Functions.control_hwnd(@window.hwnd, @locators)
|
@@ -24,11 +33,13 @@ module RAutomation
|
|
24
33
|
end
|
25
34
|
end
|
26
35
|
|
27
|
-
|
36
|
+
# @see RAutomation::Button#value
|
37
|
+
def value
|
28
38
|
Functions.control_value(Functions.control_hwnd(@window.hwnd, @locators))
|
29
39
|
end
|
30
40
|
|
31
|
-
|
41
|
+
# @see RAutomation::Button#exists?
|
42
|
+
def exists?
|
32
43
|
!!Functions.control_hwnd(@window.hwnd, @locators)
|
33
44
|
end
|
34
45
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module RAutomation
|
2
2
|
module Adapter
|
3
3
|
module Ffi
|
4
|
+
# @private
|
4
5
|
module Constants
|
5
6
|
WM_GETTEXT = 0xD
|
6
7
|
WM_SETTEXT = 0xC
|
@@ -20,10 +21,6 @@ module RAutomation
|
|
20
21
|
BM_CLICK = 0xF5
|
21
22
|
|
22
23
|
# keybd_event constants
|
23
|
-
# http://msdn.microsoft.com/en-us/library/ms646304(VS.85).aspx
|
24
|
-
#
|
25
|
-
# keycodes themselves are at:
|
26
|
-
# http://msdn.microsoft.com/en-us/library/dd375731(v=VS.85).aspx
|
27
24
|
KEYEVENTF_EXTENDEDKEY = 0x1
|
28
25
|
KEYEVENTF_KEYUP = 0x2
|
29
26
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module RAutomation
|
2
2
|
module Adapter
|
3
3
|
module Ffi
|
4
|
+
# @private
|
4
5
|
module Functions
|
5
6
|
extend FFI::Library
|
6
7
|
|
@@ -88,6 +89,12 @@ module RAutomation
|
|
88
89
|
end
|
89
90
|
end
|
90
91
|
|
92
|
+
def window_pid(hwnd)
|
93
|
+
pid = FFI::MemoryPointer.new :int
|
94
|
+
window_thread_process_id(hwnd, pid)
|
95
|
+
pid.read_int
|
96
|
+
end
|
97
|
+
|
91
98
|
def window_class(hwnd)
|
92
99
|
class_name = FFI::MemoryPointer.new :char, 512
|
93
100
|
_window_class(hwnd, class_name, 512)
|
@@ -102,9 +109,7 @@ module RAutomation
|
|
102
109
|
0, nil, Constants::SMTO_ABORTIFHUNG, 1000, nil)
|
103
110
|
# force it to close
|
104
111
|
unless closed
|
105
|
-
|
106
|
-
window_thread_process_id(hwnd, pid)
|
107
|
-
process_hwnd = open_process(Constants::PROCESS_ALL_ACCESS, false, pid.read_int)
|
112
|
+
process_hwnd = open_process(Constants::PROCESS_ALL_ACCESS, false, window_pid(hwnd))
|
108
113
|
terminate_process(process_hwnd, 0)
|
109
114
|
close_handle(process_hwnd)
|
110
115
|
end
|
@@ -1,13 +1,19 @@
|
|
1
1
|
module RAutomation
|
2
2
|
module Adapter
|
3
3
|
module Ffi
|
4
|
+
# @private
|
4
5
|
module Locators
|
5
6
|
|
6
7
|
private
|
7
8
|
|
8
|
-
def extract(locators)
|
9
|
-
|
9
|
+
def extract(locators)
|
10
|
+
# windows locators
|
11
|
+
@hwnd = locators[:hwnd].to_i if locators[:hwnd]
|
12
|
+
locators[:pid] = locators[:pid].to_i if locators[:pid]
|
10
13
|
locators[:index] = locators[:index].to_i if locators[:index]
|
14
|
+
|
15
|
+
# control locator
|
16
|
+
locators[:id] = locators[:id].to_i if locators[:id]
|
11
17
|
@locators = locators
|
12
18
|
end
|
13
19
|
end
|
@@ -5,13 +5,22 @@ module RAutomation
|
|
5
5
|
include WaitHelper
|
6
6
|
include Locators
|
7
7
|
|
8
|
-
#
|
8
|
+
# Creates the text field object.
|
9
|
+
# @note this method is not meant to be accessed directly, but only through {RAutomation::Window#text_field}!
|
10
|
+
# @param [RAutomation::Window] window this text field belongs to.
|
11
|
+
# @param [Hash] locators for searching the text field.
|
12
|
+
# @option locators [String, Regexp] :class Internal class name of the text field
|
13
|
+
# @option locators [String, Regexp] :value Value (text) of the text field
|
14
|
+
# @option locators [String, Fixnum] :id Internal ID of the text field
|
15
|
+
# @option locators [String, Fixnum] :index 0-based index to specify n-th text field if all other criteria match
|
16
|
+
# @see RAutomation::Window#text_field
|
9
17
|
def initialize(window, locators)
|
10
18
|
@window = window
|
11
19
|
extract(locators)
|
12
20
|
end
|
13
21
|
|
14
|
-
|
22
|
+
# @see RAutomation::TextField#set
|
23
|
+
def set(text)
|
15
24
|
wait_until do
|
16
25
|
hwnd = Functions.control_hwnd(@window.hwnd, @locators)
|
17
26
|
@window.activate
|
@@ -22,15 +31,18 @@ module RAutomation
|
|
22
31
|
end
|
23
32
|
end
|
24
33
|
|
25
|
-
|
34
|
+
# @see RAutomation::TextField#clear
|
35
|
+
def clear
|
26
36
|
set ""
|
27
37
|
end
|
28
38
|
|
29
|
-
|
39
|
+
# @see RAutomation::TextField#value
|
40
|
+
def value
|
30
41
|
Functions.control_value(Functions.control_hwnd(@window.hwnd, @locators))
|
31
42
|
end
|
32
43
|
|
33
|
-
|
44
|
+
# @see RAutomation::TextField#exists?
|
45
|
+
def exists?
|
34
46
|
!!Functions.control_hwnd(@window.hwnd, @locators)
|
35
47
|
end
|
36
48
|
|
@@ -5,71 +5,100 @@ module RAutomation
|
|
5
5
|
include WaitHelper
|
6
6
|
include Locators
|
7
7
|
|
8
|
+
# Locators of the window.
|
8
9
|
attr_reader :locators
|
9
10
|
|
10
|
-
# Possible locators are :title, :text, :hwnd and :
|
11
|
+
# Possible locators are :title, :text, :hwnd, :pid, :class and :index.
|
12
|
+
|
13
|
+
# Creates the window object.
|
14
|
+
# @note this method is not meant to be accessed directly, but only through {RAutomation::Window#initialize}!
|
15
|
+
# @param [Hash] locators for searching the window.
|
16
|
+
# @option locators [String, Regexp] :title Title of the window
|
17
|
+
# @option locators [String, Regexp] :text Visible text of the window
|
18
|
+
# @option locators [String, Regexp] :class Internal class name of the window
|
19
|
+
# @option locators [String, Fixnum] :hwnd Window handle in decimal format
|
20
|
+
# @option locators [String, Fixnum] :pid Window process ID (PID)
|
21
|
+
# @option locators [String, Fixnum] :index 0-based index to specify n-th window if all other criteria match
|
22
|
+
# all other criteria match
|
23
|
+
# @see RAutomation::Window#initialize
|
11
24
|
def initialize(locators)
|
12
|
-
@hwnd = locators.delete(:hwnd)
|
13
25
|
extract(locators)
|
14
26
|
end
|
15
27
|
|
16
|
-
#
|
17
|
-
# Searches only for visible windows with having some text at all.
|
18
|
-
|
28
|
+
# Retrieves handle of the window.
|
29
|
+
# @note Searches only for visible windows with having some text at all.
|
30
|
+
# @see RAutomation::Window#hwnd
|
31
|
+
def hwnd
|
19
32
|
@hwnd ||= Functions.window_hwnd(@locators)
|
20
33
|
end
|
21
34
|
|
22
|
-
|
35
|
+
# @see RAutomation::Window#pid
|
36
|
+
def pid
|
37
|
+
Functions.window_pid(hwnd)
|
38
|
+
end
|
39
|
+
|
40
|
+
# @see RAutomation::Window#title
|
41
|
+
def title
|
23
42
|
Functions.window_title(hwnd)
|
24
43
|
end
|
25
44
|
|
26
|
-
|
45
|
+
# @see RAutomation::Window#activate
|
46
|
+
def activate
|
27
47
|
return if !exists? || active?
|
28
48
|
restore if minimized?
|
29
49
|
Functions.activate_window(hwnd)
|
30
50
|
sleep 1
|
31
51
|
end
|
32
52
|
|
33
|
-
|
53
|
+
# @see RAutomation::Window#active?
|
54
|
+
def active?
|
34
55
|
exists? && Functions.foreground_window == hwnd
|
35
56
|
end
|
36
57
|
|
37
|
-
|
58
|
+
# @see RAutomation::Window#text
|
59
|
+
def text
|
38
60
|
Functions.window_text(hwnd)
|
39
61
|
end
|
40
62
|
|
41
|
-
|
63
|
+
# @see RAutomation::Window#exists?
|
64
|
+
def exists?
|
42
65
|
result = hwnd && Functions.window_exists(hwnd)
|
43
66
|
!!result
|
44
67
|
end
|
45
68
|
|
46
|
-
|
69
|
+
# @see RAutomation::Window#visible?
|
70
|
+
def visible?
|
47
71
|
Functions.window_visible(hwnd)
|
48
72
|
end
|
49
73
|
|
50
|
-
|
74
|
+
# @see RAutomation::Window#maximize
|
75
|
+
def maximize
|
51
76
|
Functions.show_window(hwnd, Constants::SW_MAXIMIZE)
|
52
77
|
sleep 1
|
53
78
|
end
|
54
79
|
|
55
|
-
|
80
|
+
# @see RAutomation::Window#minimize
|
81
|
+
def minimize
|
56
82
|
Functions.show_window(hwnd, Constants::SW_MINIMIZE)
|
57
83
|
sleep 1
|
58
84
|
end
|
59
85
|
|
60
|
-
|
86
|
+
# @see RAutomation::Window#minimized?
|
87
|
+
def minimized?
|
61
88
|
Functions.minimized(hwnd)
|
62
89
|
end
|
63
90
|
|
64
|
-
|
91
|
+
# @see RAutomation::Window#restore
|
92
|
+
def restore
|
65
93
|
Functions.show_window(hwnd, Constants::SW_RESTORE)
|
66
94
|
sleep 1
|
67
95
|
end
|
68
96
|
|
69
|
-
# Activates the
|
97
|
+
# Activates the window and sends keys to it.
|
70
98
|
#
|
71
99
|
# Refer to MSDN documentation at http://msdn.microsoft.com/en-us/library/dd375731(v=VS.85).aspx
|
72
|
-
# for keycodes.
|
100
|
+
# for the keycodes.
|
101
|
+
# @see RAutomation::Window#send_keys
|
73
102
|
def send_keys(*keys)
|
74
103
|
keys.each do |key|
|
75
104
|
wait_until do
|
@@ -81,21 +110,29 @@ module RAutomation
|
|
81
110
|
end
|
82
111
|
end
|
83
112
|
|
84
|
-
|
113
|
+
# @see RAutomation::Window#close
|
114
|
+
def close
|
85
115
|
Functions.close_window(hwnd)
|
86
116
|
end
|
87
117
|
|
88
|
-
|
118
|
+
# @see Button#initialize
|
119
|
+
# @see RAutomation::Window#button
|
120
|
+
def button(locator)
|
89
121
|
Button.new(self, locator)
|
90
122
|
end
|
91
123
|
|
92
|
-
|
124
|
+
# @see TextField#initialize
|
125
|
+
# @see RAutomation::Window#text_field
|
126
|
+
def text_field(locator)
|
93
127
|
TextField.new(self, locator)
|
94
128
|
end
|
95
129
|
|
96
|
-
|
130
|
+
# Redirects all method calls not part of the public API to the {Functions} directly.
|
131
|
+
# @see RAutomation::Window#method_missing
|
132
|
+
def method_missing(name, *args)
|
97
133
|
Functions.respond_to?(name) ? Functions.send(name, *args) : super
|
98
134
|
end
|
135
|
+
|
99
136
|
end
|
100
137
|
end
|
101
138
|
end
|
data/lib/rautomation/button.rb
CHANGED
@@ -1,29 +1,30 @@
|
|
1
1
|
module RAutomation
|
2
2
|
class Button
|
3
|
-
#
|
4
|
-
|
3
|
+
# @private
|
4
|
+
# This constructor is meant to be accessed only through {Window#button} method.
|
5
|
+
def initialize(window, locators)
|
5
6
|
@window = window
|
6
7
|
@locators = locators
|
7
8
|
@button = @window.button(@locators)
|
8
9
|
end
|
9
10
|
|
10
11
|
# Performs a click on the Button.
|
11
|
-
#
|
12
|
-
# Raises an UnknownButtonException if the Button itself doesn't exist.
|
12
|
+
# @raise [UnknownButtonException] if the button doesn't exist.
|
13
13
|
def click
|
14
14
|
wait_until_exists
|
15
15
|
@button.click
|
16
16
|
end
|
17
17
|
|
18
|
-
# Retrieves the value of the
|
19
|
-
#
|
20
|
-
#
|
18
|
+
# Retrieves the value (text) of the button, usually the visible text.
|
19
|
+
# @return [String] the value (text) of the button.
|
20
|
+
# @raise [UnknownButtonException] if the button doesn't exist.
|
21
21
|
def value
|
22
22
|
wait_until_exists
|
23
23
|
@button.value
|
24
24
|
end
|
25
25
|
|
26
|
-
#
|
26
|
+
# Checks if the button exists.
|
27
|
+
# @return [Boolean] true if button exists, false otherwise.
|
27
28
|
def exists?
|
28
29
|
@button.exists?
|
29
30
|
end
|
@@ -1,37 +1,38 @@
|
|
1
1
|
module RAutomation
|
2
2
|
class TextField
|
3
|
-
#
|
3
|
+
# @private
|
4
|
+
# This constructor is meant to be accessed only through {Window#text_field} method.
|
4
5
|
def initialize(window, locators) #:nodoc:
|
5
6
|
@window = window
|
6
7
|
@locators = locators
|
7
8
|
@text_field = @window.text_field(@locators)
|
8
9
|
end
|
9
10
|
|
10
|
-
# Sets
|
11
|
-
#
|
12
|
-
#
|
11
|
+
# Sets text of the text field.
|
12
|
+
# @param [String] text of the field to set.
|
13
|
+
# @raise [UnknownTextFieldException] if the text field doesn't exist.
|
13
14
|
def set(text)
|
14
15
|
wait_until_exists
|
15
16
|
@text_field.set(text)
|
16
17
|
end
|
17
18
|
|
18
|
-
# Clears
|
19
|
-
#
|
20
|
-
# Raises an UnknownTextFieldException if the TextField itself doesn't exist.
|
19
|
+
# Clears text field's text.
|
20
|
+
# @raise [UnknownTextFieldException] if the text field doesn't exist.
|
21
21
|
def clear
|
22
22
|
wait_until_exists
|
23
23
|
@text_field.clear
|
24
24
|
end
|
25
25
|
|
26
|
-
# Returns
|
27
|
-
#
|
28
|
-
#
|
26
|
+
# Returns text field's current value (text).
|
27
|
+
# @return [String] the value (text) of the text field.
|
28
|
+
# @raise [UnknownTextFieldException] if the text field doesn't exist.
|
29
29
|
def value
|
30
30
|
wait_until_exists
|
31
31
|
@text_field.value
|
32
32
|
end
|
33
33
|
|
34
|
-
#
|
34
|
+
# Checks if the text field exists.
|
35
|
+
# @return [Boolean] true if text field exists, false otherwise.
|
35
36
|
def exists?
|
36
37
|
@text_field.exists?
|
37
38
|
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
module RAutomation
|
2
|
+
# Waiting with timeout
|
2
3
|
module WaitHelper
|
3
4
|
extend self
|
4
5
|
|
5
6
|
class TimeoutError < StandardError
|
6
7
|
end
|
7
8
|
|
8
|
-
#
|
9
|
+
# @private
|
9
10
|
# Wait until the block evaluates to true or times out.
|
10
|
-
#
|
11
11
|
def wait_until(timeout = 60, &block)
|
12
12
|
end_time = ::Time.now + timeout
|
13
13
|
|
data/lib/rautomation/window.rb
CHANGED
@@ -9,173 +9,181 @@ module RAutomation
|
|
9
9
|
class Window
|
10
10
|
include Adapter::Helper
|
11
11
|
|
12
|
+
# Currently used {Adapter}.
|
12
13
|
attr_reader :adapter
|
13
14
|
|
14
|
-
# Creates
|
15
|
+
# Creates the window object.
|
15
16
|
#
|
16
|
-
# Possible
|
17
|
+
# Possible window _locators_ may depend of the used platform and adapter, but
|
17
18
|
# following examples will use :title, :class and :hwnd.
|
18
19
|
#
|
19
|
-
# Use window with
|
20
|
+
# @example Use window with some title:
|
20
21
|
# RAutomation::Window.new(:title => "some title")
|
21
22
|
#
|
22
|
-
# Use window with Regexp title:
|
23
|
+
# @example Use window with Regexp title:
|
23
24
|
# RAutomation::Window.new(:title => /some title/i)
|
24
25
|
#
|
25
|
-
# Use window with handle
|
26
|
+
# @example Use window with handle (hwnd):
|
26
27
|
# RAutomation::Window.new(:hwnd => 123456)
|
27
28
|
#
|
28
|
-
#
|
29
|
+
# @example Use multiple locators, every locator will be matched (AND-ed) to the window:
|
29
30
|
# RAutomation::Window.new(:title => "some title", :class => "IEFrame")
|
30
31
|
#
|
31
|
-
# Refer to all possible
|
32
|
+
# @note Refer to all possible _locators_ in each {Adapter} documentation.
|
32
33
|
#
|
33
34
|
# _locators_ may also include a key called :adapter to change default adapter,
|
34
35
|
# which is dependent of the platform, to automate windows and their controls.
|
35
36
|
#
|
36
|
-
# It is also possible to change default adapter by using environment variable
|
37
|
-
#
|
37
|
+
# It is also possible to change the default adapter by using environment variable called
|
38
|
+
# __RAUTOMATION_ADAPTER__
|
38
39
|
#
|
39
|
-
#
|
40
|
-
#
|
40
|
+
# @note This constructor doesn't ensure window's existance.
|
41
|
+
# @note Window to be searched for has to be visible.
|
42
|
+
# @param [Hash] locators for the window.
|
41
43
|
def initialize(locators)
|
42
44
|
@adapter = locators.delete(:adapter) || ENV["RAUTOMATION_ADAPTER"] && ENV["RAUTOMATION_ADAPTER"].to_sym || default_adapter
|
43
45
|
@window = Adapter.const_get(normalize(@adapter)).const_get(:Window).new(locators)
|
44
46
|
end
|
45
47
|
|
46
48
|
class << self
|
47
|
-
# Timeout for waiting until object exists. If the timeout exceeds then an
|
49
|
+
# Timeout for waiting until object exists. If the timeout exceeds then an {WaitHelper::TimeoutError} is raised.
|
48
50
|
@@wait_timeout = 60
|
49
51
|
|
52
|
+
# Change the timeout to wait before {WaitHelper::TimeoutError} is raised.
|
53
|
+
# @param [Fixnum] timeout in seconds.
|
50
54
|
def wait_timeout=(timeout)
|
51
55
|
@@wait_timeout = timeout
|
52
56
|
end
|
53
57
|
|
58
|
+
# Retrieve current timeout in seconds to wait before {WaitHelper::TimeoutError} is raised.
|
59
|
+
# @return [Fixnum] timeout in seconds
|
54
60
|
def wait_timeout
|
55
61
|
@@wait_timeout
|
56
62
|
end
|
57
63
|
end
|
58
64
|
|
59
|
-
#
|
60
|
-
#
|
61
|
-
# This handle will be used internally for all operations.
|
65
|
+
# @return [Fixnum] handle of the window which is used internally for other methods.
|
62
66
|
def hwnd
|
63
67
|
wait_until_exists
|
64
68
|
@window.hwnd
|
65
69
|
end
|
66
70
|
|
67
|
-
#
|
68
|
-
|
69
|
-
|
71
|
+
# @return [Fixnum] process identifier (PID) of the window.
|
72
|
+
def pid
|
73
|
+
wait_until_exists
|
74
|
+
@window.pid
|
75
|
+
end
|
76
|
+
|
77
|
+
# @return [String] title of the window.
|
78
|
+
# @raise [UnknownWindowException] if the window doesn't exist.
|
70
79
|
def title
|
71
80
|
wait_until_exists
|
72
81
|
@window.title
|
73
82
|
end
|
74
83
|
|
75
|
-
# Activates the Window, e.g. brings to the top.
|
84
|
+
# Activates the Window, e.g. brings it to the top of other windows.
|
76
85
|
def activate
|
77
86
|
@window.activate
|
78
87
|
end
|
79
88
|
|
80
|
-
#
|
89
|
+
# Checks if the window is active, e.g. on the top of other windows.
|
90
|
+
# @return [Boolean] true if the window is active, false otherwise.
|
81
91
|
def active?
|
82
92
|
@window.active?
|
83
93
|
end
|
84
94
|
|
85
95
|
# Returns visible text of the Window.
|
86
|
-
#
|
87
|
-
#
|
96
|
+
# @return [String] visible text of the window.
|
97
|
+
# @raise [UnknownWindowException] if the window doesn't exist.
|
88
98
|
def text
|
89
99
|
wait_until_exists
|
90
100
|
@window.text
|
91
101
|
end
|
92
102
|
|
93
|
-
#
|
103
|
+
# Checks if the window exists (does have to be visible).
|
104
|
+
# @return [Boolean] true if the window exists, false otherwise.
|
94
105
|
def exists?
|
95
106
|
@window.exists?
|
96
107
|
end
|
97
108
|
|
98
109
|
alias_method :exist?, :exists?
|
99
110
|
|
100
|
-
#
|
101
|
-
# Window is also visible, if it is behind other windows or minimized.
|
102
|
-
#
|
103
|
-
#
|
111
|
+
# Checks if window is visible.
|
112
|
+
# @note Window is also visible, if it is behind other windows or minimized.
|
113
|
+
# @return [Boolean] true if window is visible, false otherwise.
|
114
|
+
# @raise [UnknownWindowException] if the window doesn't exist.
|
104
115
|
def visible?
|
105
116
|
wait_until_exists
|
106
117
|
@window.visible?
|
107
118
|
end
|
108
119
|
|
109
|
-
#
|
120
|
+
# Checks if the window exists and is visible.
|
121
|
+
# @return [Boolean] true if window exists and is visible, false otherwise
|
110
122
|
def present?
|
111
123
|
exists? && visible?
|
112
124
|
end
|
113
125
|
|
114
|
-
# Maximizes the
|
115
|
-
#
|
116
|
-
# Raises an UnknownWindowException if the Window itself doesn't exist.
|
126
|
+
# Maximizes the window.
|
127
|
+
# @raise [UnknownWindowException] if the window doesn't exist.
|
117
128
|
def maximize
|
118
129
|
wait_until_exists
|
119
130
|
@window.maximize
|
120
131
|
end
|
121
132
|
|
122
|
-
# Minimizes the
|
123
|
-
#
|
124
|
-
# Raises an UnknownWindowException if the Window itself doesn't exist.
|
133
|
+
# Minimizes the window.
|
134
|
+
# @raise [UnknownWindowException] if the window doesn't exist.
|
125
135
|
def minimize
|
126
136
|
wait_until_exists
|
127
137
|
@window.minimize
|
128
138
|
end
|
129
139
|
|
130
|
-
#
|
131
|
-
#
|
132
|
-
#
|
140
|
+
# Checks if window is minimized.
|
141
|
+
# @return [Boolean] true if window is minimized, false otherwise.
|
142
|
+
# @raise [UnknownWindowException] if the window doesn't exist.
|
133
143
|
def minimized?
|
134
144
|
wait_until_exists
|
135
145
|
@window.minimized?
|
136
146
|
end
|
137
147
|
|
138
|
-
# Restores the
|
139
|
-
#
|
140
|
-
#
|
148
|
+
# Restores the window size and position.
|
149
|
+
# @note If the window is minimized, makes it visible again.
|
150
|
+
# @raise [UnknownWindowException] if the window doesn't exist.
|
141
151
|
def restore
|
142
152
|
wait_until_exists
|
143
153
|
@window.restore
|
144
154
|
end
|
145
155
|
|
146
|
-
# Sends keys to the
|
147
|
-
#
|
148
|
-
# Raises an UnknownWindowException if the Window itself doesn't exist.
|
156
|
+
# Sends keyboard keys to the window. Refer to specific {Adapter} documentation for all possible values.
|
157
|
+
# @raise [UnknownWindowException] if the window doesn't exist.
|
149
158
|
def send_keys(*keys)
|
150
159
|
wait_until_exists
|
151
160
|
@window.send_keys(*keys)
|
152
161
|
end
|
153
162
|
|
154
|
-
# Closes the
|
163
|
+
# Closes the window if it exists.
|
155
164
|
def close
|
156
165
|
return unless @window.exists?
|
157
166
|
@window.close
|
158
167
|
end
|
159
168
|
|
160
|
-
#
|
161
|
-
# Refer to specific
|
162
|
-
#
|
163
|
-
#
|
169
|
+
# Retrieves {Button} on the window.
|
170
|
+
# @note Refer to specific {Adapter} documentation for possible _locator_ parameters.
|
171
|
+
# @param [Hash] locators for the {Button}.
|
172
|
+
# @raise [UnknownWindowException] if the window doesn't exist.
|
164
173
|
def button(locators)
|
165
174
|
wait_until_exists
|
166
175
|
Button.new(@window, locators)
|
167
176
|
end
|
168
177
|
|
169
|
-
#
|
170
|
-
# Refer to specific
|
171
|
-
#
|
172
|
-
# Raises an UnknownWindowException if the Window itself doesn't exist.
|
178
|
+
# Retrieves {TextField} on the window.
|
179
|
+
# @note Refer to specific {Adapter} documentation for possible _locators_ parameters.
|
180
|
+
# @raise [UnknownWindowException] if the window doesn't exist.
|
173
181
|
def text_field(locators)
|
174
182
|
wait_until_exists
|
175
183
|
TextField.new(@window, locators)
|
176
184
|
end
|
177
185
|
|
178
|
-
#
|
186
|
+
# Allows to execute specific {Adapter} methods not part of the public API.
|
179
187
|
def method_missing(name, *args)
|
180
188
|
@window.send(name, *args)
|
181
189
|
end
|
data/rautomation.gemspec
CHANGED
@@ -5,19 +5,19 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{rautomation}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Jarmo Pertman"]
|
12
|
-
s.date = %q{2010-12-
|
13
|
-
s.description = %q{RAutomation
|
12
|
+
s.date = %q{2010-12-17}
|
13
|
+
s.description = %q{RAutomation is a small and easy to use library for helping out to automate windows and their controls
|
14
14
|
for automated testing.
|
15
15
|
|
16
|
-
RAutomation
|
17
|
-
* Easy to use and user-friendly API (inspired by Watir http://www.watir.com)
|
16
|
+
RAutomation provides:
|
17
|
+
* Easy to use and user-friendly API (inspired by Watir http://www.watir.com)
|
18
18
|
* Cross-platform compatibility
|
19
|
-
* Easy extensibility -
|
20
|
-
|
19
|
+
* Easy extensibility - with small scripting effort it's possible to add support for not yet
|
20
|
+
supported platforms or technologies}
|
21
21
|
s.email = %q{jarmo.p@gmail.com}
|
22
22
|
s.extra_rdoc_files = [
|
23
23
|
"LICENSE",
|
data/spec/spec_helper.rb
CHANGED
@@ -31,6 +31,7 @@ module SpecHelper
|
|
31
31
|
:window2_button_text => "OK",
|
32
32
|
# Window 2 should have a text field with the specified class name.
|
33
33
|
:window2_text_field_class => "Edit",
|
34
|
+
# Adapter internal method invocation for getting title of window2
|
34
35
|
:title_proc => lambda {|win| win.WinGetTitle("[TITLE:Explorer User Prompt]")}
|
35
36
|
},
|
36
37
|
# This adapter needs Windows OS with Internet Explorer installed into 'c:\program files\internet explorer'.
|
@@ -53,6 +54,7 @@ module SpecHelper
|
|
53
54
|
:window2_button_text => "OK",
|
54
55
|
# Window 2 should have a text field with the specified class name.
|
55
56
|
:window2_text_field_class => "Edit",
|
57
|
+
# Adapter internal method invocation for getting title of window2
|
56
58
|
:title_proc => lambda {|win| win.window_title(win.hwnd)}
|
57
59
|
}
|
58
60
|
}[ENV["RAUTOMATION_ADAPTER"] && ENV["RAUTOMATION_ADAPTER"].to_sym || RAutomation::Adapter::Helper.default_adapter]
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rautomation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 2
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jarmo Pertman
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-12-
|
18
|
+
date: 2010-12-17 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -34,14 +34,14 @@ dependencies:
|
|
34
34
|
type: :development
|
35
35
|
version_requirements: *id001
|
36
36
|
description: |-
|
37
|
-
RAutomation
|
37
|
+
RAutomation is a small and easy to use library for helping out to automate windows and their controls
|
38
38
|
for automated testing.
|
39
39
|
|
40
|
-
RAutomation
|
41
|
-
* Easy to use and user-friendly API (inspired by Watir http://www.watir.com)
|
40
|
+
RAutomation provides:
|
41
|
+
* Easy to use and user-friendly API (inspired by Watir http://www.watir.com)
|
42
42
|
* Cross-platform compatibility
|
43
|
-
* Easy extensibility -
|
44
|
-
|
43
|
+
* Easy extensibility - with small scripting effort it's possible to add support for not yet
|
44
|
+
supported platforms or technologies
|
45
45
|
email: jarmo.p@gmail.com
|
46
46
|
executables: []
|
47
47
|
|