win_gui 0.2.1 → 0.2.3
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/HISTORY +8 -0
- data/VERSION +1 -1
- data/lib/extension.rb +31 -0
- data/lib/win_gui/convenience.rb +15 -11
- data/lib/win_gui/window.rb +41 -43
- data/lib/win_gui.rb +1 -0
- data/spec/extension_spec.rb +64 -0
- data/spec/spec_helper.rb +12 -13
- data/spec/win_gui/convenience_spec.rb +15 -14
- data/spec/win_gui/window_spec.rb +27 -13
- metadata +6 -3
data/HISTORY
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.3
|
data/lib/extension.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
class String
|
2
|
+
# converts one-char string into keyboard-scan 'Virtual key' code
|
3
|
+
# TODO: only letters and numbers convertible so far, need to extend further
|
4
|
+
def to_key
|
5
|
+
unless size == 1
|
6
|
+
raise "Can't convert but a single character: #{self}"
|
7
|
+
end
|
8
|
+
ascii = upcase.unpack('C')[0]
|
9
|
+
# puts "I'm here with #{self}->#{ascii}"
|
10
|
+
case self
|
11
|
+
when 'a'..'z', '0'..'9', ' '
|
12
|
+
[ascii]
|
13
|
+
when 'A'..'Z'
|
14
|
+
[WinGui.const_get(:VK_SHIFT), ascii]
|
15
|
+
when ','
|
16
|
+
[WinGui.const_get(:VK_OEM_COMMA)]
|
17
|
+
when '.'
|
18
|
+
[WinGui.const_get(:VK_OEM_PERIOD)]
|
19
|
+
when ':'
|
20
|
+
[:VK_SHIFT, :VK_OEM_1].map {|s| WinGui.const_get s}
|
21
|
+
when "\\"
|
22
|
+
[WinGui.const_get(:VK_OEM_102)]
|
23
|
+
else
|
24
|
+
raise "Can't convert unknown character: #{self}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_print
|
29
|
+
force_encoding('cp1251').encode(Encoding.default_external, :undef => :replace)
|
30
|
+
end
|
31
|
+
end
|
data/lib/win_gui/convenience.rb
CHANGED
@@ -2,7 +2,7 @@ require 'win/gui'
|
|
2
2
|
|
3
3
|
module WinGui
|
4
4
|
include Win::Gui
|
5
|
-
|
5
|
+
extend Win::Gui
|
6
6
|
|
7
7
|
# Delay between key commands/events (in sec)
|
8
8
|
KEY_DELAY = 0.00001
|
@@ -12,38 +12,42 @@ module WinGui
|
|
12
12
|
CLOSE_TIMEOUT = 1
|
13
13
|
# Default timeout for dialog operations (in sec)
|
14
14
|
LOOKUP_TIMEOUT = 3
|
15
|
+
|
16
|
+
# Window class identifying standard modal dialog window
|
15
17
|
DIALOG_WINDOW_CLASS = '#32770'
|
16
18
|
|
17
|
-
# Module defines convenience methods on top of straightforward Win32 API functions
|
19
|
+
# Module defines convenience methods on top of straightforward Win32 API functions:
|
18
20
|
|
19
21
|
# Finds top-level dialog window by title and yields found dialog window to attached block.
|
20
22
|
# We work with dialog window in a block, and then we wait for it to close before proceeding.
|
21
23
|
# That is, unless your block returns nil, in which case dialog is ignored and method immediately returns nil
|
22
|
-
# If no block is given, method just returns found dialog window or nil
|
23
|
-
def dialog(
|
24
|
-
dialog = Window.top_level(class: DIALOG_WINDOW_CLASS,
|
25
|
-
|
24
|
+
# If no block is given, method just returns found dialog window (or nil if dialog is not found)
|
25
|
+
def dialog(opts={})
|
26
|
+
dialog = Window.top_level( {class: DIALOG_WINDOW_CLASS, timeout: LOOKUP_TIMEOUT}.merge opts )
|
27
|
+
dialog.set_foreground_window if dialog
|
26
28
|
wait = block_given? ? yield(dialog) : false
|
27
29
|
dialog.wait_for_close if dialog && wait
|
28
30
|
dialog
|
29
31
|
end
|
30
32
|
|
31
33
|
# Emulates combinations of (any amount of) keys pressed one after another (Ctrl+Alt+P) and then released
|
32
|
-
# *keys should be a sequence of a virtual-key codes.
|
34
|
+
# *keys should be a sequence of a virtual-key codes. These codes must be a value in the range 1 to 254.
|
33
35
|
# For a complete list, see msdn:Virtual Key Codes.
|
36
|
+
# If alphanumerical char is given instead of virtual key code, only lowercase letters result (no VK_SHIFT!).
|
34
37
|
def keystroke(*keys)
|
35
38
|
return if keys.empty?
|
36
|
-
|
39
|
+
key = String === keys.first ? keys.first.upcase.ord : keys.first.to_i
|
40
|
+
keybd_event key, 0, KEYEVENTF_KEYDOWN, 0
|
37
41
|
sleep KEY_DELAY
|
38
42
|
keystroke *keys[1..-1]
|
39
43
|
sleep KEY_DELAY
|
40
|
-
keybd_event
|
44
|
+
keybd_event key, 0, KEYEVENTF_KEYUP, 0
|
41
45
|
end
|
42
46
|
|
43
|
-
# types text message into window holding the focus
|
47
|
+
# types text message into a window currently holding the focus
|
44
48
|
def type_in(message)
|
45
49
|
message.scan(/./m) do |char|
|
46
|
-
keystroke(*char.
|
50
|
+
keystroke(*char.to_key)
|
47
51
|
end
|
48
52
|
end
|
49
53
|
|
data/lib/win_gui/window.rb
CHANGED
@@ -4,8 +4,8 @@ module WinGui
|
|
4
4
|
class Window
|
5
5
|
# Make convenience methods from both WinGui and Win::Gui available as both class and instance methods
|
6
6
|
# Looks a bit circular though...
|
7
|
-
include WinGui
|
8
|
-
extend WinGui
|
7
|
+
# include WinGui
|
8
|
+
# extend WinGui
|
9
9
|
|
10
10
|
def initialize(handle)
|
11
11
|
@handle = handle
|
@@ -22,46 +22,33 @@ module WinGui
|
|
22
22
|
def self.top_level(opts={})
|
23
23
|
window_title = opts[:title]
|
24
24
|
window_class = opts[:class]
|
25
|
-
timeout = opts[:timeout] # || LOOKUP_TIMEOUT
|
25
|
+
timeout = opts[:timeout] # || LOOKUP_TIMEOUT ? # no timeout by default
|
26
26
|
|
27
27
|
if timeout
|
28
28
|
begin
|
29
29
|
timeout(timeout) do
|
30
|
-
sleep SLEEP_DELAY while (@handle = find_window window_class, window_title) == nil
|
30
|
+
sleep SLEEP_DELAY while (@handle = WinGui.find_window window_class, window_title) == nil
|
31
31
|
end
|
32
32
|
rescue TimeoutError
|
33
33
|
nil
|
34
34
|
end
|
35
35
|
else
|
36
|
-
@handle = find_window window_class, window_title
|
36
|
+
@handle = WinGui.find_window window_class, window_title
|
37
37
|
end
|
38
38
|
Window.new(@handle) if @handle
|
39
39
|
end
|
40
40
|
|
41
|
-
# def self.top_level(title, seconds=10, wnd_class = nil)
|
42
|
-
# @handle = timeout(seconds) do
|
43
|
-
# loop do
|
44
|
-
# h = find_window wnd_class, title
|
45
|
-
# break h if h > 0
|
46
|
-
# sleep 0.3
|
47
|
-
# end
|
48
|
-
# end
|
49
|
-
#
|
50
|
-
# Gui.new @handle
|
51
|
-
# end
|
52
|
-
# end
|
53
|
-
|
54
41
|
# find child window (control) by title, window class, or control ID:
|
55
42
|
def child(id)
|
56
43
|
result = case id
|
57
44
|
when String
|
58
|
-
by_title = find_window_ex
|
59
|
-
by_class = find_window_ex
|
45
|
+
by_title = find_window_ex 0, nil, id.gsub('_', '&' )
|
46
|
+
by_class = find_window_ex 0, id, nil
|
60
47
|
by_title ? by_title : by_class
|
61
48
|
when Fixnum
|
62
|
-
get_dlg_item
|
49
|
+
get_dlg_item id
|
63
50
|
when nil
|
64
|
-
find_window_ex
|
51
|
+
find_window_ex 0, nil, nil
|
65
52
|
else
|
66
53
|
nil
|
67
54
|
end
|
@@ -69,40 +56,51 @@ module WinGui
|
|
69
56
|
Window.new result
|
70
57
|
end
|
71
58
|
|
72
|
-
# returns array of Windows that are descendants (not only
|
59
|
+
# returns array of Windows that are descendants (not only DIRECT children) of a given Window
|
73
60
|
def children
|
74
|
-
enum_child_windows
|
61
|
+
enum_child_windows.map{|child_handle| Window.new child_handle}
|
75
62
|
end
|
76
63
|
|
77
64
|
# emulate click of the control identified by id
|
78
65
|
def click(id)
|
79
|
-
left, top, right, bottom =
|
66
|
+
left, top, right, bottom = child(id).get_window_rect
|
80
67
|
center = [(left + right) / 2, (top + bottom) / 2]
|
81
|
-
set_cursor_pos *center
|
82
|
-
mouse_event MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
|
83
|
-
mouse_event MOUSEEVENTF_LEFTUP, 0, 0, 0, 0
|
84
|
-
end
|
85
|
-
|
86
|
-
def close
|
87
|
-
post_message @handle, WM_SYSCOMMAND, SC_CLOSE, nil
|
68
|
+
WinGui.set_cursor_pos *center
|
69
|
+
WinGui.mouse_event WinGui::MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
|
70
|
+
WinGui.mouse_event WinGui::MOUSEEVENTF_LEFTUP, 0, 0, 0, 0
|
88
71
|
end
|
89
72
|
|
90
|
-
def wait_for_close
|
91
|
-
timeout(
|
92
|
-
sleep SLEEP_DELAY while window_visible?
|
73
|
+
def wait_for_close(timeout =CLOSE_TIMEOUT )
|
74
|
+
timeout(timeout) do
|
75
|
+
sleep SLEEP_DELAY while window_visible?
|
93
76
|
end
|
94
77
|
end
|
95
78
|
|
96
|
-
#
|
97
|
-
|
98
|
-
|
79
|
+
# We alias convenience method shut_window (from Win::Gui::WIndow) with even more convenient
|
80
|
+
# window.close
|
81
|
+
# Please keep in mind that Win32 API has another function CloseWindow that merely MINIMIZES window.
|
82
|
+
# If you want to invoke this function, you can do it like this:
|
83
|
+
# window.close_window
|
84
|
+
def close
|
85
|
+
shut_window
|
99
86
|
end
|
100
87
|
|
101
|
-
# Window
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
88
|
+
# Since Window instances wrap actual window handles, they should support WinGui functions
|
89
|
+
# manipulating these handles. Therefore, when unsupported instance method is invoked, we check if
|
90
|
+
# WinGui responds to such method, and if yes, call it with our window handle as a first argument.
|
91
|
+
# This gives us all handle-related WinGui functions as instance methods for Window instances, like so:
|
92
|
+
# window.visible?
|
93
|
+
# This API is much more Ruby-like compared to:
|
94
|
+
# visible?(window.handle)
|
95
|
+
# Of course, if we unvoke WinGui function that DOESN'T accept handle as a first arg this way, we are screwed.
|
96
|
+
# Call such functions only like this:
|
97
|
+
# WinGui.function(*args)
|
98
|
+
def method_missing(name, *args, &block)
|
99
|
+
if WinGui.respond_to? name
|
100
|
+
WinGui.send(name, @handle, *args, &block)
|
101
|
+
else
|
102
|
+
super
|
103
|
+
end
|
106
104
|
end
|
107
105
|
end
|
108
106
|
end
|
data/lib/win_gui.rb
CHANGED
@@ -0,0 +1,64 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require File.join(File.dirname(__FILE__), "spec_helper" )
|
3
|
+
|
4
|
+
module WinGuiTest
|
5
|
+
|
6
|
+
describe String do
|
7
|
+
describe '#to_key' do
|
8
|
+
it 'transforms number char into [equivalent key code]' do
|
9
|
+
('0'..'9').each {|char| char.to_key.should == char.unpack('C')}
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'transforms uppercase letters into [shift, equivalent key code]' do
|
13
|
+
('A'..'Z').each {|char| char.to_key.should == [0x10, *char.unpack('C')]}
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'transforms lowercase letters into [(upcase) key code]' do
|
17
|
+
('a'..'z').each {|char| char.to_key.should == char.upcase.unpack('C')}
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'transforms space into [equivalent key code]' do
|
21
|
+
' '.to_key.should == " ".unpack('C')
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'transforms .,:\\ into [equivalent key code]' do
|
25
|
+
','.to_key.should == [VK_OEM_COMMA]
|
26
|
+
'.'.to_key.should == [VK_OEM_PERIOD]
|
27
|
+
':'.to_key.should == [VK_SHIFT, VK_OEM_1]
|
28
|
+
"\\".to_key.should == [VK_OEM_102]
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'raises error if char is not implemented punctuation' do
|
32
|
+
('!'..'+').each {|char| lambda {char.to_key}.should raise_error ERROR_CONVERSION }
|
33
|
+
(';'..'@').each {|char| lambda {char.to_key}.should raise_error ERROR_CONVERSION }
|
34
|
+
(']'..'`').each {|char| lambda {char.to_key}.should raise_error ERROR_CONVERSION }
|
35
|
+
('{'..'~').each {|char| lambda {char.to_key}.should raise_error ERROR_CONVERSION }
|
36
|
+
['-', '/', '['].each {|char| lambda {char.to_key}.should raise_error ERROR_CONVERSION }
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'raises error if char is non-printable or non-ascii' do
|
40
|
+
lambda {1.chr.to_key}.should raise_error ERROR_CONVERSION
|
41
|
+
lambda {230.chr.to_key}.should raise_error ERROR_CONVERSION
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'raises error if string is multi-char' do
|
45
|
+
lambda {'hello'.to_key}.should raise_error ERROR_CONVERSION
|
46
|
+
lambda {'23'.to_key}.should raise_error ERROR_CONVERSION
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '#to_print' do
|
51
|
+
it 'converts String from (implied) WinCyrillic (CP1251) to default output encoding' do
|
52
|
+
string = "Широкая электрификация южных губерний даст мощный толчок подъёму сельского хозяйства"
|
53
|
+
win_string = string.encode('cp1251')
|
54
|
+
print_string = win_string.encode(Encoding.default_external, :undef => :replace)
|
55
|
+
win_string_thought_utf8 = win_string.force_encoding('utf-8')
|
56
|
+
win_string_thought_dos = win_string.force_encoding('cp866')
|
57
|
+
|
58
|
+
win_string_thought_utf8.to_print.should == print_string
|
59
|
+
win_string_thought_dos.to_print.should == print_string
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -62,29 +62,28 @@ module WinGuiTest
|
|
62
62
|
|
63
63
|
def launch_test_app
|
64
64
|
system APP_START
|
65
|
-
|
66
|
-
@launched_test_app = Window.new handle
|
65
|
+
@test_app = Window.top_level( title: WIN_TITLE, timeout: 10)
|
67
66
|
|
68
|
-
def @
|
69
|
-
Window.new find_window_ex(self.handle, 0, TEXTAREA_CLASS, nil)
|
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)
|
70
69
|
end
|
71
70
|
|
72
|
-
@
|
71
|
+
@test_app
|
73
72
|
end
|
74
73
|
|
75
|
-
def close_test_app
|
76
|
-
while
|
77
|
-
|
78
|
-
|
74
|
+
def close_test_app
|
75
|
+
while @test_app && find_window(nil, WIN_TITLE)
|
76
|
+
@test_app.close
|
77
|
+
# Dealing with closing confirmation modal dialog
|
78
|
+
keystroke("N") if Window.top_level( title: "Steganos Locknote", timeout: SLEEP_DELAY*5)
|
79
79
|
end
|
80
|
-
@
|
80
|
+
@test_app = nil
|
81
81
|
end
|
82
82
|
|
83
83
|
# Creates test app object and yields it back to the block
|
84
84
|
def test_app
|
85
|
-
|
86
|
-
|
87
|
-
yield app
|
85
|
+
test_app = launch_test_app
|
86
|
+
yield test_app
|
88
87
|
close_test_app
|
89
88
|
end
|
90
89
|
|
@@ -7,18 +7,20 @@ module WinGuiTest
|
|
7
7
|
after(:each) { close_test_app }
|
8
8
|
|
9
9
|
describe '#dialog' do
|
10
|
-
|
11
|
-
|
10
|
+
# Open "Save as" modal dialog
|
11
|
+
before(:each){ keystroke(VK_ALT, 'F', 'A') }
|
12
|
+
# Close modal dialog if it is opened
|
13
|
+
after(:each) { keystroke(VK_ESCAPE) if Window.top_level( title: "Save As", timeout: 0.1) }
|
12
14
|
|
13
15
|
it 'returns top-level dialog window with given title if no block attached' do
|
14
|
-
dialog_window = dialog(DIALOG_TITLE, 0.1)
|
16
|
+
dialog_window = dialog(title: DIALOG_TITLE, timeout: 0.1)
|
15
17
|
dialog_window.should_not == nil
|
16
18
|
dialog_window.should be_a Window
|
17
19
|
dialog_window.text.should == DIALOG_TITLE
|
18
20
|
end
|
19
21
|
|
20
22
|
it 'yields found dialog window to block if block is attached' do
|
21
|
-
dialog(DIALOG_TITLE
|
23
|
+
dialog(title: DIALOG_TITLE) do |dialog_window|
|
22
24
|
dialog_window.should_not == nil
|
23
25
|
dialog_window.should be_a Window
|
24
26
|
dialog_window.text.should == DIALOG_TITLE
|
@@ -26,39 +28,38 @@ module WinGuiTest
|
|
26
28
|
end
|
27
29
|
|
28
30
|
it 'returns nil if there is no dialog with given title' do
|
29
|
-
dialog(IMPOSSIBLE, 0.1).should == nil
|
31
|
+
dialog(title: IMPOSSIBLE, timeout: 0.1).should == nil
|
30
32
|
end
|
31
33
|
|
32
34
|
it 'yields nil to attached block if no dialog found' do
|
33
|
-
dialog(IMPOSSIBLE, 0.1) do |dialog_window|
|
35
|
+
dialog(title: IMPOSSIBLE, timeout: 0.1) do |dialog_window|
|
34
36
|
dialog_window.should == nil
|
35
37
|
end
|
36
38
|
end
|
37
39
|
|
38
|
-
it 'considers
|
39
|
-
dialog_window = dialog(
|
40
|
-
dialog_window.text.should == DIALOG_TITLE
|
40
|
+
it 'considers all arguments optional' do
|
41
|
+
use { dialog_window = dialog() }
|
41
42
|
end
|
42
43
|
end # describe dialog
|
43
44
|
|
44
45
|
describe 'convenience input methods on top of Windows API' do
|
45
46
|
describe '#keystroke' do
|
46
|
-
spec{ use{ keystroke( vkey = 30,
|
47
|
+
spec{ use{ keystroke( vkey = 30, char = 'Z') }}
|
47
48
|
|
48
49
|
it 'emulates combinations of keys pressed (Ctrl+Alt+P+M, etc)' do
|
49
|
-
keystroke(VK_CONTROL, 'A'
|
50
|
+
keystroke(VK_CONTROL, 'A')
|
50
51
|
keystroke(VK_SPACE)
|
51
52
|
@app.textarea.text.should.should == ' '
|
52
|
-
|
53
|
+
keystroke('1', '2', 'A', 'B'.ord)
|
54
|
+
@app.textarea.text.should.should == ' 12ab'
|
53
55
|
end
|
54
56
|
end # describe '#keystroke'
|
55
57
|
|
56
58
|
describe '#type_in' do
|
57
59
|
it 'types text message into the window holding the focus' do
|
58
|
-
text = '
|
60
|
+
text = '1234 abcdefg'
|
59
61
|
type_in(text)
|
60
62
|
@app.textarea.text.should =~ Regexp.new(text)
|
61
|
-
5.times {keystroke(VK_CONTROL, 'Z'.ord)} # rolling back changes to allow window closing without dialog!
|
62
63
|
end
|
63
64
|
end # describe '#type_in'
|
64
65
|
|
data/spec/win_gui/window_spec.rb
CHANGED
@@ -14,20 +14,11 @@ module WinGuiTest
|
|
14
14
|
end
|
15
15
|
|
16
16
|
context 'manipulating' do
|
17
|
-
|
18
17
|
it 'has handle property equal to underlying window handle' do
|
19
18
|
any = Window.new any_handle
|
20
19
|
any.handle.should == any_handle
|
21
20
|
end
|
22
21
|
|
23
|
-
it 'has class_name property' do
|
24
|
-
@app.class_name.should == WIN_CLASS
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'has text property equal to underlying window text(title)' do
|
28
|
-
@app.text.should == WIN_TITLE
|
29
|
-
end
|
30
|
-
|
31
22
|
it 'closes when asked nicely' do
|
32
23
|
@app.close
|
33
24
|
sleep SLEEP_DELAY # needed to ensure window had enough time to close down
|
@@ -44,6 +35,29 @@ module WinGuiTest
|
|
44
35
|
end
|
45
36
|
end
|
46
37
|
|
38
|
+
context 'handle-related WinGui functions as instance methods' do
|
39
|
+
it 'calls all WinGui functions as instance methods (with handle as implicit first argument)' do
|
40
|
+
@app.window?.should == true
|
41
|
+
@app.visible?.should == true
|
42
|
+
@app.foreground?.should == true
|
43
|
+
@app.maximized?.should == false
|
44
|
+
@app.maximized?.should == false
|
45
|
+
@app.child?(any_handle).should == false
|
46
|
+
|
47
|
+
@app.window_rect.should be_an Array
|
48
|
+
@app.window_thread_process_id.should be_an Array
|
49
|
+
@app.enum_child_windows.should be_an Array
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'has class_name and text properties (derived from WinGui function calls)' do
|
53
|
+
@app.class_name.should == WIN_CLASS
|
54
|
+
# window_text propery accessed via GetWindowText
|
55
|
+
@app.window_text.should == WIN_TITLE
|
56
|
+
# text propery accessed by sending WM_GETTEXT directly to window (convenience method in WinGui)
|
57
|
+
@app.text.should == WIN_TITLE
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
47
61
|
describe '.top_level' do
|
48
62
|
it 'finds top-level window by title and wraps it in a Window object' do
|
49
63
|
win = Window.top_level( title: WIN_TITLE, timeout: 1)
|
@@ -68,8 +82,8 @@ module WinGuiTest
|
|
68
82
|
|
69
83
|
it 'returns nil after timeout if top-level window with given title not found' do
|
70
84
|
start = Time.now
|
71
|
-
Window.top_level( title: IMPOSSIBLE, timeout:
|
72
|
-
(Time.now - start).should be_close
|
85
|
+
Window.top_level( title: IMPOSSIBLE, timeout: 0.5).should == nil
|
86
|
+
(Time.now - start).should be_close 0.5, 0.02
|
73
87
|
end
|
74
88
|
end
|
75
89
|
|
@@ -104,13 +118,13 @@ module WinGuiTest
|
|
104
118
|
describe '#children' do
|
105
119
|
spec { use { children = @app.children }}
|
106
120
|
|
107
|
-
it 'returns an array of Windows that are descendants (not only
|
121
|
+
it 'returns an array of Windows that are descendants (not only DIRECT children) of a given Window' do
|
108
122
|
children = @app.children
|
109
123
|
children.should be_a_kind_of Array
|
110
124
|
children.should_not be_empty
|
111
125
|
children.should have(2).elements
|
112
126
|
children.each{|child| child?(@app.handle, child.handle).should == true }
|
113
|
-
|
127
|
+
children.last.class_name.should == TEXTAREA_CLASS
|
114
128
|
end
|
115
129
|
|
116
130
|
# it 'finds child window(control) by name' do
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 2
|
8
|
-
-
|
9
|
-
version: 0.2.
|
8
|
+
- 3
|
9
|
+
version: 0.2.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- arvicco
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-06-03 00:00:00 +04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -68,10 +68,12 @@ extra_rdoc_files:
|
|
68
68
|
- HISTORY
|
69
69
|
- README.rdoc
|
70
70
|
files:
|
71
|
+
- lib/extension.rb
|
71
72
|
- lib/version.rb
|
72
73
|
- lib/win_gui/convenience.rb
|
73
74
|
- lib/win_gui/window.rb
|
74
75
|
- lib/win_gui.rb
|
76
|
+
- spec/extension_spec.rb
|
75
77
|
- spec/spec.opts
|
76
78
|
- spec/spec_helper.rb
|
77
79
|
- spec/win_gui/convenience_spec.rb
|
@@ -127,6 +129,7 @@ signing_key:
|
|
127
129
|
specification_version: 3
|
128
130
|
summary: Abstractions/wrappers around GUI-related Win32 API functions
|
129
131
|
test_files:
|
132
|
+
- spec/extension_spec.rb
|
130
133
|
- spec/spec.opts
|
131
134
|
- spec/spec_helper.rb
|
132
135
|
- spec/win_gui/convenience_spec.rb
|