win_gui 0.1.0
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/.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
|