win_gui 0.2.10 → 0.2.12
Sign up to get free protection for your applications and to get access to all the features.
- data/HISTORY +8 -0
- data/VERSION +1 -1
- data/lib/win_gui/application.rb +82 -0
- data/lib/win_gui/convenience.rb +1 -1
- data/lib/win_gui/window.rb +6 -5
- data/lib/win_gui.rb +5 -0
- data/spec/spec_helper.rb +4 -16
- data/spec/win_gui/application_spec.rb +105 -0
- data/spec/win_gui/convenience_spec.rb +6 -4
- data/spec/win_gui/window_spec.rb +55 -64
- metadata +18 -4
data/HISTORY
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.12
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module WinGui
|
2
|
+
|
3
|
+
# This class is a wrapper around Windows App
|
4
|
+
class App
|
5
|
+
LAUNCH_TIMEOUT = 0.2
|
6
|
+
|
7
|
+
attr_accessor :main_window # Main App window (top level)
|
8
|
+
|
9
|
+
def initialize(window_or_handle)
|
10
|
+
@main_window = case window_or_handle
|
11
|
+
when Window
|
12
|
+
window_or_handle
|
13
|
+
when Integer
|
14
|
+
Window.new window_or_handle
|
15
|
+
else
|
16
|
+
raise WinGui::Errors::InitError, "Unable to create App from #{window_or_handle.inspect}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def close
|
21
|
+
@main_window.close
|
22
|
+
end
|
23
|
+
alias_method :exit, :close
|
24
|
+
|
25
|
+
class << self
|
26
|
+
# Finds already launched Application. Either title or class for main window is obligatory.
|
27
|
+
# Returns nil if no such Application found.
|
28
|
+
# Options:
|
29
|
+
# :title:: main window title
|
30
|
+
# :class:: main window class
|
31
|
+
# :timeout:: timeout (seconds) finding main window
|
32
|
+
# :raise:: raise this exception instead of returning nil if nothing found
|
33
|
+
#
|
34
|
+
def find(opts)
|
35
|
+
main_window = Window.top_level(opts)
|
36
|
+
# raise WinGui::Errors::InitError, "Unable to find App with #{opts.inspect}" unless main_window
|
37
|
+
main_window ? new(main_window) : nil
|
38
|
+
end
|
39
|
+
|
40
|
+
# Launch new Application. Expects executable path and options to find main Window.
|
41
|
+
# Options:
|
42
|
+
# :path/:app_path:: path to App's executable file
|
43
|
+
# :dir/:cd:: change to this dir before launching App
|
44
|
+
# :title:: main window title
|
45
|
+
# :class:: main window class
|
46
|
+
# :timeout:: timeout (seconds) finding main window
|
47
|
+
# :raise:: raise this exception instead of returning nil if launched app window not found
|
48
|
+
#
|
49
|
+
def launch(opts)
|
50
|
+
app_path = opts.delete(:path) || opts.delete(:app_path)
|
51
|
+
dir_path = opts.delete(:dir) || opts.delete(:cd)
|
52
|
+
|
53
|
+
launch_app app_path, dir_path
|
54
|
+
|
55
|
+
defaults = {timeout: LAUNCH_TIMEOUT,
|
56
|
+
raise: WinGui::Errors::InitError.new("Unable to launch App with #{opts.inspect}")}
|
57
|
+
find(defaults.merge opts)
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def cygwin?
|
63
|
+
RUBY_PLATFORM =~ /cygwin/
|
64
|
+
end
|
65
|
+
|
66
|
+
def launch_app(app_path, dir_path)
|
67
|
+
|
68
|
+
raise WinGui::Errors::InitError, "Unable to launch #{app_path.inspect}" unless File.exists? app_path.to_s
|
69
|
+
command = cygwin? ? "cmd /c start `cygpath -w #{app_path}`" : "start #{app_path.to_s.gsub(/\//, "\\")}"
|
70
|
+
|
71
|
+
if dir_path
|
72
|
+
raise WinGui::Errors::InitError, "Unable to change to #{dir_path.inspect}" unless File.exists? dir_path.to_s
|
73
|
+
command = "cd #{cygwin? ? dir_path : dir_path.to_s.gsub(/\//, "\\")} && #{command}"
|
74
|
+
end
|
75
|
+
|
76
|
+
# Launch App in a separate window
|
77
|
+
system command # TODO: make sure only valid commands are fed into system
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/lib/win_gui/convenience.rb
CHANGED
@@ -25,7 +25,7 @@ module WinGui
|
|
25
25
|
|
26
26
|
# Finds top-level dialog window by title and yields found dialog window to attached block.
|
27
27
|
# We work with dialog window in a block, and then we wait for it to close before proceeding.
|
28
|
-
# That is, unless your block returns nil, in which case dialog is ignored and method immediately returns nil.
|
28
|
+
# That is, unless your block returns nil, in which case dialog is ignored (and method immediately returns nil?).
|
29
29
|
# If no block is given, method just returns found dialog window (or nil if dialog is not found).
|
30
30
|
# Options:
|
31
31
|
# :title:: dialog title
|
data/lib/win_gui/window.rb
CHANGED
@@ -41,7 +41,8 @@ module WinGui
|
|
41
41
|
lookup_window(opts) { WinGui.find_window opts[:class], opts[:title] }
|
42
42
|
end
|
43
43
|
|
44
|
-
# Finds
|
44
|
+
# Finds child window (control) by either control ID or window class/title.
|
45
|
+
# By default, only direct children are searched.
|
45
46
|
# Options:
|
46
47
|
# :id:: integer control id (such as IDOK, IDCANCEL, etc)
|
47
48
|
# :title:: window title
|
@@ -158,13 +159,13 @@ module WinGui
|
|
158
159
|
# window.visible?
|
159
160
|
# This API is much more Ruby-like compared to:
|
160
161
|
# visible?(window.handle)
|
161
|
-
# Of course, if we
|
162
|
+
# Of course, if we invoke WinGui function that DOESN'T accept handle as a first arg this way, we are screwed.
|
162
163
|
# Call such functions only like this:
|
163
164
|
# WinGui.function(*args)
|
164
165
|
# TODO: Such setup is problematic if WinGui is included into Window ancestor chain.
|
165
|
-
# TODO:
|
166
|
-
# TODO:
|
167
|
-
# TODO: instead of showing off cool meta-programming skillz.
|
166
|
+
# TODO: In this case, all WinGui functions become available as instance methods, and method_missing never fires.
|
167
|
+
# TODO: It may be a better solution to explicitly define all needed instance methods,
|
168
|
+
# TODO: instead of showing off cool meta-programming skillz. ;-)
|
168
169
|
#
|
169
170
|
def method_missing(name, *args, &block)
|
170
171
|
if WinGui.respond_to? name
|
data/lib/win_gui.rb
CHANGED
@@ -18,6 +18,11 @@ module WinGui
|
|
18
18
|
Pathname.glob(name.to_s).sort.each {|rb| require rb}
|
19
19
|
end
|
20
20
|
end
|
21
|
+
|
22
|
+
module Errors # :nodoc:
|
23
|
+
class InitError < RuntimeError # :nodoc:
|
24
|
+
end
|
25
|
+
end
|
21
26
|
end # module WinGui
|
22
27
|
|
23
28
|
# Require all ruby source files located under directory lib/win_gui
|
data/spec/spec_helper.rb
CHANGED
@@ -30,14 +30,9 @@ module WinGuiTest
|
|
30
30
|
KEY_DELAY = 0.001
|
31
31
|
SLEEP_DELAY = 0.01
|
32
32
|
APP_PATH = File.join(File.dirname(__FILE__), "../misc/locknote/LockNote.exe" )
|
33
|
-
APP_START = RUBY_PLATFORM =~ /cygwin/ ? "cmd /c start `cygpath -w #{APP_PATH}`" : "start #{APP_PATH}"
|
34
|
-
# 'start "" "' + APP_PATH + '"'
|
35
33
|
DIALOG_TITLE = "Save As"
|
36
34
|
WIN_TITLE = 'LockNote - Steganos LockNote'
|
37
35
|
WIN_CLASS = 'ATL:00434098'
|
38
|
-
WIN_RECT = [710, 400, 1210, 800]
|
39
|
-
MAX_RECT = [-4, -4, 1924, 1204] # on my 1920x1200 display
|
40
|
-
MIN_RECT = [-32000, -32000, -31840, -31976]
|
41
36
|
TEXTAREA_CLASS = 'ATL:00434310'
|
42
37
|
STATUSBAR_CLASS = 'msctls_statusbar32'
|
43
38
|
IMPOSSIBLE = 'Impossible'
|
@@ -61,18 +56,12 @@ module WinGuiTest
|
|
61
56
|
end
|
62
57
|
|
63
58
|
def launch_test_app
|
64
|
-
system APP_START
|
65
|
-
@test_app =
|
66
|
-
|
67
|
-
def @test_app.textarea #define singleton method retrieving app's text area
|
68
|
-
Window.new WinGui::find_window_ex(self.handle, 0, TEXTAREA_CLASS, nil)
|
69
|
-
end
|
70
|
-
|
71
|
-
@test_app
|
59
|
+
#system APP_START
|
60
|
+
@test_app = App.launch( path: APP_PATH, title: WIN_TITLE, timeout: 1)
|
72
61
|
end
|
73
62
|
|
74
63
|
def close_test_app
|
75
|
-
|
64
|
+
while @test_app && @test_app.main_window.window?
|
76
65
|
@test_app.close
|
77
66
|
# Dealing with closing confirmation modal dialog
|
78
67
|
if dialog = dialog( title: "Steganos Locknote", timeout: SLEEP_DELAY)
|
@@ -85,8 +74,7 @@ module WinGuiTest
|
|
85
74
|
|
86
75
|
# Creates test app object and yields it back to the block
|
87
76
|
def test_app
|
88
|
-
|
89
|
-
yield test_app
|
77
|
+
yield launch_test_app
|
90
78
|
close_test_app
|
91
79
|
end
|
92
80
|
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "spec_helper" )
|
2
|
+
|
3
|
+
module WinGuiTest
|
4
|
+
|
5
|
+
describe App do
|
6
|
+
after(:each) do # Reliably closes launched app window (without calling close_test_app)
|
7
|
+
app = App.find(title: WIN_TITLE)
|
8
|
+
app.exit if app
|
9
|
+
end
|
10
|
+
|
11
|
+
context 'initializing' do
|
12
|
+
context '::new' do
|
13
|
+
before(:each) { launch_test_app }
|
14
|
+
after(:each){ close_test_app }
|
15
|
+
|
16
|
+
it 'wraps new App around existing Window' do
|
17
|
+
window = Window.top_level(title: WIN_TITLE)
|
18
|
+
@app = App.new(window)
|
19
|
+
@app.should be_an App
|
20
|
+
@app.main_window.should == window
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'wraps new App around active window handle (of top-level Window)' do
|
24
|
+
window = Window.top_level(title: WIN_TITLE)
|
25
|
+
@app = App.new(window.handle)
|
26
|
+
@app.should be_an App
|
27
|
+
@app.main_window.handle.should == window.handle
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'raises error trying to create App with wrong init args' do
|
31
|
+
expect{ App.new() }.to raise_error ArgumentError, /wrong number of arguments/
|
32
|
+
[[nil], 1.2, {title: WIN_TITLE}].each do |args|
|
33
|
+
expect{ App.new(*args) }.to raise_error WinGui::Errors::InitError
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context '::find' do
|
39
|
+
before(:each) { launch_test_app }
|
40
|
+
after(:each){ close_test_app }
|
41
|
+
|
42
|
+
it 'finds already launched App given valid Window info' do
|
43
|
+
use{ @app = App.find(title: WIN_TITLE) }
|
44
|
+
@app.should be_an App
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'returns nil if asked to find App with invalid Window info' do
|
48
|
+
App.find(title: IMPOSSIBLE).should == nil
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'raises error only if asked to find App with invalid Window info and :raise option is set' do
|
52
|
+
expect{ App.find(title: IMPOSSIBLE, raise: WinGui::Errors::InitError) }.
|
53
|
+
to raise_error WinGui::Errors::InitError
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context '::launch' do
|
58
|
+
|
59
|
+
it 'launches new App given valid path and Window info' do
|
60
|
+
use{ @app = App.launch(path: APP_PATH, title: WIN_TITLE) }
|
61
|
+
@app.should be_an App
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'raises error if asked to launch App with invalid path' do
|
65
|
+
expect{ App.launch(path: IMPOSSIBLE, title: WIN_TITLE) }.
|
66
|
+
to raise_error WinGui::Errors::InitError, /Unable to launch "Impossible"/
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'raises error if asked to launch App with invalid Window info' do
|
70
|
+
expect{ App.launch(path: APP_PATH, title: IMPOSSIBLE) }.
|
71
|
+
to raise_error WinGui::Errors::InitError, /Unable to launch App with .*?:title=>"Impossible"/
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'properties:' do
|
77
|
+
before(:each) { @app = App.launch(path: APP_PATH, title: WIN_TITLE) }
|
78
|
+
after(:each) { @app.close }
|
79
|
+
|
80
|
+
it 'main_window' do
|
81
|
+
@app.main_window.should be_a Window
|
82
|
+
@app.main_window.title.should == WIN_TITLE
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'manipulating' do
|
88
|
+
before(:each) {@app = App.launch(path: APP_PATH, title: WIN_TITLE)}
|
89
|
+
|
90
|
+
it 'exits App gracefully' do
|
91
|
+
@app.exit
|
92
|
+
sleep SLEEP_DELAY # needed to ensure window had enough time to close down
|
93
|
+
@app.main_window.visible?.should == false
|
94
|
+
@app.main_window.window?.should == false
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'closes App gracefully' do
|
98
|
+
@app.close
|
99
|
+
sleep SLEEP_DELAY # needed to ensure window had enough time to close down
|
100
|
+
@app.main_window.visible?.should == false
|
101
|
+
@app.main_window.window?.should == false
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -3,7 +3,7 @@ require File.join(File.dirname(__FILE__), "..", "spec_helper" )
|
|
3
3
|
module WinGuiTest
|
4
4
|
|
5
5
|
describe 'Convenience methods' do
|
6
|
-
before(:each){ @
|
6
|
+
before(:each){ @win = launch_test_app.main_window }
|
7
7
|
after(:each) { close_test_app }
|
8
8
|
|
9
9
|
describe '#dialog' do
|
@@ -54,9 +54,10 @@ module WinGuiTest
|
|
54
54
|
it 'emulates combinations of keys pressed (Ctrl+Alt+P+M, etc)' do
|
55
55
|
keystroke(VK_CONTROL, 'A')
|
56
56
|
keystroke(VK_SPACE)
|
57
|
-
|
57
|
+
textarea = @win.child(class: TEXTAREA_CLASS)
|
58
|
+
textarea.text.should.should == ' '
|
58
59
|
keystroke('1', '2', 'A', 'B'.ord)
|
59
|
-
|
60
|
+
textarea.text.should.should == ' 12ab'
|
60
61
|
end
|
61
62
|
end # describe '#keystroke'
|
62
63
|
|
@@ -64,7 +65,8 @@ module WinGuiTest
|
|
64
65
|
it 'types text message into the window holding the focus' do
|
65
66
|
text = '1234 abcdefg'
|
66
67
|
type_in(text)
|
67
|
-
|
68
|
+
textarea = @win.child(class: TEXTAREA_CLASS)
|
69
|
+
textarea.text.should =~ Regexp.new(text)
|
68
70
|
end
|
69
71
|
end # describe '#type_in'
|
70
72
|
|
data/spec/win_gui/window_spec.rb
CHANGED
@@ -3,7 +3,7 @@ require File.join(File.dirname(__FILE__), "..", "spec_helper" )
|
|
3
3
|
module WinGuiTest
|
4
4
|
|
5
5
|
describe Window do
|
6
|
-
before(:each) { @
|
6
|
+
before(:each) { @win = launch_test_app.main_window }
|
7
7
|
after(:each){ close_test_app }
|
8
8
|
|
9
9
|
context 'initializing' do
|
@@ -15,33 +15,33 @@ module WinGuiTest
|
|
15
15
|
|
16
16
|
context 'manipulating' do
|
17
17
|
it 'closes when asked nicely' do
|
18
|
-
@
|
18
|
+
@win.close
|
19
19
|
sleep SLEEP_DELAY # needed to ensure window had enough time to close down
|
20
20
|
find_window(nil, WIN_TITLE).should == nil
|
21
21
|
end
|
22
22
|
|
23
23
|
it 'waits for window to disappear (NB: this happens before handle is released!)' do
|
24
24
|
start = Time.now
|
25
|
-
@
|
26
|
-
@
|
25
|
+
@win.close
|
26
|
+
@win.wait_for_close
|
27
27
|
(Time.now - start).should be <= CLOSE_TIMEOUT
|
28
|
-
window_visible?(@
|
29
|
-
window?(@
|
28
|
+
window_visible?(@win.handle).should be false
|
29
|
+
window?(@win.handle).should be false
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
33
|
context 'handle-related WinGui functions as instance methods' do
|
34
34
|
it 'calls all WinGui functions as instance methods (with handle as implicit first argument)' do
|
35
|
-
@
|
36
|
-
@
|
37
|
-
@
|
38
|
-
@
|
39
|
-
@
|
40
|
-
@
|
41
|
-
|
42
|
-
@
|
43
|
-
@
|
44
|
-
@
|
35
|
+
@win.window?.should == true
|
36
|
+
@win.visible?.should == true
|
37
|
+
@win.foreground?.should == true
|
38
|
+
@win.maximized?.should == false
|
39
|
+
@win.minimized?.should == false
|
40
|
+
@win.child?(any_handle).should == false
|
41
|
+
|
42
|
+
@win.window_rect.should be_an Array
|
43
|
+
@win.window_thread_process_id.should be_an Array
|
44
|
+
@win.enum_child_windows.should be_an Array
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
@@ -52,52 +52,52 @@ module WinGuiTest
|
|
52
52
|
end
|
53
53
|
|
54
54
|
it 'has class_name and text/title properties (derived from WinGui function calls)' do
|
55
|
-
@
|
55
|
+
@win.class_name.should == WIN_CLASS
|
56
56
|
# text propery accessed by sending WM_GETTEXT directly to window (convenience method in WinGui)
|
57
|
-
@
|
57
|
+
@win.text.should == WIN_TITLE
|
58
58
|
# window_text propery accessed via GetWindowText
|
59
|
-
@
|
59
|
+
@win.window_text.should == WIN_TITLE
|
60
60
|
# title property is just an alias for window_text
|
61
|
-
@
|
61
|
+
@win.title.should == WIN_TITLE
|
62
62
|
end
|
63
63
|
|
64
64
|
it 'has thread and process properties derived from get_window_thread_process_id' do
|
65
|
-
thread = @
|
66
|
-
process = @
|
67
|
-
[thread, process].should == get_window_thread_process_id(@
|
65
|
+
thread = @win.thread
|
66
|
+
process = @win.process
|
67
|
+
[thread, process].should == get_window_thread_process_id(@win.handle)
|
68
68
|
end
|
69
69
|
|
70
70
|
it 'has id property that only makes sense for controls' do
|
71
|
-
use{ @
|
71
|
+
use{ @win.id }
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
75
|
-
describe '
|
75
|
+
describe '::top_level' do
|
76
76
|
it 'finds top-level window by title and wraps it in a Window object' do
|
77
|
-
|
78
|
-
|
77
|
+
window = Window.top_level( title: WIN_TITLE, timeout: 1)
|
78
|
+
window.handle.should == @win.handle
|
79
79
|
end
|
80
80
|
|
81
81
|
it 'finds top-level window by class and wraps it in a Window object' do
|
82
|
-
|
83
|
-
|
82
|
+
window = Window.top_level( class: WIN_CLASS, timeout: 1)
|
83
|
+
window.handle.should == @win.handle
|
84
84
|
end
|
85
85
|
|
86
86
|
it 'finds ANY top-level window without args and wraps it in a Window object' do
|
87
|
-
use { @
|
88
|
-
|
87
|
+
use { @window = Window.top_level() }
|
88
|
+
@window.should be_a Window
|
89
89
|
end
|
90
90
|
|
91
91
|
it 'returns nil immediately if top-level window with given title not found' do
|
92
92
|
start = Time.now
|
93
93
|
Window.top_level( title: IMPOSSIBLE).should == nil
|
94
|
-
(Time.now - start).should be_close 0, 0.
|
94
|
+
(Time.now - start).should be_close 0, 0.03
|
95
95
|
end
|
96
96
|
|
97
97
|
it 'returns nil after timeout if top-level window with given title not found' do
|
98
98
|
start = Time.now
|
99
|
-
Window.top_level( title: IMPOSSIBLE, timeout: 0.
|
100
|
-
(Time.now - start).should be_close 0.
|
99
|
+
Window.top_level( title: IMPOSSIBLE, timeout: 0.3).should == nil
|
100
|
+
(Time.now - start).should be_close 0.3, 0.03
|
101
101
|
end
|
102
102
|
|
103
103
|
it 'raises exception if asked to' do
|
@@ -106,42 +106,40 @@ module WinGuiTest
|
|
106
106
|
end # describe .top_level
|
107
107
|
|
108
108
|
describe '#child' do
|
109
|
-
spec { use { @child = @
|
109
|
+
spec { use { @child = @win.child(title: "Title", class: "Class", id: 0) }}
|
110
110
|
|
111
111
|
it 'returns nil immediately if specific child not found' do
|
112
112
|
start = Time.now
|
113
|
-
@
|
114
|
-
(Time.now - start).should be_close 0, 0.
|
113
|
+
@win.child( title: IMPOSSIBLE).should == nil
|
114
|
+
(Time.now - start).should be_close 0, 0.03
|
115
115
|
end
|
116
116
|
|
117
117
|
it 'returns nil after timeout if specific child not found' do
|
118
118
|
start = Time.now
|
119
|
-
@
|
120
|
-
(Time.now - start).should be_close 0.5, 0.
|
119
|
+
@win.child( title: IMPOSSIBLE, timeout: 0.5).should == nil
|
120
|
+
(Time.now - start).should be_close 0.5, 0.03
|
121
121
|
end
|
122
122
|
|
123
123
|
it 'finds ANY child window without args' do
|
124
|
-
use { @child = @
|
124
|
+
use { @child = @win.child() }
|
125
125
|
@child.should_not == nil
|
126
|
-
@
|
126
|
+
@win.child?(@child.handle).should == true
|
127
127
|
end
|
128
128
|
|
129
129
|
it 'finds child window by class and returns it as a Window object (no timeout)' do
|
130
|
-
child = @
|
130
|
+
child = @win.child( class: TEXTAREA_CLASS)
|
131
131
|
child.should_not == nil
|
132
|
-
@
|
132
|
+
@win.child?(child.handle).should == true
|
133
133
|
end
|
134
134
|
|
135
135
|
it 'finds child window by class and returns it as a Window object (with timeout)' do
|
136
|
-
|
137
|
-
# p @app.find_window_ex(0, STATUSBAR_CLASS, nil)
|
138
|
-
child = @app.child( class: TEXTAREA_CLASS, timeout: 0.5)
|
136
|
+
child = @win.child( class: TEXTAREA_CLASS, timeout: 0.5)
|
139
137
|
child.should_not == nil
|
140
138
|
|
141
|
-
@
|
142
|
-
child = @
|
139
|
+
@win.child?(child.handle).should == true
|
140
|
+
child = @win.child( class: STATUSBAR_CLASS, timeout: 0.5)
|
143
141
|
child.should_not == nil
|
144
|
-
@
|
142
|
+
@win.child?(child.handle).should == true
|
145
143
|
end
|
146
144
|
|
147
145
|
it 'finds child with specific text and returns it as a Window object' do
|
@@ -169,19 +167,19 @@ module WinGuiTest
|
|
169
167
|
|
170
168
|
context 'indirect child' do
|
171
169
|
it 'returns nil if specified child not found' do
|
172
|
-
@
|
170
|
+
@win.child( title: IMPOSSIBLE, indirect: true).should == nil
|
173
171
|
end
|
174
172
|
|
175
173
|
it 'finds ANY child window without other args' do
|
176
|
-
use { @child = @
|
174
|
+
use { @child = @win.child(indirect: true) }
|
177
175
|
@child.should_not == nil
|
178
|
-
@
|
176
|
+
@win.child?(@child.handle).should == true
|
179
177
|
end
|
180
178
|
|
181
179
|
it 'finds child window by class' do
|
182
|
-
child = @
|
180
|
+
child = @win.child( class: TEXTAREA_CLASS, indirect: true)
|
183
181
|
child.should_not == nil
|
184
|
-
@
|
182
|
+
@win.child?(child.handle).should == true
|
185
183
|
end
|
186
184
|
|
187
185
|
it 'finds child with specific text' do
|
@@ -210,26 +208,19 @@ module WinGuiTest
|
|
210
208
|
end # describe child
|
211
209
|
|
212
210
|
describe '#children' do
|
213
|
-
spec { use { children = @
|
211
|
+
spec { use { children = @win.children }}
|
214
212
|
|
215
213
|
it 'returns an array of Windows that are descendants (not only DIRECT children) of a given Window' do
|
216
|
-
children = @
|
214
|
+
children = @win.children
|
217
215
|
children.should be_a_kind_of Array
|
218
216
|
children.should_not be_empty
|
219
217
|
children.should have(2).elements
|
220
|
-
children.each{|child| child?(@
|
218
|
+
children.each{|child| child?(@win.handle, child.handle).should == true }
|
221
219
|
children.last.class_name.should == TEXTAREA_CLASS
|
222
220
|
end
|
223
221
|
end # describe #children
|
224
222
|
|
225
223
|
describe '#click' do
|
226
|
-
# it 'tests' do
|
227
|
-
# with_dialog(:save) do |dialog|
|
228
|
-
# dialog.children.each{|child| puts "#{child.handle}, #{child.class_name}, #{child.window_text}, #{dialog.child?(child.handle)}"}
|
229
|
-
# true.should == false
|
230
|
-
# end
|
231
|
-
# end
|
232
|
-
|
233
224
|
it 'emulates left click of the control identified by id, returns click coords' do
|
234
225
|
with_dialog(:save) do |dialog|
|
235
226
|
point = dialog.click(id: IDCANCEL)
|
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: win_gui
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
+
hash: 15
|
4
5
|
prerelease: false
|
5
6
|
segments:
|
6
7
|
- 0
|
7
8
|
- 2
|
8
|
-
-
|
9
|
-
version: 0.2.
|
9
|
+
- 12
|
10
|
+
version: 0.2.12
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- arvicco
|
@@ -14,16 +15,18 @@ autorequire:
|
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
17
|
|
17
|
-
date: 2010-
|
18
|
+
date: 2010-10-02 00:00:00 +04:00
|
18
19
|
default_executable:
|
19
20
|
dependencies:
|
20
21
|
- !ruby/object:Gem::Dependency
|
21
22
|
name: rspec
|
22
23
|
prerelease: false
|
23
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
24
26
|
requirements:
|
25
27
|
- - ">="
|
26
28
|
- !ruby/object:Gem::Version
|
29
|
+
hash: 13
|
27
30
|
segments:
|
28
31
|
- 1
|
29
32
|
- 2
|
@@ -35,9 +38,11 @@ dependencies:
|
|
35
38
|
name: cucumber
|
36
39
|
prerelease: false
|
37
40
|
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
38
42
|
requirements:
|
39
43
|
- - ">="
|
40
44
|
- !ruby/object:Gem::Version
|
45
|
+
hash: 3
|
41
46
|
segments:
|
42
47
|
- 0
|
43
48
|
version: "0"
|
@@ -47,9 +52,11 @@ dependencies:
|
|
47
52
|
name: win
|
48
53
|
prerelease: false
|
49
54
|
requirement: &id003 !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
50
56
|
requirements:
|
51
57
|
- - ">="
|
52
58
|
- !ruby/object:Gem::Version
|
59
|
+
hash: 17
|
53
60
|
segments:
|
54
61
|
- 0
|
55
62
|
- 3
|
@@ -70,12 +77,14 @@ extra_rdoc_files:
|
|
70
77
|
files:
|
71
78
|
- lib/extension.rb
|
72
79
|
- lib/version.rb
|
80
|
+
- lib/win_gui/application.rb
|
73
81
|
- lib/win_gui/convenience.rb
|
74
82
|
- lib/win_gui/window.rb
|
75
83
|
- lib/win_gui.rb
|
76
84
|
- spec/extension_spec.rb
|
77
85
|
- spec/spec.opts
|
78
86
|
- spec/spec_helper.rb
|
87
|
+
- spec/win_gui/application_spec.rb
|
79
88
|
- spec/win_gui/convenience_spec.rb
|
80
89
|
- spec/win_gui/window_spec.rb
|
81
90
|
- features/step_definitions/win_gui_steps.rb
|
@@ -108,23 +117,27 @@ rdoc_options:
|
|
108
117
|
require_paths:
|
109
118
|
- lib
|
110
119
|
required_ruby_version: !ruby/object:Gem::Requirement
|
120
|
+
none: false
|
111
121
|
requirements:
|
112
122
|
- - ">="
|
113
123
|
- !ruby/object:Gem::Version
|
124
|
+
hash: 3
|
114
125
|
segments:
|
115
126
|
- 0
|
116
127
|
version: "0"
|
117
128
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
118
130
|
requirements:
|
119
131
|
- - ">="
|
120
132
|
- !ruby/object:Gem::Version
|
133
|
+
hash: 3
|
121
134
|
segments:
|
122
135
|
- 0
|
123
136
|
version: "0"
|
124
137
|
requirements: []
|
125
138
|
|
126
139
|
rubyforge_project: ""
|
127
|
-
rubygems_version: 1.3.
|
140
|
+
rubygems_version: 1.3.7
|
128
141
|
signing_key:
|
129
142
|
specification_version: 3
|
130
143
|
summary: Abstractions/wrappers around GUI-related Win32 API functions
|
@@ -132,5 +145,6 @@ test_files:
|
|
132
145
|
- spec/extension_spec.rb
|
133
146
|
- spec/spec.opts
|
134
147
|
- spec/spec_helper.rb
|
148
|
+
- spec/win_gui/application_spec.rb
|
135
149
|
- spec/win_gui/convenience_spec.rb
|
136
150
|
- spec/win_gui/window_spec.rb
|