uia 0.3.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +5 -0
- data/ext/UiaDll/Release/UIA.Helper.dll +0 -0
- data/ext/UiaDll/Release/UiaDll.dll +0 -0
- data/ext/UiaDll/UIA.Helper/Element.cs +5 -0
- data/ext/UiaDll/UIA.Helper/Extensions.cs +5 -0
- data/ext/UiaDll/UiaDll/MenuItemMethods.cpp +27 -0
- data/ext/UiaDll/UiaDll/UiaDll.vcxproj +1 -0
- data/ext/UiaDll/UiaDll/UiaDll.vcxproj.filters +6 -0
- data/lib/core_ext/module.rb +7 -0
- data/lib/core_ext/symbol.rb +5 -3
- data/lib/uia/control_types/menu_item.rb +10 -0
- data/lib/uia/element.rb +4 -0
- data/lib/uia/library.rb +19 -17
- data/lib/uia/version.rb +1 -1
- data/lib/uia.rb +1 -0
- data/spec/uia/control_types/menu_item_spec.rb +27 -0
- metadata +9 -4
data/ChangeLog
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
=== Version 0.3.2 / 2014-05-13
|
2
|
+
* Enhancements
|
3
|
+
* added #with method to extend an Element based on ControlPatterns
|
4
|
+
* Uia::ControlPatterns::MenuItems can select a menu item by name or path
|
5
|
+
|
1
6
|
=== Version 0.3.1 / 2014-05-07
|
2
7
|
* Enhancements
|
3
8
|
* added Table#row_at method
|
Binary file
|
Binary file
|
@@ -167,6 +167,11 @@ namespace UIA.Helper
|
|
167
167
|
return NullOr(AutomationElement.FromHandle(windowHandle));
|
168
168
|
}
|
169
169
|
|
170
|
+
public Element MenuItem(string name)
|
171
|
+
{
|
172
|
+
return FindFirst(TreeScope.Subtree, new AndCondition(name.NameCondition(), ControlType.MenuItem.Condition()));
|
173
|
+
}
|
174
|
+
|
170
175
|
public static Element ByRuntimeId(int[] runtimeId)
|
171
176
|
{
|
172
177
|
return FindFirst(new PropertyCondition(AutomationElement.RuntimeIdProperty, runtimeId), TreeScope.Descendants);
|
@@ -35,6 +35,11 @@ namespace UIA.Helper
|
|
35
35
|
return new PropertyCondition(AutomationElement.NameProperty, name);
|
36
36
|
}
|
37
37
|
|
38
|
+
public static Condition Condition(this ControlType controlType)
|
39
|
+
{
|
40
|
+
return new PropertyCondition(AutomationElement.ControlTypeProperty, controlType);
|
41
|
+
}
|
42
|
+
|
38
43
|
public static int PropertyId(this string propertyName)
|
39
44
|
{
|
40
45
|
var automationField = typeof(AutomationElement).GetField(propertyName);
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#include "Stdafx.h"
|
2
|
+
|
3
|
+
extern "C" {
|
4
|
+
void SelectMenuItemPath(ElementInformationPtr element, char* errorInfo, const int errorInfoLength, list<const char*>& items) {
|
5
|
+
try {
|
6
|
+
auto current = ElementFrom(element);
|
7
|
+
|
8
|
+
for(auto item = items.begin(); item != items.end(); ++item) {
|
9
|
+
auto name = gcnew String(*item);
|
10
|
+
|
11
|
+
current = current->MenuItem(name);
|
12
|
+
if( nullptr == current) {
|
13
|
+
throw gcnew Exception(String::Format("the menu item \"{0}\" was not found", name));
|
14
|
+
}
|
15
|
+
|
16
|
+
current->As<InvokePattern^>(InvokePattern::Pattern)->Invoke();
|
17
|
+
}
|
18
|
+
} catch(Exception^ e) {
|
19
|
+
StringHelper::CopyToUnmanagedString(e->Message, errorInfo, errorInfoLength);
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
__declspec(dllexport) void MenuItem_SelectPath(ElementInformationPtr element, char* errorInfo, const int errorInfoLength, const int n, const char* arg0, ...) {
|
24
|
+
GRAB_VARARGS(menuItems, const char*, n);
|
25
|
+
SelectMenuItemPath(element, errorInfo, errorInfoLength, menuItems);
|
26
|
+
}
|
27
|
+
}
|
@@ -95,6 +95,7 @@
|
|
95
95
|
<ClCompile Include="ElementMethods.cpp" />
|
96
96
|
<ClCompile Include="ExpandCollapseMethods.cpp" />
|
97
97
|
<ClCompile Include="InvokePatternMethods.cpp" />
|
98
|
+
<ClCompile Include="MenuItemMethods.cpp" />
|
98
99
|
<ClCompile Include="MouseMethods.cpp" />
|
99
100
|
<ClCompile Include="RangeValueMethods.cpp" />
|
100
101
|
<ClCompile Include="SelectionItemMethods.cpp" />
|
@@ -16,6 +16,9 @@
|
|
16
16
|
<Filter Include="Source Files\Patterns">
|
17
17
|
<UniqueIdentifier>{a1dddb33-e832-4b83-b6d7-46462084fad2}</UniqueIdentifier>
|
18
18
|
</Filter>
|
19
|
+
<Filter Include="Source Files\ControlTypes">
|
20
|
+
<UniqueIdentifier>{f17fb0d5-c4d9-44ae-9cf3-518f4f70839d}</UniqueIdentifier>
|
21
|
+
</Filter>
|
19
22
|
</ItemGroup>
|
20
23
|
<ItemGroup>
|
21
24
|
<ClInclude Include="Stdafx.h">
|
@@ -98,5 +101,8 @@
|
|
98
101
|
<ClCompile Include="ConditionMethods.cpp">
|
99
102
|
<Filter>Source Files</Filter>
|
100
103
|
</ClCompile>
|
104
|
+
<ClCompile Include="MenuItemMethods.cpp">
|
105
|
+
<Filter>Source Files\ControlTypes</Filter>
|
106
|
+
</ClCompile>
|
101
107
|
</ItemGroup>
|
102
108
|
</Project>
|
data/lib/core_ext/symbol.rb
CHANGED
@@ -9,9 +9,11 @@ class Symbol
|
|
9
9
|
|
10
10
|
# :selection_item => Uia::Patterns::SelectionItem
|
11
11
|
def to_pattern_const
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
Uia::Patterns.const_get_path "#{self.capitalize}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_control_type
|
16
|
+
Uia::ControlTypes.const_get_path "#{self.capitalize}"
|
15
17
|
end
|
16
18
|
|
17
19
|
def to_control_type_const
|
data/lib/uia/element.rb
CHANGED
@@ -91,6 +91,10 @@ module Uia
|
|
91
91
|
extend pattern.to_pattern_const
|
92
92
|
end
|
93
93
|
|
94
|
+
def with(control_types)
|
95
|
+
extend control_types.to_control_type
|
96
|
+
end
|
97
|
+
|
94
98
|
def patterns
|
95
99
|
@element.pattern_ids.map { |id| Library::Constants::Patterns.find(@default) { |_, v| v == id }.first }
|
96
100
|
end
|
data/lib/uia/library.rb
CHANGED
@@ -75,12 +75,10 @@ module Uia
|
|
75
75
|
attach_function :Condition_ControlType, [:int, :varargs], SearchCondition.by_ref
|
76
76
|
|
77
77
|
def self.pattern_condition(*patterns)
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
raise error_info unless error_info.empty?
|
83
|
-
result
|
78
|
+
try_catch do |s, n|
|
79
|
+
pattern_strings = patterns.flatten.map(&:to_pattern_available_property)
|
80
|
+
Condition_Pattern s, n, pattern_strings.count, *pattern_strings.to_var_args(:string)
|
81
|
+
end
|
84
82
|
end
|
85
83
|
|
86
84
|
def self.control_type_condition(*control_types)
|
@@ -153,6 +151,12 @@ module Uia
|
|
153
151
|
p.read_string
|
154
152
|
end
|
155
153
|
|
154
|
+
# MenuItem methods
|
155
|
+
attach_function :MenuItem_SelectPath, [:pointer, :pointer, :int, :int, :varargs], :void
|
156
|
+
def self.select_menu_path(element, *path)
|
157
|
+
try_catch {|s, n| MenuItem_SelectPath element, s, n, path.count, *path.to_var_args(:string) }
|
158
|
+
end
|
159
|
+
|
156
160
|
def self.find_by_runtime_id(id)
|
157
161
|
p = FFI::MemoryPointer.new :int, id.count
|
158
162
|
p.write_array_of_int(id)
|
@@ -160,35 +164,33 @@ module Uia
|
|
160
164
|
Uia::Element.new(result) unless result.empty?
|
161
165
|
end
|
162
166
|
|
163
|
-
def self.
|
167
|
+
def self.try_catch(&block)
|
164
168
|
string_buffer = FFI::MemoryPointer.new :char, 1024
|
165
|
-
result =
|
169
|
+
result = block.call(string_buffer, 1024)
|
166
170
|
error_info = string_buffer.read_string
|
167
171
|
raise error_info unless error_info.empty?
|
168
172
|
result
|
169
173
|
end
|
170
174
|
|
175
|
+
def self.can_throw(method, *args)
|
176
|
+
try_catch {|s, n| send method, *(args << s << n) }
|
177
|
+
end
|
178
|
+
|
171
179
|
def self.find_first(element, scope, *conditions)
|
172
|
-
|
173
|
-
result = FindFirst element, scope, string_buffer, 1024, conditions.count, *conditions.to_var_args(:pointer)
|
174
|
-
error_info = string_buffer.read_string
|
175
|
-
raise error_info unless error_info.empty?
|
180
|
+
result = try_catch {|s, n| FindFirst element, scope, s, n, conditions.count, *conditions.to_var_args(:pointer) }
|
176
181
|
Uia::Element.new(result) unless result.empty?
|
177
182
|
end
|
178
183
|
|
179
184
|
def self.find_all(element, scope, *conditions)
|
180
185
|
elements_pointer = FFI::MemoryPointer.new :pointer
|
181
|
-
|
182
|
-
result = FindAll element, elements_pointer, scope, string_buffer, 1024, conditions.count, *conditions.to_var_args(:pointer)
|
183
|
-
error_info = string_buffer.read_string
|
184
|
-
raise error_info unless error_info.empty?
|
186
|
+
result = try_catch {|s, n| FindAll element, elements_pointer, scope, s, n, conditions.count, *conditions.to_var_args(:pointer) }
|
185
187
|
result.times.collect do |which_element|
|
186
188
|
pointer = elements_pointer.read_pointer + which_element * ManagedElementStruct.size
|
187
189
|
Uia::Element.new(ManagedElementStruct.new(pointer))
|
188
190
|
end
|
189
191
|
end
|
190
192
|
|
191
|
-
rescue LoadError
|
193
|
+
rescue LoadError
|
192
194
|
raise LoadError, 'You must install the Visual Studio 2012 C++ Runtime Environment to use the Uia gem (http://www.microsoft.com/en-us/download/details.aspx?id=30679)'
|
193
195
|
end
|
194
196
|
end
|
data/lib/uia/version.rb
CHANGED
data/lib/uia.rb
CHANGED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Uia::ControlTypes::MenuItems do
|
4
|
+
Given(:main) { Uia.find_element(title: 'MainFormWindow').with(:menu_items) }
|
5
|
+
|
6
|
+
after(:each) do
|
7
|
+
about = Uia.find_element(title: 'About')
|
8
|
+
about.send_keys [:alt, :f4] if about
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'selecting individually' do
|
12
|
+
When { main.select_menu_item 'About' }
|
13
|
+
Then { Uia.find_element(title: 'About') != nil }
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'selecting a path' do
|
17
|
+
context 'valid' do
|
18
|
+
When { main.select_menu_path 'File', 'Roundabout Way', 'To', 'About' }
|
19
|
+
Then { Uia.find_element(title: 'About') != nil }
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'invalid' do
|
23
|
+
Given(:bad_path) { main.select_menu_path 'File', 'Roundabout Way', 'To', 'Something Not There' }
|
24
|
+
Then { expect { bad_path }.to raise_error(RuntimeError, /Something Not There/) }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: uia
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-05-
|
12
|
+
date: 2014-05-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ffi
|
@@ -172,6 +172,7 @@ files:
|
|
172
172
|
- ext/UiaDll/UiaDll/ElementStructures.h
|
173
173
|
- ext/UiaDll/UiaDll/ExpandCollapseMethods.cpp
|
174
174
|
- ext/UiaDll/UiaDll/InvokePatternMethods.cpp
|
175
|
+
- ext/UiaDll/UiaDll/MenuItemMethods.cpp
|
175
176
|
- ext/UiaDll/UiaDll/MouseMethods.cpp
|
176
177
|
- ext/UiaDll/UiaDll/PatternInformationStructures.h
|
177
178
|
- ext/UiaDll/UiaDll/RangeValueMethods.cpp
|
@@ -194,9 +195,11 @@ files:
|
|
194
195
|
- ext/UiaDll/UiaDll/WindowMethods.cpp
|
195
196
|
- ext/UiaDll/UiaDll/app.rc
|
196
197
|
- lib/core_ext/array.rb
|
198
|
+
- lib/core_ext/module.rb
|
197
199
|
- lib/core_ext/string.rb
|
198
200
|
- lib/core_ext/symbol.rb
|
199
201
|
- lib/uia.rb
|
202
|
+
- lib/uia/control_types/menu_item.rb
|
200
203
|
- lib/uia/element.rb
|
201
204
|
- lib/uia/finder.rb
|
202
205
|
- lib/uia/keys.rb
|
@@ -225,6 +228,7 @@ files:
|
|
225
228
|
- spec/app/WindowsForms.exe
|
226
229
|
- spec/core_ext/symbol_spec.rb
|
227
230
|
- spec/spec_helper.rb
|
231
|
+
- spec/uia/control_types/menu_item_spec.rb
|
228
232
|
- spec/uia/element_spec.rb
|
229
233
|
- spec/uia/keys_spec.rb
|
230
234
|
- spec/uia/patterns/expand_collapse_spec.rb
|
@@ -257,7 +261,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
257
261
|
version: '0'
|
258
262
|
segments:
|
259
263
|
- 0
|
260
|
-
hash:
|
264
|
+
hash: 59019763
|
261
265
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
262
266
|
none: false
|
263
267
|
requirements:
|
@@ -266,7 +270,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
266
270
|
version: '0'
|
267
271
|
segments:
|
268
272
|
- 0
|
269
|
-
hash:
|
273
|
+
hash: 59019763
|
270
274
|
requirements: []
|
271
275
|
rubyforge_project:
|
272
276
|
rubygems_version: 1.8.28
|
@@ -279,6 +283,7 @@ test_files:
|
|
279
283
|
- spec/app/WindowsForms.exe
|
280
284
|
- spec/core_ext/symbol_spec.rb
|
281
285
|
- spec/spec_helper.rb
|
286
|
+
- spec/uia/control_types/menu_item_spec.rb
|
282
287
|
- spec/uia/element_spec.rb
|
283
288
|
- spec/uia/keys_spec.rb
|
284
289
|
- spec/uia/patterns/expand_collapse_spec.rb
|