bewildr 0.1.8 → 0.1.9

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/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.8'
13
+ s.version = '0.1.9'
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'
@@ -21,6 +21,7 @@ spec = Gem::Specification.new do |s|
21
21
  s.files = %w(LICENSE README.rdoc Rakefile) + Dir.glob("{bin,lib}/**/*")
22
22
  s.require_path = "lib"
23
23
  s.bindir = "bin"
24
+ s.add_dependency('activesupport', '>= 3.0.0')
24
25
  end
25
26
 
26
27
  Rake::GemPackageTask.new(spec) do |p|
@@ -11,6 +11,7 @@ load_assembly 'UIAutomationClient, Version=3.0.0.0, Culture=neutral, PublicKeyTo
11
11
  load_assembly 'UIAutomationTypes, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
12
12
  load_assembly 'System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
13
13
  load_assembly 'System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
14
+ load_assembly 'WindowsBase, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
14
15
 
15
16
  #require BewildrClickr - stopgap until the ffi gem works under ironruby
16
17
  require File.join(File.expand_path(File.dirname(__FILE__)), "bewildr", "ext", "BewildrClickr.dll")
@@ -18,6 +19,8 @@ CLICKR = Bewildr::Clickr::Clickr.new
18
19
 
19
20
  #load plain old ruby libraries
20
21
  require 'timeout'
22
+ require 'singleton'
23
+ require 'active_support/core_ext/string/inflections'
21
24
 
22
25
  #require ruby extensions
23
26
  require 'bewildr/ext/extensions'
@@ -30,6 +33,7 @@ require 'bewildr/finder'
30
33
  require 'bewildr/application'
31
34
  require 'bewildr/windows'
32
35
  require 'bewildr/element'
36
+ require 'bewildr/mouse'
33
37
 
34
38
  require 'bewildr/control_patterns/window_pattern'
35
39
  require 'bewildr/control_patterns/value_pattern'
@@ -1,35 +1,52 @@
1
1
  #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
2
 
3
3
  module Bewildr
4
+ #Wraps System::Diagnostics::Process object and provides class methods to interrogate currently running
5
+ #processes, attach to processes or start new ones
4
6
  class Application
7
+ #Returns a new instance of Bewildr::Application that wraps the process passed as the argument
5
8
  def initialize(proc)
6
9
  @proc = proc
7
10
  @proc.wait_for_input_idle(10)
8
- @proc_id = proc.id
9
11
  end
10
12
  private :initialize
11
13
 
14
+ #Returns the id of the underlying process
15
+ def proc_id
16
+ running? ? @proc.id.to_i : nil
17
+ end
18
+
19
+ #Return the name of the underlying process
20
+ def name
21
+ running? ? @proc.process_name.to_s : nil
22
+ end
23
+
24
+ #kills this process. Uses taskkill to perform the butchery
12
25
  def kill
13
- `taskkill /f /t /pid #{@proc_id}`
26
+ `taskkill /f /t /pid #{proc_id}`
14
27
  Timeout::timeout(5) do
15
28
  sleep 0.1 while running?
16
29
  end
17
30
  end
18
31
 
32
+ #Returns true if this process is running, false if it isn't
19
33
  def running?
20
34
  @proc.nil? ? false : !@proc.has_exited
21
35
  end
22
36
 
37
+ #Waits for up to 30 seconds for the process to terminate
23
38
  def wait_for_termination
24
39
  Timeout::timeout(30) do
25
40
  sleep 0.2 while running?
26
41
  end
27
42
  end
28
43
 
44
+ #Returns a list of windows associated with this application
29
45
  def windows
30
- Bewildr::Windows.windows_by_process_id(@proc_id)
46
+ Bewildr::Windows.windows_by_process_id(proc_id)
31
47
  end
32
48
 
49
+ #Returns a window whose title matches the string or regex passed in as the argument
33
50
  def window_by_name(input)
34
51
  case input
35
52
  when String then return windows.select{|window| window.name.strip == input.strip}.first
@@ -40,6 +57,9 @@ module Bewildr
40
57
  end
41
58
  alias :window :window_by_name
42
59
 
60
+ #Waits for up to 30 seconds for a window belonging to this application to appear. When it does, a
61
+ #Bewildr::Element representing the window is returned. This method allows you in one line to wait
62
+ #for a window to appear and also return it
43
63
  def wait_for_window(input, wait_time = 30)
44
64
  begin
45
65
  Timeout::timeout(wait_time) do
@@ -57,12 +77,15 @@ module Bewildr
57
77
  end
58
78
  end
59
79
 
60
- #takes name or full path of exe to start
80
+ #Returns a new instance of Bewildr::Application wrapping the process created when the specified exe file is invoked.
81
+ # Application.start("notepad.exe")
82
+ # Application.start("c:\some\path\my_app.exe")
61
83
  def self.start(process_name)
62
84
  raise "Can't find: #{process_name}" unless File.exist?(process_name)
63
85
  Bewildr::Application.new(System::Diagnostics::Process.start(process_name))
64
86
  end
65
87
 
88
+ #Same as the start method but allows the passing of arguments
66
89
  def self.start_with_settings(path_to_exe, settings_hash)
67
90
  start_info = System::Diagnostics::ProcessStartInfo.new(path_to_exe)
68
91
  unless settings_hash[:args].nil? and settings_hash[:args].size > 0
@@ -71,14 +94,18 @@ module Bewildr
71
94
  Bewildr::Application.new(System::Diagnostics::Process.start(start_info))
72
95
  end
73
96
 
97
+ #Returns a Bewildr::Application wrapping a process already in memory where the argument is the process name
74
98
  def self.attach_to_process_name(process_name)
75
99
  Bewildr::Application.new(System::Diagnostics::Process.get_processes_by_name(process_name).first)
76
100
  end
77
101
 
102
+ #Returns a Bewildr::Application wrapping a process already in memory where the argument is the process object to be wrapped
78
103
  def self.attach_to_process(process)
79
104
  Bewildr::Application.new(process)
80
105
  end
81
106
 
107
+ #Given an exe name/path this method will return a new Bewildr::Application based either on a process already in memory
108
+ #or the process started by executing the app at the path specified in the argument
82
109
  def self.attach_or_launch(path_to_exe)
83
110
  #if app is already open attach to it
84
111
  potential_process_name = File.basename(path_to_exe, ".exe")
@@ -91,12 +118,15 @@ module Bewildr
91
118
  end
92
119
  end
93
120
 
121
+ #Starts the app specified in the first argument and then waits and returns the window that matches the
122
+ #string or regex passed as the second argument
94
123
  def self.start_app_and_wait_for_window(path, window_name)
95
124
  app = Bewildr::Application.start(path)
96
125
  window = app.wait_for_window(window_name)
97
126
  return app, window
98
127
  end
99
128
 
129
+ #Kills all processes that match the name passed as an argument
100
130
  def self.kill_all_processes_with_name(input)
101
131
  System::Diagnostics::Process.get_processes_by_name(input).each do |p|
102
132
  p.kill
@@ -104,10 +134,14 @@ module Bewildr
104
134
  end
105
135
  end
106
136
 
137
+ #Returns an array of Bewildr::Application instances wrapping processes whose name match the string
138
+ #passed as an argument
107
139
  def self.processes_with_name(input)
108
140
  System::Diagnostics::Process.get_processes_by_name(input).collect {|p| Bewildr::Application.attach_to_process(p) }
109
141
  end
110
142
 
143
+ #Waits for and eventually returns a Bewildr::Application wrapping the process whose name matches
144
+ #the string passed as an argument
111
145
  def self.wait_for_process_with_name(input)
112
146
  Timeout.timeout(30) {sleep 0.1 until System::Diagnostics::Process.get_processes_by_name(input).size > 0}
113
147
  self.attach_to_process_name(input)
@@ -32,8 +32,12 @@ module Bewildr
32
32
  state
33
33
  end
34
34
  when :button
35
- def toggle(value)
36
- set_state_to(value)
35
+ def toggle_on
36
+ set_state_to(:on)
37
+ end
38
+
39
+ def toggle_off
40
+ set_state_to(:off)
37
41
  end
38
42
 
39
43
  def toggle_state
@@ -49,7 +49,7 @@ module Bewildr
49
49
  raise "Index must be 0 or greater" if input < 0
50
50
  begin
51
51
  expand_combo
52
- my_item = list_items[input].select
52
+ list_items[input].select
53
53
  ensure
54
54
  collapse_combo
55
55
  end
@@ -43,10 +43,11 @@ module Bewildr
43
43
 
44
44
  def select_by_index(input)
45
45
  raise "Index must be 0 or greater" if input < 0
46
- my_item = list_items[input].select
46
+ list_items[input].select
47
47
  end
48
48
 
49
49
  def selected
50
+ return nil if get_selection.empty?
50
51
  get_selection.first.name
51
52
  end
52
53
  end
@@ -23,7 +23,7 @@ module Bewildr
23
23
  end
24
24
 
25
25
  def page_down_to_bottom_of_scroll_bar
26
- scroll_down_one_page while vertical_scroll_percent < 100.0
26
+ scroll_down_one_page while vertical_scroll_percent < 99.99
27
27
  end
28
28
  end
29
29
  end
@@ -1,10 +1,14 @@
1
1
  #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
2
 
3
3
  module Bewildr
4
+ #All MS UI Automation elements accessed using bewildr are represented as instances of Bewildr::Element.
4
5
  class Element
5
6
  attr_reader :automation_element
6
7
  attr_reader :control_type
7
8
 
9
+ #Returns a new instance of Bewildr::Element wrapping the MS UI Automation Element passed in as an
10
+ #argument. You probably won't be calling this method directly - if you are then you probably know
11
+ #what your'e doing
8
12
  def initialize(input)
9
13
  @automation_element = input
10
14
  case input
@@ -17,16 +21,19 @@ module Bewildr
17
21
  end
18
22
  end
19
23
 
24
+ #Returns the underlying automation element's name property
20
25
  def name
21
26
  existence_check
22
27
  @automation_element.current.name.to_s
23
28
  end
24
29
 
30
+ #Returns the underlying automation element's automation id property
25
31
  def automation_id
26
32
  existence_check
27
33
  @automation_element.current.automation_id.to_s
28
34
  end
29
35
 
36
+ #Returns true if the element exists, false if it doesn't
30
37
  def exists?
31
38
  return false if @control_type == :non_existent
32
39
  begin
@@ -38,21 +45,26 @@ module Bewildr
38
45
  end
39
46
  alias :exist? :exists?
40
47
 
48
+ #Returns true if the element is visible, false if it isn't
41
49
  def visible?
42
50
  existence_check
43
51
  !@automation_element.current.is_offscreen
44
52
  end
45
53
 
54
+ #Returns true if this element has a descendant that meets the search criteria, false if it doesn't
55
+ #Takes a condition hash
46
56
  def contains?(condition_hash)
47
57
  get(condition_hash).exists?
48
58
  end
49
59
  alias :contain? :contains?
50
60
 
61
+ #Returns true if the underlying automation element is enabled, false if it's not
51
62
  def enabled?
52
63
  existence_check
53
64
  @automation_element.current.is_enabled
54
65
  end
55
66
 
67
+ #Waits up to 30 seconds for a descendant of this element to exist that meets the search criteria
56
68
  def wait_for_existence_of(condition_hash)
57
69
  Timeout.timeout(30) do
58
70
  sleep 0.1 until contains?(condition_hash)
@@ -60,26 +72,31 @@ module Bewildr
60
72
  get(condition_hash)
61
73
  end
62
74
 
75
+ #Waits for up to 30 seconds for this element to no longer have a descendant element that meest the criteria
63
76
  def wait_for_non_existence_of(condition_hash)
64
77
  Timeout.timeout(30) do
65
78
  sleep 0.1 unless contains?(condition_hash)
66
79
  end
67
80
  end
68
81
 
82
+ #Gives this element focus
69
83
  def focus
70
84
  @automation_element.set_focus
71
85
  end
72
86
 
87
+ #Returns true if this element is scrollable, false if it isn't.
73
88
  def scrollable?
74
89
  return false unless @automation_element.get_supported_patterns.collect {|pattern| pattern.programmatic_name.to_s }.include?("ScrollPatternIdentifiers.Pattern")
75
90
  vertically_scrollable
76
91
  end
77
92
 
78
- #:id => "id"
79
- #:name => "bob"
80
- #:type => :button
81
- #:scope => :children / :descendants
82
- #:how_many => :first / :all
93
+ #Returns the result of searching this element's children or descendants for the first or all matches of
94
+ #a particular id, name or type (or combination!). See Bewildr::Finder for more details
95
+ # :id => "id"
96
+ # :name => "bob"
97
+ # :type => :button
98
+ # :scope => :children / :descendants
99
+ # :how_many => :first / :all
83
100
  def get(condition_hash)
84
101
  existence_check
85
102
  condition = Finder.condition_for(condition_hash)
@@ -99,12 +116,12 @@ module Bewildr
99
116
  end
100
117
  end
101
118
 
102
- #add "children/child" and "descendants/descendant" methods
103
-
119
+ #Returns true if this element is the root element of the UI element tree
104
120
  def root?
105
121
  @automation_element == System::Windows::Automation::AutomationElement.root_element
106
122
  end
107
123
 
124
+ #Returns a new element representing this element's parent in the UI element tree
108
125
  def parent
109
126
  return nil if root?
110
127
  walker = System::Windows::Automation::TreeWalker.RawViewWalker
@@ -112,11 +129,13 @@ module Bewildr
112
129
  Bewildr::Element.new(potential_parent)
113
130
  end
114
131
 
132
+ #Returns true if this element has descendants, false if it doesn't
115
133
  def has_children?
116
134
  walker = System::Windows::Automation::TreeWalker.RawViewWalker
117
135
  !walker.get_first_child(@automation_element).nil?
118
136
  end
119
137
 
138
+ #Returns an array containing this element's (direct) children
120
139
  def children
121
140
  return [] unless has_children?
122
141
  walker = System::Windows::Automation::TreeWalker.ControlViewWalker #RawViewWalker
@@ -129,24 +148,22 @@ module Bewildr
129
148
  bewildred_children
130
149
  end
131
150
 
151
+ #Clicks this element - this is done by actual mouse moves and clicks. The automation element's underlying InvokePattern is not used.
132
152
  def click
133
- CLICKR.click(clickable_point)
153
+ Bewildr::Mouse.click(clickable_point)
134
154
  end
135
155
 
156
+ #Double clicks this element - this is done by actual mouse moves and clicks. The automation element's underlying InvokePattern is not used.
136
157
  def double_click
137
- CLICKR.double_click(clickable_point)
158
+ Bewildr::Mouse.double_click(clickable_point)
138
159
  end
139
160
 
161
+ #Right clicks this element - this is done by actual mouse moves and clicks. The automation element's underlying InvokePattern is not used.
140
162
  def right_click
141
- CLICKR.right_click(clickable_point)
142
- end
143
-
144
- private
145
-
146
- def existence_check
147
- raise Bewildr::ElementDoesntExist unless exists?
163
+ Bewildr::Mouse.right_click(clickable_point)
148
164
  end
149
165
 
166
+ #Returns the underlying automation element's clickable point property - this is used by the various click methods
150
167
  def clickable_point
151
168
  existence_check
152
169
  Timeout.timeout(30) do
@@ -160,14 +177,24 @@ module Bewildr
160
177
  end
161
178
  end
162
179
 
180
+ private
181
+
182
+ #Raises an exception if this element no longer exists
183
+ def existence_check
184
+ raise Bewildr::ElementDoesntExist unless exists?
185
+ end
186
+
187
+ #Used to add scrollability to an element if it becomes scrollable subsequent to its initial discovery
163
188
  def prepare_element
164
189
  load_all_items_hack if scrollable?
165
190
  end
166
191
 
192
+ #Figures out this element's control type
167
193
  def set_control_type
168
194
  @control_type = Bewildr::ControlType.symbol_for_enum(@automation_element.current.control_type)
169
195
  end
170
196
 
197
+ #Mixes in bewildr control patterns dynamically based on what patterns the underlying automation element has
171
198
  def build_element
172
199
  @automation_element.get_supported_patterns.each do |pattern|
173
200
  pattern_name = pattern.programmatic_name.to_s.gsub(/Identifiers\.Pattern/, "")
@@ -176,22 +203,15 @@ module Bewildr
176
203
  end
177
204
  end
178
205
 
206
+ #Adds control type addition modules to this element based on the underlying automation element's control type.
179
207
  #list of control types comes from http://msdn.microsoft.com/en-us/library/ms750574.aspx
180
208
  def include_additions
181
- case @control_type
182
- when :combo_box then extend Bewildr::ControlTypeAdditions::ComboBoxAdditions
183
- when :data_grid then extend Bewildr::ControlTypeAdditions::DataGridAdditions
184
- when :document then extend Bewildr::ControlTypeAdditions::DocumentAdditions
185
- when :hyperlink then extend Bewildr::ControlTypeAdditions::TextAdditions
186
- when :list then extend Bewildr::ControlTypeAdditions::ListAdditions
187
- when :menu then extend Bewildr::ControlTypeAdditions::MenuAdditions
188
- when :menu_item then extend Bewildr::ControlTypeAdditions::MenuItemAdditions
189
- when :tab then extend Bewildr::ControlTypeAdditions::TabAdditions
190
- when :text then extend Bewildr::ControlTypeAdditions::TextAdditions
191
- when :tree then extend Bewildr::ControlTypeAdditions::TreeAdditions
192
- when :tree_item then extend Bewildr::ControlTypeAdditions::TreeItemAdditions
193
- when :window then extend Bewildr::ControlTypeAdditions::WindowAdditions
194
- end
209
+ #the following looks like could have performance issues, but the tests don't take any longer to execute...
210
+ potential_addition = Bewildr::ControlTypeAdditions.submodules.select {|mod| mod.name.demodulize == "#{@control_type.to_s.classify}Additions"}.first
211
+ extend potential_addition unless potential_addition.nil?
212
+
213
+ #non-standards - move this to another method in the near future
214
+ extend Bewildr::ControlTypeAdditions::TextAdditions if @control_type == :hyperlink
195
215
 
196
216
  #add scrolling capability if relevant - TODO: this ugliness will be fixed later
197
217
  if @automation_element.get_supported_patterns.collect {|pattern| pattern.programmatic_name.to_s }.include?("ScrollPatternIdentifiers.Pattern")
@@ -1,10 +1,20 @@
1
1
  #Copyright (c) 2010, Nathaniel Ritmeyer. All rights reserved.
2
2
 
3
3
  module Bewildr
4
+ #Wraps the Search Condition paradigm used by MS UI Automation to find objects in the UI Element tree. It contains various
5
+ #methods that build up the parts needed for to search for elements. These methods are called by Bewildr::Element#get in
6
+ #order to get and test for existence of descendent elements in the UI element tree. All of the methods take a condition
7
+ #hash, this is made up of at least one, but can be several key/value pairs.
4
8
  class Finder
5
9
  extend Bewildr::BewildrHelpers
6
10
 
7
11
  class << self
12
+ #Returns a System::Windows::Automation::PropertyCondition or AndCondition based on a translation of the condition hash.
13
+ #The condition hash must contain at least one of the following keys:
14
+ # :id => "some id"
15
+ # :name => "some name"
16
+ # :type => :some_control_type
17
+ #These keys can be combined to create more complex search criteria
8
18
  def condition_for(condition_hash)
9
19
  conditions = condition_hash.select {|key, value| [:id, :name, :type].include?(key) }
10
20
  conditions = Hash[*conditions.flatten]
@@ -15,6 +25,11 @@ module Bewildr
15
25
  end
16
26
  end
17
27
 
28
+ #Returns whether the seach should interrogate only children, or all descendants. If neither is specified, the default
29
+ #is to search the descendants. The condition hash should contain one of the following options:
30
+ # :scope => :children
31
+ # :scope => :descendants
32
+ # nothing
18
33
  def scope_for(condition_hash)
19
34
  case condition_hash[:scope]
20
35
  when :children then System::Windows::Automation::TreeScope.Children
@@ -22,7 +37,12 @@ module Bewildr
22
37
  end
23
38
  end
24
39
 
25
- #returns the method to call
40
+ #Returns whether the seach should stop at the first element that matches the criteria or whether it should find all
41
+ #elements that match. If neither is specified, the default is to find only the first element that matches. The condition
42
+ #hash should contain one of the following options:
43
+ # :how_many => :first
44
+ # :how_many => :all
45
+ # nothing
26
46
  def how_many_for(condition_hash)
27
47
  case condition_hash[:how_many]
28
48
  when :first, nil then :find_first
@@ -33,12 +53,16 @@ module Bewildr
33
53
 
34
54
  private
35
55
 
56
+ #Used to create an AndCondition that takes into account all of the search conditions. This is done by
57
+ #creating a single condition for each of the conditions and then creating an AndCondition combining
58
+ #the individual search conditions
36
59
  def multiple_conditions(condition_hash)
37
60
  condition_array = []
38
61
  condition_hash.keys.each {|key| condition_array << single_condition({key => condition_hash[key]}) }
39
62
  System::Windows::Automation::AndCondition.new(r_array_to_cs_array_of_conditions(condition_array))
40
63
  end
41
64
 
65
+ #Calls the condition hash's corresponding condition creation method
42
66
  def single_condition(condition_hash)
43
67
  case condition_hash.keys.first
44
68
  when :id then id_condition(condition_hash)
@@ -47,16 +71,19 @@ module Bewildr
47
71
  end
48
72
  end
49
73
 
74
+ #Returns a PropertyCondition when :id has been specified as the condition type
50
75
  def id_condition(condition_hash)
51
76
  value = r_string_to_c_string(condition_hash[:id].to_s)
52
77
  System::Windows::Automation::PropertyCondition.new(System::Windows::Automation::AutomationElement.automation_id_property, value)
53
78
  end
54
79
 
80
+ #Returns a PropertyCondition when :name has been specified as the condition type
55
81
  def name_condition(condition_hash)
56
82
  value = r_string_to_c_string(condition_hash[:name])
57
83
  System::Windows::Automation::PropertyCondition.new(System::Windows::Automation::AutomationElement.name_property, value)
58
84
  end
59
85
 
86
+ #Returns a PropertyCondition when :type has been specified as the condition type
60
87
  def type_condition(condition_hash)
61
88
  value = Bewildr::ControlType.enum_for_symbol(condition_hash[:type])
62
89
  System::Windows::Automation::PropertyCondition.new(System::Windows::Automation::AutomationElement.control_type_property, value)
@@ -0,0 +1,99 @@
1
+ #Represents and gives access to mouse actions. Implemented as a singleton, but accessed through class methods to make the API more contained.
2
+ class Bewildr::Mouse
3
+ include Singleton
4
+
5
+ def initialize
6
+ @clickr = Bewildr::Clickr::Clickr.new
7
+ end
8
+
9
+ #Returns the BewildrClickr instance - don't use!
10
+ def clickr
11
+ @clickr
12
+ end
13
+
14
+ #Clicks the mouse at the supplied point
15
+ def self.click(point)
16
+ instance.clickr.click(point)
17
+ end
18
+
19
+ #Double clicks the mouse at the supplied point
20
+ def self.double_click(point)
21
+ instance.clickr.double_click(point)
22
+ end
23
+
24
+ #Right clicks the mouse at the supplied point
25
+ def self.right_click(point)
26
+ instance.clickr.right_click(point)
27
+ end
28
+
29
+ #Press the left mouse button down at the current point
30
+ def self.left_down
31
+ instance.clickr.left_mouse_button_down
32
+ end
33
+
34
+ #Release the left mouse button
35
+ def self.left_up
36
+ instance.clickr.left_mouse_button_up
37
+ end
38
+
39
+ #Moves the mouse to the supplied point
40
+ def self.move_to(point)
41
+ instance.clickr.set_location(point)
42
+ end
43
+
44
+ #Drags the mouse from one location to another, and optionally, via another! Pass a has containing the following keys:
45
+ # :from
46
+ # :to
47
+ # :via (optional)
48
+ # :wait_at_via_for
49
+ #The value for each of those keys should be either a point or an element apart from :wait_at_via_for which
50
+ #takes seconds (eg: 0.2, 3, etc). If an element is supplied, the drag point will be the element's clickable point
51
+ def self.drag(args)
52
+ raise "Can't drag without a :from key in the hash" unless args.keys.include?(:from)
53
+ raise "Can't drag without a :to key in the hash" unless args.keys.include?(:to)
54
+
55
+ point_from = args[:from]
56
+ point_to = args[:to]
57
+ point_via = args[:via]
58
+ args[:wait_at_via_for].nil? ? wait_time = 2 : wait_time = args[:wait_at_via_for]
59
+
60
+ point_from = point_from.clickable_point if point_from.instance_of?(Bewildr::Element)
61
+ point_to = point_to.clickable_point if point_to.instance_of?(Bewildr::Element)
62
+ point_via = point_via.clickable_point if !point_via.nil? && point_via.instance_of?(Bewildr::Element)
63
+
64
+ raise "Supplied :from was not an Element or a Point" unless point_from.class == System::Windows::Point
65
+ raise "Supplied :to was not an Element or a Point" unless point_to.class == System::Windows::Point
66
+ raise "Supplied :via was not an Element or a Point" unless point_via.nil? || point_via.class == System::Windows::Point
67
+
68
+ self.move_to(point_from)
69
+ self.left_down
70
+ sleep 0.2
71
+
72
+ if point_via.instance_of?(System::Windows::Point)
73
+ almost_midway = System::Windows::Point.new
74
+ almost_midway.x = point_via.x + 1
75
+ almost_midway.y = point_via.y + 1
76
+ self.move_to(almost_midway)
77
+ sleep 0.3
78
+ self.move_to(point_via)
79
+ sleep wait_time
80
+ end
81
+
82
+ almost_there = System::Windows::Point.new
83
+ almost_there.x = point_to.x + 1
84
+ almost_there.y = point_to.y + 1
85
+
86
+ self.move_to(almost_there)
87
+ sleep 0.2
88
+ self.move_to(point_to)
89
+ self.left_up
90
+ end
91
+ end
92
+
93
+ =begin
94
+ Methods in BewildrClickr dll that need wrapping here...
95
+
96
+ public void Drag(Point startingLocation, Point targetLocation)
97
+ public void RightMouseButtonDown()
98
+ public void RightMouseButtonUp()
99
+ =end
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: 11
4
+ hash: 9
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 8
10
- version: 0.1.8
9
+ - 9
10
+ version: 0.1.9
11
11
  platform: ruby
12
12
  authors:
13
13
  - Nat Ritmeyer
@@ -15,10 +15,25 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-12-08 00:00:00 +00:00
18
+ date: 2011-01-20 00:00:00 +00:00
19
19
  default_executable:
20
- dependencies: []
21
-
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: activesupport
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 7
30
+ segments:
31
+ - 3
32
+ - 0
33
+ - 0
34
+ version: 3.0.0
35
+ type: :runtime
36
+ version_requirements: *id001
22
37
  description: Test WPF UI apps with IronRuby
23
38
  email: nat@natontesting.com
24
39
  executables: []
@@ -64,6 +79,7 @@ files:
64
79
  - lib/bewildr/ext/BewildrClickr.dll
65
80
  - lib/bewildr/ext/extensions.rb
66
81
  - lib/bewildr/finder.rb
82
+ - lib/bewildr/mouse.rb
67
83
  - lib/bewildr/windows.rb
68
84
  - lib/bewildr.rb
69
85
  has_rdoc: true