win32-autogui 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/.gemfiles +3 -0
  2. data/Gemfile +1 -1
  3. data/Gemfile.lock +5 -10
  4. data/HISTORY.markdown +9 -1
  5. data/LICENSE +1 -1
  6. data/README.markdown +84 -48
  7. data/Rakefile +3 -3
  8. data/TODO.markdown +1 -1
  9. data/VERSION +1 -1
  10. data/examples/quicknote/FormMainU.pas +1 -1
  11. data/examples/quicknote/README.markdown +1 -1
  12. data/examples/quicknote/lib/quicknote.rb +29 -30
  13. data/examples/quicknote/spec/aruba_helper.rb +25 -0
  14. data/examples/quicknote/spec/quicknote/form_about_spec.rb +2 -2
  15. data/examples/quicknote/spec/quicknote/form_main_spec.rb +29 -28
  16. data/examples/quicknote/spec/quicknote/form_splash_spec.rb +1 -1
  17. data/examples/quicknote/spec/spec_helper.rb +1 -21
  18. data/examples/skeleton/README.markdown +4 -4
  19. data/examples/skeleton/features/step_definitions/application_steps.rb +20 -9
  20. data/examples/skeleton/features/support/env.rb +11 -1
  21. data/examples/skeleton/lib/myapp.rb +53 -26
  22. data/examples/skeleton/spec/aruba_helper.rb +25 -0
  23. data/examples/skeleton/spec/myapp/form_about_spec.rb +3 -2
  24. data/examples/skeleton/spec/myapp/form_main_spec.rb +10 -17
  25. data/examples/skeleton/spec/spec_helper.rb +1 -21
  26. data/examples/skeleton/spec/watchr.rb +43 -24
  27. data/features/step_definitions/calculator_steps.rb +1 -1
  28. data/features/support/env.rb +3 -1
  29. data/lib/win32/autogui.rb +6 -4
  30. data/lib/win32/autogui/application.rb +35 -35
  31. data/lib/win32/autogui/input.rb +61 -20
  32. data/lib/win32/autogui/logging.rb +8 -8
  33. data/lib/win32/autogui/window.rb +19 -16
  34. data/lib/win32/autogui/windows/window.rb +1 -1
  35. data/spec/applications/calculator.rb +4 -4
  36. data/spec/aruba_helper.rb +25 -0
  37. data/spec/auto_gui/application_spec.rb +7 -7
  38. data/spec/auto_gui/logging_spec.rb +1 -2
  39. data/spec/auto_gui/window_spec.rb +36 -6
  40. data/spec/basic_gem/aruba_helper_spec.rb +2 -2
  41. data/spec/basic_gem/basic_gem_spec.rb +67 -1
  42. data/spec/basic_gem/gemspec_spec.rb +36 -36
  43. data/spec/spec_helper.rb +1 -21
  44. data/spec/watchr.rb +2 -3
  45. data/win32-autogui.gemspec +11 -11
  46. metadata +11 -8
@@ -0,0 +1,25 @@
1
+ module Aruba
2
+ module Api
3
+
4
+ # @return full path to files in the aruba tmp folder
5
+ def fullpath(filename)
6
+ path = File.expand_path(File.join(current_dir, filename))
7
+ if path.match(/^\/cygdrive/)
8
+ # match /cygdrive/c/path/to and return c:\\path\\to
9
+ path = `cygpath -w #{path}`.chomp
10
+ elsif path.match(/.\:/)
11
+ # match c:/path/to and return c:\\path\\to
12
+ path = path.gsub(/\//, '\\')
13
+ end
14
+ path
15
+ end
16
+
17
+ # @return the contents of "filename" in the aruba tmp folder
18
+ def get_file_contents(filename)
19
+ in_current_dir do
20
+ IO.read(filename)
21
+ end
22
+ end
23
+
24
+ end
25
+ end
@@ -7,6 +7,7 @@
7
7
 
8
8
  before(:all) do
9
9
  @application = Myapp.new
10
+ keystroke(VK_RETURN) if @application.dialog_login(:timeout => 5)
10
11
  end
11
12
 
12
13
  after(:all) do
@@ -17,7 +18,7 @@
17
18
  before(:each) do
18
19
  @application.dialog_about.should be_nil
19
20
  @application.set_focus
20
- keystroke(VK_MENU, VK_H, VK_A)
21
+ keystroke(VK_MENU, VK_H, VK_A)
21
22
  @dialog_about = @application.dialog_about
22
23
  @dialog_about.should_not be_nil
23
24
  @dialog_about.is_window?.should == true
@@ -34,7 +35,7 @@
34
35
 
35
36
  it "should close by hitting return" do
36
37
  @dialog_about.set_focus
37
- keystroke(VK_RETURN)
38
+ keystroke(VK_RETURN)
38
39
  @application.dialog_about.should be_nil
39
40
  end
40
41
 
@@ -8,10 +8,10 @@
8
8
  describe "FormMain" do
9
9
  before(:all) do
10
10
  @application = Myapp.new
11
- FileUtils.rm_rf(current_dir)
12
- #logger.debug "FormMain before(:all)"
13
- #logger.debug "application:\n#{@application.inspect}\n"
14
- #logger.debug "application.combined_text:\n #{@application.combined_text}\n"
11
+ keystroke(VK_RETURN) if @application.dialog_login(:timeout => 5)
12
+ #logger.debug "FormMain before(:all)"
13
+ #logger.debug "application:\n#{@application.inspect}\n"
14
+ #logger.debug "application.combined_text:\n #{@application.combined_text}\n"
15
15
  end
16
16
  before(:each) do
17
17
  @application = Myapp.new unless @application.running?
@@ -20,7 +20,7 @@
20
20
  end
21
21
  after(:all) do
22
22
  if @application.running?
23
- @application.file_exit
23
+ @application.file_exit
24
24
  # still running? force it to close
25
25
  @application.close(:wait_for_close => true)
26
26
  @application.should_not be_running
@@ -28,8 +28,8 @@
28
28
  end
29
29
  after(:each) do
30
30
  if @application.running?
31
- keystroke(VK_N) if @application.message_dialog_confirm || @application.dialog_overwrite_confirm
32
- keystroke(VK_ESCAPE) if @application.error_dialog
31
+ keystroke(VK_N) if @application.dialog_confirm || @application.dialog_overwrite_confirm
32
+ keystroke(VK_ESCAPE) if @application.dialog_error
33
33
  end
34
34
  end
35
35
 
@@ -40,16 +40,9 @@
40
40
  end
41
41
 
42
42
  describe "file exit (VK_MENU, VK_F, VK_X)" do
43
- it "should prompt and save with modified text" do
44
- type_in("anything")
45
- keystroke(VK_MENU, VK_F, VK_X)
46
- @application.message_dialog_confirm.should_not be_nil
47
- @application.main_window.is_window?.should == true
48
- @application.should be_running
49
- end
50
- it "should not prompt to save with unmodified text" do
51
- keystroke(VK_MENU, VK_F, VK_X)
52
- @application.message_dialog_confirm.should be_nil
43
+ it "should exit without prompts" do
44
+ keystroke(VK_MENU, VK_F, VK_X)
45
+ @application.dialog_confirm.should be_nil
53
46
  @application.main_window.is_window?.should == false
54
47
  @application.should_not be_running
55
48
  end
@@ -9,27 +9,7 @@
9
9
  require 'spec'
10
10
  require 'spec/autorun'
11
11
  require 'aruba/api'
12
-
13
- # aruba helpers
14
- #
15
- # @return full path to files in the aruba tmp folder
16
- def fullpath(filename)
17
- path = File.expand_path(File.join(current_dir, filename))
18
- if path.match(/^\/cygdrive/)
19
- # match /cygdrive/c/path/to and return c:\\path\\to
20
- path = `cygpath -w #{path}`.chomp
21
- elsif path.match(/.\:/)
22
- # match c:/path/to and return c:\\path\\to
23
- path = path.gsub(/\//, '\\')
24
- end
25
- path
26
- end
27
- # @return the contents of "filename" in the aruba tmp folder
28
- def get_file_contents(filename)
29
- in_current_dir do
30
- IO.read(filename)
31
- end
32
- end
12
+ require 'aruba_helper'
33
13
 
34
14
  Spec::Runner.configure do |config|
35
15
  config.include Aruba::Api
@@ -7,8 +7,19 @@
7
7
  # $ watchr spec/watchr.rb
8
8
 
9
9
  require 'term/ansicolor'
10
+ require 'rbconfig'
10
11
 
11
- $c = Term::ANSIColor
12
+ WINDOWS = Config::CONFIG['host_os'] =~ /mswin|mingw/i unless defined?(WINDOWS)
13
+ require 'win32/process' if WINDOWS
14
+
15
+ if WINDOWS
16
+ begin
17
+ require 'Win32/Console/ANSI'
18
+ $c = Term::ANSIColor
19
+ rescue LoadError
20
+ STDERR.puts 'WARNING: You must "gem install win32console" (1.2.0 or higher) to get color output on MRI/Windows'
21
+ end
22
+ end
12
23
 
13
24
  def getch
14
25
  state = `stty -g`
@@ -35,14 +46,19 @@ def run(cmd)
35
46
 
36
47
  pid = fork do
37
48
  puts "\n"
38
- print $c.cyan, cmd, $c.clear, "\n"
49
+ if $c
50
+ print $c.cyan, cmd, $c.clear, "\n"
51
+ else
52
+ puts cmd
53
+ end
54
+
39
55
  exec(cmd)
40
56
  end
41
57
  Signal.trap('INT') do
42
58
  puts "sending KILL to pid: #{pid}"
43
59
  Process.kill("KILL", pid)
44
60
  end
45
- Process.waitpid(pid)
61
+ Process.waitpid(pid) if (pid > 0)
46
62
 
47
63
  prompt
48
64
  end
@@ -80,7 +96,6 @@ def run_default_spec
80
96
 
81
97
  def run_all_specs
82
98
  cmd = "spec _1.3.1_ --color --format s #{all_spec_files.join(' ')}"
83
- p cmd
84
99
  run(cmd)
85
100
  end
86
101
 
@@ -95,7 +110,10 @@ def run_last_spec
95
110
  end
96
111
 
97
112
  def prompt
98
- puts "Ctrl-\\ for menu, Ctrl-C to quit"
113
+ menu = "Ctrl-C to quit"
114
+ menu = menu + ", Ctrl-\\ for menu" if Signal.list.include?('QUIT')
115
+
116
+ puts menu
99
117
  end
100
118
 
101
119
  # init
@@ -107,7 +125,7 @@ def prompt
107
125
  # --------------------------------------------------
108
126
  watch( '^features/(.*)\.feature' ) { run_default_cucumber }
109
127
 
110
- #watch( '^bin/(.*)' ) { run_default_cucumber }
128
+ watch( '^bin/(.*)' ) { run_default_cucumber }
111
129
  watch( '^lib/(.*)' ) { run_default_cucumber }
112
130
 
113
131
  watch( '^features/step_definitions/(.*)\.rb' ) { run_default_cucumber }
@@ -119,25 +137,26 @@ def prompt
119
137
  watch( '^lib/(.*)' ) { run_default_spec }
120
138
 
121
139
  # --------------------------------------------------
122
- # Signal Handling
140
+ # Signal Handling (May not be supported on Windows)
123
141
  # --------------------------------------------------
142
+ if Signal.list.include?('QUIT')
143
+ # Ctrl-\
144
+ Signal.trap('QUIT') do
145
+
146
+ puts "\n\nMENU: a = all , f = features s = specs, l = last feature (#{$last_feature ? $last_feature : 'none'}), q = quit\n\n"
147
+ c = getch
148
+ puts c.chr
149
+ if c.chr == "a"
150
+ run_all
151
+ elsif c.chr == "f"
152
+ run_default_cucumber
153
+ elsif c.chr == "s"
154
+ run_all_specs
155
+ elsif c.chr == "q"
156
+ abort("exiting\n")
157
+ elsif c.chr == "l"
158
+ run_last_feature
159
+ end
124
160
 
125
- # Ctrl-\
126
- Signal.trap('QUIT') do
127
-
128
- puts "\n\nMENU: a = all , f = features s = specs, l = last feature (#{$last_feature ? $last_feature : 'none'}), q = quit\n\n"
129
- c = getch
130
- puts c.chr
131
- if c.chr == "a"
132
- run_all
133
- elsif c.chr == "f"
134
- run_default_cucumber
135
- elsif c.chr == "s"
136
- run_all_specs
137
- elsif c.chr == "q"
138
- abort("exiting\n")
139
- elsif c.chr == "l"
140
- run_last_feature
141
161
  end
142
-
143
162
  end
@@ -9,7 +9,7 @@
9
9
  end
10
10
  end
11
11
 
12
- Given /^a GUI application named calculator$/ do
12
+ Given /^a GUI application named calculator$/ do
13
13
  @calculator = Calculator.new
14
14
  @calculator.should be_running
15
15
  end
@@ -1,4 +1,6 @@
1
1
  $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
+ require 'rubygems'
2
3
  require 'win32/autogui'
3
- require 'aruba'
4
4
  require 'spec/expectations'
5
+ require 'aruba'
6
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec/aruba_helper')
data/lib/win32/autogui.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # require all files here
2
+ require 'rbconfig'
2
3
  require 'win32/autogui/logging'
3
4
  require 'win32/autogui/input'
4
5
  require 'win32/autogui/window'
@@ -6,7 +7,7 @@
6
7
 
7
8
  # Master namespace
8
9
  module Autogui
9
-
10
+
10
11
  # Contents of the VERSION file
11
12
  #
12
13
  # Example format: 0.0.1
@@ -19,9 +20,10 @@ def self.version
19
20
  end
20
21
  end
21
22
 
22
- # @return (Boolean) false (nil) or True (Integer)
23
- def self.win32?
24
- RUBY_PLATFORM =~ /mingw|mswin|cygwin/i
23
+ # Platform constants
24
+ unless defined?(Autogui::WINDOWS)
25
+ WINDOWS = Config::CONFIG['host_os'] =~ /mswin|mingw/i
26
+ CYGWIN = Config::CONFIG['host_os'] =~ /cygwin/i
25
27
  end
26
28
 
27
29
  end
@@ -7,15 +7,15 @@
7
7
 
8
8
  module Autogui
9
9
 
10
- # Wrapper class for text portion of the RubyGem win32/clipboard
10
+ # Wrapper class for text portion of the RubyGem win32/clipboard
11
11
  # @see http://github.com/djberg96/win32-clipboard
12
12
  class Clipboard
13
13
 
14
14
  # Clipboard text getter
15
- #
15
+ #
16
16
  # @return [String] clipboard data
17
17
  #
18
- def text
18
+ def text
19
19
  Win32::Clipboard.data
20
20
  end
21
21
 
@@ -29,7 +29,7 @@ def text=(str)
29
29
 
30
30
  end
31
31
 
32
- # The Application class wraps a binary application so
32
+ # The Application class wraps a binary application so
33
33
  # that it can be started and controlled via Ruby. This
34
34
  # class is meant to be subclassed.
35
35
  #
@@ -51,7 +51,7 @@ def text=(str)
51
51
  # end
52
52
  #
53
53
  # def dialog_about
54
- # Autogui::EnumerateDesktopWindows.new.find do |w|
54
+ # Autogui::EnumerateDesktopWindows.new.find do |w|
55
55
  # w.title.match(/About Calculator/) && (w.pid == pid)
56
56
  # end
57
57
  # end
@@ -63,19 +63,19 @@ def text=(str)
63
63
  # end
64
64
  #
65
65
  class Application
66
- include Windows::Process
66
+ include Windows::Process
67
67
  include Windows::Synchronize
68
68
  include Windows::Handle
69
69
  include Autogui::Logging
70
70
 
71
71
  # @return [String] the executable name of the application
72
- attr_accessor :name
73
-
74
- # @return [String] the executable application parameters
75
- attr_accessor :parameters
76
-
72
+ attr_accessor :name
73
+
74
+ # @return [String] the executable application parameters
75
+ attr_accessor :parameters
76
+
77
77
  # @return [String] window title of the application
78
- attr_accessor :title
78
+ attr_accessor :title
79
79
 
80
80
  # @return [Number] the process identifier (PID) returned by Process.create
81
81
  attr_reader :pid
@@ -85,25 +85,25 @@ class Application
85
85
 
86
86
  # @return [Number] the main_window wait timeout in seconds
87
87
  attr_accessor :main_window_timeout
88
-
88
+
89
89
  # @return [Number] the wait timeout in seconds used by Process.create
90
90
  attr_accessor :create_process_timeout
91
-
91
+
92
92
  # @example initialize an application on the path
93
93
  #
94
- # app = Application.new :name => "calc"
94
+ # app = Application.new :name => "calc"
95
95
  #
96
96
  # @example initialize with relative DOS path
97
97
  #
98
- # app = Application.new :name => "binaries\\mybinary.exe"
98
+ # app = Application.new :name => "binaries\\mybinary.exe"
99
99
  #
100
100
  # @example initialize with full DOS path
101
101
  #
102
- # app = Application.new :name => "\\windows\\system32\\calc.exe"
102
+ # app = Application.new :name => "\\windows\\system32\\calc.exe"
103
103
  #
104
104
  # @example initialize with logging to file at the default WARN level (STDOUT logging is the default)
105
105
  #
106
- # app = Application.new :name => "calc", :logger_logfile => 'log/calc.log'
106
+ # app = Application.new :name => "calc", :logger_logfile => 'log/calc.log'
107
107
  #
108
108
  # @example initialize with logging to file at DEBUG level
109
109
  #
@@ -120,7 +120,7 @@ class Application
120
120
  # @option options [String] :name a valid win32 exe name with optional path
121
121
  # @option options [String] :title the application window title, used along with the pid to locate the application main window, defaults to :name
122
122
  # @option options [Number] :parameters command line parameters used by Process.create
123
- # @option options [Number] :create_process_timeout (10) timeout in seconds to wait for the create_process to return
123
+ # @option options [Number] :create_process_timeout (10) timeout in seconds to wait for the create_process to return
124
124
  # @option options [Number] :main_window_timeout (10) timeout in seconds to wait for main_window to appear
125
125
  # @option options [String] :logger_logfile (nil) initialize logger's output filename
126
126
  # @option options [String] :logger_level (Autogui::Logging::WARN) initialize logger's initial level
@@ -142,11 +142,11 @@ def initialize(options = {})
142
142
  logger.level = options[:logger_level] if options[:logger_level]
143
143
 
144
144
  # sanity checks
145
- raise_error 'application name not set' unless name
145
+ raise_error 'application name not set' unless name
146
146
 
147
147
  start
148
148
  end
149
-
149
+
150
150
  # Start up the binary application via Process.create and
151
151
  # set the window focus to the main_window
152
152
  #
@@ -156,7 +156,7 @@ def initialize(options = {})
156
156
  # @return [Number] the pid
157
157
  #
158
158
  def start
159
-
159
+
160
160
  command_line = name
161
161
  command_line = name + ' ' + parameters if parameters
162
162
 
@@ -178,12 +178,12 @@ def start
178
178
  CloseHandle(process_handle)
179
179
  CloseHandle(thread_handle)
180
180
 
181
- raise_error "start command failed on create_process_timeout" if ret == WAIT_TIMEOUT
181
+ raise_error "start command failed on create_process_timeout" if ret == WAIT_TIMEOUT
182
182
  raise_error "start command failed while waiting for idle input, reason unknown" unless (ret == 0)
183
183
  @pid
184
184
  end
185
185
 
186
- # The application main window found by enumerating windows
186
+ # The application main window found by enumerating windows
187
187
  # by title and application pid. This method will keep looking
188
188
  # unit main_window_timeout (default: 10s) is exceeded.
189
189
  #
@@ -191,7 +191,7 @@ def start
191
191
  #
192
192
  # @return [Autogui::Window]
193
193
  # @see initialize for options
194
- #
194
+ #
195
195
  def main_window
196
196
  return @main_window if @main_window
197
197
 
@@ -202,10 +202,10 @@ def main_window
202
202
  timeout(main_window_timeout) do
203
203
  begin
204
204
  # There may be multiple instances, use title and pid to id our main window
205
- @main_window = Autogui::EnumerateDesktopWindows.new.find do |w|
206
- w.title.match(title) && w.pid == pid
205
+ @main_window = Autogui::EnumerateDesktopWindows.new.find do |w|
206
+ w.title.match(title) && w.pid == pid
207
207
  end
208
- sleep 0.1
208
+ sleep 0.1
209
209
  end until @main_window
210
210
  end
211
211
 
@@ -238,14 +238,14 @@ def running?
238
238
  end
239
239
 
240
240
  # Set the application input focus to the main_window
241
- #
241
+ #
242
242
  # @return [Number] nonzero number if sucess, nil or zero if failed
243
- #
243
+ #
244
244
  def set_focus
245
- main_window.set_focus if running?
245
+ main_window.set_focus if running?
246
246
  end
247
247
 
248
- # The main_window text including all child windows
248
+ # The main_window text including all child windows
249
249
  # joined together with newlines. Faciliates matching text.
250
250
  #
251
251
  # @example partial match of the Window's calulator's about dialog copywrite text
@@ -257,7 +257,7 @@ def set_focus
257
257
  # @return [String] with newlines
258
258
  #
259
259
  def combined_text
260
- main_window.combined_text if running?
260
+ main_window.combined_text if running?
261
261
  end
262
262
 
263
263
  # @example set the clipboard text and paste it with Control-V
@@ -265,10 +265,10 @@ def combined_text
265
265
  # @calculator.edit_window.set_focus
266
266
  # @calculator.clipboard.text = "12345"
267
267
  # @calculator.edit_window.text.strip.should == "0."
268
- # keystroke(VK_CONTROL, VK_V)
268
+ # keystroke(VK_CONTROL, VK_V)
269
269
  # @calculator.edit_window.text.strip.should == "12,345."
270
270
  #
271
- # @return [Clipboard]
271
+ # @return [Clipboard]
272
272
  #
273
273
  def clipboard
274
274
  @clipboard || Autogui::Clipboard.new