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.
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