uia 0.0.6.1 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +14 -0
- data/README.md +127 -46
- data/ext/UiaDll/Release/UIA.Helper.dll +0 -0
- data/ext/UiaDll/Release/UiaDll.dll +0 -0
- data/ext/UiaDll/UiaDll/ElementMethods.cpp +15 -11
- data/ext/UiaDll/UiaDll/ElementStructures.h +15 -1
- data/ext/UiaDll/UiaDll/PatternInformationStructures.h +77 -1
- data/ext/UiaDll/UiaDll/SelectionItemMethods.cpp +1 -0
- data/ext/UiaDll/UiaDll/TableItemMethods.cpp +16 -0
- data/ext/UiaDll/UiaDll/TableMethods.cpp +16 -0
- data/ext/UiaDll/UiaDll/UiaDll.vcxproj +4 -0
- data/ext/UiaDll/UiaDll/UiaDll.vcxproj.filters +9 -0
- data/ext/UiaDll/UiaDll/WindowMethods.cpp +24 -0
- data/ext/UiaDll/UiaDll.Test/ElementInformationTest.cpp +15 -0
- data/ext/UiaDll/UiaDll.Test/PatternInformationTest.cpp +14 -1
- data/ext/UiaDll/UiaDll.Test/UiaDll.Test.vcxproj +2 -0
- data/lib/core_ext/string.rb +5 -0
- data/lib/core_ext/symbol.rb +5 -0
- data/lib/uia/element.rb +26 -17
- data/lib/uia/library/element_structs.rb +95 -0
- data/lib/uia/library/pattern_structs.rb +155 -0
- data/lib/uia/library.rb +36 -12
- data/lib/uia/patterns/expand_collapse.rb +1 -1
- data/lib/uia/patterns/table.rb +32 -0
- data/lib/uia/patterns/table_item.rb +18 -0
- data/lib/uia/patterns/toggle.rb +1 -1
- data/lib/uia/patterns/window.rb +38 -0
- data/lib/uia/version.rb +1 -1
- data/lib/uia.rb +6 -2
- data/spec/uia/element_spec.rb +20 -0
- data/spec/uia/patterns/table_item_spec.rb +21 -0
- data/spec/uia/patterns/table_spec.rb +34 -0
- data/spec/uia/patterns/window_spec.rb +31 -0
- data/uia.gemspec +1 -0
- metadata +36 -5
- data/lib/uia/library/structs.rb +0 -174
data/ChangeLog
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
=== Version 0.0.7 / 2013-11-01
|
2
|
+
* Enhancements
|
3
|
+
* added a base implementation for the Window pattern
|
4
|
+
* added support for WindowPattern, TablePattern and TableItemPattern
|
5
|
+
* Element#as raises UnsupportedPattern if the element does not implement it
|
6
|
+
* added an Element#select method to filter descendants by:
|
7
|
+
- pattern
|
8
|
+
- name
|
9
|
+
- id
|
10
|
+
|
11
|
+
* Bug Fixes
|
12
|
+
* modified ffi calls that return Element arrays to be individually GC'd.
|
13
|
+
This prevents FFI::ManagedStruct from being taken out from underneath you
|
14
|
+
|
1
15
|
=== Version 0.0.6.1 / 2013-10-30
|
2
16
|
* Bug Fixes
|
3
17
|
* Fixed issue when finding root children by RegEx initially
|
data/README.md
CHANGED
@@ -1,46 +1,127 @@
|
|
1
|
-
# Uia
|
2
|
-
|
3
|
-
The `Uia` gem is a low-level driver for interacting with Microsoft UIA elements in a Windows environment.
|
4
|
-
|
5
|
-
## Installation
|
6
|
-
|
7
|
-
Add this line to your application's Gemfile:
|
8
|
-
|
9
|
-
gem 'uia'
|
10
|
-
|
11
|
-
And then execute:
|
12
|
-
|
13
|
-
$ bundle
|
14
|
-
|
15
|
-
Or install it yourself as:
|
16
|
-
|
17
|
-
$ gem install uia
|
18
|
-
|
19
|
-
## Usage
|
20
|
-
|
21
|
-
Getting started with `uia` is easy. Simply require `uia` and then include the `Uia` module wherever you would like to use it.
|
22
|
-
|
23
|
-
```ruby
|
24
|
-
require 'uia'
|
25
|
-
|
26
|
-
include Uia
|
27
|
-
|
28
|
-
main_window = find_element id: 'MainFormWindow'
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
1
|
+
# Uia
|
2
|
+
|
3
|
+
The `Uia` gem is a low-level driver for interacting with Microsoft UIA elements in a Windows environment.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'uia'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install uia
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Getting started with `uia` is easy. Simply require `uia` and then include the `Uia` module wherever you would like to use it.
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
require 'uia'
|
25
|
+
|
26
|
+
include Uia
|
27
|
+
|
28
|
+
main_window = find_element id: 'MainFormWindow'
|
29
|
+
|
30
|
+
# returns all elements under main_window that are of control type button
|
31
|
+
main_window.select(control_type: :button)
|
32
|
+
|
33
|
+
# returns the values of every element that implements the ValuePattern
|
34
|
+
main_window.select(pattern: :value).map {|e| e.as :value}.map &:value
|
35
|
+
```
|
36
|
+
|
37
|
+
### Finding Elements
|
38
|
+
|
39
|
+
You can locate elements based on the following criteria:
|
40
|
+
|
41
|
+
* `:id` - find by their `AutomationId` (`String` and `Regexp`)
|
42
|
+
* `:pid` - find an element by their process id (`String` and `Regexp`)
|
43
|
+
* `:handle` - find an element by their native window handle (`Fixnum`)
|
44
|
+
* `:runtime_id` - find an element by their `RuntimeId` (i.e. `[42, 12345]`)
|
45
|
+
|
46
|
+
### `Element`
|
47
|
+
The `Element` class is a representation of the [`AutomationElement`](http://msdn.microsoft.com/en-us/library/system.windows.automation.automationelement.aspx) class in Microsoft UIA. It is the object that is returned from the root `Uia#find_element` as well as the `Element#find` and `Element#select` methods.
|
48
|
+
|
49
|
+
#### Properties
|
50
|
+
|
51
|
+
* `id` - returns the automation id of th element
|
52
|
+
* `name` - returns the name of the element
|
53
|
+
* `handle` - returns the native window handle of the element
|
54
|
+
* `class_name` - returns the class name of the element
|
55
|
+
* `patterns` - returns the patterns that element implements (i.e. `[:window, :transform]`)
|
56
|
+
|
57
|
+
#### Methods
|
58
|
+
|
59
|
+
##### #as
|
60
|
+
The `#as` method will decorate the `Element` with the specific pattern that you would like to interact with.
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
button = Uia.find_element(id: /MainForm/).find(id: 'aboutButton').as :invoke
|
64
|
+
button.invoke
|
65
|
+
```
|
66
|
+
|
67
|
+
### Patterns
|
68
|
+
#### Window
|
69
|
+
Decorates your `Element` with the following methods:
|
70
|
+
* `visual_state` - `:minimized, :maximized, :normal`
|
71
|
+
* `visual_state=` - sets the visual state
|
72
|
+
* `can_minimize?` / `can_maximize?`
|
73
|
+
* `modal?`
|
74
|
+
* `topmost?`
|
75
|
+
* `interaction_state` - `:blocked_by_modalwindow, :closing, :not_responding, :ready_for_user_interaction, :running`
|
76
|
+
|
77
|
+
#### Value
|
78
|
+
* `value` - returns the value
|
79
|
+
* `value=` - sets the value
|
80
|
+
* `read_only?`
|
81
|
+
|
82
|
+
#### Invoke
|
83
|
+
* `invoke` - invokes the control
|
84
|
+
|
85
|
+
#### ExpandCollapse
|
86
|
+
* `expand` - expands the element
|
87
|
+
* `collapse` - collapses the element
|
88
|
+
* `expand_collapse_state` - `:collapsed, :expanded, :leaf_node, :partially_expanded`
|
89
|
+
|
90
|
+
#### Toggle
|
91
|
+
* `toggle` - toggles the element
|
92
|
+
* `toggle_state` - `:on, :off, :indeterminate`
|
93
|
+
* `toggle_state=` - sets the toggle state
|
94
|
+
|
95
|
+
#### Table
|
96
|
+
* `row_count`
|
97
|
+
* `column_count`
|
98
|
+
* `headers` - returns the `Element` objects that make up the headers
|
99
|
+
* `rows` - returns all `Element` objects that are of control type `data_item`
|
100
|
+
* extends each `Element` with `Table::Row`
|
101
|
+
|
102
|
+
#### Table::Row
|
103
|
+
* `items` - returns all descendants of the row that implement the `:table_item` pattern
|
104
|
+
|
105
|
+
#### TableItem
|
106
|
+
* `column`
|
107
|
+
* `row`
|
108
|
+
|
109
|
+
#### Selection
|
110
|
+
* `selection_items` - return all descendants of the `Selection` that implement the `:selection_item` pattern
|
111
|
+
* `multi_select?`
|
112
|
+
* `selection_required?`
|
113
|
+
|
114
|
+
#### SelectionItem
|
115
|
+
* `select` - selects the item
|
116
|
+
* `add_to_selection` - adds the element to the selection
|
117
|
+
* `remove_from_selection` - removes the element from the selection
|
118
|
+
* `selected?` - whether or not it is selected
|
119
|
+
* `container` - the `Selection` container
|
120
|
+
|
121
|
+
## Contributing
|
122
|
+
|
123
|
+
1. Fork it
|
124
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
125
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
126
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
127
|
+
5. Create new Pull Request
|
Binary file
|
Binary file
|
@@ -97,33 +97,37 @@ extern "C" {
|
|
97
97
|
return NULL;
|
98
98
|
}
|
99
99
|
|
100
|
-
__declspec(dllexport)
|
100
|
+
__declspec(dllexport) int Root_Children(ElementInformation** children, char* errorInfo, const int errorInfoLength) {
|
101
101
|
try {
|
102
|
-
|
102
|
+
auto windows = Element::Windows;
|
103
|
+
*children = ElementInformation::From(windows);
|
104
|
+
return windows->Length;
|
103
105
|
} catch(Exception^ e) {
|
104
106
|
StringHelper::CopyToUnmanagedString(e->Message, errorInfo, errorInfoLength);
|
105
|
-
return
|
107
|
+
return 0;
|
106
108
|
}
|
107
109
|
}
|
108
110
|
|
109
|
-
__declspec(dllexport)
|
111
|
+
__declspec(dllexport) int Element_Children(ElementInformationPtr parentElement, ElementInformation** children, char* errorInfo, const int errorLength) {
|
110
112
|
try {
|
111
|
-
|
113
|
+
auto elements = Find(parentElement)->Children;
|
114
|
+
*children = ElementInformation::From(elements);
|
115
|
+
return elements->Length;
|
112
116
|
} catch(Exception^ error) {
|
113
117
|
StringHelper::CopyToUnmanagedString(error->Message, errorInfo, errorLength);
|
118
|
+
return 0;
|
114
119
|
}
|
115
|
-
|
116
|
-
return NULL;
|
117
120
|
}
|
118
121
|
|
119
|
-
__declspec(dllexport)
|
122
|
+
__declspec(dllexport) int Element_Descendants(ElementInformationPtr parentElement, ElementInformation** descendants, char* errorInfo, const int errorLength) {
|
120
123
|
try {
|
121
|
-
|
124
|
+
auto elements = Find(parentElement)->Descendants;
|
125
|
+
*descendants = ElementInformation::From(elements);
|
126
|
+
return elements->Length;
|
122
127
|
} catch(Exception^ error) {
|
123
128
|
StringHelper::CopyToUnmanagedString(error->Message, errorInfo, errorLength);
|
129
|
+
return 0;
|
124
130
|
}
|
125
|
-
|
126
|
-
return NULL;
|
127
131
|
}
|
128
132
|
|
129
133
|
__declspec(dllexport) void Element_Click(ElementInformationPtr element, char* errorInfo, const int errorLength) {
|
@@ -25,6 +25,18 @@ typedef struct _ElementInformation {
|
|
25
25
|
return nullptr != element ? new _ElementInformation(element) : NULL;
|
26
26
|
}
|
27
27
|
|
28
|
+
static _ElementInformation* From(...array<Element^>^ elements) {
|
29
|
+
if( nullptr == elements || elements->Length == 0 ) return NULL;
|
30
|
+
|
31
|
+
auto elementInformation = new _ElementInformation[elements->Length];
|
32
|
+
auto index = 0;
|
33
|
+
for each(auto element in elements) {
|
34
|
+
elementInformation[index++].Refresh(element);
|
35
|
+
}
|
36
|
+
|
37
|
+
return elementInformation;
|
38
|
+
}
|
39
|
+
|
28
40
|
void Refresh(Element^ element) {
|
29
41
|
Reset();
|
30
42
|
id = StringHelper::ToUnmanaged(element->Id);
|
@@ -58,7 +70,9 @@ typedef struct _Elements {
|
|
58
70
|
|
59
71
|
_Elements() : length(0), elements(NULL) {}
|
60
72
|
|
61
|
-
_Elements(array<Element^>^ elements) : elements(NULL) {
|
73
|
+
_Elements(array<Element^>^ elements) : length(0), elements(NULL) {
|
74
|
+
if( nullptr == elements ) return;
|
75
|
+
|
62
76
|
length = elements->Length;
|
63
77
|
if( length > 0 ) this->elements = new ElementInformation[length];
|
64
78
|
|
@@ -3,6 +3,8 @@
|
|
3
3
|
#include "StringHelper.h"
|
4
4
|
#include "ElementStructures.h"
|
5
5
|
|
6
|
+
using namespace System;
|
7
|
+
using namespace System::Linq;
|
6
8
|
using namespace System::Windows::Automation;
|
7
9
|
|
8
10
|
typedef struct _ValuePatternInformation {
|
@@ -87,4 +89,78 @@ typedef struct _ExpandCollapseInfo {
|
|
87
89
|
~_ExpandCollapseInfo() {
|
88
90
|
delete[] ExpandCollapseState;
|
89
91
|
}
|
90
|
-
} ExpandCollapseInfo, *ExpandCollapseInfoPtr;
|
92
|
+
} ExpandCollapseInfo, *ExpandCollapseInfoPtr;
|
93
|
+
|
94
|
+
typedef struct _WindowInformation {
|
95
|
+
char* VisualState;
|
96
|
+
char* InteractionState;
|
97
|
+
bool CanMinimize;
|
98
|
+
bool CanMaximize;
|
99
|
+
bool IsModal;
|
100
|
+
bool IsTopmost;
|
101
|
+
|
102
|
+
_WindowInformation(WindowVisualState visualState, WindowInteractionState interactionState) {
|
103
|
+
init(visualState, interactionState);
|
104
|
+
}
|
105
|
+
|
106
|
+
_WindowInformation(WindowPattern::WindowPatternInformation^ windowInformation) {
|
107
|
+
init(windowInformation->WindowVisualState, windowInformation->WindowInteractionState);
|
108
|
+
CanMinimize = windowInformation->CanMinimize;
|
109
|
+
CanMaximize = windowInformation->CanMaximize;
|
110
|
+
IsModal = windowInformation->IsModal;
|
111
|
+
IsTopmost = windowInformation->IsTopmost;
|
112
|
+
}
|
113
|
+
|
114
|
+
~_WindowInformation() {
|
115
|
+
delete[] VisualState;
|
116
|
+
delete[] InteractionState;
|
117
|
+
}
|
118
|
+
|
119
|
+
private:
|
120
|
+
void init(WindowVisualState visualState, WindowInteractionState interactionState) {
|
121
|
+
VisualState = StringHelper::ToUnmanaged(visualState.ToString());
|
122
|
+
InteractionState = StringHelper::ToUnmanaged(interactionState.ToString());
|
123
|
+
}
|
124
|
+
|
125
|
+
} WindowInformation, *WindowInformationPtr;
|
126
|
+
|
127
|
+
typedef struct _TableInformation {
|
128
|
+
int RowCount;
|
129
|
+
int ColumnCount;
|
130
|
+
ElementsPtr Headers;
|
131
|
+
|
132
|
+
_TableInformation(int rowCount, int columnCount, ...array<Element^> ^headers) {
|
133
|
+
init(rowCount, columnCount, headers);
|
134
|
+
}
|
135
|
+
|
136
|
+
_TableInformation(TablePattern::TablePatternInformation^ tableInfo) {
|
137
|
+
auto headers = tableInfo->GetColumnHeaders();
|
138
|
+
auto toElementFunc = gcnew Func<AutomationElement^, Element^>(Element::From);
|
139
|
+
|
140
|
+
init(tableInfo->RowCount, tableInfo->ColumnCount, Enumerable::ToArray(Enumerable::Select<AutomationElement^, Element^>(headers, toElementFunc)));
|
141
|
+
}
|
142
|
+
|
143
|
+
~_TableInformation() {
|
144
|
+
delete Headers;
|
145
|
+
}
|
146
|
+
|
147
|
+
private:
|
148
|
+
void init(int rowCount, int columnCount, ...array<Element^> ^headers) {
|
149
|
+
RowCount = rowCount;
|
150
|
+
ColumnCount = columnCount;
|
151
|
+
|
152
|
+
Headers = new Elements(headers);
|
153
|
+
}
|
154
|
+
|
155
|
+
} TableInformation, *TableInformationPtr;
|
156
|
+
|
157
|
+
typedef struct _TableItemInformation {
|
158
|
+
int Column;
|
159
|
+
int Row;
|
160
|
+
|
161
|
+
_TableItemInformation(TableItemPattern::TableItemPatternInformation^ tableItemInfo) {
|
162
|
+
Column = tableItemInfo->Column;
|
163
|
+
Row = tableItemInfo->Row;
|
164
|
+
}
|
165
|
+
|
166
|
+
} TableItemInformation, *TableItemInformationPtr;
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#include "Stdafx.h"
|
2
|
+
|
3
|
+
extern "C" {
|
4
|
+
__declspec(dllexport) void TableItem_Release(TableItemInformationPtr tableItemInfo) {
|
5
|
+
delete tableItemInfo;
|
6
|
+
}
|
7
|
+
|
8
|
+
__declspec(dllexport) TableItemInformationPtr TableItem_Information(ElementInformationPtr element, char* errorInfo, const int errorInfoLength) {
|
9
|
+
try {
|
10
|
+
return new TableItemInformation(Find(element)->As<TableItemPattern^>(TableItemPattern::Pattern)->Current);
|
11
|
+
} catch(Exception^ e) {
|
12
|
+
StringHelper::CopyToUnmanagedString(e->Message, errorInfo, errorInfoLength);
|
13
|
+
return NULL;
|
14
|
+
}
|
15
|
+
}
|
16
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#include "Stdafx.h"
|
2
|
+
|
3
|
+
extern "C" {
|
4
|
+
__declspec(dllexport) void Table_Release(TableInformationPtr tableInfo) {
|
5
|
+
delete tableInfo;
|
6
|
+
}
|
7
|
+
|
8
|
+
__declspec(dllexport) TableInformationPtr Table_Information(ElementInformationPtr element, char* errorInfo, const int errorInfoLength) {
|
9
|
+
try {
|
10
|
+
return new TableInformation(Find(element)->As<TablePattern^>(TablePattern::Pattern)->Current);
|
11
|
+
} catch(Exception^ e) {
|
12
|
+
StringHelper::CopyToUnmanagedString(e->Message, errorInfo, errorInfoLength);
|
13
|
+
return NULL;
|
14
|
+
}
|
15
|
+
}
|
16
|
+
}
|
@@ -72,6 +72,7 @@
|
|
72
72
|
</ItemDefinitionGroup>
|
73
73
|
<ItemGroup>
|
74
74
|
<Reference Include="System" />
|
75
|
+
<Reference Include="System.Core" />
|
75
76
|
<Reference Include="System.Data" />
|
76
77
|
<Reference Include="System.Xml" />
|
77
78
|
<Reference Include="UIAutomationClient" />
|
@@ -97,9 +98,12 @@
|
|
97
98
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
98
99
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
|
99
100
|
</ClCompile>
|
101
|
+
<ClCompile Include="TableItemMethods.cpp" />
|
102
|
+
<ClCompile Include="TableMethods.cpp" />
|
100
103
|
<ClCompile Include="ToggleMethods.cpp" />
|
101
104
|
<ClCompile Include="UiaDll.cpp" />
|
102
105
|
<ClCompile Include="ValuePatternMethods.cpp" />
|
106
|
+
<ClCompile Include="WindowMethods.cpp" />
|
103
107
|
</ItemGroup>
|
104
108
|
<ItemGroup>
|
105
109
|
<ProjectReference Include="..\UIA.Helper\UIA.Helper.csproj">
|
@@ -71,5 +71,14 @@
|
|
71
71
|
<ClCompile Include="ExpandCollapseMethods.cpp">
|
72
72
|
<Filter>Source Files\Patterns</Filter>
|
73
73
|
</ClCompile>
|
74
|
+
<ClCompile Include="WindowMethods.cpp">
|
75
|
+
<Filter>Source Files\Patterns</Filter>
|
76
|
+
</ClCompile>
|
77
|
+
<ClCompile Include="TableMethods.cpp">
|
78
|
+
<Filter>Source Files\Patterns</Filter>
|
79
|
+
</ClCompile>
|
80
|
+
<ClCompile Include="TableItemMethods.cpp">
|
81
|
+
<Filter>Source Files\Patterns</Filter>
|
82
|
+
</ClCompile>
|
74
83
|
</ItemGroup>
|
75
84
|
</Project>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#include "Stdafx.h"
|
2
|
+
|
3
|
+
extern "C" {
|
4
|
+
__declspec(dllexport) void Window_Release(WindowInformationPtr windowInformation) {
|
5
|
+
delete windowInformation;
|
6
|
+
}
|
7
|
+
|
8
|
+
__declspec(dllexport) WindowInformationPtr Window_Information(ElementInformationPtr element, char* errorInfo, const int errorInfoLength) {
|
9
|
+
try {
|
10
|
+
return new WindowInformation(Find(element)->As<WindowPattern^>(WindowPattern::Pattern)->Current);
|
11
|
+
} catch(Exception^ e) {
|
12
|
+
StringHelper::CopyToUnmanagedString(e->Message, errorInfo, errorInfoLength);
|
13
|
+
return NULL;
|
14
|
+
}
|
15
|
+
}
|
16
|
+
|
17
|
+
__declspec(dllexport) void Window_SetVisualState(ElementInformationPtr element, const char* visualState, char* errorInfo, const int errorInfoLength) {
|
18
|
+
try {
|
19
|
+
Find(element)->As<WindowPattern^>(WindowPattern::Pattern)->SetWindowVisualState((WindowVisualState) Enum::Parse(WindowVisualState::typeid, gcnew String(visualState), false));
|
20
|
+
} catch(Exception^ e) {
|
21
|
+
StringHelper::CopyToUnmanagedString(e->Message, errorInfo, errorInfoLength);
|
22
|
+
}
|
23
|
+
}
|
24
|
+
}
|
@@ -103,3 +103,18 @@ TEST_F(ElementInformationTest, ItCanBeRefreshed)
|
|
103
103
|
ASSERT_STREQ("Refreshed", elementInformation.name);
|
104
104
|
ASSERT_EQ(123, elementInformation.nativeWindowHandle);
|
105
105
|
}
|
106
|
+
|
107
|
+
TEST_F(ElementInformationTest, ItCanBeInitializedFromManyElements) {
|
108
|
+
auto elementInformation = ElementInformation::From(gcnew ElementStub("First Element", 123), gcnew ElementStub("Second Element", 456));
|
109
|
+
|
110
|
+
ASSERT_STREQ("First Element", elementInformation[0].name);
|
111
|
+
ASSERT_STREQ("Second Element", elementInformation[1].name);
|
112
|
+
delete[] elementInformation;
|
113
|
+
}
|
114
|
+
|
115
|
+
TEST_F(ElementInformationTest, ItIsNullIfThereAreNoElements) {
|
116
|
+
ASSERT_EQ(NULL, ElementInformation::From(gcnew array<Element^>(0)));
|
117
|
+
|
118
|
+
array<Element^>^ nullElements = nullptr;
|
119
|
+
ASSERT_EQ(NULL, ElementInformation::From(nullElements));
|
120
|
+
}
|
@@ -3,6 +3,8 @@
|
|
3
3
|
#include <PatternInformationStructures.h>
|
4
4
|
#include "ElementStub.h"
|
5
5
|
|
6
|
+
using namespace System::Windows::Automation;
|
7
|
+
|
6
8
|
TEST(ValueInformation, CanBeInitialized)
|
7
9
|
{
|
8
10
|
auto valueInfo = new ValuePatternInformation("Whatever", true);
|
@@ -32,4 +34,15 @@ TEST(SelectionItemInformation, CanBeInitialized)
|
|
32
34
|
TEST(ExpandCollapseInfo, CanBeInitialized) {
|
33
35
|
auto expandCollapseInfo = ExpandCollapseInfo("Collapsed");
|
34
36
|
ASSERT_STREQ("Collapsed", expandCollapseInfo.ExpandCollapseState);
|
35
|
-
}
|
37
|
+
}
|
38
|
+
|
39
|
+
TEST(WindowInformation, CanBeInitialized) {
|
40
|
+
auto windowInformation = WindowInformation(WindowVisualState::Minimized, WindowInteractionState::Closing);
|
41
|
+
ASSERT_STREQ("Minimized", windowInformation.VisualState);
|
42
|
+
ASSERT_STREQ("Closing", windowInformation.InteractionState);
|
43
|
+
}
|
44
|
+
|
45
|
+
TEST(TableInformation, NullHeadersYieldsEmptyElements) {
|
46
|
+
auto tableInformation = TableInformation(0, 0, nullptr);
|
47
|
+
ASSERT_EQ(0, tableInformation.Headers->length);
|
48
|
+
}
|
@@ -84,9 +84,11 @@
|
|
84
84
|
</ItemDefinitionGroup>
|
85
85
|
<ItemGroup>
|
86
86
|
<Reference Include="System" />
|
87
|
+
<Reference Include="System.Core" />
|
87
88
|
<Reference Include="System.Data" />
|
88
89
|
<Reference Include="System.Xml" />
|
89
90
|
<Reference Include="UIAutomationClient" />
|
91
|
+
<Reference Include="UIAutomationTypes" />
|
90
92
|
</ItemGroup>
|
91
93
|
<ItemGroup>
|
92
94
|
<Text Include="ReadMe.txt" />
|
data/lib/uia/element.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
|
-
require 'uia/patterns/expand_collapse'
|
2
|
-
require 'uia/patterns/invoke'
|
3
|
-
require 'uia/patterns/selection'
|
4
|
-
require 'uia/patterns/selection_item'
|
5
|
-
require 'uia/patterns/toggle'
|
6
|
-
require 'uia/patterns/value'
|
7
1
|
require 'uia/library/element_attributes'
|
8
2
|
|
9
3
|
module Uia
|
4
|
+
class UnsupportedPattern < StandardError
|
5
|
+
def initialize(expected, actual)
|
6
|
+
super "Pattern #{expected} not found in #{actual}"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
10
|
class Element
|
11
11
|
extend ElementAttributes
|
12
12
|
|
@@ -15,7 +15,7 @@ module Uia
|
|
15
15
|
@default = lambda { [:unknown] }
|
16
16
|
end
|
17
17
|
|
18
|
-
element_attr :id, :name, :handle, :runtime_id, :enabled?, :class_name
|
18
|
+
element_attr :id, :name, :handle, :runtime_id, :enabled?, :class_name, :children, :descendants
|
19
19
|
|
20
20
|
def control_type
|
21
21
|
Library::Constants::ControlTypes.find(@default) { |_, v| v == @element.control_type_id }.first
|
@@ -35,23 +35,32 @@ module Uia
|
|
35
35
|
end
|
36
36
|
end
|
37
37
|
|
38
|
-
def
|
39
|
-
|
40
|
-
|
38
|
+
def locators_match?(locator)
|
39
|
+
locator.all? do |locator, value|
|
40
|
+
case locator
|
41
|
+
when :pattern
|
42
|
+
patterns.include? value
|
43
|
+
else
|
44
|
+
send(locator) == value
|
45
|
+
end
|
41
46
|
end
|
42
|
-
extend which
|
43
47
|
end
|
44
48
|
|
45
|
-
def
|
46
|
-
|
49
|
+
def select(locator)
|
50
|
+
descendants.select { |e| e.locators_match? locator }
|
47
51
|
end
|
48
52
|
|
49
|
-
def
|
50
|
-
|
53
|
+
def as(pattern)
|
54
|
+
raise UnsupportedPattern.new(pattern, patterns) unless patterns.include? pattern
|
55
|
+
|
56
|
+
which = "Uia::Patterns::#{pattern.to_s.capitalize}".split('::').reduce(Object) do |m, current|
|
57
|
+
m.const_get current.split('_').map(&:capitalize).join
|
58
|
+
end
|
59
|
+
extend which
|
51
60
|
end
|
52
61
|
|
53
|
-
def
|
54
|
-
@element.
|
62
|
+
def patterns
|
63
|
+
@element.pattern_ids.map { |id| Library::Constants::Patterns.find(@default) { |_, v| v == id }.first }
|
55
64
|
end
|
56
65
|
|
57
66
|
def click
|