rautomation 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/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
|
|