bewildr 0.1.9 → 0.1.10
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.
- data/README.rdoc +1 -1
- data/Rakefile +1 -1
- data/lib/bewildr/control_patterns/expand_collapse_pattern.rb +7 -0
- data/lib/bewildr/control_patterns/grid_pattern.rb +3 -0
- data/lib/bewildr/control_patterns/range_value_pattern.rb +4 -0
- data/lib/bewildr/control_patterns/scroll_pattern.rb +26 -25
- data/lib/bewildr/control_patterns/selection_item_pattern.rb +3 -0
- data/lib/bewildr/control_patterns/selection_pattern.rb +3 -0
- data/lib/bewildr/control_patterns/table_item_pattern.rb +2 -0
- data/lib/bewildr/control_patterns/table_pattern.rb +2 -0
- data/lib/bewildr/control_patterns/text_pattern.rb +2 -0
- data/lib/bewildr/control_patterns/toggle_pattern.rb +61 -36
- data/lib/bewildr/control_patterns/value_pattern.rb +3 -0
- data/lib/bewildr/control_patterns/window_pattern.rb +8 -0
- data/lib/bewildr/control_type_additions/combo_box_additions.rb +70 -65
- data/lib/bewildr/control_type_additions/data_grid_additions.rb +3 -6
- data/lib/bewildr/control_type_additions/document_additions.rb +21 -22
- data/lib/bewildr/control_type_additions/list_additions.rb +51 -47
- data/lib/bewildr/control_type_additions/menu_additions.rb +49 -44
- data/lib/bewildr/control_type_additions/menu_item_additions.rb +6 -10
- data/lib/bewildr/control_type_additions/scroll_additions.rb +16 -20
- data/lib/bewildr/control_type_additions/tab_additions.rb +17 -17
- data/lib/bewildr/control_type_additions/text_additions.rb +4 -7
- data/lib/bewildr/control_type_additions/tree_additions.rb +45 -41
- data/lib/bewildr/control_type_additions/tree_item_additions.rb +14 -17
- data/lib/bewildr/control_type_additions/window_additions.rb +8 -10
- data/lib/bewildr/element.rb +10 -0
- data/lib/bewildr/windows.rb +1 -0
- metadata +4 -4
data/README.rdoc
CHANGED
@@ -9,7 +9,7 @@ Documentation is on the way; until then, take a look at the tests or read the AP
|
|
9
9
|
==Getting started
|
10
10
|
===Dependencies
|
11
11
|
1. Install .net 3 and 4 (http://www.microsoft.com/downloads/details.aspx?FamilyID=10cc340b-f857-4a14-83f5-25634c3bf043&displaylang=en & http://msdn.microsoft.com/en-us/netframework/aa569263.aspx)
|
12
|
-
2. Install the latest ironruby (http://
|
12
|
+
2. Install the latest ironruby (http://ironruby.codeplex.com/), and for your own sanity install it in c:\\\\ironruby instead of the default location.
|
13
13
|
3. You'll need at least rubygems version 1.3.6:
|
14
14
|
gem update --system
|
15
15
|
|
data/Rakefile
CHANGED
@@ -10,7 +10,7 @@ require 'cucumber/rake/task'
|
|
10
10
|
|
11
11
|
spec = Gem::Specification.new do |s|
|
12
12
|
s.name = 'bewildr'
|
13
|
-
s.version = '0.1.
|
13
|
+
s.version = '0.1.10'
|
14
14
|
s.has_rdoc = true
|
15
15
|
s.extra_rdoc_files = ['README.rdoc', 'LICENSE']
|
16
16
|
s.summary = 'Test WPF UI apps with IronRuby'
|
@@ -3,14 +3,21 @@
|
|
3
3
|
module Bewildr
|
4
4
|
module ControlPatterns
|
5
5
|
module ExpandCollapsePattern
|
6
|
+
#Expands the element - use to open combo boxes
|
6
7
|
def expand
|
7
8
|
@automation_element.get_current_pattern(System::Windows::Automation::ExpandCollapsePattern.pattern).expand unless expand_state == :expanded or expand_state == :leaf
|
8
9
|
end
|
9
10
|
|
11
|
+
#Collapses the element - use to close combo boxes
|
10
12
|
def collapse
|
11
13
|
@automation_element.get_current_pattern(System::Windows::Automation::ExpandCollapsePattern.pattern).collapse unless expand_state == :collapsed or expand_state == :leaf
|
12
14
|
end
|
13
15
|
|
16
|
+
#Returns the expand-state of the element. The available states are:
|
17
|
+
# :collapsed
|
18
|
+
# :expanded
|
19
|
+
# :partially_expanded
|
20
|
+
# :leaf
|
14
21
|
def expand_state
|
15
22
|
case @automation_element.get_current_pattern(System::Windows::Automation::ExpandCollapsePattern.pattern).current.expand_collapse_state
|
16
23
|
when System::Windows::Automation::ExpandCollapseState.collapsed then return :collapsed
|
@@ -3,14 +3,17 @@
|
|
3
3
|
module Bewildr
|
4
4
|
module ControlPatterns
|
5
5
|
module GridPattern
|
6
|
+
#Returns the number of rows in the grid
|
6
7
|
def row_count
|
7
8
|
@automation_element.get_current_pattern(System::Windows::Automation::GridPattern.pattern).current.row_count.to_i
|
8
9
|
end
|
9
10
|
|
11
|
+
#Returns the number of columns in the grid
|
10
12
|
def column_count
|
11
13
|
@automation_element.get_current_pattern(System::Windows::Automation::GridPattern.pattern).current.column_count.to_i
|
12
14
|
end
|
13
15
|
|
16
|
+
#Returns an item from the grid
|
14
17
|
def get_item(row, column)
|
15
18
|
item = @automation_element.get_current_pattern(System::Windows::Automation::GridPattern.pattern).get_item(row, column)
|
16
19
|
Bewildr::Element.new(item)
|
@@ -3,18 +3,22 @@
|
|
3
3
|
module Bewildr
|
4
4
|
module ControlPatterns
|
5
5
|
module RangeValuePattern
|
6
|
+
#Returns the current value of the element
|
6
7
|
def value
|
7
8
|
@automation_element.get_current_pattern(System::Windows::Automation::RangeValuePattern.pattern).current.value.to_f
|
8
9
|
end
|
9
10
|
|
11
|
+
#Sets the value of the element
|
10
12
|
def value=(input)
|
11
13
|
@automation_element.get_current_pattern(System::Windows::Automation::RangeValuePattern.pattern).set_value(input.to_f)
|
12
14
|
end
|
13
15
|
|
16
|
+
#Returns the maximum value of the element
|
14
17
|
def maximum
|
15
18
|
@automation_element.get_current_pattern(System::Windows::Automation::RangeValuePattern.pattern).current.maximum.to_f
|
16
19
|
end
|
17
20
|
|
21
|
+
#Returns the minimum value of the element
|
18
22
|
def minimum
|
19
23
|
@automation_element.get_current_pattern(System::Windows::Automation::RangeValuePattern.pattern).current.minimum.to_f
|
20
24
|
end
|
@@ -3,35 +3,36 @@
|
|
3
3
|
module Bewildr
|
4
4
|
module ControlPatterns
|
5
5
|
module ScrollPattern
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
#Returns true if the element is vertically scrollable, false if it's not
|
7
|
+
def vertically_scrollable
|
8
|
+
@automation_element.get_current_pattern(System::Windows::Automation::ScrollPattern.pattern).current.vertically_scrollable
|
9
|
+
end
|
10
|
+
|
11
|
+
#Returns the current vertical scroll percent
|
12
|
+
def vertical_scroll_percent
|
13
|
+
@automation_element.get_current_pattern(System::Windows::Automation::ScrollPattern.pattern).current.vertical_scroll_percent.to_f
|
14
|
+
end
|
15
|
+
alias :scroll_percent :vertical_scroll_percent
|
12
16
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
+
#Set the scroll percent of the element
|
18
|
+
def set_scroll_percent(percent_horizontal, percent_vertical)
|
19
|
+
@automation_element.get_current_pattern(System::Windows::Automation::ScrollPattern.pattern).set_scroll_percent(percent_horizontal, percent_vertical)
|
20
|
+
end
|
17
21
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
set_scroll_percent(System::Windows::Automation::ScrollPattern.NoScroll, target_percentage)
|
24
|
-
end
|
25
|
-
alias :scroll_to :scroll_vertically_to
|
22
|
+
#Set the vertical scroll percent of the element
|
23
|
+
def scroll_vertically_to(target_percentage)
|
24
|
+
set_scroll_percent(System::Windows::Automation::ScrollPattern.NoScroll, target_percentage)
|
25
|
+
end
|
26
|
+
alias :scroll_to :scroll_vertically_to
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
28
|
+
#Set the horizontal scroll percent of the element
|
29
|
+
def scroll_horizontally_to(target_percentage)
|
30
|
+
set_scroll_percent(target_percentage, System::Windows::Automation::ScrollPattern.NoScroll)
|
31
|
+
end
|
30
32
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
end
|
33
|
+
#Scrolls vertically down by one 'page'
|
34
|
+
def scroll_down_one_page
|
35
|
+
@automation_element.get_current_pattern(System::Windows::Automation::ScrollPattern.pattern).scroll_vertical(System::Windows::Automation::ScrollAmount.LargeIncrement)
|
35
36
|
end
|
36
37
|
end
|
37
38
|
end
|
@@ -4,14 +4,17 @@
|
|
4
4
|
module Bewildr
|
5
5
|
module ControlPatterns
|
6
6
|
module SelectionItemPattern
|
7
|
+
#Selects the element
|
7
8
|
def select
|
8
9
|
@automation_element.get_current_pattern(System::Windows::Automation::SelectionItemPattern.pattern).select
|
9
10
|
end
|
10
11
|
|
12
|
+
#Returns true if the element is selected, false if it's not
|
11
13
|
def selected?
|
12
14
|
@automation_element.get_current_pattern(System::Windows::Automation::SelectionItemPattern.pattern).current.is_selected
|
13
15
|
end
|
14
16
|
|
17
|
+
#Returns false if the element is selected, true if it's not
|
15
18
|
def unselected?
|
16
19
|
!selected?
|
17
20
|
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
module Bewildr
|
4
4
|
module ControlPatterns
|
5
5
|
module SelectionPattern
|
6
|
+
#Returns the elements that are selected
|
6
7
|
def get_selection
|
7
8
|
my_selected_items = @automation_element.get_current_pattern(System::Windows::Automation::SelectionPattern.pattern).current.get_selection
|
8
9
|
|
@@ -13,11 +14,13 @@ module Bewildr
|
|
13
14
|
item_array.to_a.collect {|item| Bewildr::Element.new(item)}
|
14
15
|
end
|
15
16
|
|
17
|
+
#Returns true if more than one selection is possible, false if it's not
|
16
18
|
def multi_selectable?
|
17
19
|
@automation_element.get_current_pattern(System::Windows::Automation::SelectionPattern.pattern).current.can_select_multiple
|
18
20
|
end
|
19
21
|
alias :can_select_multiple? :multi_selectable?
|
20
22
|
|
23
|
+
#Returns the (first - if relevant) selected item
|
21
24
|
def selected
|
22
25
|
multi_selectable? ? get_selection : get_selection.first
|
23
26
|
end
|
@@ -3,10 +3,12 @@
|
|
3
3
|
module Bewildr
|
4
4
|
module ControlPatterns
|
5
5
|
module TableItemPattern
|
6
|
+
#Returns the number of rows the element spans
|
6
7
|
def row_span
|
7
8
|
@automation_element.get_current_pattern(System::Windows::Automation::TableItemPattern.pattern).current.row_span.to_i
|
8
9
|
end
|
9
10
|
|
11
|
+
#Returns the number of columns the element spans
|
10
12
|
def column_span
|
11
13
|
@automation_element.get_current_pattern(System::Windows::Automation::TableItemPattern.pattern).current.column_span.to_i
|
12
14
|
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
module Bewildr
|
4
4
|
module ControlPatterns
|
5
5
|
module TablePattern
|
6
|
+
#Returns an array of elements containing the column headers
|
6
7
|
def column_headers
|
7
8
|
#the following line seems to prompt the table pattern into giving up the column header
|
8
9
|
#information that's called on the line that follows it. Weird? tell me about it...
|
@@ -12,6 +13,7 @@ module Bewildr
|
|
12
13
|
end
|
13
14
|
end
|
14
15
|
|
16
|
+
#Returns a string array containing the column header names
|
15
17
|
def column_header_names
|
16
18
|
column_headers.collect {|header| header.name }
|
17
19
|
end
|
@@ -3,10 +3,12 @@
|
|
3
3
|
module Bewildr
|
4
4
|
module ControlPatterns
|
5
5
|
module TextPattern
|
6
|
+
#Selects all of the text in the element
|
6
7
|
def select_all
|
7
8
|
@automation_element.get_current_pattern(System::Windows::Automation::TextPattern.pattern).document_range.select
|
8
9
|
end
|
9
10
|
|
11
|
+
#Returns all the element's text
|
10
12
|
def get_text
|
11
13
|
@automation_element.get_current_pattern(System::Windows::Automation::TextPattern.pattern).document_range.get_text(-1).to_s
|
12
14
|
end
|
@@ -2,51 +2,76 @@
|
|
2
2
|
|
3
3
|
module Bewildr
|
4
4
|
module ControlPatterns
|
5
|
-
module
|
5
|
+
module TogglePatternForButton
|
6
|
+
#Toggle on the element
|
7
|
+
def toggle_on
|
8
|
+
set_state_to(:on)
|
9
|
+
end
|
6
10
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
def check
|
12
|
-
set_state_to :on
|
13
|
-
end
|
11
|
+
#Toggle off the element
|
12
|
+
def toggle_off
|
13
|
+
set_state_to(:off)
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
16
|
+
#Return the toggle state. The available states are:
|
17
|
+
# :on
|
18
|
+
# :off
|
19
|
+
# :indeterminate
|
20
|
+
def toggle_state
|
21
|
+
state
|
22
|
+
end
|
18
23
|
|
19
|
-
|
20
|
-
|
21
|
-
|
24
|
+
#Toggle the element
|
25
|
+
def toggle
|
26
|
+
flip_state
|
27
|
+
end
|
28
|
+
end
|
22
29
|
|
23
|
-
|
24
|
-
|
25
|
-
|
30
|
+
module TogglePatternForCheckBox
|
31
|
+
#Check the element
|
32
|
+
def check
|
33
|
+
set_state_to :on
|
34
|
+
end
|
26
35
|
|
27
|
-
|
28
|
-
|
29
|
-
|
36
|
+
#Uncheck the element
|
37
|
+
def uncheck
|
38
|
+
set_state_to :off
|
39
|
+
end
|
30
40
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
41
|
+
#Return true if the element is checked, false if it's not
|
42
|
+
def checked?
|
43
|
+
state == :on
|
44
|
+
end
|
45
|
+
|
46
|
+
#Return true if the element is unchecked, false if it's not
|
47
|
+
def unchecked?
|
48
|
+
state == :off
|
49
|
+
end
|
38
50
|
|
39
|
-
|
40
|
-
|
41
|
-
|
51
|
+
#Return true if the element is indeterminate, false if it's not
|
52
|
+
def indeterminate?
|
53
|
+
state == :indeterminate
|
54
|
+
end
|
42
55
|
|
43
|
-
|
44
|
-
|
45
|
-
|
56
|
+
#Returns the checked state. The available states are:
|
57
|
+
# :on
|
58
|
+
# :off
|
59
|
+
# :indeterminate
|
60
|
+
def checked_state
|
61
|
+
state
|
62
|
+
end
|
63
|
+
end
|
46
64
|
|
47
|
-
|
48
|
-
|
49
|
-
|
65
|
+
#These are not the toggle patterns you are looking for [wave of the hand/]. If you are dealing with a button, look for Bewildr::ControlPatterns::TogglePatternForButton.
|
66
|
+
#If you're dealing with a checkbox, take a look at Bewildr::ControlPatterns::TogglePatternForCheckBox
|
67
|
+
module TogglePattern
|
68
|
+
def self.extended(base)
|
69
|
+
base.instance_eval do
|
70
|
+
case @control_type
|
71
|
+
when :check_box
|
72
|
+
base.extend(Bewildr::ControlPatterns::TogglePatternForCheckBox)
|
73
|
+
when :button
|
74
|
+
base.extend(Bewildr::ControlPatterns::TogglePatternForButton)
|
50
75
|
end
|
51
76
|
end
|
52
77
|
end
|
@@ -3,15 +3,18 @@
|
|
3
3
|
module Bewildr
|
4
4
|
module ControlPatterns
|
5
5
|
module ValuePattern
|
6
|
+
#Returns true if the element is a password field, false if it's not
|
6
7
|
def password_field?
|
7
8
|
@automation_element.current.class_name.to_s == "PasswordBox" ? true : false
|
8
9
|
end
|
9
10
|
|
11
|
+
#Returns the element's text
|
10
12
|
def text
|
11
13
|
raise Bewildr::PasswordFieldReadAttempt, "You can't get the text of a password field" if password_field?
|
12
14
|
@automation_element.get_current_pattern(System::Windows::Automation::ValuePattern.pattern).current.value.to_s
|
13
15
|
end
|
14
16
|
|
17
|
+
#Sets the element's text
|
15
18
|
def text=(input)
|
16
19
|
raise Bewildr::ElementNotEnabled unless enabled?
|
17
20
|
@automation_element.get_current_pattern(System::Windows::Automation::ValuePattern.pattern).set_value(input)
|
@@ -3,22 +3,30 @@
|
|
3
3
|
module Bewildr
|
4
4
|
module ControlPatterns
|
5
5
|
module WindowPattern
|
6
|
+
#Closes the window
|
6
7
|
def close
|
7
8
|
@automation_element.get_current_pattern(System::Windows::Automation::WindowPattern.pattern).close
|
8
9
|
end
|
9
10
|
|
11
|
+
#Minimizes the window
|
10
12
|
def minimize
|
11
13
|
@automation_element.get_current_pattern(System::Windows::Automation::WindowPattern.pattern).set_window_visual_state(System::Windows::Automation::WindowVisualState.minimized)
|
12
14
|
end
|
13
15
|
|
16
|
+
#Maximizes the window
|
14
17
|
def maximize
|
15
18
|
@automation_element.get_current_pattern(System::Windows::Automation::WindowPattern.pattern).set_window_visual_state(System::Windows::Automation::WindowVisualState.maximized)
|
16
19
|
end
|
17
20
|
|
21
|
+
#Restores the window
|
18
22
|
def restore
|
19
23
|
@automation_element.get_current_pattern(System::Windows::Automation::WindowPattern.pattern).set_window_visual_state(System::Windows::Automation::WindowVisualState.normal)
|
20
24
|
end
|
21
25
|
|
26
|
+
#Returns the visual state of the window. Available states are:
|
27
|
+
# :maximized
|
28
|
+
# :minimized
|
29
|
+
# :normal
|
22
30
|
def visual_state
|
23
31
|
case @automation_element.get_current_pattern(System::Windows::Automation::WindowPattern.pattern).current.window_visual_state
|
24
32
|
when System::Windows::Automation::WindowVisualState.maximized then return :maximized
|
@@ -3,79 +3,84 @@
|
|
3
3
|
module Bewildr
|
4
4
|
module ControlTypeAdditions
|
5
5
|
module ComboBoxAdditions
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
end
|
6
|
+
#Returns a string array containing the element's item names
|
7
|
+
def items
|
8
|
+
my_list_items = list_items
|
9
|
+
return nil if my_list_items.nil?
|
10
|
+
my_list_items.collect {|item| item.name}
|
11
|
+
end
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
13
|
+
#Returns an array containing the combobox items
|
14
|
+
def list_items
|
15
|
+
begin
|
16
|
+
expand_combo
|
17
|
+
bewildr_list_items = get(:type => :list_item, :scope => :children, :how_many => :all)
|
18
|
+
bewildr_list_items.nil? ? nil : bewildr_list_items
|
19
|
+
ensure
|
20
|
+
collapse_combo
|
21
|
+
end
|
22
|
+
end
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
#Returns the number of items in the combobox
|
25
|
+
def count
|
26
|
+
my_items = items
|
27
|
+
my_items.nil? ? 0 : my_items.size
|
28
|
+
end
|
28
29
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
30
|
+
#Selects a combobox item. Takes a string (and selects the first item whose name matches) or an integer and selects the respective element
|
31
|
+
def select(input)
|
32
|
+
case input
|
33
|
+
when String then select_by_name(input)
|
34
|
+
when Integer then select_by_index(input)
|
35
|
+
else raise ArgumentError, "Select by name or by index"
|
36
|
+
end
|
37
|
+
end
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
39
|
+
#Selects the first item whose name matches the input
|
40
|
+
def select_by_name(input)
|
41
|
+
begin
|
42
|
+
expand_combo
|
43
|
+
my_item = list_items.find {|item| item.name == input}
|
44
|
+
raise Bewildr::NoSuchItemInComboBox if my_item.nil?
|
45
|
+
my_item.select
|
46
|
+
ensure
|
47
|
+
collapse_combo
|
48
|
+
end
|
49
|
+
end
|
47
50
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
51
|
+
#Selects the item at the supplied position
|
52
|
+
def select_by_index(input)
|
53
|
+
raise "Index must be 0 or greater" if input < 0
|
54
|
+
begin
|
55
|
+
expand_combo
|
56
|
+
list_items[input].select
|
57
|
+
ensure
|
58
|
+
collapse_combo
|
59
|
+
end
|
60
|
+
end
|
57
61
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
62
|
+
#Returns the selected combobox item
|
63
|
+
def selected
|
64
|
+
#TODO: find a way to not need to expand and collapse before getting the selected item
|
65
|
+
expand_combo
|
66
|
+
collapse_combo
|
67
|
+
#get_selection.first
|
68
|
+
get_selection.first.name
|
69
|
+
end
|
65
70
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
71
|
+
#Expands the combobox
|
72
|
+
def expand_combo
|
73
|
+
expand
|
74
|
+
Timeout.timeout(30) do
|
75
|
+
sleep 0.2 until expand_state == :expanded
|
76
|
+
end
|
77
|
+
end
|
72
78
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
end
|
79
|
+
#Collapses the combobox
|
80
|
+
def collapse_combo
|
81
|
+
collapse
|
82
|
+
Timeout.timeout(30) do
|
83
|
+
sleep 0.2 until expand_state == :collapsed
|
79
84
|
end
|
80
85
|
end
|
81
86
|
end
|
@@ -3,12 +3,9 @@
|
|
3
3
|
module Bewildr
|
4
4
|
module ControlTypeAdditions
|
5
5
|
module DataGridAdditions
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
get_item(row, column)
|
10
|
-
end
|
11
|
-
end
|
6
|
+
#Returns the cell at the supplied row and column
|
7
|
+
def cell(row, column)
|
8
|
+
get_item(row, column)
|
12
9
|
end
|
13
10
|
end
|
14
11
|
end
|
@@ -3,31 +3,30 @@
|
|
3
3
|
module Bewildr
|
4
4
|
module ControlTypeAdditions
|
5
5
|
module DocumentAdditions
|
6
|
-
|
7
|
-
|
6
|
+
#Returns the document text
|
7
|
+
def text
|
8
|
+
get_text
|
9
|
+
end
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
11
|
+
#Sets the document text to the supplied input
|
12
|
+
def text=(input)
|
13
|
+
cleaned_string = clean_string(input)
|
14
|
+
focus
|
15
|
+
select_all
|
16
|
+
System::Windows::Forms::SendKeys.send_wait("{DEL}")
|
17
|
+
System::Windows::Forms::SendKeys.send_wait(cleaned_string)
|
18
|
+
end
|
18
19
|
|
19
|
-
|
20
|
-
get_text
|
21
|
-
end
|
20
|
+
private
|
22
21
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
22
|
+
def clean_string(input)
|
23
|
+
#add special chars as necessary. Ref: http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.send.aspx
|
24
|
+
replacements = {
|
25
|
+
/\n/ => "{ENTER}"
|
26
|
+
}
|
27
|
+
cleaned_string = input
|
28
|
+
replacements.keys.each {|key| cleaned_string.gsub!(key, replacements[key])}
|
29
|
+
cleaned_string
|
31
30
|
end
|
32
31
|
end
|
33
32
|
end
|
@@ -3,55 +3,59 @@
|
|
3
3
|
module Bewildr
|
4
4
|
module ControlTypeAdditions
|
5
5
|
module ListAdditions
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
def select_by_name(input)
|
39
|
-
my_item = list_items.find {|item| item.name == input}
|
40
|
-
raise Bewildr::NoSuchItemInListBox if my_item.nil?
|
41
|
-
my_item.select
|
42
|
-
end
|
43
|
-
|
44
|
-
def select_by_index(input)
|
45
|
-
raise "Index must be 0 or greater" if input < 0
|
46
|
-
list_items[input].select
|
47
|
-
end
|
48
|
-
|
49
|
-
def selected
|
50
|
-
return nil if get_selection.empty?
|
51
|
-
get_selection.first.name
|
52
|
-
end
|
6
|
+
#Select the list item whose name matches the supplied input
|
7
|
+
def select(input)
|
8
|
+
selectable_elements = get(:type => :list_item, :scope => :children, :how_many => :all)
|
9
|
+
selectable_elements.find {|selectable_element| selectable_element.name == input}.select
|
10
|
+
end
|
11
|
+
|
12
|
+
#Returns a string array containing the list item names
|
13
|
+
def items
|
14
|
+
my_list_items = list_items
|
15
|
+
return nil if my_list_items.nil?
|
16
|
+
my_list_items.collect {|item| item.name}
|
17
|
+
end
|
18
|
+
|
19
|
+
#Returns an array containing the list items
|
20
|
+
def list_items
|
21
|
+
prepare_element
|
22
|
+
bewildr_list_items = get(:type => :list_item, :scope => :children, :how_many => :all)
|
23
|
+
bewildr_list_items.nil? ? nil : bewildr_list_items
|
24
|
+
end
|
25
|
+
|
26
|
+
#Returns the number of items in the list
|
27
|
+
def count
|
28
|
+
my_items = items
|
29
|
+
my_items.nil? ? 0 : my_items.size
|
30
|
+
end
|
31
|
+
|
32
|
+
#Selects a list item. Takes a string (and selects the first item whose name matches) or an integer and selects the respective element
|
33
|
+
def select(input)
|
34
|
+
case input
|
35
|
+
when String then select_by_name(input)
|
36
|
+
when Integer then select_by_index(input)
|
37
|
+
else raise ArgumentError, "Select by name or by index"
|
53
38
|
end
|
54
39
|
end
|
40
|
+
|
41
|
+
#Selects the first item whose name matches the input
|
42
|
+
def select_by_name(input)
|
43
|
+
my_item = list_items.find {|item| item.name == input}
|
44
|
+
raise Bewildr::NoSuchItemInListBox if my_item.nil?
|
45
|
+
my_item.select
|
46
|
+
end
|
47
|
+
|
48
|
+
#Selects the item at the supplied position
|
49
|
+
def select_by_index(input)
|
50
|
+
raise "Index must be 0 or greater" if input < 0
|
51
|
+
list_items[input].select
|
52
|
+
end
|
53
|
+
|
54
|
+
#Returns the selected list item
|
55
|
+
def selected
|
56
|
+
return nil if get_selection.empty?
|
57
|
+
get_selection.first.name
|
58
|
+
end
|
55
59
|
end
|
56
60
|
end
|
57
61
|
end
|
@@ -3,56 +3,61 @@
|
|
3
3
|
module Bewildr
|
4
4
|
module ControlTypeAdditions
|
5
5
|
module MenuAdditions
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
6
|
+
#Returns an array containing the menu's root items
|
7
|
+
def root_menu_items
|
8
|
+
get(:type => :menu_item, :scope => :children, :how_many => :all)
|
9
|
+
end
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
def select_menu(path)
|
17
|
-
menu_item(path).click
|
18
|
-
end
|
11
|
+
#Returns a string array containing the root items' names
|
12
|
+
def root_menu_item_names
|
13
|
+
root_menu_items.collect {|menu_item| menu_item.name}
|
14
|
+
end
|
19
15
|
|
20
|
-
|
21
|
-
|
22
|
-
|
16
|
+
#Clicks the menu described by the input, eg:
|
17
|
+
# select_menu(["File", "Close"])
|
18
|
+
def select_menu(path)
|
19
|
+
menu_item(path).click
|
20
|
+
end
|
23
21
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
when Array
|
30
|
-
matching_menu_item = current_menu_items.find {|node| node.name == target_menu_item} #TODO: make this work with regexes as well as strings...
|
31
|
-
raise Bewildr::ElementDoesntExist if matching_menu_item.nil?
|
32
|
-
when Bewildr::Element
|
33
|
-
if current_menu_items.name == target_menu_item #TODO: make this work with regexes as well as strings...
|
34
|
-
matching_menu_item = current_menu_items
|
35
|
-
else
|
36
|
-
raise Bewildr::ElementDoesntExist
|
37
|
-
end
|
38
|
-
end
|
39
|
-
raise Bewildr::ElementDoesntExist if matching_menu_item.nil?
|
40
|
-
if path.size != index + 1
|
41
|
-
matching_menu_item.expand
|
42
|
-
current_menu_items = matching_menu_item.sub_menus
|
43
|
-
end
|
44
|
-
end
|
45
|
-
return matching_menu_item
|
46
|
-
end
|
22
|
+
#Selects the menu described by the input, eg:
|
23
|
+
# select_node(["File", "Close"])
|
24
|
+
def select_node(path)
|
25
|
+
node(path).select
|
26
|
+
end
|
47
27
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
28
|
+
#Returns the menu item described by the input, eg:
|
29
|
+
# menu_item(["File", "Close"])
|
30
|
+
def menu_item(path)
|
31
|
+
current_menu_items = root_menu_items
|
32
|
+
matching_menu_item = nil
|
33
|
+
path.each_with_index do |target_menu_item, index|
|
34
|
+
case current_menu_items
|
35
|
+
when Array
|
36
|
+
matching_menu_item = current_menu_items.find {|node| node.name == target_menu_item} #TODO: make this work with regexes as well as strings...
|
37
|
+
raise Bewildr::ElementDoesntExist if matching_menu_item.nil?
|
38
|
+
when Bewildr::Element
|
39
|
+
if current_menu_items.name == target_menu_item #TODO: make this work with regexes as well as strings...
|
40
|
+
matching_menu_item = current_menu_items
|
41
|
+
else
|
42
|
+
raise Bewildr::ElementDoesntExist
|
54
43
|
end
|
55
44
|
end
|
45
|
+
raise Bewildr::ElementDoesntExist if matching_menu_item.nil?
|
46
|
+
if path.size != index + 1
|
47
|
+
matching_menu_item.expand
|
48
|
+
current_menu_items = matching_menu_item.sub_menus
|
49
|
+
end
|
50
|
+
end
|
51
|
+
return matching_menu_item
|
52
|
+
end
|
53
|
+
|
54
|
+
#Returns true if the menu contains the item described by the input, false if it doesn't
|
55
|
+
def contains_menu_item?(path)
|
56
|
+
begin
|
57
|
+
menu_item(path)
|
58
|
+
return true
|
59
|
+
rescue ElementDoesntExist => e
|
60
|
+
return false
|
56
61
|
end
|
57
62
|
end
|
58
63
|
end
|
@@ -3,17 +3,13 @@
|
|
3
3
|
module Bewildr
|
4
4
|
module ControlTypeAdditions
|
5
5
|
module MenuItemAdditions
|
6
|
-
def
|
7
|
-
|
8
|
-
|
9
|
-
get(:type => :menu_item, :scope => :children, :how_many => :all)
|
10
|
-
end
|
6
|
+
def sub_menus
|
7
|
+
get(:type => :menu_item, :scope => :children, :how_many => :all)
|
8
|
+
end
|
11
9
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
end
|
16
|
-
end
|
10
|
+
#menu items like 'invoke', not a proper mouse click
|
11
|
+
def click
|
12
|
+
@automation_element.get_current_pattern(System::Windows::Automation::InvokePattern.pattern).invoke
|
17
13
|
end
|
18
14
|
end
|
19
15
|
end
|
@@ -3,29 +3,25 @@
|
|
3
3
|
module Bewildr
|
4
4
|
module ControlTypeAdditions
|
5
5
|
module ScrollAdditions
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
#the scroll back where it was before we started this nonsense.
|
15
|
-
def load_all_items_hack
|
16
|
-
return unless scrollable?
|
6
|
+
#required because when a list is displayed, UI Automation only knows
|
7
|
+
#about the visible items. This method stores where the scroll value is,
|
8
|
+
#then moves the scroller to the top of the scroll bar and proceeds to
|
9
|
+
#page-down until the bottom of the scroll bar is reached. At this point,
|
10
|
+
#UI Automation knows about all the items in the list and we can put
|
11
|
+
#the scroll back where it was before we started this nonsense.
|
12
|
+
def load_all_items_hack
|
13
|
+
return unless scrollable?
|
17
14
|
|
18
|
-
|
15
|
+
initial_scroll_value = vertical_scroll_percent
|
19
16
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
17
|
+
scroll_to 0.0
|
18
|
+
page_down_to_bottom_of_scroll_bar
|
19
|
+
scroll_to initial_scroll_value
|
20
|
+
end
|
24
21
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
end
|
22
|
+
#Scrolls down to the bottom, page by page
|
23
|
+
def page_down_to_bottom_of_scroll_bar
|
24
|
+
scroll_down_one_page while vertical_scroll_percent < 99.99
|
29
25
|
end
|
30
26
|
end
|
31
27
|
end
|
@@ -3,26 +3,26 @@
|
|
3
3
|
module Bewildr
|
4
4
|
module ControlTypeAdditions
|
5
5
|
module TabAdditions
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
end
|
6
|
+
#Selects the tab whose name matches the input
|
7
|
+
def select(input)
|
8
|
+
raise Bewildr::NoSuchTab unless tab_names.include?(input)
|
9
|
+
selectable_elements = tabs
|
10
|
+
selectable_elements.find {|selectable_element| selectable_element.name == input}.select
|
11
|
+
end
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
#Returns an array containing the tab items belonging to the tab control
|
14
|
+
def tabs
|
15
|
+
get(:type => :tab_item, :scope => :children, :how_many => :all)
|
16
|
+
end
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
#Returns a string array containing the names of all the tabs in the tab control
|
19
|
+
def tab_names
|
20
|
+
tabs.collect {|tab| tab.name}
|
21
|
+
end
|
21
22
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
23
|
+
#Returns the selected tab
|
24
|
+
def selected
|
25
|
+
tabs.find {|tab| tab.selected?}
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
@@ -3,13 +3,10 @@
|
|
3
3
|
module Bewildr
|
4
4
|
module ControlTypeAdditions
|
5
5
|
module TextAdditions
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
name
|
11
|
-
end
|
12
|
-
end
|
6
|
+
#Returns the element's text
|
7
|
+
def text
|
8
|
+
existence_check
|
9
|
+
name
|
13
10
|
end
|
14
11
|
end
|
15
12
|
end
|
@@ -3,54 +3,58 @@
|
|
3
3
|
module Bewildr
|
4
4
|
module ControlTypeAdditions
|
5
5
|
module TreeAdditions
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
6
|
+
#Returns an array containing the tree's root nodes
|
7
|
+
def root_nodes
|
8
|
+
prepare_element
|
9
|
+
get(:type => :tree_item, :scope => :children)
|
10
|
+
end
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
#Returns the root node
|
13
|
+
def root_node
|
14
|
+
root_nodes.first
|
15
|
+
end
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
#Selects the tree node described by the input, eg:
|
18
|
+
# select_node(["parent node", "child node"])
|
19
|
+
def select_node(path)
|
20
|
+
node(path).select
|
21
|
+
end
|
20
22
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
raise Bewildr::ElementDoesntExist if matching_node.nil?
|
37
|
-
if path.size != index + 1
|
38
|
-
matching_node.expand
|
39
|
-
current_nodes = matching_node.child_nodes
|
40
|
-
end
|
23
|
+
#Returns the tree node described by the input, eg:
|
24
|
+
# node(["parent node", "child node"])
|
25
|
+
def node(path)
|
26
|
+
current_nodes = root_nodes
|
27
|
+
matching_node = nil
|
28
|
+
path.each_with_index do |target_node, index|
|
29
|
+
case current_nodes
|
30
|
+
when Array
|
31
|
+
matching_node = current_nodes.find {|node| node.name == target_node} #TODO: make this work with regexes as well as strings...
|
32
|
+
raise Bewildr::ElementDoesntExist if matching_node.nil?
|
33
|
+
when Bewildr::Element
|
34
|
+
if current_nodes.name == target_node #TODO: make this work with regexes as well as strings...
|
35
|
+
matching_node = current_nodes
|
36
|
+
else
|
37
|
+
raise Bewildr::ElementDoesntExist
|
41
38
|
end
|
42
|
-
return matching_node
|
43
39
|
end
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
rescue ElementDoesntExist => e
|
50
|
-
return false
|
51
|
-
end
|
40
|
+
raise Bewildr::ElementDoesntExist if matching_node.nil?
|
41
|
+
if path.size != index + 1
|
42
|
+
matching_node.expand
|
43
|
+
load_all_items_hack
|
44
|
+
current_nodes = matching_node.child_nodes
|
52
45
|
end
|
53
46
|
end
|
47
|
+
return matching_node
|
48
|
+
end
|
49
|
+
|
50
|
+
#Returns true if the tree contains the item described by the input, false if it doesn't
|
51
|
+
def contains_node?(path)
|
52
|
+
begin
|
53
|
+
node(path)
|
54
|
+
return true
|
55
|
+
rescue ElementDoesntExist => e
|
56
|
+
return false
|
57
|
+
end
|
54
58
|
end
|
55
59
|
end
|
56
60
|
end
|
@@ -3,24 +3,21 @@
|
|
3
3
|
module Bewildr
|
4
4
|
module ControlTypeAdditions
|
5
5
|
module TreeItemAdditions
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
6
|
+
#Returns the tree item's child nodes
|
7
|
+
def child_nodes
|
8
|
+
get(:type => :tree_item, :scope => :children)
|
9
|
+
end
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
end
|
23
|
-
end
|
11
|
+
#horrible, but necessary - clickable point for tree items doesn't work like you think it would...
|
12
|
+
#I've added 7 to y and 22 to x... that's working for now... this is hardly the ideal solution...
|
13
|
+
#To see what's going on with the following code, take a look at a tree node under uispy - you'll
|
14
|
+
#understand - a picture paints a thousand words and all that.
|
15
|
+
def clickable_point
|
16
|
+
existence_check
|
17
|
+
ae_top_left_point = @automation_element.current.bounding_rectangle.top_left
|
18
|
+
ae_top_left_point.x += 22
|
19
|
+
ae_top_left_point.y += 7
|
20
|
+
ae_top_left_point
|
24
21
|
end
|
25
22
|
end
|
26
23
|
end
|
@@ -3,17 +3,15 @@
|
|
3
3
|
module Bewildr
|
4
4
|
module ControlTypeAdditions
|
5
5
|
module WindowAdditions
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
6
|
+
#Returns true if the window is open, false if it's not
|
7
|
+
def open?
|
8
|
+
exists?
|
9
|
+
end
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
11
|
+
#Waits up to 30 seconds for the window to close
|
12
|
+
def wait_for_close
|
13
|
+
Timeout::timeout(30) do
|
14
|
+
sleep 0.2 while open?
|
17
15
|
end
|
18
16
|
end
|
19
17
|
end
|
data/lib/bewildr/element.rb
CHANGED
@@ -177,6 +177,16 @@ module Bewildr
|
|
177
177
|
end
|
178
178
|
end
|
179
179
|
|
180
|
+
#Returns the height of the element in pixels
|
181
|
+
def height
|
182
|
+
@automation_element.current.bounding_rectangle.height.to_i
|
183
|
+
end
|
184
|
+
|
185
|
+
#Returns the width of the element in pixels
|
186
|
+
def width
|
187
|
+
@automation_element.current.bounding_rectangle.width.to_i
|
188
|
+
end
|
189
|
+
|
180
190
|
private
|
181
191
|
|
182
192
|
#Raises an exception if this element no longer exists
|
data/lib/bewildr/windows.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bewildr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 15
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 10
|
10
|
+
version: 0.1.10
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Nat Ritmeyer
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-02-08 00:00:00 +00:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|