rautomation 0.2.1 → 0.3.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 +6 -4
- data/VERSION +1 -1
- data/lib/rautomation/adapter/ffi/constants.rb +3 -0
- data/lib/rautomation/adapter/ffi/functions.rb +22 -0
- data/lib/rautomation/adapter/ffi/window.rb +8 -0
- data/rautomation.gemspec +2 -2
- data/spec/button_spec.rb +6 -6
- data/spec/spec_helper.rb +8 -1
- data/spec/text_field_spec.rb +8 -8
- data/spec/window_spec.rb +30 -21
- metadata +5 -5
data/History.rdoc
CHANGED
data/README.rdoc
CHANGED
@@ -70,10 +70,12 @@ about that matter - or even better, follow the instructions at "How to create a
|
|
70
70
|
1. Fork the project.
|
71
71
|
2. Create entry point file to lib/rautomation/adapter which should load all adapter specific files.
|
72
72
|
3. Add `autoload` statement into lib/rautomation/adapter/helper.rb for that file.
|
73
|
-
4.
|
74
|
-
5.
|
75
|
-
6.
|
76
|
-
7.
|
73
|
+
4. Create a directory for your adapter's specific code into lib/rautomation/adapter
|
74
|
+
5. Copy button.rb, text_field.rb and window.rb from some of the existing adapter's directory.
|
75
|
+
6. Add spec data for your adapter into spec/spec_helper DATA constant.
|
76
|
+
7. Use environment variable __RAUTOMATION_ADAPTER__ to point to that adapter.
|
77
|
+
8. Start coding and spec-ing until as much of possible of the public API is satisfied.
|
78
|
+
9. Make me a pull request.
|
77
79
|
|
78
80
|
Don't forget to fix the documentation for that adapter also!
|
79
81
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
@@ -55,6 +55,8 @@ module RAutomation
|
|
55
55
|
[:long], :int
|
56
56
|
attach_function :_set_control_focus, :SetFocus,
|
57
57
|
[:long], :long
|
58
|
+
attach_function :get_window, :GetWindow,
|
59
|
+
[:long, :uint], :long
|
58
60
|
|
59
61
|
# kernel32
|
60
62
|
attach_function :open_process, :OpenProcess,
|
@@ -72,6 +74,8 @@ module RAutomation
|
|
72
74
|
title.read_string
|
73
75
|
end
|
74
76
|
|
77
|
+
alias_method :control_title, :window_title
|
78
|
+
|
75
79
|
def window_text(hwnd)
|
76
80
|
found_text = ""
|
77
81
|
window_callback = FFI::Function.new(:bool, [:long, :pointer], {:convention => :stdcall}) do |child_hwnd, _|
|
@@ -82,6 +86,8 @@ module RAutomation
|
|
82
86
|
found_text
|
83
87
|
end
|
84
88
|
|
89
|
+
alias_method :control_text, :window_text
|
90
|
+
|
85
91
|
def window_hwnd(locators)
|
86
92
|
find_hwnd(locators) do |hwnd|
|
87
93
|
window_visible(hwnd) && !window_text(hwnd).empty? &&
|
@@ -89,6 +95,20 @@ module RAutomation
|
|
89
95
|
end
|
90
96
|
end
|
91
97
|
|
98
|
+
def child_window_locators(parent_hwnd, locators)
|
99
|
+
child_hwnd = locators[:hwnd] || child_hwnd(parent_hwnd, locators)
|
100
|
+
if child_hwnd
|
101
|
+
locators.merge!(:hwnd => child_hwnd)
|
102
|
+
else
|
103
|
+
popup_hwnd = get_window(parent_hwnd, Constants::GW_ENABLEDPOPUP)
|
104
|
+
if popup_hwnd != parent_hwnd
|
105
|
+
popup_properties = window_properties(popup_hwnd, locators)
|
106
|
+
locators.merge!(:hwnd => popup_hwnd) if locators_match?(locators, popup_properties)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
locators
|
110
|
+
end
|
111
|
+
|
92
112
|
def window_pid(hwnd)
|
93
113
|
pid = FFI::MemoryPointer.new :int
|
94
114
|
window_thread_process_id(hwnd, pid)
|
@@ -132,6 +152,8 @@ module RAutomation
|
|
132
152
|
end
|
133
153
|
end
|
134
154
|
|
155
|
+
alias_method :child_hwnd, :control_hwnd
|
156
|
+
|
135
157
|
def control_value(control_hwnd)
|
136
158
|
text_for(control_hwnd)
|
137
159
|
end
|
@@ -133,6 +133,14 @@ module RAutomation
|
|
133
133
|
Functions.respond_to?(name) ? Functions.send(name, *args) : super
|
134
134
|
end
|
135
135
|
|
136
|
+
# Creates the child window object.
|
137
|
+
# @note This is an Ffi adapter specific method, not part of the public API
|
138
|
+
# @param (see Window#initialize)
|
139
|
+
# @return [RAutomation::Window] child window, popup or regular window.
|
140
|
+
def child(locators)
|
141
|
+
RAutomation::Window.new Functions.child_window_locators(hwnd, locators)
|
142
|
+
end
|
143
|
+
|
136
144
|
end
|
137
145
|
end
|
138
146
|
end
|
data/rautomation.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{rautomation}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.3.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-
|
12
|
+
s.date = %q{2010-12-18}
|
13
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
|
|
data/spec/button_spec.rb
CHANGED
@@ -6,8 +6,8 @@ describe RAutomation::Button do
|
|
6
6
|
button(:value => SpecHelper::DATA[:window2_button_text]).should exist
|
7
7
|
|
8
8
|
RAutomation::Window.wait_timeout = 0.1
|
9
|
-
|
10
|
-
|
9
|
+
expect {RAutomation::Window.new(:title => "non-existing-window").button(:value => "Something")}.
|
10
|
+
to raise_exception(RAutomation::UnknownWindowException)
|
11
11
|
end
|
12
12
|
|
13
13
|
it "#value" do
|
@@ -15,8 +15,8 @@ describe RAutomation::Button do
|
|
15
15
|
button(:value => SpecHelper::DATA[:window2_button_text]).value.should == SpecHelper::DATA[:window2_button_text]
|
16
16
|
|
17
17
|
RAutomation::Window.wait_timeout = 0.1
|
18
|
-
|
19
|
-
|
18
|
+
expect {RAutomation::Window.new(:title => SpecHelper::DATA[:window2_title]).button(:value => "non-existent-button").value}.
|
19
|
+
to raise_exception(RAutomation::UnknownButtonException)
|
20
20
|
end
|
21
21
|
|
22
22
|
it "#exists?" do
|
@@ -28,8 +28,8 @@ describe RAutomation::Button do
|
|
28
28
|
it "#click" do
|
29
29
|
window = RAutomation::Window.new(:title => SpecHelper::DATA[:window2_title])
|
30
30
|
RAutomation::Window.wait_timeout = 0.1
|
31
|
-
|
32
|
-
|
31
|
+
expect {window.button(:value => "non-existent-button").click}.
|
32
|
+
to raise_exception(RAutomation::UnknownButtonException)
|
33
33
|
|
34
34
|
button = window.button(:value => SpecHelper::DATA[:window2_button_text])
|
35
35
|
button.should exist
|
data/spec/spec_helper.rb
CHANGED
@@ -3,6 +3,13 @@ require 'rautomation'
|
|
3
3
|
require 'rspec'
|
4
4
|
|
5
5
|
module SpecHelper
|
6
|
+
# @private
|
7
|
+
def adapter
|
8
|
+
ENV["RAUTOMATION_ADAPTER"] && ENV["RAUTOMATION_ADAPTER"].to_sym || RAutomation::Adapter::Helper.default_adapter
|
9
|
+
end
|
10
|
+
|
11
|
+
module_function :adapter
|
12
|
+
|
6
13
|
# Since adapters are different then the windows to be tested
|
7
14
|
# might be different also.
|
8
15
|
#
|
@@ -57,7 +64,7 @@ module SpecHelper
|
|
57
64
|
# Adapter internal method invocation for getting title of window2
|
58
65
|
:title_proc => lambda {|win| win.window_title(win.hwnd)}
|
59
66
|
}
|
60
|
-
}[
|
67
|
+
}[adapter]
|
61
68
|
end
|
62
69
|
|
63
70
|
RSpec.configure do |config|
|
data/spec/text_field_spec.rb
CHANGED
@@ -6,9 +6,9 @@ describe RAutomation::TextField do
|
|
6
6
|
text_field(:class => SpecHelper::DATA[:window2_text_field_class]).should exist
|
7
7
|
|
8
8
|
RAutomation::Window.wait_timeout = 0.1
|
9
|
-
|
9
|
+
expect {RAutomation::Window.new(:title => "non-existent-window").
|
10
10
|
text_field(:class => SpecHelper::DATA[:window2_text_field_class])}.
|
11
|
-
|
11
|
+
to raise_exception(RAutomation::UnknownWindowException)
|
12
12
|
end
|
13
13
|
|
14
14
|
it "#set" do
|
@@ -16,8 +16,8 @@ describe RAutomation::TextField do
|
|
16
16
|
window.text_field(:class => SpecHelper::DATA[:window2_text_field_class]).set "hello!"
|
17
17
|
|
18
18
|
RAutomation::Window.wait_timeout = 0.1
|
19
|
-
|
20
|
-
|
19
|
+
expect {window.text_field(:class => "non-existing-field").set "hello!"}.
|
20
|
+
to raise_exception(RAutomation::UnknownTextFieldException)
|
21
21
|
end
|
22
22
|
|
23
23
|
it "#clear"do
|
@@ -29,8 +29,8 @@ describe RAutomation::TextField do
|
|
29
29
|
field.value.should be_empty
|
30
30
|
|
31
31
|
RAutomation::Window.wait_timeout = 0.1
|
32
|
-
|
33
|
-
|
32
|
+
expect {window.text_field(:class => "non-existent-field").clear}.
|
33
|
+
to raise_exception(RAutomation::UnknownTextFieldException)
|
34
34
|
end
|
35
35
|
|
36
36
|
it "#value" do
|
@@ -40,8 +40,8 @@ describe RAutomation::TextField do
|
|
40
40
|
field.value.should == "hello!"
|
41
41
|
|
42
42
|
RAutomation::Window.wait_timeout = 0.1
|
43
|
-
|
44
|
-
|
43
|
+
expect {window.text_field(:class => "non-existent-field").value}.
|
44
|
+
to raise_exception(RAutomation::UnknownTextFieldException)
|
45
45
|
end
|
46
46
|
|
47
47
|
it "#exists?" do
|
data/spec/window_spec.rb
CHANGED
@@ -36,8 +36,8 @@ describe RAutomation::Window do
|
|
36
36
|
it "#visible?"do
|
37
37
|
RAutomation::Window.new(:title => SpecHelper::DATA[:window1_title]).should be_visible
|
38
38
|
RAutomation::Window.wait_timeout = 0.1
|
39
|
-
|
40
|
-
|
39
|
+
expect {RAutomation::Window.new(:title => "non-existing-window").visible?}.
|
40
|
+
to raise_exception(RAutomation::UnknownWindowException)
|
41
41
|
end
|
42
42
|
|
43
43
|
it "#present?"do
|
@@ -48,15 +48,15 @@ describe RAutomation::Window do
|
|
48
48
|
it "#hwnd" do
|
49
49
|
RAutomation::Window.new(:title => SpecHelper::DATA[:window1_title]).hwnd.should be_a(Fixnum)
|
50
50
|
RAutomation::Window.wait_timeout = 0.1
|
51
|
-
|
52
|
-
|
51
|
+
expect {RAutomation::Window.new(:title => "non-existing-window").hwnd}.
|
52
|
+
to raise_exception(RAutomation::UnknownWindowException)
|
53
53
|
end
|
54
54
|
|
55
55
|
it "#title" do
|
56
56
|
RAutomation::Window.new(:title => SpecHelper::DATA[:window2_title]).title.should == SpecHelper::DATA[:window2_title]
|
57
57
|
RAutomation::Window.wait_timeout = 0.1
|
58
|
-
|
59
|
-
|
58
|
+
expect {RAutomation::Window.new(:title => "non-existing-window").title}.
|
59
|
+
to raise_exception(RAutomation::UnknownWindowException)
|
60
60
|
end
|
61
61
|
|
62
62
|
it "#activate & #active?" do
|
@@ -71,35 +71,44 @@ describe RAutomation::Window do
|
|
71
71
|
it "#text" do
|
72
72
|
RAutomation::Window.new(:title => SpecHelper::DATA[:window2_title]).text.should include(SpecHelper::DATA[:window2_text])
|
73
73
|
RAutomation::Window.wait_timeout = 0.1
|
74
|
-
|
75
|
-
|
74
|
+
expect {RAutomation::Window.new(:title => "non-existing-window").text}.
|
75
|
+
to raise_exception(RAutomation::UnknownWindowException)
|
76
76
|
end
|
77
77
|
|
78
78
|
it "#maximize" do
|
79
79
|
RAutomation::Window.new(:title => SpecHelper::DATA[:window1_title]).maximize
|
80
80
|
RAutomation::Window.wait_timeout = 0.1
|
81
|
-
|
82
|
-
|
81
|
+
expect {RAutomation::Window.new(:title => "non-existing-window").maximize}.
|
82
|
+
to raise_exception(RAutomation::UnknownWindowException)
|
83
83
|
end
|
84
84
|
|
85
|
-
it "#minimize
|
85
|
+
it "#minimize & #minimized?" do
|
86
86
|
window = RAutomation::Window.new(:title => SpecHelper::DATA[:window1_title])
|
87
87
|
window.should_not be_minimized
|
88
88
|
window.minimize
|
89
89
|
window.should be_minimized
|
90
90
|
|
91
91
|
RAutomation::Window.wait_timeout = 0.1
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
92
|
+
expect {RAutomation::Window.new(:title => "non-existing-window").minimize}.
|
93
|
+
to raise_exception(RAutomation::UnknownWindowException)
|
94
|
+
expect {RAutomation::Window.new(:title => "non-existing-window").minimized?}.
|
95
|
+
to raise_exception(RAutomation::UnknownWindowException)
|
96
96
|
end
|
97
97
|
|
98
98
|
it "#restore" do
|
99
99
|
RAutomation::Window.new(:title => SpecHelper::DATA[:window1_title]).restore
|
100
100
|
RAutomation::Window.wait_timeout = 0.1
|
101
|
-
|
102
|
-
|
101
|
+
expect {RAutomation::Window.new(:title => "non-existing-window").restore}.
|
102
|
+
to raise_exception(RAutomation::UnknownWindowException)
|
103
|
+
end
|
104
|
+
|
105
|
+
it "#child", :if => SpecHelper.adapter == :ffi do
|
106
|
+
window = RAutomation::Window.new(:title => /Windows Internet Explorer/i)
|
107
|
+
window.should exist
|
108
|
+
child = window.child(:title => SpecHelper::DATA[:window2_title])
|
109
|
+
child.should exist
|
110
|
+
child.title.should == SpecHelper::DATA[:window2_title]
|
111
|
+
child.text.should include(SpecHelper::DATA[:window2_text])
|
103
112
|
end
|
104
113
|
|
105
114
|
it "#method_missing" do
|
@@ -114,8 +123,8 @@ describe RAutomation::Window do
|
|
114
123
|
RAutomation::WaitHelper.wait_until(15) {not window.exists?}
|
115
124
|
|
116
125
|
RAutomation::Window.wait_timeout = 0.1
|
117
|
-
|
118
|
-
|
126
|
+
expect {RAutomation::Window.new(:title => "non-existing-window").send_keys("123")}.
|
127
|
+
to raise_exception(RAutomation::UnknownWindowException)
|
119
128
|
end
|
120
129
|
|
121
130
|
it "#close" do
|
@@ -124,7 +133,7 @@ describe RAutomation::Window do
|
|
124
133
|
window.close
|
125
134
|
window.should_not exist
|
126
135
|
|
127
|
-
|
128
|
-
|
136
|
+
expect {RAutomation::Window.new(:title => "non-existing-window").close}.
|
137
|
+
to_not raise_exception
|
129
138
|
end
|
130
139
|
end
|
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: 19
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 3
|
9
|
+
- 0
|
10
|
+
version: 0.3.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-18 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|