bewildr 0.1.8 → 0.1.9

Sign up to get free protection for your applications and to get access to all the features.
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