uia 0.0.6.1 → 0.0.7

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.
Files changed (36) hide show
  1. data/ChangeLog +14 -0
  2. data/README.md +127 -46
  3. data/ext/UiaDll/Release/UIA.Helper.dll +0 -0
  4. data/ext/UiaDll/Release/UiaDll.dll +0 -0
  5. data/ext/UiaDll/UiaDll/ElementMethods.cpp +15 -11
  6. data/ext/UiaDll/UiaDll/ElementStructures.h +15 -1
  7. data/ext/UiaDll/UiaDll/PatternInformationStructures.h +77 -1
  8. data/ext/UiaDll/UiaDll/SelectionItemMethods.cpp +1 -0
  9. data/ext/UiaDll/UiaDll/TableItemMethods.cpp +16 -0
  10. data/ext/UiaDll/UiaDll/TableMethods.cpp +16 -0
  11. data/ext/UiaDll/UiaDll/UiaDll.vcxproj +4 -0
  12. data/ext/UiaDll/UiaDll/UiaDll.vcxproj.filters +9 -0
  13. data/ext/UiaDll/UiaDll/WindowMethods.cpp +24 -0
  14. data/ext/UiaDll/UiaDll.Test/ElementInformationTest.cpp +15 -0
  15. data/ext/UiaDll/UiaDll.Test/PatternInformationTest.cpp +14 -1
  16. data/ext/UiaDll/UiaDll.Test/UiaDll.Test.vcxproj +2 -0
  17. data/lib/core_ext/string.rb +5 -0
  18. data/lib/core_ext/symbol.rb +5 -0
  19. data/lib/uia/element.rb +26 -17
  20. data/lib/uia/library/element_structs.rb +95 -0
  21. data/lib/uia/library/pattern_structs.rb +155 -0
  22. data/lib/uia/library.rb +36 -12
  23. data/lib/uia/patterns/expand_collapse.rb +1 -1
  24. data/lib/uia/patterns/table.rb +32 -0
  25. data/lib/uia/patterns/table_item.rb +18 -0
  26. data/lib/uia/patterns/toggle.rb +1 -1
  27. data/lib/uia/patterns/window.rb +38 -0
  28. data/lib/uia/version.rb +1 -1
  29. data/lib/uia.rb +6 -2
  30. data/spec/uia/element_spec.rb +20 -0
  31. data/spec/uia/patterns/table_item_spec.rb +21 -0
  32. data/spec/uia/patterns/table_spec.rb +34 -0
  33. data/spec/uia/patterns/window_spec.rb +31 -0
  34. data/uia.gemspec +1 -0
  35. metadata +36 -5
  36. 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
- ### Finding Elements
32
-
33
- You can locate elements based on the following criteria:
34
-
35
- * `:id` - find by their `AutomationId`
36
- * `:pid` - find an element by their process id
37
- * `:handle` - find an element by their native window handle
38
- * `:runtime_id` - find an element by their `RuntimeId` (i.e. `[42, 12345]`)
39
-
40
- ## Contributing
41
-
42
- 1. Fork it
43
- 2. Create your feature branch (`git checkout -b my-new-feature`)
44
- 3. Commit your changes (`git commit -am 'Add some feature'`)
45
- 4. Push to the branch (`git push origin my-new-feature`)
46
- 5. Create new Pull Request
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) ElementsPtr Root_Children(char* errorInfo, const int errorInfoLength) {
100
+ __declspec(dllexport) int Root_Children(ElementInformation** children, char* errorInfo, const int errorInfoLength) {
101
101
  try {
102
- return new Elements(Element::Windows);
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 NULL;
107
+ return 0;
106
108
  }
107
109
  }
108
110
 
109
- __declspec(dllexport) ElementsPtr Element_Children(ElementInformationPtr parentElement, char* errorInfo, const int errorLength) {
111
+ __declspec(dllexport) int Element_Children(ElementInformationPtr parentElement, ElementInformation** children, char* errorInfo, const int errorLength) {
110
112
  try {
111
- return new Elements(Find(parentElement)->Children);
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) ElementsPtr Element_Descendants(ElementInformationPtr parentElement, char* errorInfo, const int errorLength) {
122
+ __declspec(dllexport) int Element_Descendants(ElementInformationPtr parentElement, ElementInformation** descendants, char* errorInfo, const int errorLength) {
120
123
  try {
121
- return new Elements(Find(parentElement)->Descendants);
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;
@@ -11,6 +11,7 @@ extern "C" {
11
11
  return new SelectionItemInformation(info);
12
12
  } catch(Exception^ e) {
13
13
  StringHelper::CopyToUnmanagedString(e->Message, errorInfo, errorInfoLength);
14
+ return NULL;
14
15
  }
15
16
  }
16
17
 
@@ -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" />
@@ -0,0 +1,5 @@
1
+ class String
2
+ def to_snake_case_sym
3
+ self.gsub(/(.)([A-Z])/, '\1_\2').downcase.to_sym
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class Symbol
2
+ def to_camelized_s
3
+ self.to_s.split('_').map(&:capitalize).join(' ')
4
+ end
5
+ end
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 as(pattern)
39
- which = "Uia::Patterns::#{pattern.to_s.capitalize}".split('::').reduce(Object) do |m, current|
40
- m.const_get current.split('_').map(&:capitalize).join
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 patterns
46
- @element.pattern_ids.map {|id| Library::Constants::Patterns.find(@default) { |_, v| v == id }.first }
49
+ def select(locator)
50
+ descendants.select { |e| e.locators_match? locator }
47
51
  end
48
52
 
49
- def children
50
- @element.children
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 descendants
54
- @element.descendants
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