win_gui 0.1.6 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (169) hide show
  1. data/.gitignore +21 -21
  2. data/HISTORY +7 -0
  3. data/LICENSE +20 -20
  4. data/README.rdoc +77 -114
  5. data/Rakefile +24 -58
  6. data/VERSION +1 -1
  7. data/features/support/env.rb +7 -4
  8. data/features/win_gui.feature +9 -9
  9. data/lib/version.rb +8 -0
  10. data/lib/win_gui/window.rb +78 -69
  11. data/lib/win_gui.rb +25 -3
  12. data/spec/spec.opts +1 -1
  13. data/spec/spec_helper.rb +90 -118
  14. data/spec/win_gui/window_spec.rb +120 -123
  15. data/tasks/common.rake +14 -0
  16. data/tasks/doc.rake +14 -0
  17. data/tasks/gem.rake +39 -0
  18. data/tasks/git.rake +34 -0
  19. data/tasks/spec.rake +19 -0
  20. data/tasks/version.rake +71 -0
  21. metadata +68 -188
  22. data/.document +0 -5
  23. data/book_code/early_success/bundle.rb +0 -34
  24. data/book_code/early_success/english.txt +0 -1
  25. data/book_code/early_success/jruby_basics.rb +0 -47
  26. data/book_code/early_success/windows_basics.rb +0 -97
  27. data/book_code/guessing/locknote.rb +0 -379
  28. data/book_code/guessing/monkeyshines.rb +0 -14
  29. data/book_code/guessing/note.rb +0 -120
  30. data/book_code/guessing/note_spec.rb +0 -175
  31. data/book_code/guessing/replay.rb +0 -21
  32. data/book_code/guessing/seed.rb +0 -9
  33. data/book_code/guessing/spec_helper.rb +0 -69
  34. data/book_code/guessing/windows_gui.rb +0 -247
  35. data/book_code/home_stretch/junquenote.rb +0 -151
  36. data/book_code/home_stretch/locknote.rb +0 -180
  37. data/book_code/home_stretch/note.rb +0 -144
  38. data/book_code/home_stretch/note_spec.rb +0 -191
  39. data/book_code/home_stretch/spec_helper.rb +0 -55
  40. data/book_code/home_stretch/swing_gui.rb +0 -50
  41. data/book_code/home_stretch/windows_gui.rb +0 -232
  42. data/book_code/junquenote/exports.sh +0 -10
  43. data/book_code/junquenote/jruby_mac.sh +0 -10
  44. data/book_code/junquenote/junquenote_app.rb +0 -262
  45. data/book_code/novite/Rakefile +0 -10
  46. data/book_code/novite/app/controllers/application.rb +0 -18
  47. data/book_code/novite/app/controllers/guests_controller.rb +0 -28
  48. data/book_code/novite/app/controllers/parties_controller.rb +0 -77
  49. data/book_code/novite/app/helpers/application_helper.rb +0 -11
  50. data/book_code/novite/app/helpers/guests_helper.rb +0 -10
  51. data/book_code/novite/app/helpers/parties_helper.rb +0 -10
  52. data/book_code/novite/app/models/guest.rb +0 -11
  53. data/book_code/novite/app/models/party.rb +0 -32
  54. data/book_code/novite/app/models/party_mailer.rb +0 -19
  55. data/book_code/novite/app/views/layouts/application.rhtml +0 -44
  56. data/book_code/novite/app/views/parties/new.html.erb +0 -42
  57. data/book_code/novite/app/views/parties/show.html.erb +0 -43
  58. data/book_code/novite/app/views/party_mailer/invite.erb +0 -17
  59. data/book_code/novite/config/boot.rb +0 -117
  60. data/book_code/novite/config/database.yml +0 -19
  61. data/book_code/novite/config/environment.rb +0 -67
  62. data/book_code/novite/config/environments/development.rb +0 -29
  63. data/book_code/novite/config/environments/production.rb +0 -27
  64. data/book_code/novite/config/environments/test.rb +0 -30
  65. data/book_code/novite/config/initializers/inflections.rb +0 -18
  66. data/book_code/novite/config/initializers/mime_types.rb +0 -13
  67. data/book_code/novite/config/routes.rb +0 -47
  68. data/book_code/novite/db/migrate/001_create_parties.rb +0 -26
  69. data/book_code/novite/db/migrate/002_create_guests.rb +0 -23
  70. data/book_code/novite/db/schema.rb +0 -41
  71. data/book_code/novite/log/empty.txt +0 -0
  72. data/book_code/novite/public/.htaccess +0 -40
  73. data/book_code/novite/public/404.html +0 -38
  74. data/book_code/novite/public/422.html +0 -38
  75. data/book_code/novite/public/500.html +0 -38
  76. data/book_code/novite/public/dispatch.cgi +0 -10
  77. data/book_code/novite/public/dispatch.fcgi +0 -24
  78. data/book_code/novite/public/dispatch.rb +0 -18
  79. data/book_code/novite/public/favicon.ico +0 -0
  80. data/book_code/novite/public/images/rails.png +0 -0
  81. data/book_code/novite/public/index.html +0 -285
  82. data/book_code/novite/public/javascripts/application.js +0 -10
  83. data/book_code/novite/public/javascripts/controls.js +0 -971
  84. data/book_code/novite/public/javascripts/dragdrop.js +0 -980
  85. data/book_code/novite/public/javascripts/effects.js +0 -1128
  86. data/book_code/novite/public/javascripts/prototype.js +0 -4233
  87. data/book_code/novite/public/robots.txt +0 -5
  88. data/book_code/novite/script/about +0 -3
  89. data/book_code/novite/script/console +0 -3
  90. data/book_code/novite/script/destroy +0 -3
  91. data/book_code/novite/script/generate +0 -3
  92. data/book_code/novite/script/performance/benchmarker +0 -3
  93. data/book_code/novite/script/performance/profiler +0 -3
  94. data/book_code/novite/script/performance/request +0 -3
  95. data/book_code/novite/script/plugin +0 -3
  96. data/book_code/novite/script/process/inspector +0 -3
  97. data/book_code/novite/script/process/reaper +0 -3
  98. data/book_code/novite/script/process/spawner +0 -3
  99. data/book_code/novite/script/runner +0 -3
  100. data/book_code/novite/script/server +0 -3
  101. data/book_code/novite/test/test_helper.rb +0 -46
  102. data/book_code/one_more_thing/applescript.rb +0 -68
  103. data/book_code/one_more_thing/note_spec.rb +0 -50
  104. data/book_code/one_more_thing/spec_helper.rb +0 -17
  105. data/book_code/one_more_thing/textedit-pure.rb +0 -28
  106. data/book_code/one_more_thing/textedit.applescript +0 -26
  107. data/book_code/one_more_thing/textedit.rb +0 -32
  108. data/book_code/one_more_thing/textnote.rb +0 -87
  109. data/book_code/simplify/junquenote.rb +0 -48
  110. data/book_code/simplify/locknote.rb +0 -46
  111. data/book_code/simplify/note.rb +0 -35
  112. data/book_code/simplify/note_spec.rb +0 -28
  113. data/book_code/simplify/swing_gui.rb +0 -45
  114. data/book_code/simplify/windows_gui.rb +0 -232
  115. data/book_code/simplify/windows_gui_spec.rb +0 -35
  116. data/book_code/story/invite.story +0 -19
  117. data/book_code/story/journal.txt +0 -29
  118. data/book_code/story/novite_stories.rb +0 -156
  119. data/book_code/story/party.rb +0 -149
  120. data/book_code/story/password.rb +0 -61
  121. data/book_code/story/password.story +0 -26
  122. data/book_code/story/rsvp.story +0 -29
  123. data/book_code/tables/TestTime.html +0 -93
  124. data/book_code/tables/TestTimeSample.html +0 -63
  125. data/book_code/tables/calculate_time.rb +0 -39
  126. data/book_code/tables/calculator.rb +0 -108
  127. data/book_code/tables/calculator_actions.rb +0 -27
  128. data/book_code/tables/calculator_spec.rb +0 -47
  129. data/book_code/tables/fit.rb +0 -32
  130. data/book_code/tables/matrix.rb +0 -109
  131. data/book_code/tables/pseudocode.rb +0 -17
  132. data/book_code/tubes/book_selenium.rb +0 -67
  133. data/book_code/tubes/book_watir.rb +0 -60
  134. data/book_code/tubes/dragdrop.html +0 -81
  135. data/book_code/tubes/html_capture.rb +0 -33
  136. data/book_code/tubes/joke_list.rb +0 -67
  137. data/book_code/tubes/list_spec.rb +0 -41
  138. data/book_code/tubes/search_spec.rb +0 -32
  139. data/book_code/tubes/selenium_example.rb +0 -66
  140. data/book_code/tubes/selenium_link.rb +0 -23
  141. data/book_code/tubes/web_server.rb +0 -14
  142. data/book_code/windows/wgui.rb +0 -29
  143. data/book_code/windows/wobj.rb +0 -25
  144. data/book_code/windows/wsh.rb +0 -25
  145. data/book_code/with_rspec/empty_spec.rb +0 -13
  146. data/book_code/with_rspec/junquenote.rb +0 -60
  147. data/book_code/with_rspec/locknote.rb +0 -129
  148. data/book_code/with_rspec/note_spec.rb +0 -32
  149. data/book_code/with_rspec/should_examples.rb +0 -18
  150. data/lib/note/java/jemmy.jar +0 -0
  151. data/lib/note/java/jnote.rb +0 -48
  152. data/lib/note/java/jruby_basics.rb +0 -37
  153. data/lib/note/java/junquenote_app.rb +0 -262
  154. data/lib/note/java/note_spec.rb +0 -20
  155. data/lib/note/win/locknote.rb +0 -19
  156. data/lib/note.rb +0 -15
  157. data/lib/win_gui/constants.rb +0 -82
  158. data/lib/win_gui/def_api.rb +0 -160
  159. data/lib/win_gui/string_extensions.rb +0 -36
  160. data/lib/win_gui/win_gui.rb +0 -437
  161. data/old/windows_basics.rb +0 -80
  162. data/old/wnote.rb +0 -80
  163. data/old/wnote_spec.rb +0 -20
  164. data/spec/note/win/locknote_spec.rb +0 -7
  165. data/spec/test_apps/locknote/LockNote.exe +0 -0
  166. data/spec/win_gui/def_api_spec.rb +0 -339
  167. data/spec/win_gui/string_extensions_spec.rb +0 -61
  168. data/spec/win_gui/win_gui_spec.rb +0 -537
  169. data/win_gui.gemspec +0 -215
@@ -1,232 +0,0 @@
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
- class String
11
- def snake_case
12
- gsub(/([a-z])([A-Z0-9])/, '\1_\2').downcase #(1)
13
- end
14
- end
15
-
16
-
17
-
18
-
19
- require 'Win32API'
20
-
21
- module WindowsGui
22
- def self.def_api(function, parameters, return_value) #(2)
23
- api = Win32API.new 'user32', function, parameters, return_value
24
-
25
- define_method(function.snake_case) do |*args| #(3)
26
- api.call *args #(4)
27
- end
28
- end
29
- end
30
-
31
-
32
-
33
-
34
- module WindowsGui
35
- def_api 'FindWindow', ['P', 'P'], 'L'
36
- def_api 'keybd_event', ['I', 'I', 'L', 'L'], 'V'
37
-
38
- # rest of API definitions here...
39
-
40
- WM_GETTEXT = 0x000D
41
- WM_SYSCOMMAND = 0x0112
42
-
43
- # rest of constant definitions here...
44
- end
45
-
46
-
47
-
48
- module WindowsGui
49
- def_api 'FindWindow', ['P', 'P'], 'L'
50
- def_api 'FindWindowEx', ['L', 'L', 'P', 'P'], 'L'
51
- def_api 'PostMessage', ['L', 'L', 'L', 'L'], 'L'
52
- def_api 'SendMessage', ['L', 'L', 'L', 'P'], 'L'
53
- def_api 'keybd_event', ['I', 'I', 'L', 'L'], 'V'
54
- def_api 'GetDlgItem', ['L', 'L'], 'L'
55
- def_api 'GetWindowRect', ['L', 'P'], 'I'
56
- def_api 'SetCursorPos', ['L', 'L'], 'I'
57
- def_api 'mouse_event', ['L', 'L', 'L', 'L', 'L'], 'V'
58
- def_api 'IsWindowVisible', ['L'], 'L'
59
-
60
- SC_CLOSE = 0xF060
61
-
62
- IDNO = 7
63
-
64
- MOUSEEVENTF_LEFTDOWN = 0x0002
65
- MOUSEEVENTF_LEFTUP = 0x0004
66
-
67
- KEYEVENTF_KEYDOWN = 0
68
- KEYEVENTF_KEYUP = 2
69
- end
70
-
71
-
72
-
73
- module WindowsGui
74
- VK_SHIFT = 0x10
75
- VK_CONTROL = 0x11
76
- VK_BACK = 0x08
77
- end
78
-
79
-
80
-
81
-
82
- class String
83
- def to_keys
84
- unless size == 1 #(5)
85
- raise "conversion is for single characters only"
86
- end
87
-
88
- ascii = unpack('C')[0] #(6)
89
-
90
- case self #(7)
91
- when '0'..'9'
92
- [ascii - ?0 + 0x30]
93
- when 'A'..'Z'
94
- [WindowsGui.const_get(:VK_SHIFT), ascii]
95
- when 'a'..'z'
96
- [ascii - ?a + ?A]
97
- when ' '
98
- [ascii]
99
- else
100
- raise "Can't convert unknown character #{self}"
101
- end
102
- end
103
- end
104
-
105
-
106
-
107
-
108
- module WindowsGui
109
- def keystroke(*keys)
110
- return if keys.empty?
111
-
112
- keybd_event keys.first, 0, KEYEVENTF_KEYDOWN, 0
113
- sleep 0.05
114
- keystroke *keys[1..-1]
115
- sleep 0.05
116
- keybd_event keys.first, 0, KEYEVENTF_KEYUP, 0
117
- end
118
- end
119
-
120
-
121
-
122
-
123
- module WindowsGui
124
- def type_in(message)
125
- message.scan(/./m) do |char|
126
- keystroke(*char.to_keys)
127
- end
128
- end
129
- end
130
-
131
-
132
-
133
-
134
- module WindowsGui
135
- class Window
136
- include WindowsGui #(8)
137
-
138
- attr_reader :handle
139
-
140
- def initialize(handle)
141
- @handle = handle
142
- end
143
-
144
- def close
145
- post_message @handle, WM_SYSCOMMAND, SC_CLOSE, 0
146
- end
147
-
148
- def wait_for_close #(9)
149
- timeout(5) do
150
- sleep 0.2 until 0 == is_window_visible(@handle)
151
- end
152
- end
153
-
154
- def text
155
- buffer = '\0' * 2048
156
- length = send_message @handle, WM_GETTEXT, buffer.length, buffer
157
- length == 0 ? '' : buffer[0..length - 1]
158
- end
159
- end
160
- end
161
-
162
-
163
-
164
-
165
- class WindowsGui::Window
166
- extend WindowsGui #(10)
167
-
168
- def self.top_level(title, seconds=3)
169
- @handle = timeout(seconds) do
170
- sleep 0.2 while (h = find_window nil, title) <= 0; h
171
- end
172
-
173
- Window.new @handle
174
- end
175
- end
176
-
177
-
178
-
179
-
180
- class WindowsGui::Window
181
- def child(id)
182
- result = case id
183
- when String
184
- by_title = find_window_ex @handle, 0, nil, id.gsub('_', '&') #(11)
185
- by_class = find_window_ex @handle, 0, id, nil
186
- by_title > 0 ? by_title : by_class
187
- when Fixnum
188
- get_dlg_item @handle, id
189
- else
190
- 0
191
- end
192
-
193
- raise "Control '#{id}' not found" if result == 0
194
- Window.new result
195
- end
196
- end
197
-
198
-
199
-
200
-
201
- class WindowsGui::Window
202
- def click(id)
203
- h = child(id).handle
204
-
205
- rectangle = [0, 0, 0, 0].pack 'LLLL'
206
- get_window_rect h, rectangle
207
- left, top, right, bottom = rectangle.unpack 'LLLL'
208
-
209
- center = [(left + right) / 2, (top + bottom) / 2]
210
- set_cursor_pos *center
211
-
212
- mouse_event MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
213
- mouse_event MOUSEEVENTF_LEFTUP, 0, 0, 0, 0
214
- end
215
- end
216
-
217
-
218
-
219
-
220
- module WindowsGui
221
- def dialog(title, seconds=3)
222
- d = begin
223
- w = Window.top_level(title, seconds)
224
- yield(w) ? w : nil #(12)
225
- rescue TimeoutError
226
- end
227
-
228
- d.wait_for_close if d
229
- return d
230
- end
231
- end
232
-
@@ -1,35 +0,0 @@
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 'windows_gui'
11
-
12
- describe WindowsGui do #(1)
13
- include WindowsGui
14
-
15
- it 'wraps a Windows call with a method' do
16
- find_window(nil, nil).should_not == 0 #(2)
17
- end
18
-
19
- it 'enforces the argument count' do
20
- lambda {find_window}.should raise_error #(3)
21
- end
22
- end
23
-
24
-
25
-
26
-
27
- describe String, '#snake_case' do
28
- it 'transforms CamelCase strings' do
29
- 'GetCharWidth32'.snake_case.should == 'get_char_width_32'
30
- end
31
-
32
- it 'leaves snake_case strings intact' do
33
- 'keybd_event'.snake_case.should == 'keybd_event'
34
- end
35
- end
@@ -1,19 +0,0 @@
1
- Story: minimalist invites
2
- As a host with lots to do
3
- I want to plan a party with a minimum of mouse clicks
4
- So that I can get on with the rest of my tasks
5
-
6
- Scenario: manual invites
7
- Given a party called "Celebration"
8
- And a description of "There's a party goin' on"
9
- And a location of "Right here"
10
- And a starting time of September 29, 2010 at 12:30 PM
11
- And an ending time of September 29, 2010 at 12:35 PM
12
-
13
- When I view the invitation
14
- Then I should see the Web address to send to my friends
15
- And the name should be "Celebration"
16
- And the description should be "There's a party goin' on"
17
- And the location should be "Right here"
18
- And the party should begin on September 29, 2010 at 12:30 PM
19
- And the party should end on September 29, 2010 at 12:35 PM
@@ -1,29 +0,0 @@
1
- Make sure you install the Selenium gem, with a capital S.
2
-
3
- First story.
4
-
5
- Add browser code.
6
-
7
- ./script/generate rspec_scaffold Party name:string description:text location:text begins_at:datetime ends_at:datetime
8
-
9
- rake db:migrate
10
-
11
- ./script/generate migration AddLinkToParty link:string
12
-
13
- Edit view.
14
-
15
- RESTful with to_param
16
-
17
- Make sure date/time updates!!!!
18
-
19
- Scenario: email invites
20
- Given a blank invitation
21
- When I plan a party called "Celebration"
22
- And I enter a description of "Good times, come on"
23
- And I enter a location of "Right here in Jersey City, NJ"
24
- And I enter a starting time of "Sep. 29, 1980, 8 PM"
25
- And I enter an ending time of "Sep. 29, 1980, 10 PM"
26
- And I enter a recipient address of "example@example.com"
27
- Then I should see an email preview
28
- When I confirm the email
29
- Then I should see a confirmation
@@ -1,156 +0,0 @@
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 'rubygems'
11
- require 'spec/story'
12
- require 'chronic'
13
- require 'party'
14
-
15
- class Listener
16
- attr_reader :browser
17
-
18
- def run_started(num_scenarios)
19
- @browser = Selenium::SeleniumDriver.new \
20
- 'localhost', 4444, '*firefox', 'http://localhost:3000', 10000
21
- @browser.start
22
- end
23
-
24
- def run_ended
25
- @browser.stop
26
- end
27
-
28
- def method_missing(name, *args, &block)
29
- # We don't care about the rest of the Story Runner events.
30
- end
31
- end
32
-
33
- listener = Listener.new
34
- Spec::Story::Runner.register_listener(listener)
35
-
36
-
37
-
38
-
39
- steps_for :planning do
40
- Given 'a party called "$name"' do |name|
41
- @party = Party.new(listener.browser)
42
- @party.name = name
43
- end
44
-
45
- Given 'a description of "$desc"' do |desc|
46
- @party.description = desc
47
- end
48
-
49
- Given 'a location of "$loc"' do |loc|
50
- @party.location = loc
51
- end
52
-
53
- Given /an? $event time of $sometime/ do |event, sometime| #(1)
54
- clean = sometime.gsub ',', ' '
55
- date_time = Chronic.parse clean, :now => Time.now - 86400 #(2)
56
-
57
- if event == 'starting'
58
- @party.begins_at = date_time
59
- else
60
- @party.ends_at = date_time
61
- end
62
- end
63
-
64
- When 'I view the invitation' do
65
- @party.save_and_view
66
- end
67
- end
68
-
69
-
70
-
71
-
72
- steps_for :reviewing do
73
- Then 'the $setting should be "$value"' do |setting, value|
74
- @party.send(setting).should == value
75
- end
76
-
77
- Then 'the party should $event on $date_time' do |event, date_time|
78
- actual_time =
79
- (event == 'begin') ?
80
- @party.begins_at :
81
- @party.ends_at
82
-
83
- clean = date_time.gsub ',', ' '
84
- expected_time = Chronic.parse clean, :now => Time.now - 86400
85
-
86
- actual_time.should == expected_time
87
- end
88
-
89
- Then 'I should see the Web address to send to my friends' do
90
- @party.link.should match(%r{^http://})
91
- end
92
- end
93
-
94
-
95
-
96
-
97
- steps_for :rsvp do
98
- Then 'I should see the party details' do
99
- @party.should have_name
100
- @party.should have_description
101
- @party.should have_location
102
- @party.should have_times
103
- end
104
-
105
- When /I answer that "$guest" will( not)? attend/ do |guest, answer|
106
- attending = !answer.include?('not')
107
- @party.rsvp guest, attending
108
- end
109
-
110
- Then 'I should see "$guest" in the list of $type' do |guest, type|
111
- want_attending = (type == 'partygoers')
112
- @party.responses(want_attending).should include(guest)
113
- end
114
- end
115
-
116
-
117
-
118
-
119
- steps_for :email do
120
- Given 'a guest list of "$list"' do |list|
121
- @party.recipients = list
122
- end
123
-
124
- Then 'I should see that e-mail was sent to "$list"' do |list|
125
- @party.notice.include?(list).should be_true
126
- end
127
-
128
- When 'I view the e-mail that was sent to "$address"' do |address|
129
- @email = @party.email_to address
130
- end
131
-
132
- Then 'I should see "Yes/No" links' do
133
- @email.should match(%r{Yes - http://})
134
- @email.should match(%r{No - http://})
135
- end
136
-
137
- When 'I follow the "$answer" link' do |answer|
138
- link = %r{#{answer} - (http://.+)}.match(@email)[1]
139
- @party.rsvp_at link
140
- end
141
- end
142
-
143
-
144
-
145
-
146
- with_steps_for :planning, :reviewing do
147
- run 'invite.story'
148
- end
149
-
150
-
151
-
152
-
153
- with_steps_for :planning, :reviewing, :rsvp, :email do
154
- run 'rsvp.story'
155
- end
156
-
@@ -1,149 +0,0 @@
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 'rubygems'
11
- require 'selenium'
12
- require 'time'
13
-
14
- class Party
15
- def initialize(browser)
16
- @browser = browser
17
- @browser.open '/parties/new'
18
- end
19
-
20
- def self.def_setting(setting, type = :read_write)
21
- if type == :readable || type == :read_write
22
- define_method(setting) do
23
- @browser.get_text("id=party_#{setting}")
24
- end
25
-
26
- define_method("has_#{setting}?") do
27
- send(setting) rescue nil
28
- end
29
- end
30
-
31
- if type == :writable || type == :read_write
32
- define_method("#{setting}=") do |value|
33
- @browser.type "id=party_#{setting}", value
34
- end
35
- end
36
- end
37
-
38
- def_setting :name
39
- def_setting :description
40
- def_setting :location
41
- def_setting :link, :readable
42
- def_setting :notice, :readable
43
- def_setting :recipients, :writable
44
- end
45
-
46
-
47
-
48
-
49
- class Party
50
- def begins_at=(time); set_time(:begin, time) end
51
- def ends_at= (time); set_time(:end, time) end
52
-
53
- def set_time(event, time)
54
- ['%Y', '%B', '%d', '%H', '%M'].each_with_index do |part, index|
55
- element = "id=party_#{event}s_at_#{index + 1}i"
56
- value = time.strftime part
57
-
58
- @browser.select element, value
59
- end
60
- end
61
- end
62
-
63
-
64
-
65
-
66
- class Party
67
- def begins_at; get_times.first end
68
- def ends_at; get_times.last end
69
-
70
- def get_times
71
- begins_on = @browser.get_text 'party_begins_on'
72
- begins_at = @browser.get_text 'party_begins_at'
73
- ends_at = @browser.get_text 'party_ends_at'
74
-
75
- begins = Time.parse(begins_on + ' ' + begins_at)
76
- ends = Time.parse(begins_on + ' ' + ends_at)
77
- ends += 86400 if ends < begins
78
-
79
- [begins, ends]
80
- end
81
-
82
- def has_times?
83
- get_times rescue nil
84
- end
85
- end
86
-
87
-
88
-
89
-
90
- class Party
91
- def save_and_view
92
- @browser.click 'id=party_submit'
93
- @browser.wait_for_page_to_load 5000
94
- @saved = true
95
- end
96
- end
97
-
98
-
99
-
100
-
101
- class Party
102
- def rsvp(name, attending)
103
- @browser.type 'guest_name', name
104
- @browser.click 'guest_attending' unless attending
105
- @browser.click 'rsvp'
106
- @browser.wait_for_page_to_load 5000
107
- end
108
- end
109
-
110
-
111
-
112
-
113
- class Party
114
- RsvpItem = '//ul[@id="guests"]/li'
115
-
116
- def responses(want_attending)
117
- num_guests = @browser.get_xpath_count(RsvpItem).to_i
118
- return [] unless num_guests >= 1
119
-
120
- all = (1..num_guests).map do |i|
121
- name = @browser.get_text \
122
- "#{RsvpItem}[#{i}]/span[@class='rsvp_name']"
123
- rsvp = @browser.get_text \
124
- "#{RsvpItem}[#{i}]/span[@class='rsvp_attending']"
125
- [name, rsvp]
126
- end
127
-
128
- matching = all.select do |name, rsvp|
129
- is_attending = !rsvp.include?('not')
130
- !(want_attending ^ is_attending)
131
- end
132
-
133
- matching.map {|name, rsvp| name}
134
- end
135
- end
136
-
137
-
138
-
139
-
140
- class Party
141
- def email_to(address)
142
- @browser.open link + '.txt?email=' + address
143
- @browser.get_body_text
144
- end
145
-
146
- def rsvp_at(rsvp_link)
147
- @browser.open rsvp_link
148
- end
149
- end
@@ -1,61 +0,0 @@
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 'rubygems'
11
- require 'spec/story'
12
-
13
- steps_for :app_state do #(1)
14
- Given 'a new document' do
15
- @note = Note.open
16
- end
17
-
18
- When 'I exit the app' do
19
- @note.exit!
20
- end
21
-
22
- Then 'the app should be running' do
23
- @note.should be_running
24
- end
25
- end
26
-
27
-
28
-
29
-
30
- steps_for :documents do
31
- When 'I type "$something"' do |something|
32
- @note.text = something
33
- end
34
-
35
- When 'I save the document as "$name" with password "$password"' do #(2)
36
- |name, password|
37
- @note.save_as name, :password => password
38
- end
39
-
40
- When 'I open the document "$name" with password "$password"' do
41
- |name, password|
42
- @note = Note.open name, :password => password
43
- end
44
-
45
- When 'I change the password from "$old" to "$password"' do
46
- |old, password|
47
- @note.change_password :old_password => old, :password => password
48
- end
49
-
50
- Then 'the text should be "$something"' do |something|
51
- @note.text.should == something
52
- end
53
- end
54
-
55
-
56
-
57
-
58
- with_steps_for :app_state, :documents do
59
- run 'password.story'
60
- end
61
-
@@ -1,26 +0,0 @@
1
- START: password_story
2
- Story: Password protection
3
-
4
- As a security-conscious person
5
- I want to encrypt each document with a password
6
- So that only I (and the NSA) can read it
7
- END: password_story
8
-
9
- START: password_scenario
10
- Scenario: Changing the password
11
- Given a new document
12
- When I type "this is my document"
13
- And I save the document as "Secrets" with password "unguessable"
14
- And I exit the app
15
- And I open the document "Secrets" with password "unguessable"
16
- Then the app should be running
17
- And the text should be "this is my document"
18
-
19
- When I change the password from "unguessable" to "uncrackable"
20
- And I exit the app
21
- And I open the document "Secrets" with password "uncrackable"
22
- Then the app should be running
23
- And the text should be "this is my document"
24
- END: password_scenario
25
-
26
- When I exit the app