win_gui 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (164) hide show
  1. data/.document +5 -0
  2. data/.gitignore +21 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +43 -0
  5. data/Rakefile +58 -0
  6. data/VERSION +1 -0
  7. data/book_code/early_success/bundle.rb +34 -0
  8. data/book_code/early_success/english.txt +1 -0
  9. data/book_code/early_success/jruby_basics.rb +47 -0
  10. data/book_code/early_success/windows_basics.rb +97 -0
  11. data/book_code/guessing/locknote.rb +379 -0
  12. data/book_code/guessing/monkeyshines.rb +14 -0
  13. data/book_code/guessing/note.rb +120 -0
  14. data/book_code/guessing/note_spec.rb +175 -0
  15. data/book_code/guessing/replay.rb +21 -0
  16. data/book_code/guessing/seed.rb +9 -0
  17. data/book_code/guessing/spec_helper.rb +69 -0
  18. data/book_code/guessing/windows_gui.rb +247 -0
  19. data/book_code/home_stretch/junquenote.rb +151 -0
  20. data/book_code/home_stretch/locknote.rb +180 -0
  21. data/book_code/home_stretch/note.rb +144 -0
  22. data/book_code/home_stretch/note_spec.rb +191 -0
  23. data/book_code/home_stretch/spec_helper.rb +55 -0
  24. data/book_code/home_stretch/swing_gui.rb +50 -0
  25. data/book_code/home_stretch/windows_gui.rb +232 -0
  26. data/book_code/junquenote/exports.sh +10 -0
  27. data/book_code/junquenote/jruby_mac.sh +10 -0
  28. data/book_code/junquenote/junquenote_app.rb +262 -0
  29. data/book_code/novite/Rakefile +10 -0
  30. data/book_code/novite/app/controllers/application.rb +18 -0
  31. data/book_code/novite/app/controllers/guests_controller.rb +28 -0
  32. data/book_code/novite/app/controllers/parties_controller.rb +77 -0
  33. data/book_code/novite/app/helpers/application_helper.rb +11 -0
  34. data/book_code/novite/app/helpers/guests_helper.rb +10 -0
  35. data/book_code/novite/app/helpers/parties_helper.rb +10 -0
  36. data/book_code/novite/app/models/guest.rb +11 -0
  37. data/book_code/novite/app/models/party.rb +32 -0
  38. data/book_code/novite/app/models/party_mailer.rb +19 -0
  39. data/book_code/novite/app/views/layouts/application.rhtml +44 -0
  40. data/book_code/novite/app/views/parties/new.html.erb +42 -0
  41. data/book_code/novite/app/views/parties/show.html.erb +43 -0
  42. data/book_code/novite/app/views/party_mailer/invite.erb +17 -0
  43. data/book_code/novite/config/boot.rb +117 -0
  44. data/book_code/novite/config/database.yml +19 -0
  45. data/book_code/novite/config/environment.rb +67 -0
  46. data/book_code/novite/config/environments/development.rb +29 -0
  47. data/book_code/novite/config/environments/production.rb +27 -0
  48. data/book_code/novite/config/environments/test.rb +30 -0
  49. data/book_code/novite/config/initializers/inflections.rb +18 -0
  50. data/book_code/novite/config/initializers/mime_types.rb +13 -0
  51. data/book_code/novite/config/routes.rb +47 -0
  52. data/book_code/novite/db/migrate/001_create_parties.rb +26 -0
  53. data/book_code/novite/db/migrate/002_create_guests.rb +23 -0
  54. data/book_code/novite/db/schema.rb +41 -0
  55. data/book_code/novite/log/empty.txt +0 -0
  56. data/book_code/novite/public/.htaccess +40 -0
  57. data/book_code/novite/public/404.html +38 -0
  58. data/book_code/novite/public/422.html +38 -0
  59. data/book_code/novite/public/500.html +38 -0
  60. data/book_code/novite/public/dispatch.cgi +10 -0
  61. data/book_code/novite/public/dispatch.fcgi +24 -0
  62. data/book_code/novite/public/dispatch.rb +18 -0
  63. data/book_code/novite/public/favicon.ico +0 -0
  64. data/book_code/novite/public/images/rails.png +0 -0
  65. data/book_code/novite/public/index.html +285 -0
  66. data/book_code/novite/public/javascripts/application.js +10 -0
  67. data/book_code/novite/public/javascripts/controls.js +971 -0
  68. data/book_code/novite/public/javascripts/dragdrop.js +980 -0
  69. data/book_code/novite/public/javascripts/effects.js +1128 -0
  70. data/book_code/novite/public/javascripts/prototype.js +4233 -0
  71. data/book_code/novite/public/robots.txt +5 -0
  72. data/book_code/novite/script/about +3 -0
  73. data/book_code/novite/script/console +3 -0
  74. data/book_code/novite/script/destroy +3 -0
  75. data/book_code/novite/script/generate +3 -0
  76. data/book_code/novite/script/performance/benchmarker +3 -0
  77. data/book_code/novite/script/performance/profiler +3 -0
  78. data/book_code/novite/script/performance/request +3 -0
  79. data/book_code/novite/script/plugin +3 -0
  80. data/book_code/novite/script/process/inspector +3 -0
  81. data/book_code/novite/script/process/reaper +3 -0
  82. data/book_code/novite/script/process/spawner +3 -0
  83. data/book_code/novite/script/runner +3 -0
  84. data/book_code/novite/script/server +3 -0
  85. data/book_code/novite/test/test_helper.rb +46 -0
  86. data/book_code/one_more_thing/applescript.rb +68 -0
  87. data/book_code/one_more_thing/note_spec.rb +50 -0
  88. data/book_code/one_more_thing/spec_helper.rb +17 -0
  89. data/book_code/one_more_thing/textedit-pure.rb +28 -0
  90. data/book_code/one_more_thing/textedit.applescript +26 -0
  91. data/book_code/one_more_thing/textedit.rb +32 -0
  92. data/book_code/one_more_thing/textnote.rb +87 -0
  93. data/book_code/simplify/junquenote.rb +48 -0
  94. data/book_code/simplify/locknote.rb +46 -0
  95. data/book_code/simplify/note.rb +35 -0
  96. data/book_code/simplify/note_spec.rb +28 -0
  97. data/book_code/simplify/swing_gui.rb +45 -0
  98. data/book_code/simplify/windows_gui.rb +232 -0
  99. data/book_code/simplify/windows_gui_spec.rb +35 -0
  100. data/book_code/story/invite.story +19 -0
  101. data/book_code/story/journal.txt +29 -0
  102. data/book_code/story/novite_stories.rb +156 -0
  103. data/book_code/story/party.rb +149 -0
  104. data/book_code/story/password.rb +61 -0
  105. data/book_code/story/password.story +26 -0
  106. data/book_code/story/rsvp.story +29 -0
  107. data/book_code/tables/TestTime.html +93 -0
  108. data/book_code/tables/TestTimeSample.html +63 -0
  109. data/book_code/tables/calculate_time.rb +39 -0
  110. data/book_code/tables/calculator.rb +108 -0
  111. data/book_code/tables/calculator_actions.rb +27 -0
  112. data/book_code/tables/calculator_spec.rb +47 -0
  113. data/book_code/tables/fit.rb +32 -0
  114. data/book_code/tables/matrix.rb +109 -0
  115. data/book_code/tables/pseudocode.rb +17 -0
  116. data/book_code/tubes/book_selenium.rb +67 -0
  117. data/book_code/tubes/book_watir.rb +60 -0
  118. data/book_code/tubes/dragdrop.html +81 -0
  119. data/book_code/tubes/html_capture.rb +33 -0
  120. data/book_code/tubes/joke_list.rb +67 -0
  121. data/book_code/tubes/list_spec.rb +41 -0
  122. data/book_code/tubes/search_spec.rb +32 -0
  123. data/book_code/tubes/selenium_example.rb +66 -0
  124. data/book_code/tubes/selenium_link.rb +23 -0
  125. data/book_code/tubes/web_server.rb +14 -0
  126. data/book_code/windows/wgui.rb +29 -0
  127. data/book_code/windows/wobj.rb +25 -0
  128. data/book_code/windows/wsh.rb +25 -0
  129. data/book_code/with_rspec/empty_spec.rb +13 -0
  130. data/book_code/with_rspec/junquenote.rb +60 -0
  131. data/book_code/with_rspec/locknote.rb +129 -0
  132. data/book_code/with_rspec/note_spec.rb +32 -0
  133. data/book_code/with_rspec/should_examples.rb +18 -0
  134. data/exp/exp.rb +6 -0
  135. data/exp/exp_encodings.rb +40 -0
  136. data/exp/exp_enum_windows.rb +60 -0
  137. data/exp/exp_quik.rb +38 -0
  138. data/exp/exp_wsh.rb +115 -0
  139. data/exp/old/windows_basics.rb +80 -0
  140. data/exp/old/wnote.rb +80 -0
  141. data/exp/old/wnote_spec.rb +20 -0
  142. data/features/step_definitions/win_gui_steps.rb +0 -0
  143. data/features/support/env.rb +4 -0
  144. data/features/win_gui.feature +9 -0
  145. data/lib/note/java/jemmy.jar +0 -0
  146. data/lib/note/java/jnote.rb +48 -0
  147. data/lib/note/java/jruby_basics.rb +37 -0
  148. data/lib/note/java/junquenote_app.rb +262 -0
  149. data/lib/note/java/note_spec.rb +20 -0
  150. data/lib/note/win/locknote.rb +19 -0
  151. data/lib/note.rb +15 -0
  152. data/lib/win_gui/constants.rb +66 -0
  153. data/lib/win_gui/string_extensions.rb +24 -0
  154. data/lib/win_gui/win_gui.rb +274 -0
  155. data/lib/win_gui/window.rb +70 -0
  156. data/lib/win_gui.rb +3 -0
  157. data/spec/note/win/locknote_spec.rb +7 -0
  158. data/spec/spec.opts +2 -0
  159. data/spec/spec_helper.rb +100 -0
  160. data/spec/test_apps/locknote/LockNote.exe +0 -0
  161. data/spec/win_gui/string_extensions_spec.rb +61 -0
  162. data/spec/win_gui/win_gui_spec.rb +733 -0
  163. data/spec/win_gui/window_spec.rb +124 -0
  164. 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,6 @@
1
+
2
+ p File.dirname(__FILE__),__FILE__, __LINE__
3
+ p __LINE__, File.open(__FILE__).lines.to_a[__LINE__-1]
4
+
5
+
6
+
@@ -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
@@ -0,0 +1,4 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
+ require 'win_gui'
3
+
4
+ require 'spec/expectations'
@@ -0,0 +1,9 @@
1
+ Feature: something something
2
+ In order to something something
3
+ A user something something
4
+ something something something
5
+
6
+ Scenario: something something
7
+ Given inspiration
8
+ When I create a sweet new gem
9
+ Then everyone should see how awesome I am
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