uia 0.0.7.3 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +10 -0
- data/ext/UiaDll/Release/UIA.Helper.dll +0 -0
- data/ext/UiaDll/Release/UiaDll.dll +0 -0
- data/ext/UiaDll/UIA.Helper/Clicker.cs +1 -1
- data/ext/UiaDll/UIA.Helper/Element.cs +11 -0
- data/ext/UiaDll/UIA.Helper/Extensions.cs +8 -0
- data/ext/UiaDll/UiaDll/ElementMethods.cpp +8 -4
- data/ext/UiaDll/UiaDll/ElementStructures.h +0 -23
- data/ext/UiaDll/UiaDll/PatternInformationStructures.h +2 -22
- data/ext/UiaDll/UiaDll/TableMethods.cpp +11 -0
- data/ext/UiaDll/UiaDll/TextMethods.cpp +17 -0
- data/ext/UiaDll/UiaDll/UiaDll.cpp +6 -0
- data/ext/UiaDll/UiaDll/UiaDll.vcxproj +1 -0
- data/ext/UiaDll/UiaDll/UiaDll.vcxproj.filters +3 -0
- data/ext/UiaDll/UiaDll/WindowMethods.cpp +8 -0
- data/ext/UiaDll/UiaDll.Test/PatternInformationTest.cpp +0 -5
- data/ext/UiaDll/UiaDll.Test/UiaDll.Test.vcxproj +0 -1
- data/ext/UiaDll/UiaDll.Test/UiaDll.Test.vcxproj.filters +0 -3
- data/lib/core_ext/symbol.rb +7 -0
- data/lib/uia/element.rb +9 -14
- data/lib/uia/finder.rb +67 -1
- data/lib/uia/keys.rb +76 -0
- data/lib/uia/library/element_structs.rb +0 -12
- data/lib/uia/library/pattern_structs.rb +1 -6
- data/lib/uia/library/win32.rb +35 -0
- data/lib/uia/library.rb +16 -0
- data/lib/uia/patterns/selection.rb +1 -1
- data/lib/uia/patterns/table.rb +3 -3
- data/lib/uia/patterns/text.rb +13 -0
- data/lib/uia/patterns/window.rb +4 -0
- data/lib/uia/version.rb +3 -3
- data/lib/uia.rb +1 -15
- data/spec/spec_helper.rb +10 -0
- data/spec/uia/element_spec.rb +22 -11
- data/spec/uia/keys_spec.rb +30 -0
- data/spec/uia/patterns/text_spec.rb +20 -0
- data/spec/uia/patterns/window_spec.rb +14 -0
- data/spec/uia_spec.rb +9 -2
- data/uia.gemspec +1 -1
- metadata +16 -9
- data/ext/UiaDll/UiaDll.Test/ElementsTest.cpp +0 -22
data/ChangeLog
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
=== Version 0.0.8 / 2013-12-02
|
2
|
+
* Enhancements
|
3
|
+
* Uia#find_element and Element#find can locate by :title
|
4
|
+
* Element#send_keys
|
5
|
+
* Window#close
|
6
|
+
* TextPattern support to get / set the text
|
7
|
+
|
8
|
+
* Bug Fixes
|
9
|
+
* Fix issue with selecting cells in a table
|
10
|
+
|
1
11
|
=== Version 0.0.7.3 / 2013-11-02
|
2
12
|
* Enhancements
|
3
13
|
* Element#visible?
|
Binary file
|
Binary file
|
@@ -23,7 +23,7 @@ namespace UIA.Helper
|
|
23
23
|
public static void MouseClick(AutomationElement element)
|
24
24
|
{
|
25
25
|
element.ScrollToIfPossible();
|
26
|
-
element.
|
26
|
+
element.TryToFocus();
|
27
27
|
|
28
28
|
var clickablePoint = element.GetClickablePoint();
|
29
29
|
Cursor.Position = new System.Drawing.Point((int)clickablePoint.X, (int)clickablePoint.Y);
|
@@ -22,6 +22,12 @@ namespace UIA.Helper
|
|
22
22
|
return (TPattern) _element.GetCurrentPattern(pattern);
|
23
23
|
}
|
24
24
|
|
25
|
+
public void SendKeys(string keysToSend)
|
26
|
+
{
|
27
|
+
_element.TryToFocus();
|
28
|
+
System.Windows.Forms.SendKeys.SendWait(keysToSend);
|
29
|
+
}
|
30
|
+
|
25
31
|
public virtual int[] RuntimeId
|
26
32
|
{
|
27
33
|
get { return _element.GetRuntimeId(); }
|
@@ -97,6 +103,11 @@ namespace UIA.Helper
|
|
97
103
|
return new Element(element);
|
98
104
|
}
|
99
105
|
|
106
|
+
public static Element[] From(AutomationElement[] elements)
|
107
|
+
{
|
108
|
+
return elements.Select(x => new Element(x)).ToArray();
|
109
|
+
}
|
110
|
+
|
100
111
|
public static Element ById(string automationId)
|
101
112
|
{
|
102
113
|
return FindFirst(automationId.IdCondition());
|
@@ -30,6 +30,14 @@ namespace UIA.Helper
|
|
30
30
|
|
31
31
|
public static class ElementExtensions
|
32
32
|
{
|
33
|
+
public static bool TryToFocus(this AutomationElement automationElement)
|
34
|
+
{
|
35
|
+
try
|
36
|
+
{
|
37
|
+
automationElement.SetFocus();
|
38
|
+
return true;
|
39
|
+
} catch { return false; }
|
40
|
+
}
|
33
41
|
|
34
42
|
public static bool ScrollToIfPossible(this AutomationElement automationElement)
|
35
43
|
{
|
@@ -15,10 +15,6 @@ extern "C" {
|
|
15
15
|
delete elementInformation;
|
16
16
|
}
|
17
17
|
|
18
|
-
__declspec(dllexport) void Element_ReleaseMany(ElementsPtr elements) {
|
19
|
-
delete elements;
|
20
|
-
}
|
21
|
-
|
22
18
|
__declspec(dllexport) void Element_Refresh(ElementInformationPtr element, char* errorInfo, const int errorInfoLength) {
|
23
19
|
try {
|
24
20
|
element->Refresh(Find(element));
|
@@ -27,6 +23,14 @@ extern "C" {
|
|
27
23
|
}
|
28
24
|
}
|
29
25
|
|
26
|
+
__declspec(dllexport) void Element_SendKeys(ElementInformationPtr element, const char* keysToSend, char* errorInfo, const int errorInfoLength) {
|
27
|
+
try {
|
28
|
+
Find(element)->SendKeys(gcnew String(keysToSend));
|
29
|
+
} catch(Exception^ e) {
|
30
|
+
StringHelper::CopyToUnmanagedString(e->Message, errorInfo, errorInfoLength);
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
30
34
|
__declspec(dllexport) ElementInformationPtr Element_FindById(const char* automationId, char* errorInfo, const int errorLength) {
|
31
35
|
try {
|
32
36
|
return ElementInformation::From(Element::ById(gcnew String(automationId)));
|
@@ -65,26 +65,3 @@ private:
|
|
65
65
|
}
|
66
66
|
|
67
67
|
} ElementInformation, *ElementInformationPtr;
|
68
|
-
|
69
|
-
typedef struct _Elements {
|
70
|
-
int length;
|
71
|
-
ElementInformation* elements;
|
72
|
-
|
73
|
-
_Elements() : length(0), elements(NULL) {}
|
74
|
-
|
75
|
-
_Elements(array<Element^>^ elements) : length(0), elements(NULL) {
|
76
|
-
if( nullptr == elements ) return;
|
77
|
-
|
78
|
-
length = elements->Length;
|
79
|
-
if( length > 0 ) this->elements = new ElementInformation[length];
|
80
|
-
|
81
|
-
auto index = 0;
|
82
|
-
for each(auto element in elements) {
|
83
|
-
this->elements[index++].Refresh(element);
|
84
|
-
}
|
85
|
-
}
|
86
|
-
|
87
|
-
~_Elements() {
|
88
|
-
delete[] elements;
|
89
|
-
}
|
90
|
-
} Elements, *ElementsPtr;
|
@@ -127,31 +127,11 @@ private:
|
|
127
127
|
typedef struct _TableInformation {
|
128
128
|
int RowCount;
|
129
129
|
int ColumnCount;
|
130
|
-
ElementsPtr Headers;
|
131
|
-
|
132
|
-
_TableInformation(int rowCount, int columnCount, ...array<Element^> ^headers) {
|
133
|
-
init(rowCount, columnCount, headers);
|
134
|
-
}
|
135
130
|
|
136
131
|
_TableInformation(TablePattern::TablePatternInformation^ tableInfo) {
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
init(tableInfo->RowCount, tableInfo->ColumnCount, Enumerable::ToArray(Enumerable::Select<AutomationElement^, Element^>(headers, toElementFunc)));
|
141
|
-
}
|
142
|
-
|
143
|
-
~_TableInformation() {
|
144
|
-
delete Headers;
|
132
|
+
RowCount = tableInfo->RowCount;
|
133
|
+
ColumnCount = tableInfo->ColumnCount;
|
145
134
|
}
|
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
135
|
} TableInformation, *TableInformationPtr;
|
156
136
|
|
157
137
|
typedef struct _TableItemInformation {
|
@@ -13,4 +13,15 @@ extern "C" {
|
|
13
13
|
return NULL;
|
14
14
|
}
|
15
15
|
}
|
16
|
+
|
17
|
+
__declspec(dllexport) int Table_Headers(ElementInformationPtr element, ElementInformation** headers, char* errorInfo, const int errorInfoLength) {
|
18
|
+
try {
|
19
|
+
auto headerElements = Find(element)->As<TablePattern^>(TablePattern::Pattern)->Current.GetColumnHeaders();
|
20
|
+
*headers = ElementInformation::From(Element::From(headerElements));
|
21
|
+
return headerElements->Length;
|
22
|
+
} catch(Exception^ e) {
|
23
|
+
StringHelper::CopyToUnmanagedString(e->Message, errorInfo, errorInfoLength);
|
24
|
+
return 0;
|
25
|
+
}
|
26
|
+
}
|
16
27
|
}
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#include "Stdafx.h"
|
2
|
+
|
3
|
+
extern "C" {
|
4
|
+
__declspec(dllexport) int Text_GetText(ElementInformationPtr element, char* text, const int textLength, char* errorInfo, const int errorInfoLength) {
|
5
|
+
try {
|
6
|
+
auto theText = Find(element)->As<TextPattern^>(TextPattern::Pattern)->DocumentRange->GetText(-1);
|
7
|
+
if( NULL != text ) {
|
8
|
+
StringHelper::CopyToUnmanagedString(theText, text, textLength);
|
9
|
+
}
|
10
|
+
|
11
|
+
return theText->Length;
|
12
|
+
} catch(Exception^ e) {
|
13
|
+
StringHelper::CopyToUnmanagedString(e->Message, errorInfo, errorInfoLength);
|
14
|
+
return 0;
|
15
|
+
}
|
16
|
+
}
|
17
|
+
}
|
@@ -5,5 +5,11 @@ extern "C" {
|
|
5
5
|
__declspec(dllexport) void initialize(char* privateAssemblyDirectory) {
|
6
6
|
DynamicAssemblyResolver::PrivatePath = gcnew String(privateAssemblyDirectory);
|
7
7
|
}
|
8
|
+
|
9
|
+
__declspec(dllexport) void Automation_WarmUp() {
|
10
|
+
try {
|
11
|
+
auto warmed = Element::Windows;
|
12
|
+
} catch(Exception^) {}
|
13
|
+
}
|
8
14
|
}
|
9
15
|
|
@@ -101,6 +101,7 @@
|
|
101
101
|
</ClCompile>
|
102
102
|
<ClCompile Include="TableItemMethods.cpp" />
|
103
103
|
<ClCompile Include="TableMethods.cpp" />
|
104
|
+
<ClCompile Include="TextMethods.cpp" />
|
104
105
|
<ClCompile Include="ToggleMethods.cpp" />
|
105
106
|
<ClCompile Include="UiaDll.cpp" />
|
106
107
|
<ClCompile Include="ValuePatternMethods.cpp" />
|
@@ -21,4 +21,12 @@ extern "C" {
|
|
21
21
|
StringHelper::CopyToUnmanagedString(e->Message, errorInfo, errorInfoLength);
|
22
22
|
}
|
23
23
|
}
|
24
|
+
|
25
|
+
__declspec(dllexport) void Window_Close(ElementInformationPtr element, char* errorInfo, const int errorInfoLength) {
|
26
|
+
try {
|
27
|
+
Find(element)->As<WindowPattern^>(WindowPattern::Pattern)->Close();
|
28
|
+
} catch(Exception^ e) {
|
29
|
+
StringHelper::CopyToUnmanagedString(e->Message, errorInfo, errorInfoLength);
|
30
|
+
}
|
31
|
+
}
|
24
32
|
}
|
@@ -41,8 +41,3 @@ TEST(WindowInformation, CanBeInitialized) {
|
|
41
41
|
ASSERT_STREQ("Minimized", windowInformation.VisualState);
|
42
42
|
ASSERT_STREQ("Closing", windowInformation.InteractionState);
|
43
43
|
}
|
44
|
-
|
45
|
-
TEST(TableInformation, NullHeadersYieldsEmptyElements) {
|
46
|
-
auto tableInformation = TableInformation(0, 0, nullptr);
|
47
|
-
ASSERT_EQ(0, tableInformation.Headers->length);
|
48
|
-
}
|
@@ -105,7 +105,6 @@
|
|
105
105
|
<ItemGroup>
|
106
106
|
<ClCompile Include="AssemblyInfo.cpp" />
|
107
107
|
<ClCompile Include="ElementInformationTest.cpp" />
|
108
|
-
<ClCompile Include="ElementsTest.cpp" />
|
109
108
|
<ClCompile Include="PatternInformationTest.cpp" />
|
110
109
|
<ClCompile Include="stdafx.cpp">
|
111
110
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
|
@@ -52,9 +52,6 @@
|
|
52
52
|
<ClCompile Include="ElementInformationTest.cpp">
|
53
53
|
<Filter>Source Files</Filter>
|
54
54
|
</ClCompile>
|
55
|
-
<ClCompile Include="ElementsTest.cpp">
|
56
|
-
<Filter>Source Files</Filter>
|
57
|
-
</ClCompile>
|
58
55
|
<ClCompile Include="StringHelperTest.cpp">
|
59
56
|
<Filter>Source Files</Filter>
|
60
57
|
</ClCompile>
|
data/lib/core_ext/symbol.rb
CHANGED
@@ -2,4 +2,11 @@ class Symbol
|
|
2
2
|
def to_camelized_s
|
3
3
|
self.to_s.split('_').map(&:capitalize).join(' ')
|
4
4
|
end
|
5
|
+
|
6
|
+
# :selection_item => Uia::Patterns::SelectionItem
|
7
|
+
def to_pattern_const
|
8
|
+
"Uia::Patterns::#{self.to_s.capitalize}".split('::').reduce(Object) do |m, current|
|
9
|
+
m.const_get current.split('_').map(&:capitalize).join
|
10
|
+
end
|
11
|
+
end
|
5
12
|
end
|
data/lib/uia/element.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'uia/library/element_attributes'
|
2
2
|
require 'uia/library/pattern_info_attributes'
|
3
|
+
require 'uia/keys'
|
3
4
|
|
4
5
|
module Uia
|
5
6
|
class UnsupportedPattern < StandardError
|
@@ -9,6 +10,7 @@ module Uia
|
|
9
10
|
end
|
10
11
|
|
11
12
|
class Element
|
13
|
+
include Finder
|
12
14
|
extend ElementAttributes
|
13
15
|
|
14
16
|
def initialize(element)
|
@@ -24,20 +26,17 @@ module Uia
|
|
24
26
|
Library::Constants::ControlTypes.find(@default) { |_, v| v == @element.control_type_id }.first
|
25
27
|
end
|
26
28
|
|
29
|
+
def send_keys(*keys)
|
30
|
+
Library.send_keys @element, Keys.encode(keys)
|
31
|
+
end
|
32
|
+
|
27
33
|
def refresh
|
28
34
|
Library.refresh @element
|
29
35
|
self
|
30
36
|
end
|
31
37
|
|
32
38
|
def find(locator)
|
33
|
-
|
34
|
-
|
35
|
-
case
|
36
|
-
when locator[:id]
|
37
|
-
Library::find_child_by_id(@element, locator[:id], scope)
|
38
|
-
when locator[:name]
|
39
|
-
Library::find_child_by_name(@element, locator[:name], scope)
|
40
|
-
end
|
39
|
+
find_child(@element, locator)
|
41
40
|
end
|
42
41
|
|
43
42
|
def locators_match?(locator)
|
@@ -51,17 +50,13 @@ module Uia
|
|
51
50
|
end
|
52
51
|
end
|
53
52
|
|
54
|
-
def
|
53
|
+
def filter(locator)
|
55
54
|
descendants.select { |e| e.locators_match? locator }
|
56
55
|
end
|
57
56
|
|
58
57
|
def as(pattern)
|
59
58
|
raise UnsupportedPattern.new(pattern, patterns) unless patterns.include? pattern
|
60
|
-
|
61
|
-
which = "Uia::Patterns::#{pattern.to_s.capitalize}".split('::').reduce(Object) do |m, current|
|
62
|
-
m.const_get current.split('_').map(&:capitalize).join
|
63
|
-
end
|
64
|
-
extend which
|
59
|
+
extend pattern.to_pattern_const
|
65
60
|
end
|
66
61
|
|
67
62
|
def patterns
|
data/lib/uia/finder.rb
CHANGED
@@ -1,13 +1,66 @@
|
|
1
|
+
require 'uia/library/win32'
|
2
|
+
|
1
3
|
module Uia
|
4
|
+
class BadLocator < StandardError
|
5
|
+
def initialize(locator)
|
6
|
+
super "#{locator} is not a valid locator"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
class BadChildLocator < BadLocator; end
|
10
|
+
|
2
11
|
module Finder
|
12
|
+
def find_from_root(locator)
|
13
|
+
case
|
14
|
+
when locator[:id]
|
15
|
+
find_by_id locator[:id]
|
16
|
+
when locator[:name], locator[:value]
|
17
|
+
find_by_name locator[:name] || locator[:value]
|
18
|
+
when locator[:pid]
|
19
|
+
find_by_pid locator[:pid]
|
20
|
+
when locator[:runtime_id]
|
21
|
+
find_by_runtime_id locator[:runtime_id]
|
22
|
+
when locator[:handle]
|
23
|
+
find_by_handle locator[:handle]
|
24
|
+
when locator[:title]
|
25
|
+
find_by_title locator[:title]
|
26
|
+
else
|
27
|
+
raise BadLocator, locator
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def find_child(parent, locator)
|
32
|
+
scope = (locator[:scope] || :descendants).to_s.capitalize
|
33
|
+
|
34
|
+
case
|
35
|
+
when locator[:id]
|
36
|
+
find_child_by_id parent, locator[:id], scope
|
37
|
+
when locator[:name], locator[:value]
|
38
|
+
name_or_value = locator[:name] || locator[:value]
|
39
|
+
find_child_by_name parent, name_or_value, scope
|
40
|
+
when locator[:title]
|
41
|
+
find_by_title locator[:title], parent.handle
|
42
|
+
else
|
43
|
+
raise BadChildLocator, locator
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
3
48
|
def find_by_id(id)
|
4
49
|
find_by_property(:id, id)
|
5
50
|
end
|
6
51
|
|
52
|
+
def find_child_by_id(parent, id, scope)
|
53
|
+
Library.find_child_by_id(parent, id, (scope || :descendants).to_s.capitalize)
|
54
|
+
end
|
55
|
+
|
7
56
|
def find_by_name(name)
|
8
57
|
find_by_property(:name, name)
|
9
58
|
end
|
10
59
|
|
60
|
+
def find_child_by_name(parent, name, scope)
|
61
|
+
Library.find_child_by_name(parent, name, (scope || :descendants).to_s.capitalize)
|
62
|
+
end
|
63
|
+
|
11
64
|
def find_by_pid(pid)
|
12
65
|
Library.find_by_pid(pid)
|
13
66
|
end
|
@@ -20,7 +73,20 @@ module Uia
|
|
20
73
|
Library.find_by_handle handle
|
21
74
|
end
|
22
75
|
|
23
|
-
|
76
|
+
def find_by_title(title, parent=0)
|
77
|
+
found_window = Win32.find_window(parent) do |handle|
|
78
|
+
case title
|
79
|
+
when Regexp
|
80
|
+
Win32.window_title(handle) =~ title
|
81
|
+
else
|
82
|
+
Win32.window_title(handle) == title
|
83
|
+
end
|
84
|
+
end
|
85
|
+
find_by_handle found_window if found_window
|
86
|
+
rescue
|
87
|
+
nil
|
88
|
+
end
|
89
|
+
|
24
90
|
def find_by_property(property, what)
|
25
91
|
case what
|
26
92
|
when String
|
data/lib/uia/keys.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
module Uia
|
2
|
+
class InvalidKey < StandardError; end
|
3
|
+
class Keys
|
4
|
+
# http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys(v=vs.110).aspx
|
5
|
+
KEYS = {
|
6
|
+
:shift => '+',
|
7
|
+
:control => '^',
|
8
|
+
:alt => '%',
|
9
|
+
:space => ' ',
|
10
|
+
:backspace => '{BS}',
|
11
|
+
:break => '{BREAK}',
|
12
|
+
:caps_lock => '{CAPSLOCK}',
|
13
|
+
:delete => '{DEL}',
|
14
|
+
:down => '{DOWN}',
|
15
|
+
:end => '{END}',
|
16
|
+
:enter => '{ENTER}',
|
17
|
+
:escape => '{ESC}',
|
18
|
+
:help => '{HELP}',
|
19
|
+
:home => '{HOME}',
|
20
|
+
:insert => '{INS}',
|
21
|
+
:left => '{LEFT}',
|
22
|
+
:number_lock => '{NUMLOCK}',
|
23
|
+
:page_down => '{PGDN}',
|
24
|
+
:page_up => '{PGUP}',
|
25
|
+
:print_screen => '{PRTSC}',
|
26
|
+
:right => '{RIGHT}',
|
27
|
+
:scroll_lock => '{SCROLLLOCK}',
|
28
|
+
:tab => '{TAB}',
|
29
|
+
:up => '{UP}',
|
30
|
+
:f1 => '{F1}',
|
31
|
+
:f2 => '{F2}',
|
32
|
+
:f3 => '{F3}',
|
33
|
+
:f4 => '{F4}',
|
34
|
+
:f5 => '{F5}',
|
35
|
+
:f6 => '{F6}',
|
36
|
+
:f7 => '{F7}',
|
37
|
+
:f8 => '{F8}',
|
38
|
+
:f9 => '{F9}',
|
39
|
+
:f10 => '{F10}',
|
40
|
+
:f11 => '{F11}',
|
41
|
+
:f12 => '{F12}',
|
42
|
+
:f13 => '{F13}',
|
43
|
+
:f14 => '{F14}',
|
44
|
+
:f15 => '{F15}',
|
45
|
+
:f16 => '{F16}',
|
46
|
+
:add => '{ADD}',
|
47
|
+
:subtract => '{SUBTRACT}',
|
48
|
+
:multiply => '{MULTIPLY}',
|
49
|
+
:divide => '{DIVIDE}'}
|
50
|
+
|
51
|
+
SPECIAL_KEYS = ['\+', '\^', '%', '~', '\(', '\)', '\{', '\}', '\[', '\]']
|
52
|
+
|
53
|
+
def self.encode(keys)
|
54
|
+
keys.reduce('') do |encoded, key|
|
55
|
+
encoded << case key
|
56
|
+
when String
|
57
|
+
encode_str(key)
|
58
|
+
when Symbol
|
59
|
+
encode_sym(key)
|
60
|
+
when Array
|
61
|
+
"#{encode([key.shift])}(#{encode(key)})"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.encode_str(s)
|
67
|
+
s.gsub(/([#{SPECIAL_KEYS.join ''}])/, '{\1}')
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.encode_sym(sym)
|
71
|
+
found = KEYS[sym]
|
72
|
+
raise InvalidKey, "#{sym} is not a valid key" unless found
|
73
|
+
found
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -63,17 +63,5 @@ module Uia
|
|
63
63
|
class ElementStruct < FFI::Struct
|
64
64
|
include ElementLayout
|
65
65
|
end
|
66
|
-
|
67
|
-
class Elements < FFI::Struct
|
68
|
-
layout :length, :int,
|
69
|
-
:items, :pointer
|
70
|
-
|
71
|
-
def children
|
72
|
-
self[:length].times.collect do |i|
|
73
|
-
pointer = self[:items] + i * ElementStruct.size
|
74
|
-
Uia::Element.new(ElementStruct.new(pointer))
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
66
|
end
|
79
67
|
end
|
@@ -95,15 +95,10 @@ module Uia
|
|
95
95
|
extend StructAttributes
|
96
96
|
|
97
97
|
layout :row_count, :int,
|
98
|
-
:column_count, :int
|
99
|
-
:headers, Elements.ptr
|
98
|
+
:column_count, :int
|
100
99
|
|
101
100
|
struct_attr :row_count, :column_count
|
102
101
|
|
103
|
-
def headers
|
104
|
-
self[:headers].children
|
105
|
-
end
|
106
|
-
|
107
102
|
def self.release(pointer)
|
108
103
|
Library.release_table_info(pointer)
|
109
104
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
|
3
|
+
module Win32
|
4
|
+
extend FFI::Library
|
5
|
+
|
6
|
+
ffi_lib 'user32'
|
7
|
+
|
8
|
+
callback :enum_callback, [:long, :long], :bool
|
9
|
+
|
10
|
+
attach_function :enum_child_windows, :EnumChildWindows,
|
11
|
+
[:long, :enum_callback, :long], :long
|
12
|
+
attach_function :_window_title, :GetWindowTextA,
|
13
|
+
[:long, :pointer, :int], :int
|
14
|
+
attach_function :window_title_length, :GetWindowTextLengthA,
|
15
|
+
[:long], :int
|
16
|
+
|
17
|
+
class << self
|
18
|
+
def window_title(handle)
|
19
|
+
length = window_title_length(handle) + 1
|
20
|
+
title = FFI::MemoryPointer.new :char, length
|
21
|
+
_window_title handle, title, length
|
22
|
+
title.read_string
|
23
|
+
end
|
24
|
+
|
25
|
+
def find_window(parent, &block)
|
26
|
+
found_window = nil
|
27
|
+
window_callback = FFI::Function.new(:bool, [:long, :pointer], {convention: :stdcall}) do |handle, _|
|
28
|
+
found_window = handle if block.call handle
|
29
|
+
!found_window
|
30
|
+
end
|
31
|
+
Win32.enum_child_windows parent, window_callback, 0
|
32
|
+
found_window
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/uia/library.rb
CHANGED
@@ -16,6 +16,9 @@ module Uia
|
|
16
16
|
attach_function :init, :initialize, [:string], :void
|
17
17
|
init(uia_directory)
|
18
18
|
|
19
|
+
attach_function :warm_up_automation, :Automation_WarmUp, [], :void
|
20
|
+
warm_up_automation
|
21
|
+
|
19
22
|
def self.attach_throwable_function(name_alias, name, arg_types, return_type, &block)
|
20
23
|
attach_function name, arg_types + [:pointer, :int], return_type
|
21
24
|
define_singleton_method(name_alias) do |*args|
|
@@ -62,6 +65,7 @@ module Uia
|
|
62
65
|
attach_function :Element_FindByRuntimeId, [:pointer, :int, :pointer, :int], ManagedElementStruct.by_ref
|
63
66
|
|
64
67
|
# element methods
|
68
|
+
attach_throwable_function :send_keys, :Element_SendKeys, [:pointer, :string], :void
|
65
69
|
attach_throwable_function :find_child_by_id, :Element_FindChildById, [:pointer, :string, :string], ManagedElementStruct.by_ref, &element_or_nil
|
66
70
|
attach_throwable_function :find_child_by_name, :Element_FindChildByName, [:pointer, :string, :string], ManagedElementStruct.by_ref, &element_or_nil
|
67
71
|
elements_from :children, :Element_Children, [:pointer]
|
@@ -72,6 +76,7 @@ module Uia
|
|
72
76
|
# WindowPattern methods
|
73
77
|
attach_throwable_function :window_information, :Window_Information, [:pointer], WindowInformation.by_ref
|
74
78
|
attach_throwable_function :set_visual_state, :Window_SetVisualState, [:pointer, :string], :void
|
79
|
+
attach_throwable_function :close_window, :Window_Close, [:pointer], :void
|
75
80
|
|
76
81
|
# ValuePattern methods
|
77
82
|
attach_throwable_function :set_value, :Value_Set, [:pointer, :string], :void
|
@@ -100,6 +105,7 @@ module Uia
|
|
100
105
|
|
101
106
|
# TablePattern methods
|
102
107
|
attach_throwable_function :table_info, :Table_Information, [:pointer], TableInformation.by_ref
|
108
|
+
elements_from :table_headers, :Table_Headers, [:pointer]
|
103
109
|
|
104
110
|
# TableItemPattern methods
|
105
111
|
attach_throwable_function :table_item_info, :TableItem_Information, [:pointer], TableItemInformation.by_ref
|
@@ -108,6 +114,16 @@ module Uia
|
|
108
114
|
attach_throwable_function :range_value_info, :RangeValue_Information, [:pointer], RangeValueInformation.by_ref
|
109
115
|
attach_throwable_function :set_range_value, :RangeValue_SetValue, [:pointer, :double], :void
|
110
116
|
|
117
|
+
# TextPattern methods
|
118
|
+
attach_function :Text_GetText, [:pointer, :pointer, :int, :pointer, :int], :int
|
119
|
+
|
120
|
+
def self.get_text(element)
|
121
|
+
length = can_throw(:Text_GetText, element, nil, 0) + 1
|
122
|
+
p = FFI::MemoryPointer.new :pointer, length
|
123
|
+
can_throw(:Text_GetText, element, p, length)
|
124
|
+
p.read_string
|
125
|
+
end
|
126
|
+
|
111
127
|
def self.find_by_runtime_id(id)
|
112
128
|
p = FFI::MemoryPointer.new :int, id.count
|
113
129
|
p.write_array_of_int(id)
|
data/lib/uia/patterns/table.rb
CHANGED
@@ -3,7 +3,7 @@ module Uia
|
|
3
3
|
module Table
|
4
4
|
module Row
|
5
5
|
def items
|
6
|
-
|
6
|
+
filter(pattern: :table_item).each { |e| e.as :table_item }
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
@@ -16,11 +16,11 @@ module Uia
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def headers
|
19
|
-
|
19
|
+
Library.table_headers @element
|
20
20
|
end
|
21
21
|
|
22
22
|
def rows
|
23
|
-
|
23
|
+
filter(control_type: :data_item).each { |e| e.extend Row }
|
24
24
|
end
|
25
25
|
|
26
26
|
private
|
data/lib/uia/patterns/window.rb
CHANGED
data/lib/uia/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
module Uia
|
2
|
-
VERSION = '0.0.
|
3
|
-
end
|
1
|
+
module Uia
|
2
|
+
VERSION = '0.0.8'
|
3
|
+
end
|
data/lib/uia.rb
CHANGED
@@ -9,7 +9,6 @@ require_rel 'uia/patterns'
|
|
9
9
|
require_rel 'core_ext'
|
10
10
|
|
11
11
|
module Uia
|
12
|
-
class BadLocator < StandardError; end
|
13
12
|
extend Finder
|
14
13
|
|
15
14
|
def self.children
|
@@ -17,19 +16,6 @@ module Uia
|
|
17
16
|
end
|
18
17
|
|
19
18
|
def self.find_element(how)
|
20
|
-
|
21
|
-
when how[:id]
|
22
|
-
find_by_id how[:id]
|
23
|
-
when how[:name]
|
24
|
-
find_by_name how[:name]
|
25
|
-
when how[:pid]
|
26
|
-
find_by_pid how[:pid]
|
27
|
-
when how[:runtime_id]
|
28
|
-
find_by_runtime_id how[:runtime_id]
|
29
|
-
when how[:handle]
|
30
|
-
find_by_handle how[:handle]
|
31
|
-
else
|
32
|
-
raise BadLocator, "#{how} is not a valid locator"
|
33
|
-
end
|
19
|
+
find_from_root(how)
|
34
20
|
end
|
35
21
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -9,6 +9,16 @@ require 'uia'
|
|
9
9
|
|
10
10
|
include Uia
|
11
11
|
|
12
|
+
def wait_until(timeout=10, &block)
|
13
|
+
start = Time.now
|
14
|
+
until (result = block.call) || (Time.now - start > timeout)
|
15
|
+
sleep 0.25
|
16
|
+
end
|
17
|
+
|
18
|
+
raise 'Timed out' unless result
|
19
|
+
result
|
20
|
+
end
|
21
|
+
|
12
22
|
RSpec.configure do |config|
|
13
23
|
config.before(:all) do
|
14
24
|
@app = ChildProcess.build('spec/app/WindowsForms.exe').start
|
data/spec/uia/element_spec.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Uia::Element do
|
4
|
-
Given(:element) { Uia.find_element(id: 'MainFormWindow') }
|
5
|
-
Given(:about_box) { Uia.find_element(id: 'AboutBox') }
|
4
|
+
Given(:element) { wait_until { Uia.find_element(id: 'MainFormWindow') } }
|
5
|
+
Given(:about_box) { wait_until { Uia.find_element(id: 'AboutBox') } }
|
6
6
|
Given { element.as(:window).visual_state = :normal }
|
7
7
|
|
8
8
|
context 'properties' do
|
@@ -54,15 +54,31 @@ describe Uia::Element do
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
+
context '#send_keys' do
|
58
|
+
Given(:text_field) { element.find(id: 'textField').as :value }
|
59
|
+
When { text_field.send_keys 'abcde', [:left] * 3, ' fgh ' }
|
60
|
+
Then { text_field.value == 'ab fgh cde'}
|
61
|
+
end
|
62
|
+
|
57
63
|
context '#find' do
|
58
64
|
context 'id' do
|
59
65
|
Then { element.find(id: 'textField') != nil }
|
60
66
|
Then { element.find(id: 'does not exist') == nil }
|
61
67
|
end
|
62
68
|
|
63
|
-
context 'name' do
|
69
|
+
context 'name, value' do
|
64
70
|
Then { element.find(name: 'No option selected') != nil }
|
65
71
|
Then { element.find(name: 'does not exist') == nil }
|
72
|
+
Then { element.find(value: 'No option selected') != nil }
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'title' do
|
76
|
+
Then { element.find(title: /Group.*of radio/i) != nil }
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'invalid' do
|
80
|
+
When(:bad_locator) { element.find(bad_locator: 123) }
|
81
|
+
Then { bad_locator.should have_failed BadLocator, "{:bad_locator=>123} is not a valid locator" }
|
66
82
|
end
|
67
83
|
|
68
84
|
context 'limiting scope' do
|
@@ -72,16 +88,16 @@ describe Uia::Element do
|
|
72
88
|
|
73
89
|
context '#select' do
|
74
90
|
context 'control_type' do
|
75
|
-
When(:buttons) { element.
|
91
|
+
When(:buttons) { element.filter(control_type: :radio_button) }
|
76
92
|
Then { buttons.map(&:control_type) == [:radio_button] * 3 }
|
77
93
|
end
|
78
94
|
|
79
95
|
context 'pattern' do
|
80
|
-
Then { element.
|
96
|
+
Then { element.filter(pattern: :value).count == 4 }
|
81
97
|
end
|
82
98
|
|
83
99
|
context 'combinations' do
|
84
|
-
Then { element.
|
100
|
+
Then { element.filter(control_type: :button, name: 'About')[0].id == 'aboutButton' }
|
85
101
|
end
|
86
102
|
end
|
87
103
|
|
@@ -94,11 +110,6 @@ describe Uia::Element do
|
|
94
110
|
Then { about_box != nil }
|
95
111
|
And { about_box.children.find { |c| c.name == 'OK' }.click }
|
96
112
|
end
|
97
|
-
|
98
|
-
context 'disabled elements' do
|
99
|
-
When(:click_disabled) { disabled_checkbox.click }
|
100
|
-
Then { click_disabled.should have_failed('Target element cannot receive focus.') }
|
101
|
-
end
|
102
113
|
end
|
103
114
|
|
104
115
|
context '#children' do
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Uia::Keys do
|
4
|
+
def encode(*keys)
|
5
|
+
Keys.encode keys
|
6
|
+
end
|
7
|
+
|
8
|
+
Then { encode('Bacon sandwich') == 'Bacon sandwich' }
|
9
|
+
Then { encode([:control, :shift, 'a']) == '^(+a)' }
|
10
|
+
|
11
|
+
context 'special keys' do
|
12
|
+
Then { encode(:shift, :f2, :left) == '+{F2}{LEFT}' }
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'special characters' do
|
16
|
+
Then { encode('1 + 2') == '1 {+} 2' }
|
17
|
+
Then { encode('1 ^^ 2') == '1 {^}{^} 2' }
|
18
|
+
Then { encode('a%b') == 'a{%}b' }
|
19
|
+
Then { encode('~ish') == '{~}ish' }
|
20
|
+
Then { encode('(1 - 2)') == '{(}1 - 2{)}' }
|
21
|
+
Then { encode('{DUDE}') == '{{}DUDE{}}' }
|
22
|
+
Then { encode('[DUDE]') == '{[}DUDE{]}' }
|
23
|
+
Then { encode('(Bacon + sand%wich^ [sweet] {}') == '{(}Bacon {+} sand{%}wich{^} {[}sweet{]} {{}{}}' }
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'invalid' do
|
27
|
+
When(:bad_keys) { encode('something', :bad_key) }
|
28
|
+
Then { bad_keys.should have_failed InvalidKey, "#{:bad_key} is not a valid key" }
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Uia::Patterns::Text do
|
4
|
+
Given(:text_field) do
|
5
|
+
Uia.find_element(id: 'MainFormWindow').children.find { |e| e.id == 'multiLineTextField' }.as :text
|
6
|
+
end
|
7
|
+
|
8
|
+
context '#text' do
|
9
|
+
context 'getting / setting' do
|
10
|
+
When { text_field.text = '{text} to be expected!' }
|
11
|
+
Then { text_field.text == '{text} to be expected!' }
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'updating' do
|
15
|
+
Given { text_field.text = 'about to be overwritten' }
|
16
|
+
When { text_field.text = 'expected update' }
|
17
|
+
Then { text_field.text == 'expected update' }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -28,4 +28,18 @@ describe Uia::Patterns::Window do
|
|
28
28
|
Then { window.visual_state == :normal }
|
29
29
|
end
|
30
30
|
end
|
31
|
+
|
32
|
+
context '#close' do
|
33
|
+
def notepad_window
|
34
|
+
Uia.find_element(title: /^Untitled.*Notepad/i)
|
35
|
+
end
|
36
|
+
|
37
|
+
Given(:notepad) do
|
38
|
+
ChildProcess.build('notepad.exe').start
|
39
|
+
wait_until { notepad_window }.as :window
|
40
|
+
end
|
41
|
+
When { notepad.close }
|
42
|
+
Then { notepad_window == nil }
|
43
|
+
end
|
44
|
+
|
31
45
|
end
|
data/spec/uia_spec.rb
CHANGED
@@ -14,9 +14,10 @@ describe Uia do
|
|
14
14
|
Then { Uia.find_element(id: 'not there') == nil }
|
15
15
|
end
|
16
16
|
|
17
|
-
context 'by name' do
|
17
|
+
context 'by name / value' do
|
18
18
|
Then { expect(Uia.find_element(name: 'MainFormWindow')).to be_instance_of(Element) }
|
19
|
-
Then { expect(Uia.find_element(name: /[Mm]ain.*Window/
|
19
|
+
Then { expect(Uia.find_element(name: /[Mm]ain.*Window/)).to be_instance_of(Element) }
|
20
|
+
Then { expect(Uia.find_element(value: /[Mm]ain.*Window/)).to be_instance_of(Element) }
|
20
21
|
Then { Uia.find_element(name: 'not there') == nil }
|
21
22
|
end
|
22
23
|
|
@@ -39,6 +40,12 @@ describe Uia do
|
|
39
40
|
Then { expect { Uia.find_element(handle: 0x0) }.to raise_error }
|
40
41
|
end
|
41
42
|
|
43
|
+
context 'by title' do
|
44
|
+
Then { expect(Uia.find_element(title: 'MainFormWindow')).to be_instance_of(Element) }
|
45
|
+
Then { expect(Uia.find_element(title: /Main[Ff]orm/)).to be_instance_of(Element) }
|
46
|
+
Then { Uia.find_element(title: 'probably will not find') == nil }
|
47
|
+
end
|
48
|
+
|
42
49
|
context 'invalid locators' do
|
43
50
|
When(:bad_input) { Uia.find_element(bad: 123) }
|
44
51
|
Then { bad_input.should have_failed(Uia::BadLocator, '{:bad=>123} is not a valid locator') }
|
data/uia.gemspec
CHANGED
@@ -25,7 +25,7 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
26
26
|
spec.require_paths = ['lib']
|
27
27
|
|
28
|
-
spec.add_runtime_dependency 'ffi'
|
28
|
+
spec.add_runtime_dependency 'ffi', '1.9.0'
|
29
29
|
spec.add_runtime_dependency 'require_all'
|
30
30
|
|
31
31
|
spec.add_development_dependency 'bundler', '~> 1.3'
|
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.0.
|
4
|
+
version: 0.0.8
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,24 +9,24 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-12-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ffi
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
|
-
- -
|
19
|
+
- - '='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
21
|
+
version: 1.9.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
25
25
|
none: false
|
26
26
|
requirements:
|
27
|
-
- -
|
27
|
+
- - '='
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
29
|
+
version: 1.9.0
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: require_all
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -147,7 +147,6 @@ files:
|
|
147
147
|
- ext/UiaDll/UiaDll.Test/AssemblyInfo.cpp
|
148
148
|
- ext/UiaDll/UiaDll.Test/ElementInformationTest.cpp
|
149
149
|
- ext/UiaDll/UiaDll.Test/ElementStub.h
|
150
|
-
- ext/UiaDll/UiaDll.Test/ElementsTest.cpp
|
151
150
|
- ext/UiaDll/UiaDll.Test/MemoryLeakDetector.h
|
152
151
|
- ext/UiaDll/UiaDll.Test/PatternInformationTest.cpp
|
153
152
|
- ext/UiaDll/UiaDll.Test/ReadMe.txt
|
@@ -179,6 +178,7 @@ files:
|
|
179
178
|
- ext/UiaDll/UiaDll/StringHelper.h
|
180
179
|
- ext/UiaDll/UiaDll/TableItemMethods.cpp
|
181
180
|
- ext/UiaDll/UiaDll/TableMethods.cpp
|
181
|
+
- ext/UiaDll/UiaDll/TextMethods.cpp
|
182
182
|
- ext/UiaDll/UiaDll/ToggleMethods.cpp
|
183
183
|
- ext/UiaDll/UiaDll/UiaDll.cpp
|
184
184
|
- ext/UiaDll/UiaDll/UiaDll.h
|
@@ -192,6 +192,7 @@ files:
|
|
192
192
|
- lib/uia.rb
|
193
193
|
- lib/uia/element.rb
|
194
194
|
- lib/uia/finder.rb
|
195
|
+
- lib/uia/keys.rb
|
195
196
|
- lib/uia/library.rb
|
196
197
|
- lib/uia/library/constants.rb
|
197
198
|
- lib/uia/library/element_attributes.rb
|
@@ -199,6 +200,7 @@ files:
|
|
199
200
|
- lib/uia/library/pattern_info_attributes.rb
|
200
201
|
- lib/uia/library/pattern_structs.rb
|
201
202
|
- lib/uia/library/struct_attributes.rb
|
203
|
+
- lib/uia/library/win32.rb
|
202
204
|
- lib/uia/patterns/expand_collapse.rb
|
203
205
|
- lib/uia/patterns/invoke.rb
|
204
206
|
- lib/uia/patterns/range_value.rb
|
@@ -206,6 +208,7 @@ files:
|
|
206
208
|
- lib/uia/patterns/selection_item.rb
|
207
209
|
- lib/uia/patterns/table.rb
|
208
210
|
- lib/uia/patterns/table_item.rb
|
211
|
+
- lib/uia/patterns/text.rb
|
209
212
|
- lib/uia/patterns/toggle.rb
|
210
213
|
- lib/uia/patterns/value.rb
|
211
214
|
- lib/uia/patterns/window.rb
|
@@ -215,6 +218,7 @@ files:
|
|
215
218
|
- spec/app/WindowsForms.exe
|
216
219
|
- spec/spec_helper.rb
|
217
220
|
- spec/uia/element_spec.rb
|
221
|
+
- spec/uia/keys_spec.rb
|
218
222
|
- spec/uia/patterns/expand_collapse_spec.rb
|
219
223
|
- spec/uia/patterns/invoke_spec.rb
|
220
224
|
- spec/uia/patterns/range_value_spec.rb
|
@@ -222,6 +226,7 @@ files:
|
|
222
226
|
- spec/uia/patterns/selection_spec.rb
|
223
227
|
- spec/uia/patterns/table_item_spec.rb
|
224
228
|
- spec/uia/patterns/table_spec.rb
|
229
|
+
- spec/uia/patterns/text_spec.rb
|
225
230
|
- spec/uia/patterns/toggle_spec.rb
|
226
231
|
- spec/uia/patterns/value_spec.rb
|
227
232
|
- spec/uia/patterns/window_spec.rb
|
@@ -244,7 +249,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
244
249
|
version: '0'
|
245
250
|
segments:
|
246
251
|
- 0
|
247
|
-
hash:
|
252
|
+
hash: 720468909
|
248
253
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
249
254
|
none: false
|
250
255
|
requirements:
|
@@ -253,7 +258,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
253
258
|
version: '0'
|
254
259
|
segments:
|
255
260
|
- 0
|
256
|
-
hash:
|
261
|
+
hash: 720468909
|
257
262
|
requirements: []
|
258
263
|
rubyforge_project:
|
259
264
|
rubygems_version: 1.8.24
|
@@ -266,6 +271,7 @@ test_files:
|
|
266
271
|
- spec/app/WindowsForms.exe
|
267
272
|
- spec/spec_helper.rb
|
268
273
|
- spec/uia/element_spec.rb
|
274
|
+
- spec/uia/keys_spec.rb
|
269
275
|
- spec/uia/patterns/expand_collapse_spec.rb
|
270
276
|
- spec/uia/patterns/invoke_spec.rb
|
271
277
|
- spec/uia/patterns/range_value_spec.rb
|
@@ -273,6 +279,7 @@ test_files:
|
|
273
279
|
- spec/uia/patterns/selection_spec.rb
|
274
280
|
- spec/uia/patterns/table_item_spec.rb
|
275
281
|
- spec/uia/patterns/table_spec.rb
|
282
|
+
- spec/uia/patterns/text_spec.rb
|
276
283
|
- spec/uia/patterns/toggle_spec.rb
|
277
284
|
- spec/uia/patterns/value_spec.rb
|
278
285
|
- spec/uia/patterns/window_spec.rb
|
@@ -1,22 +0,0 @@
|
|
1
|
-
#include "stdafx.h"
|
2
|
-
#include "ElementStub.h"
|
3
|
-
#include <ElementStructures.h>
|
4
|
-
|
5
|
-
class ElementsTest : public ::testing::Test {
|
6
|
-
public:
|
7
|
-
array<Element^>^ ElementsWithNames(...array<String^>^ names) {
|
8
|
-
auto elements = gcnew array<Element^>(names->Length);
|
9
|
-
auto index = 0;
|
10
|
-
for each(auto name in names) {
|
11
|
-
elements[index++] = gcnew ElementStub(name);
|
12
|
-
}
|
13
|
-
return elements;
|
14
|
-
}
|
15
|
-
};
|
16
|
-
|
17
|
-
TEST_F(ElementsTest, ItCanBeInitialized)
|
18
|
-
{
|
19
|
-
auto elements = Elements(ElementsWithNames("First", "Second"));
|
20
|
-
ASSERT_STREQ("First", elements.elements[0].name);
|
21
|
-
ASSERT_STREQ("Second", elements.elements[1].name);
|
22
|
-
}
|