rautomation 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.rdoc CHANGED
@@ -1,3 +1,9 @@
1
+ === Version 0.4.0 / 2010-12-23
2
+
3
+ * allow to search windows without text (like empty Notepad window for example).
4
+ * added possibility to use block for #click to specify successful clicking condition.
5
+ * renamed :ffi adapter to :win_ffi because FFI may be used on other platforms too.
6
+
1
7
  === Version 0.3.0 / 2010-12-18
2
8
 
3
9
  * added Ffi adapter specific method Window#child which searches for child windows and popups
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.4.0
File without changes
@@ -27,7 +27,7 @@ module RAutomation
27
27
  extract(locators)
28
28
  end
29
29
 
30
- # @see RAutomation::Button#click
30
+ # @see RAutomation::Button#click
31
31
  def click
32
32
  clicked = false
33
33
  wait_until do
@@ -37,7 +37,7 @@ module RAutomation
37
37
  Window.autoit.ControlClick(@window.locator_hwnd, "", @locators) == 1 &&
38
38
  clicked = true # is clicked at least once
39
39
 
40
- clicked && !exists?
40
+ block_given? ? yield : clicked && !exists?
41
41
  end
42
42
  end
43
43
 
@@ -53,4 +53,4 @@ module RAutomation
53
53
  end
54
54
  end
55
55
  end
56
- end
56
+ end
@@ -51,11 +51,11 @@ module RAutomation
51
51
  end
52
52
 
53
53
  # Retrieves handle of the window.
54
- # @note Searches only for visible windows with having some text at all.
54
+ # @note Searches only for visible windows.
55
55
  # @see RAutomation::Window#hwnd
56
56
  def hwnd
57
57
  @hwnd ||= @@autoit.WinList(@locators, @locator_text).pop.compact.
58
- find {|handle| w = self.class.new(:hwnd => handle.hex); w.visible? && !w.text.empty?}.
58
+ find {|handle| self.class.new(:hwnd => handle.hex).visible?}.
59
59
  hex rescue nil
60
60
  end
61
61
 
@@ -165,4 +165,4 @@ module RAutomation
165
165
  end
166
166
  end
167
167
  end
168
- end
168
+ end
@@ -1,7 +1,7 @@
1
1
  module RAutomation
2
2
  module Adapter
3
3
  autoload :Autoit, File.dirname(__FILE__) + "/autoit.rb"
4
- autoload :Ffi, File.dirname(__FILE__) + "/ffi.rb"
4
+ autoload :WinFfi, File.dirname(__FILE__) + "/win_ffi.rb"
5
5
 
6
6
  module Helper
7
7
  extend self
@@ -11,7 +11,7 @@ module RAutomation
11
11
  def default_adapter
12
12
  case RUBY_PLATFORM
13
13
  when /mswin|msys|mingw32/
14
- :ffi
14
+ :win_ffi
15
15
  else
16
16
  raise "unsupported platform for RAutomation: #{RUBY_PLATFORM}"
17
17
  end
@@ -0,0 +1,12 @@
1
+ begin
2
+ gem "ffi", "0.6.3"
3
+ rescue Gem::LoadError
4
+ raise Gem::LoadError, "Unable to load FFI gem. Install it with:\n\tgem install ffi -v 0.6.3"
5
+ end
6
+ require "ffi"
7
+ require File.dirname(__FILE__) + "/win_ffi/constants"
8
+ require File.dirname(__FILE__) + "/win_ffi/functions"
9
+ require File.dirname(__FILE__) + "/win_ffi/locators"
10
+ require File.dirname(__FILE__) + "/win_ffi/window"
11
+ require File.dirname(__FILE__) + "/win_ffi/button"
12
+ require File.dirname(__FILE__) + "/win_ffi/text_field"
@@ -1,6 +1,6 @@
1
1
  module RAutomation
2
2
  module Adapter
3
- module Ffi
3
+ module WinFfi
4
4
  class Button
5
5
  include WaitHelper
6
6
  include Locators
@@ -29,7 +29,8 @@ module RAutomation
29
29
  Functions.set_control_focus(hwnd) &&
30
30
  Functions.control_click(hwnd) &&
31
31
  clicked = true # is clicked at least once
32
- clicked && !exists?
32
+
33
+ block_given? ? yield : clicked && !exists?
33
34
  end
34
35
  end
35
36
 
@@ -46,4 +47,4 @@ module RAutomation
46
47
  end
47
48
  end
48
49
  end
49
- end
50
+ end
@@ -1,6 +1,6 @@
1
1
  module RAutomation
2
2
  module Adapter
3
- module Ffi
3
+ module WinFfi
4
4
  # @private
5
5
  module Constants
6
6
  WM_GETTEXT = 0xD
@@ -1,6 +1,6 @@
1
1
  module RAutomation
2
2
  module Adapter
3
- module Ffi
3
+ module WinFfi
4
4
  # @private
5
5
  module Functions
6
6
  extend FFI::Library
@@ -90,8 +90,7 @@ module RAutomation
90
90
 
91
91
  def window_hwnd(locators)
92
92
  find_hwnd(locators) do |hwnd|
93
- window_visible(hwnd) && !window_text(hwnd).empty? &&
94
- locators_match?(locators, window_properties(hwnd, locators))
93
+ window_visible(hwnd) && locators_match?(locators, window_properties(hwnd, locators))
95
94
  end
96
95
  end
97
96
 
@@ -246,4 +245,4 @@ module RAutomation
246
245
  end
247
246
  end
248
247
  end
249
- end
248
+ end
@@ -1,6 +1,6 @@
1
1
  module RAutomation
2
2
  module Adapter
3
- module Ffi
3
+ module WinFfi
4
4
  # @private
5
5
  module Locators
6
6
 
@@ -1,6 +1,6 @@
1
1
  module RAutomation
2
2
  module Adapter
3
- module Ffi
3
+ module WinFfi
4
4
  class TextField
5
5
  include WaitHelper
6
6
  include Locators
@@ -1,6 +1,6 @@
1
1
  module RAutomation
2
2
  module Adapter
3
- module Ffi
3
+ module WinFfi
4
4
  class Window
5
5
  include WaitHelper
6
6
  include Locators
@@ -26,7 +26,7 @@ module RAutomation
26
26
  end
27
27
 
28
28
  # Retrieves handle of the window.
29
- # @note Searches only for visible windows with having some text at all.
29
+ # @note Searches only for visible windows.
30
30
  # @see RAutomation::Window#hwnd
31
31
  def hwnd
32
32
  @hwnd ||= Functions.window_hwnd(@locators)
@@ -134,7 +134,10 @@ module RAutomation
134
134
  end
135
135
 
136
136
  # Creates the child window object.
137
- # @note This is an Ffi adapter specific method, not part of the public API
137
+ # @note This is an WinFfi adapter specific method, not part of the public API
138
+ # @example
139
+ # RAutomation::Window.new(:title => /Windows Internet Explorer/i).
140
+ # child(:title => /some popup/)
138
141
  # @param (see Window#initialize)
139
142
  # @return [RAutomation::Window] child window, popup or regular window.
140
143
  def child(locators)
@@ -144,4 +147,4 @@ module RAutomation
144
147
  end
145
148
  end
146
149
  end
147
- end
150
+ end
@@ -8,11 +8,19 @@ module RAutomation
8
8
  @button = @window.button(@locators)
9
9
  end
10
10
 
11
- # Performs a click on the Button.
11
+ # Performs a click on the button.
12
+ # By default click is considered successful if the button doesn't exist after clicking (e.g. window has closed)
13
+ # @yield [button] optional block specifying successful clicking condition.
14
+ # @yieldparam [Button] button which is being clicked on.
15
+ # @yieldreturn [Boolean] true if clicking on the button is successful, false otherwise.
12
16
  # @raise [UnknownButtonException] if the button doesn't exist.
13
17
  def click
14
18
  wait_until_exists
15
- @button.click
19
+ if block_given?
20
+ @button.click {yield self}
21
+ else
22
+ @button.click
23
+ end
16
24
  end
17
25
 
18
26
  # Retrieves the value (text) of the button, usually the visible text.
@@ -34,9 +42,9 @@ module RAutomation
34
42
  private
35
43
 
36
44
  def wait_until_exists
37
- WaitHelper.wait_until(RAutomation::Window.wait_timeout) {exists?}
45
+ WaitHelper.wait_until {exists?}
38
46
  rescue WaitHelper::TimeoutError
39
47
  raise UnknownButtonException, "Button #{@locators.inspect} doesn't exist on window #{@window.locators.inspect}!"
40
48
  end
41
49
  end
42
- end
50
+ end
@@ -42,9 +42,9 @@ module RAutomation
42
42
  private
43
43
 
44
44
  def wait_until_exists
45
- WaitHelper.wait_until(RAutomation::Window.wait_timeout) {exists?}
45
+ WaitHelper.wait_until {exists?}
46
46
  rescue WaitHelper::TimeoutError
47
47
  raise UnknownTextFieldException, "Text field #{@locators.inspect} doesn't exist on window #{@window.locators.inspect}!" unless exists?
48
48
  end
49
49
  end
50
- end
50
+ end
@@ -8,7 +8,7 @@ module RAutomation
8
8
 
9
9
  # @private
10
10
  # Wait until the block evaluates to true or times out.
11
- def wait_until(timeout = 60, &block)
11
+ def wait_until(timeout = Window.wait_timeout, &block)
12
12
  end_time = ::Time.now + timeout
13
13
 
14
14
  until ::Time.now > end_time
@@ -20,4 +20,4 @@ module RAutomation
20
20
  raise TimeoutError, "timed out after #{timeout} seconds"
21
21
  end
22
22
  end
23
- end
23
+ end
@@ -37,8 +37,8 @@ module RAutomation
37
37
  # It is also possible to change the default adapter by using environment variable called
38
38
  # __RAUTOMATION_ADAPTER__
39
39
  #
40
- # @note This constructor doesn't ensure window's existance.
41
- # @note Window to be searched for has to be visible.
40
+ # @note This constructor doesn't check for window's existance.
41
+ # @note Only visible Windows are supported.
42
42
  # @param [Hash] locators for the window.
43
43
  def initialize(locators)
44
44
  @adapter = locators.delete(:adapter) || ENV["RAUTOMATION_ADAPTER"] && ENV["RAUTOMATION_ADAPTER"].to_sym || default_adapter
@@ -191,7 +191,7 @@ module RAutomation
191
191
  private
192
192
 
193
193
  def wait_until_exists
194
- WaitHelper.wait_until(RAutomation::Window.wait_timeout) {exists?}
194
+ WaitHelper.wait_until {exists?}
195
195
  rescue WaitHelper::TimeoutError
196
196
  raise UnknownWindowException, "Window with locator #{@window.locators.inspect} doesn't exist!" unless exists?
197
197
  end
@@ -201,4 +201,4 @@ module RAutomation
201
201
  end
202
202
 
203
203
  end
204
- end
204
+ end
data/rautomation.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{rautomation}
8
- s.version = "0.3.0"
8
+ s.version = "0.4.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Jarmo Pertman"]
12
- s.date = %q{2010-12-18}
12
+ s.date = %q{2010-12-23}
13
13
  s.description = %q{RAutomation is a small and easy to use library for helping out to automate windows and their controls
14
14
  for automated testing.
15
15
 
@@ -35,25 +35,26 @@ RAutomation provides:
35
35
  "VERSION",
36
36
  "ext/AutoItX/AutoItX.chm",
37
37
  "ext/AutoItX/AutoItX3.dll",
38
- "lib/rautomation.rb",
38
+ "lib/RAutomation.rb",
39
39
  "lib/rautomation/adapter/autoit.rb",
40
40
  "lib/rautomation/adapter/autoit/button.rb",
41
41
  "lib/rautomation/adapter/autoit/locators.rb",
42
42
  "lib/rautomation/adapter/autoit/text_field.rb",
43
43
  "lib/rautomation/adapter/autoit/window.rb",
44
- "lib/rautomation/adapter/ffi.rb",
45
- "lib/rautomation/adapter/ffi/button.rb",
46
- "lib/rautomation/adapter/ffi/constants.rb",
47
- "lib/rautomation/adapter/ffi/functions.rb",
48
- "lib/rautomation/adapter/ffi/locators.rb",
49
- "lib/rautomation/adapter/ffi/text_field.rb",
50
- "lib/rautomation/adapter/ffi/window.rb",
51
44
  "lib/rautomation/adapter/helper.rb",
45
+ "lib/rautomation/adapter/win_ffi.rb",
46
+ "lib/rautomation/adapter/win_ffi/button.rb",
47
+ "lib/rautomation/adapter/win_ffi/constants.rb",
48
+ "lib/rautomation/adapter/win_ffi/functions.rb",
49
+ "lib/rautomation/adapter/win_ffi/locators.rb",
50
+ "lib/rautomation/adapter/win_ffi/text_field.rb",
51
+ "lib/rautomation/adapter/win_ffi/window.rb",
52
52
  "lib/rautomation/button.rb",
53
53
  "lib/rautomation/text_field.rb",
54
54
  "lib/rautomation/wait_helper.rb",
55
55
  "lib/rautomation/window.rb",
56
56
  "rautomation.gemspec",
57
+ "spec/adapter/win_ffi/window_spec.rb",
57
58
  "spec/button_spec.rb",
58
59
  "spec/spec_helper.rb",
59
60
  "spec/test.html",
@@ -66,7 +67,8 @@ RAutomation provides:
66
67
  s.rubygems_version = %q{1.3.7}
67
68
  s.summary = %q{Automate windows and their controls through user-friendly API with Ruby}
68
69
  s.test_files = [
69
- "spec/button_spec.rb",
70
+ "spec/adapter/win_ffi/window_spec.rb",
71
+ "spec/button_spec.rb",
70
72
  "spec/spec_helper.rb",
71
73
  "spec/text_field_spec.rb",
72
74
  "spec/window_spec.rb"
@@ -0,0 +1,20 @@
1
+ require "spec_helper"
2
+
3
+ describe "WinFfi::Window", :if => SpecHelper.adapter == :win_ffi do
4
+ before :all do
5
+ window = RAutomation::Window.new(:title => SpecHelper::DATA[:window1_title])
6
+ RAutomation::WaitHelper.wait_until {window.present?}
7
+
8
+ window = RAutomation::Window.new(:title => SpecHelper::DATA[:window2_title])
9
+ RAutomation::WaitHelper.wait_until {window.present?}
10
+ end
11
+
12
+ it "#child" do
13
+ window = RAutomation::Window.new(:title => /Internet Explorer$/i)
14
+ window.should exist
15
+ child = window.child(:title => SpecHelper::DATA[:window2_title])
16
+ child.should exist
17
+ child.title.should == SpecHelper::DATA[:window2_title]
18
+ child.text.should include(SpecHelper::DATA[:window2_text])
19
+ end
20
+ end
data/spec/button_spec.rb CHANGED
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe RAutomation::Button do
4
4
  it "#button" do
@@ -31,10 +31,29 @@ describe RAutomation::Button do
31
31
  expect {window.button(:value => "non-existent-button").click}.
32
32
  to raise_exception(RAutomation::UnknownButtonException)
33
33
 
34
+ RAutomation::Window.wait_timeout = 60
34
35
  button = window.button(:value => SpecHelper::DATA[:window2_button_text])
35
36
  button.should exist
36
37
  button.click
37
38
  button.should_not exist
38
39
  window.should_not exist
39
40
  end
40
- end
41
+
42
+ it "#click with a block for defining successful click" do
43
+ window = RAutomation::Window.new(:title => SpecHelper::DATA[:window2_title])
44
+ RAutomation::Window.wait_timeout = 5
45
+ button = window.button(:value => SpecHelper::DATA[:window2_button_text])
46
+ expect {button.click {false}}.
47
+ to raise_exception(RAutomation::WaitHelper::TimeoutError)
48
+ button.should_not exist
49
+ window.should_not exist
50
+
51
+ RAutomation::Window.wait_timeout = 10
52
+ window = RAutomation::Window.new(:title => SpecHelper::DATA[:window2_title])
53
+ button = window.button(:value => SpecHelper::DATA[:window2_button_text])
54
+ button.should exist
55
+ button.click {|button| !button.exists? && !window.exists?}
56
+ button.should_not exist
57
+ window.should_not exist
58
+ end
59
+ end
data/spec/spec_helper.rb CHANGED
@@ -42,7 +42,7 @@ module SpecHelper
42
42
  :title_proc => lambda {|win| win.WinGetTitle("[TITLE:Explorer User Prompt]")}
43
43
  },
44
44
  # This adapter needs Windows OS with Internet Explorer installed into 'c:\program files\internet explorer'.
45
- :ffi => {
45
+ :win_ffi => {
46
46
  # Path to some binary, which opens up a window, what can be
47
47
  # minimized, maximized, activated, closed and etc.
48
48
  :window1 => "mspaint",
data/spec/test.html CHANGED
@@ -3,11 +3,13 @@
3
3
  <title>RAutomation testing page</title>
4
4
  <script type="text/javascript">
5
5
  function showPrompt() {
6
- prompt("Where do you want to go today?");
6
+ if (prompt("Where do you want to go today?")) {
7
+ showPrompt();
8
+ }
7
9
  }
8
10
  </script>
9
11
  </head>
10
12
  <body onload="setTimeout(showPrompt, 1000)">
11
13
  <h1>RAutomation testing page</h1>
12
14
  </body>
13
- </html>
15
+ </html>
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe RAutomation::TextField do
4
4
  it "#text_field" do
@@ -50,4 +50,4 @@ describe RAutomation::TextField do
50
50
  field.should exist
51
51
  window.text_field(:class => "non-existent-field").should_not exist
52
52
  end
53
- end
53
+ end
data/spec/window_spec.rb CHANGED
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
1
+ require 'spec_helper'
2
2
 
3
3
  describe RAutomation::Window do
4
4
  before :all do
@@ -102,15 +102,6 @@ describe RAutomation::Window do
102
102
  to raise_exception(RAutomation::UnknownWindowException)
103
103
  end
104
104
 
105
- it "#child", :if => SpecHelper.adapter == :ffi do
106
- window = RAutomation::Window.new(:title => /Windows Internet Explorer/i)
107
- window.should exist
108
- child = window.child(:title => SpecHelper::DATA[:window2_title])
109
- child.should exist
110
- child.title.should == SpecHelper::DATA[:window2_title]
111
- child.text.should include(SpecHelper::DATA[:window2_text])
112
- end
113
-
114
105
  it "#method_missing" do
115
106
  win = RAutomation::Window.new(:title => SpecHelper::DATA[:window2_title])
116
107
  SpecHelper::DATA[:title_proc].call(win).should == SpecHelper::DATA[:window2_title]
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rautomation
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 15
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 3
8
+ - 4
9
9
  - 0
10
- version: 0.3.0
10
+ version: 0.4.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Jarmo Pertman
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-12-18 00:00:00 +02:00
18
+ date: 2010-12-23 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -62,25 +62,26 @@ files:
62
62
  - VERSION
63
63
  - ext/AutoItX/AutoItX.chm
64
64
  - ext/AutoItX/AutoItX3.dll
65
- - lib/rautomation.rb
65
+ - lib/RAutomation.rb
66
66
  - lib/rautomation/adapter/autoit.rb
67
67
  - lib/rautomation/adapter/autoit/button.rb
68
68
  - lib/rautomation/adapter/autoit/locators.rb
69
69
  - lib/rautomation/adapter/autoit/text_field.rb
70
70
  - lib/rautomation/adapter/autoit/window.rb
71
- - lib/rautomation/adapter/ffi.rb
72
- - lib/rautomation/adapter/ffi/button.rb
73
- - lib/rautomation/adapter/ffi/constants.rb
74
- - lib/rautomation/adapter/ffi/functions.rb
75
- - lib/rautomation/adapter/ffi/locators.rb
76
- - lib/rautomation/adapter/ffi/text_field.rb
77
- - lib/rautomation/adapter/ffi/window.rb
78
71
  - lib/rautomation/adapter/helper.rb
72
+ - lib/rautomation/adapter/win_ffi.rb
73
+ - lib/rautomation/adapter/win_ffi/button.rb
74
+ - lib/rautomation/adapter/win_ffi/constants.rb
75
+ - lib/rautomation/adapter/win_ffi/functions.rb
76
+ - lib/rautomation/adapter/win_ffi/locators.rb
77
+ - lib/rautomation/adapter/win_ffi/text_field.rb
78
+ - lib/rautomation/adapter/win_ffi/window.rb
79
79
  - lib/rautomation/button.rb
80
80
  - lib/rautomation/text_field.rb
81
81
  - lib/rautomation/wait_helper.rb
82
82
  - lib/rautomation/window.rb
83
83
  - rautomation.gemspec
84
+ - spec/adapter/win_ffi/window_spec.rb
84
85
  - spec/button_spec.rb
85
86
  - spec/spec_helper.rb
86
87
  - spec/test.html
@@ -121,6 +122,7 @@ signing_key:
121
122
  specification_version: 3
122
123
  summary: Automate windows and their controls through user-friendly API with Ruby
123
124
  test_files:
125
+ - spec/adapter/win_ffi/window_spec.rb
124
126
  - spec/button_spec.rb
125
127
  - spec/spec_helper.rb
126
128
  - spec/text_field_spec.rb
@@ -1,12 +0,0 @@
1
- begin
2
- gem "ffi", "0.6.3"
3
- rescue Gem::LoadError
4
- raise Gem::LoadError, "Unable to load FFI gem. Install it with:\n\tgem install ffi -v 0.6.3"
5
- end
6
- require "ffi"
7
- require File.dirname(__FILE__) + "/ffi/constants"
8
- require File.dirname(__FILE__) + "/ffi/functions"
9
- require File.dirname(__FILE__) + "/ffi/locators"
10
- require File.dirname(__FILE__) + "/ffi/window"
11
- require File.dirname(__FILE__) + "/ffi/button"
12
- require File.dirname(__FILE__) + "/ffi/text_field"