win_gui 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +43 -0
- data/Rakefile +58 -0
- data/VERSION +1 -0
- data/book_code/early_success/bundle.rb +34 -0
- data/book_code/early_success/english.txt +1 -0
- data/book_code/early_success/jruby_basics.rb +47 -0
- data/book_code/early_success/windows_basics.rb +97 -0
- data/book_code/guessing/locknote.rb +379 -0
- data/book_code/guessing/monkeyshines.rb +14 -0
- data/book_code/guessing/note.rb +120 -0
- data/book_code/guessing/note_spec.rb +175 -0
- data/book_code/guessing/replay.rb +21 -0
- data/book_code/guessing/seed.rb +9 -0
- data/book_code/guessing/spec_helper.rb +69 -0
- data/book_code/guessing/windows_gui.rb +247 -0
- data/book_code/home_stretch/junquenote.rb +151 -0
- data/book_code/home_stretch/locknote.rb +180 -0
- data/book_code/home_stretch/note.rb +144 -0
- data/book_code/home_stretch/note_spec.rb +191 -0
- data/book_code/home_stretch/spec_helper.rb +55 -0
- data/book_code/home_stretch/swing_gui.rb +50 -0
- data/book_code/home_stretch/windows_gui.rb +232 -0
- data/book_code/junquenote/exports.sh +10 -0
- data/book_code/junquenote/jruby_mac.sh +10 -0
- data/book_code/junquenote/junquenote_app.rb +262 -0
- data/book_code/novite/Rakefile +10 -0
- data/book_code/novite/app/controllers/application.rb +18 -0
- data/book_code/novite/app/controllers/guests_controller.rb +28 -0
- data/book_code/novite/app/controllers/parties_controller.rb +77 -0
- data/book_code/novite/app/helpers/application_helper.rb +11 -0
- data/book_code/novite/app/helpers/guests_helper.rb +10 -0
- data/book_code/novite/app/helpers/parties_helper.rb +10 -0
- data/book_code/novite/app/models/guest.rb +11 -0
- data/book_code/novite/app/models/party.rb +32 -0
- data/book_code/novite/app/models/party_mailer.rb +19 -0
- data/book_code/novite/app/views/layouts/application.rhtml +44 -0
- data/book_code/novite/app/views/parties/new.html.erb +42 -0
- data/book_code/novite/app/views/parties/show.html.erb +43 -0
- data/book_code/novite/app/views/party_mailer/invite.erb +17 -0
- data/book_code/novite/config/boot.rb +117 -0
- data/book_code/novite/config/database.yml +19 -0
- data/book_code/novite/config/environment.rb +67 -0
- data/book_code/novite/config/environments/development.rb +29 -0
- data/book_code/novite/config/environments/production.rb +27 -0
- data/book_code/novite/config/environments/test.rb +30 -0
- data/book_code/novite/config/initializers/inflections.rb +18 -0
- data/book_code/novite/config/initializers/mime_types.rb +13 -0
- data/book_code/novite/config/routes.rb +47 -0
- data/book_code/novite/db/migrate/001_create_parties.rb +26 -0
- data/book_code/novite/db/migrate/002_create_guests.rb +23 -0
- data/book_code/novite/db/schema.rb +41 -0
- data/book_code/novite/log/empty.txt +0 -0
- data/book_code/novite/public/.htaccess +40 -0
- data/book_code/novite/public/404.html +38 -0
- data/book_code/novite/public/422.html +38 -0
- data/book_code/novite/public/500.html +38 -0
- data/book_code/novite/public/dispatch.cgi +10 -0
- data/book_code/novite/public/dispatch.fcgi +24 -0
- data/book_code/novite/public/dispatch.rb +18 -0
- data/book_code/novite/public/favicon.ico +0 -0
- data/book_code/novite/public/images/rails.png +0 -0
- data/book_code/novite/public/index.html +285 -0
- data/book_code/novite/public/javascripts/application.js +10 -0
- data/book_code/novite/public/javascripts/controls.js +971 -0
- data/book_code/novite/public/javascripts/dragdrop.js +980 -0
- data/book_code/novite/public/javascripts/effects.js +1128 -0
- data/book_code/novite/public/javascripts/prototype.js +4233 -0
- data/book_code/novite/public/robots.txt +5 -0
- data/book_code/novite/script/about +3 -0
- data/book_code/novite/script/console +3 -0
- data/book_code/novite/script/destroy +3 -0
- data/book_code/novite/script/generate +3 -0
- data/book_code/novite/script/performance/benchmarker +3 -0
- data/book_code/novite/script/performance/profiler +3 -0
- data/book_code/novite/script/performance/request +3 -0
- data/book_code/novite/script/plugin +3 -0
- data/book_code/novite/script/process/inspector +3 -0
- data/book_code/novite/script/process/reaper +3 -0
- data/book_code/novite/script/process/spawner +3 -0
- data/book_code/novite/script/runner +3 -0
- data/book_code/novite/script/server +3 -0
- data/book_code/novite/test/test_helper.rb +46 -0
- data/book_code/one_more_thing/applescript.rb +68 -0
- data/book_code/one_more_thing/note_spec.rb +50 -0
- data/book_code/one_more_thing/spec_helper.rb +17 -0
- data/book_code/one_more_thing/textedit-pure.rb +28 -0
- data/book_code/one_more_thing/textedit.applescript +26 -0
- data/book_code/one_more_thing/textedit.rb +32 -0
- data/book_code/one_more_thing/textnote.rb +87 -0
- data/book_code/simplify/junquenote.rb +48 -0
- data/book_code/simplify/locknote.rb +46 -0
- data/book_code/simplify/note.rb +35 -0
- data/book_code/simplify/note_spec.rb +28 -0
- data/book_code/simplify/swing_gui.rb +45 -0
- data/book_code/simplify/windows_gui.rb +232 -0
- data/book_code/simplify/windows_gui_spec.rb +35 -0
- data/book_code/story/invite.story +19 -0
- data/book_code/story/journal.txt +29 -0
- data/book_code/story/novite_stories.rb +156 -0
- data/book_code/story/party.rb +149 -0
- data/book_code/story/password.rb +61 -0
- data/book_code/story/password.story +26 -0
- data/book_code/story/rsvp.story +29 -0
- data/book_code/tables/TestTime.html +93 -0
- data/book_code/tables/TestTimeSample.html +63 -0
- data/book_code/tables/calculate_time.rb +39 -0
- data/book_code/tables/calculator.rb +108 -0
- data/book_code/tables/calculator_actions.rb +27 -0
- data/book_code/tables/calculator_spec.rb +47 -0
- data/book_code/tables/fit.rb +32 -0
- data/book_code/tables/matrix.rb +109 -0
- data/book_code/tables/pseudocode.rb +17 -0
- data/book_code/tubes/book_selenium.rb +67 -0
- data/book_code/tubes/book_watir.rb +60 -0
- data/book_code/tubes/dragdrop.html +81 -0
- data/book_code/tubes/html_capture.rb +33 -0
- data/book_code/tubes/joke_list.rb +67 -0
- data/book_code/tubes/list_spec.rb +41 -0
- data/book_code/tubes/search_spec.rb +32 -0
- data/book_code/tubes/selenium_example.rb +66 -0
- data/book_code/tubes/selenium_link.rb +23 -0
- data/book_code/tubes/web_server.rb +14 -0
- data/book_code/windows/wgui.rb +29 -0
- data/book_code/windows/wobj.rb +25 -0
- data/book_code/windows/wsh.rb +25 -0
- data/book_code/with_rspec/empty_spec.rb +13 -0
- data/book_code/with_rspec/junquenote.rb +60 -0
- data/book_code/with_rspec/locknote.rb +129 -0
- data/book_code/with_rspec/note_spec.rb +32 -0
- data/book_code/with_rspec/should_examples.rb +18 -0
- data/exp/exp.rb +6 -0
- data/exp/exp_encodings.rb +40 -0
- data/exp/exp_enum_windows.rb +60 -0
- data/exp/exp_quik.rb +38 -0
- data/exp/exp_wsh.rb +115 -0
- data/exp/old/windows_basics.rb +80 -0
- data/exp/old/wnote.rb +80 -0
- data/exp/old/wnote_spec.rb +20 -0
- data/features/step_definitions/win_gui_steps.rb +0 -0
- data/features/support/env.rb +4 -0
- data/features/win_gui.feature +9 -0
- data/lib/note/java/jemmy.jar +0 -0
- data/lib/note/java/jnote.rb +48 -0
- data/lib/note/java/jruby_basics.rb +37 -0
- data/lib/note/java/junquenote_app.rb +262 -0
- data/lib/note/java/note_spec.rb +20 -0
- data/lib/note/win/locknote.rb +19 -0
- data/lib/note.rb +15 -0
- data/lib/win_gui/constants.rb +66 -0
- data/lib/win_gui/string_extensions.rb +24 -0
- data/lib/win_gui/win_gui.rb +274 -0
- data/lib/win_gui/window.rb +70 -0
- data/lib/win_gui.rb +3 -0
- data/spec/note/win/locknote_spec.rb +7 -0
- data/spec/spec.opts +2 -0
- data/spec/spec_helper.rb +100 -0
- data/spec/test_apps/locknote/LockNote.exe +0 -0
- data/spec/win_gui/string_extensions_spec.rb +61 -0
- data/spec/win_gui/win_gui_spec.rb +733 -0
- data/spec/win_gui/window_spec.rb +124 -0
- metadata +251 -0
@@ -0,0 +1,18 @@
|
|
1
|
+
#---
|
2
|
+
# Excerpted from "Scripted GUI Testing With Ruby",
|
3
|
+
# published by The Pragmatic Bookshelf.
|
4
|
+
# Copyrights apply to this code. It may not be used to create training material,
|
5
|
+
# courses, books, articles, and the like. Contact us if you are in doubt.
|
6
|
+
# We make no guarantees that this code is fit for any purpose.
|
7
|
+
# Visit http://www.pragmaticprogrammer.com/titles/idgtr for more book information.
|
8
|
+
#---
|
9
|
+
describe 'RSpec' do
|
10
|
+
it 'supports writing clear tests' do
|
11
|
+
|
12
|
+
(2 + 2).should == 4
|
13
|
+
1.should be < 2
|
14
|
+
['this', 'list'].should_not be_empty
|
15
|
+
{:color => 'red'}.should have_key(:color)
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
data/exp/exp.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
# encoding: CP1251
|
2
|
+
Encoding.default_internal, Encoding.default_external = ['utf-8'] * 2
|
3
|
+
t = '��������� �����������!'
|
4
|
+
d = t.encode('CP866')
|
5
|
+
utf8 = t.encode('utf-8')
|
6
|
+
|
7
|
+
puts '��������� �����������!', t, utf8, "#{d} #{d.encoding}"
|
8
|
+
|
9
|
+
str = "\xE2\x80\x93"
|
10
|
+
puts "Str: #{str}, #{str.encoding}"
|
11
|
+
|
12
|
+
p "Source encoding: #{__ENCODING__}"
|
13
|
+
p "String encoding: #{t.encoding}"
|
14
|
+
p "Def ext encoding: #{Encoding.default_external}"
|
15
|
+
p "Def int encoding: #{Encoding.default_internal}"
|
16
|
+
|
17
|
+
puts
|
18
|
+
|
19
|
+
puts 'Playing with encodings: setting default to utf-8'
|
20
|
+
Encoding.default_internal, Encoding.default_external = ['utf-8'] * 2
|
21
|
+
p "Source encoding: #{__ENCODING__}"
|
22
|
+
p "Def ext encoding: #{Encoding.default_external}"
|
23
|
+
p "Def int encoding: #{Encoding.default_internal}"
|
24
|
+
zhopa ='Yes, ��� ����!!'
|
25
|
+
puts zhopa
|
26
|
+
p "String encoding: #{zhopa.encoding}"
|
27
|
+
puts zhopa.encode!('CP866', :undef => :replace)
|
28
|
+
p "String encoding: #{zhopa.encoding}"
|
29
|
+
|
30
|
+
puts
|
31
|
+
puts 'Playing with encodings: setting default to cp866'
|
32
|
+
Encoding.default_internal, Encoding.default_external = ['cp866'] * 2
|
33
|
+
p "Source encoding: #{__ENCODING__}"
|
34
|
+
p "Def ext encoding: #{Encoding.default_external}"
|
35
|
+
p "Def int encoding: #{Encoding.default_internal}"
|
36
|
+
zhopa ='Yes, ��� ����!!'
|
37
|
+
puts zhopa
|
38
|
+
p "String encoding: #{zhopa.encoding}"
|
39
|
+
puts zhopa.encode!('CP866', :undef => :replace)
|
40
|
+
p "String encoding: #{zhopa.encoding}"
|
@@ -0,0 +1,60 @@
|
|
1
|
+
#encoding: utf-8
|
2
|
+
|
3
|
+
|
4
|
+
# When using API functions returning ANSI strings (get_window_text), force_encoding('cp1251') and encode('cp866', :undef => :replace) to display correctly
|
5
|
+
# When using API functions returning "wide" Unicode strings (get_window_text_w), force_encoding('utf-16LE') and encode('cp866', :undef => :replace) to display correctly
|
6
|
+
|
7
|
+
libdir = File.join(File.dirname(__FILE__),"lib" )
|
8
|
+
$LOAD_PATH.unshift libdir unless $LOAD_PATH.include?(libdir)
|
9
|
+
require 'spec/spec_helper'
|
10
|
+
|
11
|
+
include WinGui
|
12
|
+
include GuiTest
|
13
|
+
|
14
|
+
@child_handles = []
|
15
|
+
app = launch_test_app
|
16
|
+
#keystroke(VK_ALT, 'F'.ord)
|
17
|
+
print_callback = lambda do |handle, message|
|
18
|
+
name = get_window_text(handle)
|
19
|
+
class_name = get_class_name(handle)
|
20
|
+
thread, process = get_window_thread_process_id(handle)
|
21
|
+
puts "#{message} #{process} #{thread} #{handle} #{class_name.rstrip} #{name.force_encoding('cp1251').encode('cp866', :undef => :replace).rstrip}"
|
22
|
+
@child_handles << handle if message == 'CHILD'
|
23
|
+
true
|
24
|
+
end
|
25
|
+
|
26
|
+
@windows = []
|
27
|
+
@num = 0
|
28
|
+
map_callback = lambda do |handle, message|
|
29
|
+
name = get_window_text_w(handle)
|
30
|
+
class_name = get_class_name(handle)
|
31
|
+
thread, process = get_window_thread_process_id(handle)
|
32
|
+
@windows << { :message => message, :process => process, :thread => thread, :handle => handle, :klass => class_name.rstrip,
|
33
|
+
:name => name.encode('cp866', :undef => :replace).rstrip}
|
34
|
+
@num +=1
|
35
|
+
true
|
36
|
+
end
|
37
|
+
|
38
|
+
#print_callback = callback('LP', 'I', &print_proc)
|
39
|
+
#map_callback = callback('LP', 'I', &map_proc)
|
40
|
+
|
41
|
+
puts "Top-level Windows:"
|
42
|
+
enum_windows 'TOP', &print_callback
|
43
|
+
|
44
|
+
puts
|
45
|
+
puts "Note Windows:"
|
46
|
+
print_callback[app.handle, 'NOTE']
|
47
|
+
enum_child_windows app.handle, 'CHILD', &print_callback
|
48
|
+
|
49
|
+
@child_handles.each do |handle|
|
50
|
+
enum_child_windows handle, 'CHILD', &print_callback
|
51
|
+
end
|
52
|
+
|
53
|
+
enum_windows 'TOP', &map_callback
|
54
|
+
enum_child_windows app.handle, 'CHILD', &map_callback
|
55
|
+
puts
|
56
|
+
puts "Sorted Windows:"
|
57
|
+
puts @windows.sort_by{|w| [w[:process], w[:thread], w[:handle]]}.map{|w|w.values.join(' ')}
|
58
|
+
puts "Total #{@num} Windows"
|
59
|
+
|
60
|
+
close_test_app
|
data/exp/exp_quik.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
libdir = File.join(File.dirname(__FILE__), "lib" )
|
3
|
+
$LOAD_PATH.unshift libdir unless $LOAD_PATH.include?(libdir)
|
4
|
+
require 'spec/spec_helper'
|
5
|
+
|
6
|
+
module Quik
|
7
|
+
include WinGui
|
8
|
+
extend WinGui
|
9
|
+
include GuiTest
|
10
|
+
|
11
|
+
QUIK_APP_PATH = ['C:\Program Files\Info', '\info.exe']
|
12
|
+
QUIK_APP_START = 'start "" "' + QUIK_APP_PATH.join + '"'
|
13
|
+
QUIK_MAIN_CLASS = 'InfoClass'
|
14
|
+
QUIK_DIALOG_CLASS = '#32770'
|
15
|
+
QUIK_DIALOG_TITLE = 'Идентификация пользователя'
|
16
|
+
system 'cd "' + QUIK_APP_PATH.first + '"'
|
17
|
+
system QUIK_APP_START
|
18
|
+
handle = 0
|
19
|
+
timeout(20) do
|
20
|
+
sleep TEST_SLEEP_DELAY until (handle = find_window(QUIK_MAIN_CLASS, nil))
|
21
|
+
end
|
22
|
+
p handle
|
23
|
+
quik = Window.new handle
|
24
|
+
sleep 1
|
25
|
+
p visible? quik.handle
|
26
|
+
# hide_window(quik.handle)
|
27
|
+
p window? quik.handle
|
28
|
+
p visible? quik.handle
|
29
|
+
p QUIK_DIALOG_TITLE#.force_encoding('CP1251')
|
30
|
+
p title = QUIK_DIALOG_TITLE.encode('CP1251')
|
31
|
+
dialog( title, 1) do |dlg|
|
32
|
+
child = dlg.child 'ComboLBox'
|
33
|
+
p 'Found!', child.handle
|
34
|
+
end
|
35
|
+
# quik.close
|
36
|
+
# quik.wait_for_close
|
37
|
+
|
38
|
+
end
|
data/exp/exp_wsh.rb
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'win32ole'
|
3
|
+
|
4
|
+
p WIN32OLE.codepage
|
5
|
+
|
6
|
+
def show ole, name = 'ole_obj'
|
7
|
+
puts " #{name} is: #{ole.ole_type.inspect}" if ole.respond_to? :ole_type
|
8
|
+
puts " #{name}'s Additonal methods:"
|
9
|
+
p (ole.methods - Object.methods).map(&:to_s).uniq.sort
|
10
|
+
if ole.respond_to? :ole_methods
|
11
|
+
puts " #{name}'s OLE methods:"
|
12
|
+
#p ole.ole_methods.map(&:to_s).uniq.sort
|
13
|
+
methods = ole.ole_methods.select{ |m| m.visible? }.sort{|a, b| a.to_s<=>b.to_s}
|
14
|
+
puts methods.map {|meth| signature_for meth }
|
15
|
+
end
|
16
|
+
puts
|
17
|
+
end
|
18
|
+
|
19
|
+
def signature_for meth
|
20
|
+
sig = "#{meth.return_type} "
|
21
|
+
sig += "#{meth.return_type_detail} " unless meth.return_type_detail.size == 1
|
22
|
+
sig += "#{meth.name}("
|
23
|
+
sig += meth.params.map {|param| param_for param}.join(", ") unless meth.params.empty?
|
24
|
+
sig += ")"
|
25
|
+
end
|
26
|
+
|
27
|
+
def param_for param
|
28
|
+
if param.default
|
29
|
+
"#{param.ole_type} #{param.name}=#{param.default}"
|
30
|
+
else
|
31
|
+
"#{param.ole_type} #{param.name}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Object WScript.Shell
|
36
|
+
show wsh = WIN32OLE.new('Wscript.Shell'), 'Wscript.Shell'
|
37
|
+
|
38
|
+
#wsh.Popup( 'message', 0, 'title', 1 ) # Pop-up, Doh
|
39
|
+
#puts wsh.CurrentDirectory()
|
40
|
+
show env = wsh.Environment, "wsh.Environment"
|
41
|
+
env.each {|env_item| puts " - #{env_item}"}
|
42
|
+
puts
|
43
|
+
|
44
|
+
# Echo?
|
45
|
+
#e = WIN32OLE.new('WScript.Echo "Hello World!"')
|
46
|
+
|
47
|
+
show shell = WIN32OLE.new('Shell.Application'), 'Shell.Application'
|
48
|
+
# Must be either IE or Windows Explorer
|
49
|
+
show windows = shell.Windows, 'shell.Windows'
|
50
|
+
|
51
|
+
puts "# of windows: #{windows.count.inspect}"
|
52
|
+
show windows.ole_method('GetTypeInfo'), "ole_method('GetTypeInfo')"
|
53
|
+
|
54
|
+
show expl = windows.Item(0), "windows.Item(0)"
|
55
|
+
|
56
|
+
# Playing with CD-ROM
|
57
|
+
show my_computer = shell.NameSpace(17), 'shell.NameSpace(17) - my computer'
|
58
|
+
|
59
|
+
show cdrom = my_computer.ParseName("D:\\"), 'ParseName("D:\\") - cdrom'
|
60
|
+
|
61
|
+
cdrom.Verbs.each do |verb|
|
62
|
+
show verb, verb.Name
|
63
|
+
#verb.doIt if verb.Name == "E&ject"
|
64
|
+
end
|
65
|
+
|
66
|
+
## Documenting Win32OLE
|
67
|
+
#my_com_object = WIN32OLE.new("Library.Class")
|
68
|
+
#
|
69
|
+
## Set my_com_object = GetObject("Library.Class")
|
70
|
+
#com_collection_object = WIN32OLE.connect("Library.Class")
|
71
|
+
#
|
72
|
+
## For Each com_object In com_collection_object
|
73
|
+
## '...
|
74
|
+
## Next
|
75
|
+
#for com_object in com_collection_object
|
76
|
+
# p com_object.ole_methods
|
77
|
+
##...
|
78
|
+
#end
|
79
|
+
|
80
|
+
exit 0
|
81
|
+
|
82
|
+
# Playing with Folder
|
83
|
+
time = Time.now.to_s
|
84
|
+
if wsh.AppActivate('Фолдор')
|
85
|
+
wsh.SendKeys("%FWFRB#{time}{ENTER}")
|
86
|
+
end
|
87
|
+
|
88
|
+
# Creating new Notepad window:
|
89
|
+
if not wsh.AppActivate('Notepad')
|
90
|
+
wsh.Run('Notepad')
|
91
|
+
sleep 1
|
92
|
+
end
|
93
|
+
|
94
|
+
# Playing with created Notepad window:
|
95
|
+
if wsh.AppActivate('Notepad')
|
96
|
+
sleep 1
|
97
|
+
p 'Inside'
|
98
|
+
# Enter text into Notepad:
|
99
|
+
wsh.SendKeys('Ruby{TAB}on{TAB}Windows{ENTER}')
|
100
|
+
wsh.SendKeys("#{time}")
|
101
|
+
# ALT-F to pull down File menu, then A to select Save As...:
|
102
|
+
wsh.SendKeys('%FA')
|
103
|
+
sleep 1
|
104
|
+
wsh.SendKeys('C:\dev\apps\filename.txt{ENTER}')
|
105
|
+
sleep 1
|
106
|
+
# If prompted to overwrite existing file:
|
107
|
+
|
108
|
+
if wsh.AppActivate('Save As')
|
109
|
+
sleep 1
|
110
|
+
# Enter 'Y':
|
111
|
+
wsh.SendKeys('Y')
|
112
|
+
end
|
113
|
+
# Quit Notepad with ALT-F4:
|
114
|
+
wsh.SendKeys('%{F4}')
|
115
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
require 'Win32API'
|
3
|
+
|
4
|
+
def user32(name, param_types, return_value) #(1)
|
5
|
+
Win32API.new 'user32', name, param_types, return_value
|
6
|
+
end
|
7
|
+
|
8
|
+
find_window = user32 'FindWindow', ['P', 'P'], 'L'
|
9
|
+
|
10
|
+
system 'start "" "C:/Dev/apps/gui_testing/win/locknote/LockNote.exe"'
|
11
|
+
|
12
|
+
sleep 0.2 while (main_window = find_window.call \
|
13
|
+
nil, 'LockNote - Steganos LockNote') <= 0 #(2)
|
14
|
+
|
15
|
+
puts "The main window's handle is #{main_window}."
|
16
|
+
|
17
|
+
keybd_event = user32 'keybd_event', ['I', 'I', 'L', 'L'], 'V'
|
18
|
+
|
19
|
+
KEYEVENTF_KEYDOWN = 0
|
20
|
+
KEYEVENTF_KEYUP = 2
|
21
|
+
|
22
|
+
"this is some text".upcase.each_byte do |b| #(3)
|
23
|
+
keybd_event.call b, 0, KEYEVENTF_KEYDOWN, 0
|
24
|
+
sleep 0.05
|
25
|
+
keybd_event.call b, 0, KEYEVENTF_KEYUP, 0
|
26
|
+
sleep 0.05
|
27
|
+
end
|
28
|
+
|
29
|
+
post_message = user32 'PostMessage', ['L', 'L', 'L', 'L'], 'L'
|
30
|
+
|
31
|
+
WM_SYSCOMMAND = 0x0112
|
32
|
+
SC_CLOSE = 0xF060
|
33
|
+
|
34
|
+
post_message.call main_window, WM_SYSCOMMAND, SC_CLOSE, 0
|
35
|
+
|
36
|
+
|
37
|
+
|
38
|
+
# You might need a slight delay here.
|
39
|
+
sleep 0.5
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
get_dlg_item = user32 'GetDlgItem', ['L', 'L'], 'L'
|
44
|
+
|
45
|
+
dialog = timeout(3) do #(4)
|
46
|
+
sleep 0.2 while (h = find_window.call \
|
47
|
+
nil, 'Steganos LockNote') <= 0; h #(5)
|
48
|
+
end
|
49
|
+
|
50
|
+
IDNO = 7
|
51
|
+
button = get_dlg_item.call dialog, IDNO
|
52
|
+
|
53
|
+
|
54
|
+
|
55
|
+
|
56
|
+
get_window_rect = user32 'GetWindowRect', ['L', 'P'], 'I'
|
57
|
+
|
58
|
+
rectangle = [0, 0, 0, 0].pack 'L*'
|
59
|
+
get_window_rect.call button, rectangle
|
60
|
+
left, top, right, bottom = rectangle.unpack 'L*'
|
61
|
+
|
62
|
+
puts "The No button is #{right - left} pixels wide." #(6)
|
63
|
+
|
64
|
+
|
65
|
+
|
66
|
+
|
67
|
+
set_cursor_pos = user32 'SetCursorPos', ['L', 'L'], 'I'
|
68
|
+
|
69
|
+
mouse_event = user32 'mouse_event', ['L', 'L', 'L', 'L', 'L'], 'V'
|
70
|
+
|
71
|
+
MOUSEEVENTF_LEFTDOWN = 0x0002
|
72
|
+
MOUSEEVENTF_LEFTUP = 0x0004
|
73
|
+
|
74
|
+
center = [(left + right) / 2, (top + bottom) / 2]
|
75
|
+
|
76
|
+
set_cursor_pos.call *center #(7)
|
77
|
+
|
78
|
+
mouse_event.call MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
|
79
|
+
mouse_event.call MOUSEEVENTF_LEFTUP, 0, 0, 0, 0
|
80
|
+
|
data/exp/old/wnote.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'timeout'
|
2
|
+
require 'Win32API'
|
3
|
+
|
4
|
+
def user32(name, param_types, return_value)
|
5
|
+
Win32API.new 'user32', name, param_types, return_value
|
6
|
+
end
|
7
|
+
|
8
|
+
KEYEVENTF_KEYDOWN = 0
|
9
|
+
KEYEVENTF_KEYUP = 2
|
10
|
+
WM_GETTEXT = 0x000D
|
11
|
+
IDNO = 7
|
12
|
+
WM_SYSCOMMAND = 0x0112
|
13
|
+
SC_CLOSE = 0xF060
|
14
|
+
MOUSEEVENTF_LEFTDOWN = 0x0002
|
15
|
+
MOUSEEVENTF_LEFTUP = 0x0004
|
16
|
+
|
17
|
+
class Note
|
18
|
+
def initialize
|
19
|
+
find_window = user32 'FindWindow', ['P', 'P'], 'L'
|
20
|
+
system 'start "" "C:/Dev/apps/gui_testing/lib/win/locknote/LockNote.exe"'
|
21
|
+
sleep 0.2 while (@main_window = find_window.call nil, 'LockNote - Steganos LockNote') <= 0
|
22
|
+
#type_in 'aaaaabc'
|
23
|
+
end
|
24
|
+
|
25
|
+
def type_in(text)
|
26
|
+
keybd_event = user32 'keybd_event', ['I', 'I', 'L', 'L'], 'V'
|
27
|
+
text.upcase.each_byte do |b| # upcase needed since user32 keybd_event expects upper case chars
|
28
|
+
keybd_event.call b, 0, KEYEVENTF_KEYDOWN, 0
|
29
|
+
sleep 0.05
|
30
|
+
keybd_event.call b, 0, KEYEVENTF_KEYUP, 0
|
31
|
+
sleep 0.05
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def text
|
36
|
+
find_window_ex = user32 'FindWindowEx' , ['L' , 'L' , 'P' , 'P' ], 'L'
|
37
|
+
send_message = user32 'SendMessage' , ['L' , 'L' , 'L' , 'P' ], 'L'
|
38
|
+
edit = find_window_ex.call @main_window, 0, 'ATL:00434310' , nil
|
39
|
+
buffer = "\x0" * 2048
|
40
|
+
send_message.call edit, WM_GETTEXT, buffer.length, buffer
|
41
|
+
return buffer
|
42
|
+
end
|
43
|
+
|
44
|
+
def exit!
|
45
|
+
begin
|
46
|
+
post_message = user32 'PostMessage', ['L', 'L', 'L', 'L'], 'L'
|
47
|
+
find_window = user32 'FindWindow', ['P', 'P'], 'L'
|
48
|
+
get_dlg_item = user32 'GetDlgItem', ['L', 'L'], 'L'
|
49
|
+
get_window_rect = user32 'GetWindowRect', ['L', 'P'], 'I'
|
50
|
+
set_cursor_pos = user32 'SetCursorPos', ['L', 'L'], 'I'
|
51
|
+
mouse_event = user32 'mouse_event', ['L', 'L', 'L', 'L', 'L'], 'V'
|
52
|
+
|
53
|
+
post_message.call @main_window, WM_SYSCOMMAND, SC_CLOSE, 0
|
54
|
+
|
55
|
+
sleep 0.2 # You might need a slight delay here.
|
56
|
+
|
57
|
+
dialog = timeout(3) do #(4)
|
58
|
+
sleep 0.2 while (h = find_window.call nil, 'Steganos LockNote') <= 0; h
|
59
|
+
end
|
60
|
+
|
61
|
+
button = get_dlg_item.call dialog, IDNO
|
62
|
+
|
63
|
+
rectangle = [0, 0, 0, 0].pack 'L*'
|
64
|
+
get_window_rect.call button, rectangle
|
65
|
+
left, top, right, bottom = rectangle.unpack 'L*'
|
66
|
+
center = [(left + right) / 2, (top + bottom) / 2]
|
67
|
+
|
68
|
+
set_cursor_pos.call *center #(7)
|
69
|
+
mouse_event.call MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
|
70
|
+
mouse_event.call MOUSEEVENTF_LEFTUP, 0, 0, 0, 0
|
71
|
+
|
72
|
+
@prompted = true
|
73
|
+
rescue
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def has_prompted?
|
78
|
+
@prompted
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
describe 'The main window' do
|
2
|
+
it 'launches with a welcome message' do
|
3
|
+
note = Note.new
|
4
|
+
note.text.should include('Welcome' )
|
5
|
+
note.exit!
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'exits without a prompt if nothing has changed' do
|
9
|
+
note = Note.new
|
10
|
+
note.exit!
|
11
|
+
note.should_not have_prompted
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'prompts before exiting if the document has changed' do
|
15
|
+
note = Note.new
|
16
|
+
note.type_in "changed"
|
17
|
+
note.exit!
|
18
|
+
note.should have_prompted
|
19
|
+
end
|
20
|
+
end
|
File without changes
|
Binary file
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'java'
|
2
|
+
require 'jemmy.jar'
|
3
|
+
require 'junquenote_app'
|
4
|
+
|
5
|
+
include_class 'org.netbeans.jemmy.JemmyProperties'
|
6
|
+
include_class 'org.netbeans.jemmy.TestOut'
|
7
|
+
|
8
|
+
%w(Frame TextArea MenuBar Dialog Button).each do |o| #(1)
|
9
|
+
include_class "org.netbeans.jemmy.operators.J#{o}Operator"
|
10
|
+
end
|
11
|
+
|
12
|
+
JemmyProperties.set_current_timeout 'DialogWaiter.WaitDialogTimeout', 3000 #(2)
|
13
|
+
JemmyProperties.set_current_output TestOut.get_null_output #(3)
|
14
|
+
|
15
|
+
class Note
|
16
|
+
def initialize
|
17
|
+
JunqueNoteApp.new
|
18
|
+
@main_window = JFrameOperator.new 'JunqueNote'
|
19
|
+
end
|
20
|
+
|
21
|
+
def type_in(text)
|
22
|
+
edit = JTextAreaOperator.new @main_window
|
23
|
+
edit.type_text text
|
24
|
+
end
|
25
|
+
|
26
|
+
def text
|
27
|
+
edit = JTextAreaOperator.new @main_window
|
28
|
+
edit.text
|
29
|
+
end
|
30
|
+
|
31
|
+
def exit!
|
32
|
+
begin
|
33
|
+
menu = JMenuBarOperator.new @main_window
|
34
|
+
menu.push_menu_no_block 'File|Exit', '|'
|
35
|
+
|
36
|
+
dialog = JDialogOperator.new "Quittin' time"
|
37
|
+
button = JButtonOperator.new dialog, "No"
|
38
|
+
button.push
|
39
|
+
|
40
|
+
@prompted = true
|
41
|
+
rescue
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def has_prompted?
|
46
|
+
@prompted
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#---
|
2
|
+
# Excerpted from "Scripted GUI Testing With Ruby",
|
3
|
+
# published by The Pragmatic Bookshelf.
|
4
|
+
# Copyrights apply to this code. It may not be used to create training material,
|
5
|
+
# courses, books, articles, and the like. Contact us if you are in doubt.
|
6
|
+
# We make no guarantees that this code is fit for any purpose.
|
7
|
+
# Visit http://www.pragmaticprogrammer.com/titles/idgtr for more book information.
|
8
|
+
#---
|
9
|
+
|
10
|
+
require 'java'
|
11
|
+
require 'jemmy.jar'
|
12
|
+
require 'junquenote_app'
|
13
|
+
|
14
|
+
include_class 'org.netbeans.jemmy.JemmyProperties'
|
15
|
+
include_class 'org.netbeans.jemmy.TestOut'
|
16
|
+
|
17
|
+
%w(Frame TextArea MenuBar Dialog Button).each do |o| #(1)
|
18
|
+
include_class "org.netbeans.jemmy.operators.J#{o}Operator"
|
19
|
+
end
|
20
|
+
|
21
|
+
JemmyProperties.set_current_timeout 'DialogWaiter.WaitDialogTimeout', 3000 #(2)
|
22
|
+
JemmyProperties.set_current_output TestOut.get_null_output #(3)
|
23
|
+
|
24
|
+
JunqueNoteApp.new
|
25
|
+
main_window = JFrameOperator.new 'JunqueNote'
|
26
|
+
|
27
|
+
puts "The main window's object ID is #{main_window.object_id}."
|
28
|
+
|
29
|
+
edit = JTextAreaOperator.new main_window #(4)
|
30
|
+
edit.type_text "this is some text" #(5)
|
31
|
+
|
32
|
+
menu = JMenuBarOperator.new main_window
|
33
|
+
menu.push_menu_no_block 'File|Exit', '|'
|
34
|
+
|
35
|
+
dialog = JDialogOperator.new "Quittin' time"
|
36
|
+
button = JButtonOperator.new dialog, "No"
|
37
|
+
button.push
|