win_gui 0.2.3 → 0.2.5

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 CHANGED
@@ -17,3 +17,11 @@
17
17
  == 0.2.3 / 2010-06-03
18
18
 
19
19
  * Minor cleanup/refactoring
20
+
21
+ == 0.2.4 / 2010-06-03
22
+
23
+ * Unified interface for Window.top_level and Window#child
24
+
25
+ == 0.2.5 / 2010-06-04
26
+
27
+ * Code brought to about Book-level quality
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.3
1
+ 0.2.5
@@ -2,75 +2,75 @@ module WinGui
2
2
 
3
3
  # This class is a wrapper around window handle
4
4
  class Window
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
5
 
10
6
  def initialize(handle)
11
7
  @handle = handle
8
+ # puts "Window #{handle} created "
9
+ # p self.class.ancestors
12
10
  end
13
11
 
14
12
  attr_reader :handle
15
13
 
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 ? # no timeout by default
26
-
27
- if timeout
14
+ # Looks up window handle using code specified in attached block (either with or without :timeout)
15
+ # Returns either Window instance (for a found handle) or nil if nothing found
16
+ # Private method to dry up other window lookup methods
17
+ # :yields:
18
+ #
19
+ def self.lookup_window(opts)
20
+ # Need this to avoid handle considered local in begin..end block
21
+ handle = yield
22
+ if opts[:timeout]
28
23
  begin
29
- timeout(timeout) do
30
- sleep SLEEP_DELAY while (@handle = WinGui.find_window window_class, window_title) == nil
24
+ timeout(opts[:timeout]) do
25
+ sleep SLEEP_DELAY until handle = yield
31
26
  end
32
27
  rescue TimeoutError
33
28
  nil
34
29
  end
35
- else
36
- @handle = WinGui.find_window window_class, window_title
37
30
  end
38
- Window.new(@handle) if @handle
31
+ raise opts[:raise] if opts[:raise] && !handle
32
+ Window.new(handle) if handle
39
33
  end
40
34
 
41
- # find child window (control) by title, window class, or control ID:
42
- def child(id)
43
- result = case id
44
- when String
45
- by_title = find_window_ex 0, nil, id.gsub('_', '&' )
46
- by_class = find_window_ex 0, id, nil
47
- by_title ? by_title : by_class
48
- when Fixnum
49
- get_dlg_item id
50
- when nil
51
- find_window_ex 0, nil, nil
52
- else
53
- nil
35
+ # Find top level window by title/class, returns wrapped Window object or nil.
36
+ # If timeout option given, waits for window to appear within timeout, returns nil if it didn't
37
+ # Options:
38
+ # :title:: window title
39
+ # :class:: window class
40
+ # :timeout:: timeout (seconds)
41
+ def self.top_level(opts={})
42
+ lookup_window(opts) { WinGui.find_window opts[:class], opts[:title] }
43
+ end
44
+
45
+ # Find DIRECT child window (control) by either control ID or window class/title.
46
+ def child(opts={})
47
+ self.class.lookup_window(opts) do
48
+ opts[:id] ? get_dlg_item(opts[:id]) : find_window_ex(0, opts[:class], opts[:title])
54
49
  end
55
- raise "Control '#{id}' not found" unless result
56
- Window.new result
57
50
  end
58
51
 
59
- # returns array of Windows that are descendants (not only DIRECT children) of a given Window
52
+ # Return array of Windows that are descendants (not only DIRECT children) of a given Window
60
53
  def children
61
54
  enum_child_windows.map{|child_handle| Window.new child_handle}
62
55
  end
63
56
 
64
- # emulate click of the control identified by id
65
- def click(id)
66
- left, top, right, bottom = child(id).get_window_rect
67
- center = [(left + right) / 2, (top + bottom) / 2]
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
57
+ # Emulate click of the control identified by opts (:id, :title, :class)
58
+ # Return true if click was presumably successful, false if it failed (control was not found)
59
+ def click(opts={})
60
+ control = child(opts)
61
+ if control
62
+ left, top, right, bottom = control.get_window_rect
63
+ center = [(left + right) / 2, (top + bottom) / 2]
64
+ WinGui.set_cursor_pos *center
65
+ WinGui.mouse_event WinGui::MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
66
+ WinGui.mouse_event WinGui::MOUSEEVENTF_LEFTUP, 0, 0, 0, 0
67
+ true
68
+ else
69
+ false
70
+ end
71
71
  end
72
72
 
73
- def wait_for_close(timeout =CLOSE_TIMEOUT )
73
+ def wait_for_close(timeout=CLOSE_TIMEOUT )
74
74
  timeout(timeout) do
75
75
  sleep SLEEP_DELAY while window_visible?
76
76
  end
@@ -97,7 +97,8 @@ module WinGui
97
97
  # WinGui.function(*args)
98
98
  def method_missing(name, *args, &block)
99
99
  if WinGui.respond_to? name
100
- WinGui.send(name, @handle, *args, &block)
100
+ # puts "Window #{@handle} calling: #{name} #{@handle} #{args} &#{block}"
101
+ WinGui.send(name, @handle, *args, &block)
101
102
  else
102
103
  super
103
104
  end
data/lib/win_gui.rb CHANGED
@@ -1,5 +1,5 @@
1
- require 'version'
2
- require 'extension'
1
+ require_relative 'version'
2
+ require_relative 'extension'
3
3
 
4
4
  module WinGui
5
5
 
data/spec/spec_helper.rb CHANGED
@@ -75,7 +75,10 @@ module WinGuiTest
75
75
  while @test_app && find_window(nil, WIN_TITLE)
76
76
  @test_app.close
77
77
  # Dealing with closing confirmation modal dialog
78
- keystroke("N") if Window.top_level( title: "Steganos Locknote", timeout: SLEEP_DELAY*5)
78
+ if dialog = dialog( title: "Steganos Locknote", timeout: SLEEP_DELAY)
79
+ dialog.set_foreground_window
80
+ keystroke("N")
81
+ end
79
82
  end
80
83
  @test_app = nil
81
84
  end
@@ -87,4 +90,22 @@ module WinGuiTest
87
90
  close_test_app
88
91
  end
89
92
 
93
+ def with_dialog(type=:close)
94
+ case type
95
+ when :close
96
+ keystroke('A')
97
+ @app.close
98
+ title, key = "Steganos Locknote", "N"
99
+ when :save
100
+ keystroke(VK_ALT, 'F', 'A')
101
+ title, key = "Save As", VK_ESCAPE
102
+ end
103
+ sleep 0.01 until dialog = Window.top_level(title: title)
104
+ yield dialog
105
+ while dialog.window?
106
+ dialog.set_foreground_window
107
+ keystroke(key)
108
+ sleep 0.01
109
+ end
110
+ end
90
111
  end
@@ -7,38 +7,43 @@ module WinGuiTest
7
7
  after(:each) { close_test_app }
8
8
 
9
9
  describe '#dialog' do
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) }
14
-
15
10
  it 'returns top-level dialog window with given title if no block attached' do
16
- dialog_window = dialog(title: DIALOG_TITLE, timeout: 0.1)
17
- dialog_window.should_not == nil
18
- dialog_window.should be_a Window
19
- dialog_window.text.should == DIALOG_TITLE
20
- end
21
-
22
- it 'yields found dialog window to block if block is attached' do
23
- dialog(title: DIALOG_TITLE) do |dialog_window|
11
+ with_dialog(:save) do
12
+ dialog_window = dialog(title: DIALOG_TITLE, timeout: 0.1)
24
13
  dialog_window.should_not == nil
25
14
  dialog_window.should be_a Window
26
15
  dialog_window.text.should == DIALOG_TITLE
27
16
  end
28
17
  end
29
18
 
19
+ it 'yields found dialog window to block if block is attached' do
20
+ with_dialog(:save) do
21
+ dialog(title: DIALOG_TITLE) 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
+ end
28
+
30
29
  it 'returns nil if there is no dialog with given title' do
31
- dialog(title: IMPOSSIBLE, timeout: 0.1).should == nil
30
+ with_dialog(:save) do
31
+ dialog(title: IMPOSSIBLE, timeout: 0.1).should == nil
32
+ end
32
33
  end
33
34
 
34
35
  it 'yields nil to attached block if no dialog found' do
35
- dialog(title: IMPOSSIBLE, timeout: 0.1) do |dialog_window|
36
- dialog_window.should == nil
36
+ with_dialog(:save) do
37
+ dialog(title: IMPOSSIBLE, timeout: 0.1) do |dialog_window|
38
+ dialog_window.should == nil
39
+ end
37
40
  end
38
41
  end
39
42
 
40
43
  it 'considers all arguments optional' do
41
- use { dialog_window = dialog() }
44
+ with_dialog(:save) do
45
+ use { dialog_window = dialog() }
46
+ end
42
47
  end
43
48
  end # describe dialog
44
49
 
@@ -64,6 +69,5 @@ module WinGuiTest
64
69
  end # describe '#type_in'
65
70
 
66
71
  end # Input methods
67
-
68
- end
72
+ end # Convenience methods
69
73
  end
@@ -85,35 +85,75 @@ module WinGuiTest
85
85
  Window.top_level( title: IMPOSSIBLE, timeout: 0.5).should == nil
86
86
  (Time.now - start).should be_close 0.5, 0.02
87
87
  end
88
- end
88
+
89
+ it 'raises exception if asked to' do
90
+ expect{ Window.top_level( title: IMPOSSIBLE, raise: "Horror!")}.to raise_error "Horror!"
91
+ end
92
+ end # describe .top_level
89
93
 
90
94
  describe '#child' do
91
- spec { use { @control = @app.child(title_class_id = nil) }}
95
+ spec { use { @child = @app.child(title: "Title", class: "Class", id: 0) }}
92
96
 
93
- it 'finds any child window(control) if given nil' do
94
- @app.child(nil).should_not == nil
97
+ it 'returns nil immediately if specific child not found' do
98
+ start = Time.now
99
+ @app.child( title: IMPOSSIBLE).should == nil
100
+ (Time.now - start).should be_close 0, 0.02
95
101
  end
96
102
 
97
- it 'finds child window(control) by class' do
98
- @app.child(TEXTAREA_CLASS).should_not == nil
103
+ it 'returns nil after timeout if specific child not found' do
104
+ start = Time.now
105
+ @app.child( title: IMPOSSIBLE, timeout: 0.5).should == nil
106
+ (Time.now - start).should be_close 0.5, 0.02
99
107
  end
100
108
 
101
- it 'finds child window(control) by name' do
102
- pending 'Need to find control with short name'
103
- @app.child(TEXTAREA_TEXT).should_not == nil
109
+ it 'finds ANY child window without args' do
110
+ use { @child = @app.child() }
111
+ @child.should_not == nil
112
+ @app.child?(@child.handle).should == true
104
113
  end
105
114
 
106
- it 'finds child window(control) by control ID' do
107
- pending 'Need to find some control ID'
108
- @app.child(TEXTAREA_ID).should_not == nil
115
+ it 'finds child window by class and returns it as a Window object (no timeout)' do
116
+ child = @app.child( class: TEXTAREA_CLASS)
117
+ child.should_not == nil
118
+ @app.child?(child.handle).should == true
109
119
  end
110
120
 
111
- it 'raises error if wrong control is given' do
112
- expect { @app.child('Impossible Control')}.to raise_error "Control 'Impossible Control' not found"
121
+ it 'finds child window by class and returns it as a Window object (with timeout)' do
122
+ # p @app.find_window_ex(0, TEXTAREA_CLASS, nil)
123
+ # p @app.find_window_ex(0, STATUSBAR_CLASS, nil)
124
+ child = @app.child( class: TEXTAREA_CLASS, timeout: 0.5)
125
+ child.should_not == nil
126
+
127
+ @app.child?(child.handle).should == true
128
+ child = @app.child( class: STATUSBAR_CLASS, timeout: 0.5)
129
+ child.should_not == nil
130
+ @app.child?(child.handle).should == true
113
131
  end
114
132
 
115
- it 'substitutes & for _ when searching by title ("&Yes" type controls)' # Why?
116
- end
133
+ it 'finds child with specific text and returns it as a Window object' do
134
+ with_dialog(:save) do |dialog|
135
+ # @dialog.children.each{|child| puts "#{child.handle}, #{child.class_name}, #{child.window_text}"}
136
+ child = dialog.child( title: "Cancel")
137
+ child.should_not == nil
138
+ dialog.child?(child.handle).should == true
139
+ child.get_dlg_ctrl_id.should == IDCANCEL
140
+
141
+ child = dialog.child( title: "&Save")
142
+ child.should_not == nil
143
+ dialog.child?(child.handle).should == true
144
+ child.get_dlg_ctrl_id.should == IDOK
145
+ end
146
+ end
147
+
148
+ it 'finds child control with a given ID and returns it as a Window object' do
149
+ with_dialog(:save) do |dialog|
150
+ child = dialog.child( id: IDCANCEL)
151
+ child.should_not == nil
152
+ dialog.child?(child.handle).should == true
153
+ child.text.should == "Cancel"
154
+ end
155
+ end
156
+ end # describe child
117
157
 
118
158
  describe '#children' do
119
159
  spec { use { children = @app.children }}
@@ -126,26 +166,33 @@ module WinGuiTest
126
166
  children.each{|child| child?(@app.handle, child.handle).should == true }
127
167
  children.last.class_name.should == TEXTAREA_CLASS
128
168
  end
169
+ end # describe #children
129
170
 
130
- # it 'finds child window(control) by name' do
131
- # pending 'Need to find control with short name'
132
- # @app.child(TEXTAREA_TEXT).should_not == nil
133
- # end
134
- #
135
- # it 'finds child window(control) by control ID' do
136
- # pending 'Need to find some control ID'
137
- # @app.child(TEXTAREA_ID).should_not == nil
138
- # end
139
- #
140
- # it 'raises error if wrong control is given' do
141
- # expect { @app.child('Impossible Control')}.to raise_error "Control 'Impossible Control' not found"
142
- # end
143
- # it 'substitutes & for _ when searching by title ("&Yes" type controls)'
171
+ describe '#click' do
172
+ it 'emulates clicking of the control identified by id, returns true' do
173
+ with_dialog(:save) do |dialog|
174
+ dialog.click(id: IDCANCEL).should == true
175
+ sleep 0.5
176
+ dialog.window?.should == false
177
+ end
178
+ end
144
179
 
145
- end
180
+ it 'emulates clicking of the control identified by title, returns true' do
181
+ with_dialog(:save) do |dialog|
182
+ dialog.click(title: "Cancel").should == true
183
+ sleep 0.5
184
+ dialog.window?.should == false
185
+ end
186
+ end
146
187
 
147
- context '#click' do
148
- it 'emulates clicking of the control identified by id'
149
- end
188
+ it 'returns false if the specified control was not found' do
189
+ with_dialog(:save) do |dialog|
190
+ dialog.click(title: "Shpancel").should == false
191
+ dialog.click(id: 66).should == false
192
+ sleep 0.5
193
+ dialog.window?.should == true
194
+ end
195
+ end
196
+ end # describe #click
150
197
  end
151
198
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 2
8
- - 3
9
- version: 0.2.3
8
+ - 5
9
+ version: 0.2.5
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-06-03 00:00:00 +04:00
17
+ date: 2010-06-04 00:00:00 +04:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency