win_gui 0.2.0 → 0.2.1
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 +4 -0
- data/VERSION +1 -1
- data/lib/win_gui/convenience.rb +67 -0
- data/lib/win_gui/window.rb +67 -38
- data/spec/spec_helper.rb +10 -9
- data/spec/win_gui/convenience_spec.rb +68 -0
- data/spec/win_gui/window_spec.rb +51 -35
- metadata +6 -3
data/HISTORY
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.1
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'win/gui'
|
2
|
+
|
3
|
+
module WinGui
|
4
|
+
include Win::Gui
|
5
|
+
# extend Win::Gui
|
6
|
+
|
7
|
+
# Delay between key commands/events (in sec)
|
8
|
+
KEY_DELAY = 0.00001
|
9
|
+
# Delay when sleeping (in sec)
|
10
|
+
SLEEP_DELAY = 0.001
|
11
|
+
# Timeout waiting for Window to be closed (in sec)
|
12
|
+
CLOSE_TIMEOUT = 1
|
13
|
+
# Default timeout for dialog operations (in sec)
|
14
|
+
LOOKUP_TIMEOUT = 3
|
15
|
+
DIALOG_WINDOW_CLASS = '#32770'
|
16
|
+
|
17
|
+
# Module defines convenience methods on top of straightforward Win32 API functions.
|
18
|
+
|
19
|
+
# Finds top-level dialog window by title and yields found dialog window to attached block.
|
20
|
+
# We work with dialog window in a block, and then we wait for it to close before proceeding.
|
21
|
+
# 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(title, timeout=LOOKUP_TIMEOUT)
|
24
|
+
dialog = Window.top_level(class: DIALOG_WINDOW_CLASS, title: title, timeout: timeout)
|
25
|
+
#set_foreground_window dialog.handle if dialog # TODO: Should be converted to d_w.s_f_g call!
|
26
|
+
wait = block_given? ? yield(dialog) : false
|
27
|
+
dialog.wait_for_close if dialog && wait
|
28
|
+
dialog
|
29
|
+
end
|
30
|
+
|
31
|
+
# 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. The codes must be a value in the range 1 to 254.
|
33
|
+
# For a complete list, see msdn:Virtual Key Codes.
|
34
|
+
def keystroke(*keys)
|
35
|
+
return if keys.empty?
|
36
|
+
keybd_event keys.first, 0, KEYEVENTF_KEYDOWN, 0
|
37
|
+
sleep KEY_DELAY
|
38
|
+
keystroke *keys[1..-1]
|
39
|
+
sleep KEY_DELAY
|
40
|
+
keybd_event keys.first, 0, KEYEVENTF_KEYUP, 0
|
41
|
+
end
|
42
|
+
|
43
|
+
# types text message into window holding the focus
|
44
|
+
def type_in(message)
|
45
|
+
message.scan(/./m) do |char|
|
46
|
+
keystroke(*char.to_vkeys)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
# DialogWndClass = '#32770'
|
52
|
+
# def dialog(title, seconds=5)
|
53
|
+
# close, dlg = begin
|
54
|
+
# sleep 0.25
|
55
|
+
# w = Gui.top_level(title, seconds, DialogWndClass)
|
56
|
+
# Gui.set_foreground_window w.handle
|
57
|
+
# sleep 0.25
|
58
|
+
#
|
59
|
+
# [yield(w), w]
|
60
|
+
# rescue TimeoutError
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
# dlg.wait_for_close if dlg && close
|
64
|
+
# return dlg
|
65
|
+
# end
|
66
|
+
|
67
|
+
end
|
data/lib/win_gui/window.rb
CHANGED
@@ -1,79 +1,108 @@
|
|
1
|
-
require 'win/gui'
|
2
|
-
|
3
1
|
module WinGui
|
4
|
-
# Delay between key commands (events)
|
5
|
-
WG_KEY_DELAY = 0.00001
|
6
|
-
# Wait delay quant
|
7
|
-
WG_SLEEP_DELAY = 0.001
|
8
|
-
# Timeout waiting for Window to be closed
|
9
|
-
WG_CLOSE_TIMEOUT = 1
|
10
2
|
|
3
|
+
# This class is a wrapper around window handle
|
11
4
|
class Window
|
12
|
-
|
13
|
-
|
14
|
-
|
5
|
+
# Make convenience methods from both WinGui and Win::Gui available as both class and instance methods
|
6
|
+
# Looks a bit circular though...
|
7
|
+
include WinGui
|
8
|
+
extend WinGui
|
9
|
+
|
15
10
|
def initialize(handle)
|
16
11
|
@handle = handle
|
17
12
|
end
|
18
13
|
|
19
14
|
attr_reader :handle
|
20
|
-
|
21
|
-
#
|
22
|
-
|
23
|
-
|
24
|
-
|
15
|
+
|
16
|
+
# Finds top level window by title/class, returns wrapped Window object or nil.
|
17
|
+
# If timeout option given, waits for window to appear within timeout, returns nil if it didn't
|
18
|
+
# Options:
|
19
|
+
# :title:: window title
|
20
|
+
# :class:: window class
|
21
|
+
# :timeout:: timeout (seconds)
|
22
|
+
def self.top_level(opts={})
|
23
|
+
window_title = opts[:title]
|
24
|
+
window_class = opts[:class]
|
25
|
+
timeout = opts[:timeout] # || LOOKUP_TIMEOUT
|
26
|
+
|
27
|
+
if timeout
|
28
|
+
begin
|
29
|
+
timeout(timeout) do
|
30
|
+
sleep SLEEP_DELAY while (@handle = find_window window_class, window_title) == nil
|
31
|
+
end
|
32
|
+
rescue TimeoutError
|
33
|
+
nil
|
34
|
+
end
|
35
|
+
else
|
36
|
+
@handle = find_window window_class, window_title
|
25
37
|
end
|
26
|
-
Window.new @handle
|
27
|
-
end
|
28
|
-
|
38
|
+
Window.new(@handle) if @handle
|
39
|
+
end
|
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
|
+
|
29
54
|
# find child window (control) by title, window class, or control ID:
|
30
55
|
def child(id)
|
31
56
|
result = case id
|
32
57
|
when String
|
33
|
-
|
34
|
-
|
35
|
-
|
58
|
+
by_title = find_window_ex @handle, 0, nil, id.gsub('_', '&' )
|
59
|
+
by_class = find_window_ex @handle, 0, id, nil
|
60
|
+
by_title ? by_title : by_class
|
36
61
|
when Fixnum
|
37
|
-
|
62
|
+
get_dlg_item @handle, id
|
38
63
|
when nil
|
39
|
-
|
40
|
-
|
41
|
-
|
64
|
+
find_window_ex @handle, 0, nil, nil
|
65
|
+
else
|
66
|
+
nil
|
42
67
|
end
|
43
68
|
raise "Control '#{id}' not found" unless result
|
44
69
|
Window.new result
|
45
70
|
end
|
46
71
|
|
72
|
+
# returns array of Windows that are descendants (not only DIRECTchildren) of a given Window
|
47
73
|
def children
|
48
74
|
enum_child_windows(@handle).map{|child_handle| Window.new child_handle}
|
49
75
|
end
|
50
76
|
|
51
77
|
# emulate click of the control identified by id
|
52
78
|
def click(id)
|
53
|
-
|
54
|
-
rectangle = [0, 0, 0, 0].pack 'LLLL'
|
55
|
-
get_window_rect h, rectangle
|
56
|
-
left, top, right, bottom = rectangle.unpack 'LLLL'
|
79
|
+
left, top, right, bottom = get_window_rect child(id).handle
|
57
80
|
center = [(left + right) / 2, (top + bottom) / 2]
|
58
81
|
set_cursor_pos *center
|
59
82
|
mouse_event MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
|
60
83
|
mouse_event MOUSEEVENTF_LEFTUP, 0, 0, 0, 0
|
61
84
|
end
|
62
|
-
|
85
|
+
|
63
86
|
def close
|
64
87
|
post_message @handle, WM_SYSCOMMAND, SC_CLOSE, nil
|
65
88
|
end
|
66
|
-
|
89
|
+
|
67
90
|
def wait_for_close
|
68
|
-
timeout(
|
69
|
-
sleep
|
91
|
+
timeout(CLOSE_TIMEOUT) do
|
92
|
+
sleep SLEEP_DELAY while window_visible?(@handle)
|
70
93
|
end
|
71
94
|
end
|
72
|
-
|
95
|
+
|
96
|
+
# Window class name property - static (not changing)
|
97
|
+
def class_name
|
98
|
+
@class_name ||= get_class_name @handle
|
99
|
+
end
|
100
|
+
|
101
|
+
# Window text/title property - dynamic (changing)
|
73
102
|
def text
|
74
|
-
buffer = "\x0" * 2048
|
75
|
-
|
76
|
-
|
103
|
+
buffer = FFI::MemoryPointer.from_string("\x0" * 2048)
|
104
|
+
num_chars = send_message @handle, WM_GETTEXT, buffer.size, buffer # length?
|
105
|
+
num_chars == 0 ? '' : buffer.read_string
|
77
106
|
end
|
78
107
|
end
|
79
108
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -22,7 +22,8 @@ end
|
|
22
22
|
Spec::Runner.configure { |config| config.extend(SpecMacros) }
|
23
23
|
|
24
24
|
module WinGuiTest
|
25
|
-
include Win::Gui
|
25
|
+
include Win::Gui # This is a namespace from win gem.
|
26
|
+
include WinGui # This is our own main namespace. TODO: looks confusing... better names?
|
26
27
|
|
27
28
|
# Test related Constants:
|
28
29
|
TIMEOUT = 0.001
|
@@ -30,9 +31,8 @@ module WinGuiTest
|
|
30
31
|
SLEEP_DELAY = 0.01
|
31
32
|
APP_PATH = File.join(File.dirname(__FILE__), "../misc/locknote/LockNote.exe" )
|
32
33
|
APP_START = RUBY_PLATFORM =~ /cygwin/ ? "cmd /c start `cygpath -w #{APP_PATH}`" : "start #{APP_PATH}"
|
33
|
-
#
|
34
|
-
|
35
|
-
# 'start "" "' + APP_PATH + '"'
|
34
|
+
# 'start "" "' + APP_PATH + '"'
|
35
|
+
DIALOG_TITLE = "Save As"
|
36
36
|
WIN_TITLE = 'LockNote - Steganos LockNote'
|
37
37
|
WIN_CLASS = 'ATL:00434098'
|
38
38
|
WIN_RECT = [710, 400, 1210, 800]
|
@@ -49,7 +49,6 @@ module WinGuiTest
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def any_handle
|
52
|
-
WinGui.def_api 'FindWindow', 'PP', 'L' unless respond_to? :find_window
|
53
52
|
find_window(nil, nil)
|
54
53
|
end
|
55
54
|
|
@@ -65,6 +64,12 @@ module WinGuiTest
|
|
65
64
|
system APP_START
|
66
65
|
sleep SLEEP_DELAY until (handle = find_window(nil, WIN_TITLE))
|
67
66
|
@launched_test_app = Window.new handle
|
67
|
+
|
68
|
+
def @launched_test_app.textarea #define singleton method retrieving app's text area
|
69
|
+
Window.new find_window_ex(self.handle, 0, TEXTAREA_CLASS, nil)
|
70
|
+
end
|
71
|
+
|
72
|
+
@launched_test_app
|
68
73
|
end
|
69
74
|
|
70
75
|
def close_test_app(app = @launched_test_app)
|
@@ -79,10 +84,6 @@ module WinGuiTest
|
|
79
84
|
def test_app
|
80
85
|
app = launch_test_app
|
81
86
|
|
82
|
-
def app.textarea #define singleton method retrieving app's text area
|
83
|
-
Window.new find_window_ex(self.handle, 0, TEXTAREA_CLASS, nil)
|
84
|
-
end
|
85
|
-
|
86
87
|
yield app
|
87
88
|
close_test_app
|
88
89
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "spec_helper" )
|
2
|
+
|
3
|
+
module WinGuiTest
|
4
|
+
|
5
|
+
describe 'Convenience methods' do
|
6
|
+
before(:each){ @app = launch_test_app }
|
7
|
+
after(:each) { close_test_app }
|
8
|
+
|
9
|
+
describe '#dialog' do
|
10
|
+
before(:each){ keystroke(VK_ALT, 'F'.ord, 'A'.ord) }
|
11
|
+
after(:each) { keystroke(VK_ESCAPE) }
|
12
|
+
|
13
|
+
it 'returns top-level dialog window with given title if no block attached' do
|
14
|
+
dialog_window = dialog(DIALOG_TITLE, 0.1)
|
15
|
+
dialog_window.should_not == nil
|
16
|
+
dialog_window.should be_a Window
|
17
|
+
dialog_window.text.should == DIALOG_TITLE
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'yields found dialog window to block if block is attached' do
|
21
|
+
dialog(DIALOG_TITLE, 0.1) do |dialog_window|
|
22
|
+
dialog_window.should_not == nil
|
23
|
+
dialog_window.should be_a Window
|
24
|
+
dialog_window.text.should == DIALOG_TITLE
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'returns nil if there is no dialog with given title' do
|
29
|
+
dialog(IMPOSSIBLE, 0.1).should == nil
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'yields nil to attached block if no dialog found' do
|
33
|
+
dialog(IMPOSSIBLE, 0.1) do |dialog_window|
|
34
|
+
dialog_window.should == nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'considers timeout argument optional' do
|
39
|
+
dialog_window = dialog(DIALOG_TITLE)
|
40
|
+
dialog_window.text.should == DIALOG_TITLE
|
41
|
+
end
|
42
|
+
end # describe dialog
|
43
|
+
|
44
|
+
describe 'convenience input methods on top of Windows API' do
|
45
|
+
describe '#keystroke' do
|
46
|
+
spec{ use{ keystroke( vkey = 30, vkey = 30) }}
|
47
|
+
|
48
|
+
it 'emulates combinations of keys pressed (Ctrl+Alt+P+M, etc)' do
|
49
|
+
keystroke(VK_CONTROL, 'A'.ord)
|
50
|
+
keystroke(VK_SPACE)
|
51
|
+
@app.textarea.text.should.should == ' '
|
52
|
+
2.times {keystroke(VK_CONTROL, 'Z'.ord)} # rolling back changes to allow window closing without dialog!
|
53
|
+
end
|
54
|
+
end # describe '#keystroke'
|
55
|
+
|
56
|
+
describe '#type_in' do
|
57
|
+
it 'types text message into the window holding the focus' do
|
58
|
+
text = '12 34'
|
59
|
+
type_in(text)
|
60
|
+
@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
|
+
end
|
63
|
+
end # describe '#type_in'
|
64
|
+
|
65
|
+
end # Input methods
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
data/spec/win_gui/window_spec.rb
CHANGED
@@ -1,27 +1,29 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), ".."
|
1
|
+
require File.join(File.dirname(__FILE__), "..", "spec_helper" )
|
2
2
|
|
3
3
|
module WinGuiTest
|
4
|
-
include WinGui
|
5
4
|
|
6
5
|
describe Window do
|
7
6
|
before(:each) { @app = launch_test_app }
|
8
7
|
after(:each){ close_test_app }
|
9
|
-
|
8
|
+
|
10
9
|
context 'initializing' do
|
11
10
|
it 'can be wrapped around any existing window' do
|
12
11
|
any_handle = find_window(nil, nil)
|
13
12
|
use{ Window.new any_handle }
|
14
13
|
end
|
15
14
|
end
|
16
|
-
|
15
|
+
|
17
16
|
context 'manipulating' do
|
18
|
-
|
17
|
+
|
19
18
|
it 'has handle property equal to underlying window handle' do
|
20
|
-
any_handle = find_window(nil, nil)
|
21
19
|
any = Window.new any_handle
|
22
20
|
any.handle.should == any_handle
|
23
21
|
end
|
24
|
-
|
22
|
+
|
23
|
+
it 'has class_name property' do
|
24
|
+
@app.class_name.should == WIN_CLASS
|
25
|
+
end
|
26
|
+
|
25
27
|
it 'has text property equal to underlying window text(title)' do
|
26
28
|
@app.text.should == WIN_TITLE
|
27
29
|
end
|
@@ -31,39 +33,57 @@ module WinGuiTest
|
|
31
33
|
sleep SLEEP_DELAY # needed to ensure window had enough time to close down
|
32
34
|
find_window(nil, WIN_TITLE).should == nil
|
33
35
|
end
|
34
|
-
|
35
|
-
it 'waits
|
36
|
-
start = Time.now
|
36
|
+
|
37
|
+
it 'waits for window to disappear (NB: this happens before handle is released!)' do
|
38
|
+
start = Time.now
|
37
39
|
@app.close
|
38
40
|
@app.wait_for_close
|
39
|
-
|
41
|
+
(Time.now - start).should be <= CLOSE_TIMEOUT
|
40
42
|
window_visible?(@app.handle).should be false
|
43
|
+
window?(@app.handle).should be false
|
41
44
|
end
|
42
45
|
end
|
43
|
-
|
44
|
-
|
45
|
-
it 'finds any top-level window (title = nil) and wraps it in a Window object' do
|
46
|
-
use { @win = Window.top_level(title = nil, timeout_sec = 3) }
|
47
|
-
Window.should === @win
|
48
|
-
end
|
49
|
-
|
46
|
+
|
47
|
+
describe '.top_level' do
|
50
48
|
it 'finds top-level window by title and wraps it in a Window object' do
|
51
|
-
win = Window.top_level( WIN_TITLE, 1)
|
49
|
+
win = Window.top_level( title: WIN_TITLE, timeout: 1)
|
52
50
|
win.handle.should == @app.handle
|
53
51
|
end
|
52
|
+
|
53
|
+
it 'finds top-level window by class and wraps it in a Window object' do
|
54
|
+
win = Window.top_level( class: WIN_CLASS, timeout: 1)
|
55
|
+
win.handle.should == @app.handle
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'finds ANY top-level window without args and wraps it in a Window object' do
|
59
|
+
use { @win = Window.top_level() }
|
60
|
+
Window.should === @win
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'returns nil immediately if top-level window with given title not found' do
|
64
|
+
start = Time.now
|
65
|
+
Window.top_level( title: IMPOSSIBLE).should == nil
|
66
|
+
(Time.now - start).should be_close 0, 0.02
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'returns nil after timeout if top-level window with given title not found' do
|
70
|
+
start = Time.now
|
71
|
+
Window.top_level( title: IMPOSSIBLE, timeout: 1).should == nil
|
72
|
+
(Time.now - start).should be_close 1, 0.02
|
73
|
+
end
|
54
74
|
end
|
55
|
-
|
56
|
-
|
57
|
-
spec { use { @control = @app.child(title_class_id = nil) }}
|
75
|
+
|
76
|
+
describe '#child' do
|
77
|
+
spec { use { @control = @app.child(title_class_id = nil) }}
|
58
78
|
|
59
79
|
it 'finds any child window(control) if given nil' do
|
60
80
|
@app.child(nil).should_not == nil
|
61
81
|
end
|
62
|
-
|
82
|
+
|
63
83
|
it 'finds child window(control) by class' do
|
64
84
|
@app.child(TEXTAREA_CLASS).should_not == nil
|
65
85
|
end
|
66
|
-
|
86
|
+
|
67
87
|
it 'finds child window(control) by name' do
|
68
88
|
pending 'Need to find control with short name'
|
69
89
|
@app.child(TEXTAREA_TEXT).should_not == nil
|
@@ -73,22 +93,18 @@ module WinGuiTest
|
|
73
93
|
pending 'Need to find some control ID'
|
74
94
|
@app.child(TEXTAREA_ID).should_not == nil
|
75
95
|
end
|
76
|
-
|
96
|
+
|
77
97
|
it 'raises error if wrong control is given' do
|
78
98
|
expect { @app.child('Impossible Control')}.to raise_error "Control 'Impossible Control' not found"
|
79
99
|
end
|
80
|
-
|
81
|
-
|
100
|
+
|
101
|
+
it 'substitutes & for _ when searching by title ("&Yes" type controls)' # Why?
|
82
102
|
end
|
83
|
-
|
84
|
-
context '#children' do
|
85
|
-
spec { use { children = @app.children }}
|
86
103
|
|
87
|
-
|
88
|
-
|
89
|
-
end
|
104
|
+
describe '#children' do
|
105
|
+
spec { use { children = @app.children }}
|
90
106
|
|
91
|
-
it 'returns an array of
|
107
|
+
it 'returns an array of Windows that are descendants (not only DIRECTchildren) of a given Window' do
|
92
108
|
children = @app.children
|
93
109
|
children.should be_a_kind_of Array
|
94
110
|
children.should_not be_empty
|
@@ -111,7 +127,7 @@ module WinGuiTest
|
|
111
127
|
# expect { @app.child('Impossible Control')}.to raise_error "Control 'Impossible Control' not found"
|
112
128
|
# end
|
113
129
|
# it 'substitutes & for _ when searching by title ("&Yes" type controls)'
|
114
|
-
|
130
|
+
|
115
131
|
end
|
116
132
|
|
117
133
|
context '#click' 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
|
+
- 1
|
9
|
+
version: 0.2.1
|
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-05-
|
17
|
+
date: 2010-05-31 00:00:00 +04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -69,10 +69,12 @@ extra_rdoc_files:
|
|
69
69
|
- README.rdoc
|
70
70
|
files:
|
71
71
|
- lib/version.rb
|
72
|
+
- lib/win_gui/convenience.rb
|
72
73
|
- lib/win_gui/window.rb
|
73
74
|
- lib/win_gui.rb
|
74
75
|
- spec/spec.opts
|
75
76
|
- spec/spec_helper.rb
|
77
|
+
- spec/win_gui/convenience_spec.rb
|
76
78
|
- spec/win_gui/window_spec.rb
|
77
79
|
- features/step_definitions/win_gui_steps.rb
|
78
80
|
- features/support/env.rb
|
@@ -127,4 +129,5 @@ summary: Abstractions/wrappers around GUI-related Win32 API functions
|
|
127
129
|
test_files:
|
128
130
|
- spec/spec.opts
|
129
131
|
- spec/spec_helper.rb
|
132
|
+
- spec/win_gui/convenience_spec.rb
|
130
133
|
- spec/win_gui/window_spec.rb
|