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.
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