rwebspec 4.2.1 → 4.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +3 -0
- data/Rakefile +1 -1
- data/lib/rwebspec-common/{test_utils.rb → core.rb} +492 -396
- data/lib/rwebspec-common/load_test_helper.rb +1 -1
- data/lib/rwebspec-common/rspec_helper.rb +2 -2
- data/lib/rwebspec-common/test_script.rb +2 -2
- data/lib/rwebspec-common/web_page.rb +6 -2
- data/lib/rwebspec-common/web_testcase.rb +1 -1
- data/lib/rwebspec-watir/driver.rb +5 -11
- data/lib/rwebspec-watir/web_browser.rb +5 -0
- data/lib/rwebspec-webdriver/driver.rb +4 -22
- data/lib/rwebspec-webdriver/web_browser.rb +5 -5
- data/lib/rwebspec.rb +31 -8
- metadata +3 -3
data/CHANGELOG
CHANGED
data/Rakefile
CHANGED
@@ -78,7 +78,7 @@ end
|
|
78
78
|
spec = Gem::Specification.new do |s|
|
79
79
|
s.platform= Gem::Platform::RUBY
|
80
80
|
s.name = "rwebspec"
|
81
|
-
s.version = "4.
|
81
|
+
s.version = "4.3.1"
|
82
82
|
s.summary = "Web application functional specification in Ruby"
|
83
83
|
s.description = "Executable functional specification for web applications in RSpec syntax with Watir or Selenium"
|
84
84
|
|
@@ -1,396 +1,492 @@
|
|
1
|
-
#***********************************************************
|
2
|
-
#* Copyright (c) 2006, Zhimin Zhan.
|
3
|
-
#* Distributed open-source, see full license in MIT-LICENSE
|
4
|
-
#***********************************************************
|
5
|
-
|
6
|
-
# useful hekoer methods for testing
|
7
|
-
#
|
8
|
-
module RWebSpec
|
9
|
-
module
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
end
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
#
|
111
|
-
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
end
|
133
|
-
|
134
|
-
alias
|
135
|
-
alias
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
# default
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
#
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
end
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
#
|
210
|
-
def
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
def
|
227
|
-
|
228
|
-
end
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
alias
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
#
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
#
|
260
|
-
#
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
#
|
270
|
-
#
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
1
|
+
#***********************************************************
|
2
|
+
#* Copyright (c) 2006, Zhimin Zhan.
|
3
|
+
#* Distributed open-source, see full license in MIT-LICENSE
|
4
|
+
#***********************************************************
|
5
|
+
|
6
|
+
# useful hekoer methods for testing
|
7
|
+
#
|
8
|
+
module RWebSpec
|
9
|
+
module Core
|
10
|
+
|
11
|
+
# open a browser, and set base_url via hash, but does not acually
|
12
|
+
#
|
13
|
+
# example:
|
14
|
+
# open_browser :base_url => http://localhost:8080, :browser => :ie
|
15
|
+
#
|
16
|
+
# There are 3 ways to set base url
|
17
|
+
# 1. pass as first argument
|
18
|
+
# 2. If running using TestWise, used as confiured
|
19
|
+
# 3. Use default value set
|
20
|
+
#
|
21
|
+
#
|
22
|
+
# New Options:
|
23
|
+
# :browser => :ie | :firefox | :chrome
|
24
|
+
def open_browser(opts = {})
|
25
|
+
puts "[INFO] RWebSpec.Framework currently set to => #{RWebSpec.framework }"
|
26
|
+
=begin
|
27
|
+
if RWebSpec.framework =~ /watir/i
|
28
|
+
RWebSpec.load_watir
|
29
|
+
self.class.send(:include, RWebSpec::Driver)
|
30
|
+
load(File.dirname(__FILE__) + "/web_page.rb")
|
31
|
+
return open_browser_by_watir(opts)
|
32
|
+
end
|
33
|
+
|
34
|
+
if RWebSpec.framework =~ /selenium/i
|
35
|
+
RWebSpec.load_selenium
|
36
|
+
self.class.send(:include, RWebSpec::Driver)
|
37
|
+
load(File.dirname(__FILE__) + "/web_page.rb")
|
38
|
+
return open_browser_by_selenium(opts)
|
39
|
+
end
|
40
|
+
=end
|
41
|
+
puts "[INFO] No underlying framework is set, try to determine browser: #{opts.inspect}"
|
42
|
+
if opts.class == Hash
|
43
|
+
if opts[:browser]
|
44
|
+
|
45
|
+
if opts[:browser].to_s =~ /ie/i || opts[:browser].to_s =~ /internet\sexplorer/i
|
46
|
+
puts "[INFO] based on browser, set to Watir"
|
47
|
+
RWebSpec.framework = "Watir"
|
48
|
+
self.class.send(:include, RWebSpec::Driver)
|
49
|
+
load(File.dirname(__FILE__) + "/web_page.rb")
|
50
|
+
return open_browser_by_watir(opts)
|
51
|
+
end
|
52
|
+
|
53
|
+
puts "[INFO] based on browser, set to Selenium"
|
54
|
+
# not IE, using selenium
|
55
|
+
RWebSpec.framework = "Selenium"
|
56
|
+
self.class.send(:include, RWebSpec::Driver)
|
57
|
+
load(File.dirname(__FILE__) + "/web_page.rb")
|
58
|
+
return open_browser_by_selenium(opts)
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
puts "[INFO] browser type not specified, decide framework based on platform"
|
64
|
+
if RUBY_PLATFORM =~ /mingw/
|
65
|
+
# if it is Windows, set to Watir
|
66
|
+
RWebSpec.framework = "Watir"
|
67
|
+
self.class.send(:include, RWebSpec::Driver)
|
68
|
+
puts "[INFO] Extends of RWebSpec::Driver"
|
69
|
+
load(File.dirname(__FILE__) + "/web_page.rb")
|
70
|
+
return open_browser_by_watir(opts)
|
71
|
+
else
|
72
|
+
RWebSpec.framework = "Selenium"
|
73
|
+
self.class.send(:include, RWebSpec::Driver)
|
74
|
+
load(File.dirname(__FILE__) + "/web_page.rb")
|
75
|
+
# using extend somehow does not work for RSpec
|
76
|
+
# extend RWebSpec::Driver
|
77
|
+
|
78
|
+
return open_browser_by_selenium(opts)
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
def use_current_browser(how = :title, what = /.*/)
|
84
|
+
puts "[INFO] user current browser => #{RWebSpec.framework}"
|
85
|
+
if RWebSpec.framework =~ /watir/i
|
86
|
+
self.class.send(:include, RWebSpec::Driver)
|
87
|
+
use_current_watir_browser(how, what)
|
88
|
+
elsif RWebSpec.framework =~ /selenium/i
|
89
|
+
self.class.send(:include, RWebSpec::Driver)
|
90
|
+
use_current_selenium_browser(show, what)
|
91
|
+
else
|
92
|
+
# not specified, guess
|
93
|
+
if RUBY_PLATFORM =~ /mingw/i
|
94
|
+
RWebSpec.framework = "Watir"
|
95
|
+
self.class.send(:include, RWebSpec::Driver)
|
96
|
+
load(File.dirname(__FILE__) + "/web_page.rb")
|
97
|
+
use_current_watir_browser(how, what)
|
98
|
+
else
|
99
|
+
RWebSpec.framework = "Selenium"
|
100
|
+
self.class.send(:include, RWebSpec::Driver)
|
101
|
+
load(File.dirname(__FILE__) + "/web_page.rb")
|
102
|
+
use_current_selenium_browser(show, what)
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
# Try the operation up to specified timeout (in seconds), and sleep given interval (in seconds).
|
110
|
+
# Error will be ignored until timeout
|
111
|
+
# Example
|
112
|
+
# try_for { click_link('waiting')}
|
113
|
+
# try_for(10, 2) { click_button('Search' } # try to click the 'Search' button upto 10 seconds, try every 2 seconds
|
114
|
+
# try_for { click_button('Search' }
|
115
|
+
def try_for(timeout = $testwise_polling_timeout, polling_interval = $testwise_polling_interval || 1, &block)
|
116
|
+
start_time = Time.now
|
117
|
+
|
118
|
+
last_error = nil
|
119
|
+
until (duration = Time.now - start_time) > timeout
|
120
|
+
begin
|
121
|
+
yield
|
122
|
+
last_error = nil
|
123
|
+
return true
|
124
|
+
rescue => e
|
125
|
+
last_error = e
|
126
|
+
end
|
127
|
+
sleep polling_interval
|
128
|
+
end
|
129
|
+
|
130
|
+
raise "Timeout after #{duration.to_i} seconds with error: #{last_error}." if last_error
|
131
|
+
raise "Timeout after #{duration.to_i} seconds."
|
132
|
+
end
|
133
|
+
|
134
|
+
alias try_upto try_for
|
135
|
+
alias try_up_to try_for
|
136
|
+
alias try_until try_for
|
137
|
+
|
138
|
+
def try(timeout = $testwise_polling_timeout, polling_interval = $testwise_polling_interval || 1, &block)
|
139
|
+
puts "Warning: method 'try' is deprecated (won't support in RWebSpec 3), use try_for instead."
|
140
|
+
try_for(timeout, polling_interval) {
|
141
|
+
yield
|
142
|
+
}
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
# Try the operation up to specified times, and sleep given interval (in seconds)
|
147
|
+
# Error will be ignored until timeout
|
148
|
+
# Example
|
149
|
+
# repeat_try(3, 2) { click_button('Search' } # 3 times, 6 seconds in total
|
150
|
+
# repeat_try { click_button('Search' } # using default 5 tries, 2 second interval
|
151
|
+
def repeat_try(num_tries = $testwise_polling_timeout || 30, interval = $testwise_polling_interval || 1, & block)
|
152
|
+
num_tries ||= 1
|
153
|
+
(num_tries - 1).times do |num|
|
154
|
+
begin
|
155
|
+
yield
|
156
|
+
return
|
157
|
+
rescue => e
|
158
|
+
# puts "debug: #{num} failed: #{e}"
|
159
|
+
sleep interval
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
# last try, throw error if still fails
|
164
|
+
begin
|
165
|
+
yield
|
166
|
+
rescue => e
|
167
|
+
raise e.to_s + " after trying #{num_tries} times every #{interval} seconds"
|
168
|
+
end
|
169
|
+
yield
|
170
|
+
end
|
171
|
+
|
172
|
+
|
173
|
+
##
|
174
|
+
# Convert :first to 1, :second to 2, and so on...
|
175
|
+
def symbol_to_sequence(symb)
|
176
|
+
value = {:zero => 0,
|
177
|
+
:first => 1,
|
178
|
+
:second => 2,
|
179
|
+
:third => 3,
|
180
|
+
:fourth => 4,
|
181
|
+
:fifth => 5,
|
182
|
+
:sixth => 6,
|
183
|
+
:seventh => 7,
|
184
|
+
:eighth => 8,
|
185
|
+
:ninth => 9,
|
186
|
+
:tenth => 10}[symb]
|
187
|
+
return value || symb.to_i
|
188
|
+
end
|
189
|
+
|
190
|
+
|
191
|
+
#= Convenient functions
|
192
|
+
#
|
193
|
+
|
194
|
+
# Using Ruby block syntax to create interesting domain specific language,
|
195
|
+
# may be appeal to someone.
|
196
|
+
|
197
|
+
# Example:
|
198
|
+
# on @page do |i|
|
199
|
+
# i.enter_text('btn1')
|
200
|
+
# i.click_button('btn1')
|
201
|
+
# end
|
202
|
+
def on(page, & block)
|
203
|
+
yield page
|
204
|
+
end
|
205
|
+
|
206
|
+
# fail the test if user can perform the operation
|
207
|
+
#
|
208
|
+
# Example:
|
209
|
+
# shall_not_allow { 1/0 }
|
210
|
+
def shall_not_allow(& block)
|
211
|
+
operation_performed_ok = false
|
212
|
+
begin
|
213
|
+
yield
|
214
|
+
operation_performed_ok = true
|
215
|
+
rescue
|
216
|
+
end
|
217
|
+
raise "Operation shall not be allowed" if operation_performed_ok
|
218
|
+
end
|
219
|
+
|
220
|
+
alias do_not_allow shall_not_allow
|
221
|
+
|
222
|
+
# Does not provide real function, other than make enhancing test syntax
|
223
|
+
#
|
224
|
+
# Example:
|
225
|
+
# allow { click_button('Register') }
|
226
|
+
def allow(& block)
|
227
|
+
yield
|
228
|
+
end
|
229
|
+
|
230
|
+
alias shall_allow allow
|
231
|
+
alias allowing allow
|
232
|
+
|
233
|
+
# try operation, ignore if errors occur
|
234
|
+
#
|
235
|
+
# Example:
|
236
|
+
# failsafe { click_link("Logout") } # try logout, but it still OK if not being able to (already logout))
|
237
|
+
def failsafe(& block)
|
238
|
+
begin
|
239
|
+
yield
|
240
|
+
rescue =>e
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
alias fail_safe failsafe
|
245
|
+
|
246
|
+
# default date format returned is 29/12/2007.
|
247
|
+
# if supplied parameter is not '%m/%d/%Y' -> 12/29/2007
|
248
|
+
# Otherwise, "2007-12-29", which is most approiate date format
|
249
|
+
#
|
250
|
+
# %a - The abbreviated weekday name (``Sun'')
|
251
|
+
# %A - The full weekday name (``Sunday'')
|
252
|
+
# %b - The abbreviated month name (``Jan'')
|
253
|
+
# %B - The full month name (``January'')
|
254
|
+
# %c - The preferred local date and time representation
|
255
|
+
# %d - Day of the month (01..31)
|
256
|
+
# %H - Hour of the day, 24-hour clock (00..23)
|
257
|
+
# %I - Hour of the day, 12-hour clock (01..12)
|
258
|
+
# %j - Day of the year (001..366)
|
259
|
+
# %m - Month of the year (01..12)
|
260
|
+
# %M - Minute of the hour (00..59)
|
261
|
+
# %p - Meridian indicator (``AM'' or ``PM'')
|
262
|
+
# %S - Second of the minute (00..60)
|
263
|
+
# %U - Week number of the current year,
|
264
|
+
# starting with the first Sunday as the first
|
265
|
+
# day of the first week (00..53)
|
266
|
+
# %W - Week number of the current year,
|
267
|
+
# starting with the first Monday as the first
|
268
|
+
# day of the first week (00..53)
|
269
|
+
# %w - Day of the week (Sunday is 0, 0..6)
|
270
|
+
# %x - Preferred representation for the date alone, no time
|
271
|
+
# %X - Preferred representation for the time alone, no date
|
272
|
+
# %y - Year without a century (00..99)
|
273
|
+
# %Y - Year with century
|
274
|
+
# %Z - Time zone name
|
275
|
+
# %% - Literal ``%'' character
|
276
|
+
|
277
|
+
def today(format = nil)
|
278
|
+
format_date(Time.now, date_format(format))
|
279
|
+
end
|
280
|
+
alias getToday_AU today
|
281
|
+
alias getToday_US today
|
282
|
+
alias getToday today
|
283
|
+
|
284
|
+
|
285
|
+
def days_before(days, format = nil)
|
286
|
+
return nil if !(days.instance_of?(Fixnum))
|
287
|
+
format_date(Time.now - days * 24 * 3600, date_format(format))
|
288
|
+
end
|
289
|
+
|
290
|
+
def yesterday(format = nil)
|
291
|
+
days_before(1, date_format(format))
|
292
|
+
end
|
293
|
+
|
294
|
+
def days_from_now(days, format = nil)
|
295
|
+
return nil if !(days.instance_of?(Fixnum))
|
296
|
+
format_date(Time.now + days * 24 * 3600, date_format(format))
|
297
|
+
end
|
298
|
+
alias days_after days_from_now
|
299
|
+
|
300
|
+
def tomorrow(format = nil)
|
301
|
+
days_from_now(1, date_format(format))
|
302
|
+
end
|
303
|
+
|
304
|
+
|
305
|
+
# return a random number >= min, but <= max
|
306
|
+
def random_number(min, max)
|
307
|
+
rand(max-min+1)+min
|
308
|
+
end
|
309
|
+
|
310
|
+
def random_boolean
|
311
|
+
return random_number(0, 1) == 1
|
312
|
+
end
|
313
|
+
|
314
|
+
def random_char(lowercase = true)
|
315
|
+
if lowercase
|
316
|
+
sprintf("%c", random_number(97, 122))
|
317
|
+
else
|
318
|
+
sprintf("%c", random_number(65, 90))
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
def random_digit()
|
323
|
+
sprintf("%c", random_number(48, 57))
|
324
|
+
end
|
325
|
+
|
326
|
+
def random_str(length, lowercase = true)
|
327
|
+
randomStr = ""
|
328
|
+
length.times {
|
329
|
+
randomStr += random_char(lowercase)
|
330
|
+
}
|
331
|
+
randomStr
|
332
|
+
end
|
333
|
+
|
334
|
+
# Return a random string in a rangeof pre-defined strings
|
335
|
+
def random_string_in(arr)
|
336
|
+
return nil if arr.empty?
|
337
|
+
index = random_number(0, arr.length-1)
|
338
|
+
arr[index]
|
339
|
+
end
|
340
|
+
alias random_string_in_collection random_string_in
|
341
|
+
|
342
|
+
|
343
|
+
WORDS = %w(alias consequatur aut perferendis sit voluptatem accusantium doloremque aperiam eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo aspernatur aut odit aut fugit sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt neque dolorem ipsum quia dolor sit amet consectetur adipisci velit sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem ut enim ad minima veniam quis nostrum exercitationem ullam corporis nemo enim ipsam voluptatem quia voluptas sit suscipit laboriosam nisi ut aliquid ex ea commodi consequatur quis autem vel eum iure reprehenderit qui in ea voluptate velit esse quam nihil molestiae et iusto odio dignissimos ducimus qui blanditiis praesentium laudantium totam rem voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident sed ut perspiciatis unde omnis iste natus error similique sunt in culpa qui officia deserunt mollitia animi id est laborum et dolorum fuga et harum quidem rerum facilis est et expedita distinctio nam libero tempore cum soluta nobis est eligendi optio cumque nihil impedit quo porro quisquam est qui minus id quod maxime placeat facere possimus omnis voluptas assumenda est omnis dolor repellendus temporibus autem quibusdam et aut consequatur vel illum qui dolorem eum fugiat quo voluptas nulla pariatur at vero eos et accusamus officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae itaque earum rerum hic tenetur a sapiente delectus ut aut reiciendis voluptatibus maiores doloribus asperiores repellat)
|
344
|
+
|
345
|
+
# Pick a random value out of a given range.
|
346
|
+
def value_in_range(range)
|
347
|
+
case range.first
|
348
|
+
when Integer then number_in_range(range)
|
349
|
+
when Time then time_in_range(range)
|
350
|
+
when Date then date_in_range(range)
|
351
|
+
else range.to_a.rand
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
# Generate a given number of words. If a range is passed, it will generate
|
356
|
+
# a random number of words within that range.
|
357
|
+
def words(total)
|
358
|
+
if total.class == Range
|
359
|
+
(1..interpret_value(total)).map { WORDS[random_number(total.min, total.max)] }.join(' ')
|
360
|
+
else
|
361
|
+
(1..interpret_value(total)).map { WORDS[random_number(0, total)] }.join(' ')
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
# Generate a given number of sentences. If a range is passed, it will generate
|
366
|
+
# a random number of sentences within that range.
|
367
|
+
def sentences(total)
|
368
|
+
(1..interpret_value(total)).map do
|
369
|
+
words(5..20).capitalize
|
370
|
+
end.join('. ')
|
371
|
+
end
|
372
|
+
|
373
|
+
# Generate a given number of paragraphs. If a range is passed, it will generate
|
374
|
+
# a random number of paragraphs within that range.
|
375
|
+
def paragraphs(total)
|
376
|
+
(1..interpret_value(total)).map do
|
377
|
+
sentences(3..8).capitalize
|
378
|
+
end.join("\n\n")
|
379
|
+
end
|
380
|
+
|
381
|
+
# If an array or range is passed, a random value will be selected to match.
|
382
|
+
# All other values are simply returned.
|
383
|
+
def interpret_value(value)
|
384
|
+
case value
|
385
|
+
when Array then value.rand
|
386
|
+
when Range then value_in_range(value)
|
387
|
+
else value
|
388
|
+
end
|
389
|
+
end
|
390
|
+
|
391
|
+
private
|
392
|
+
|
393
|
+
def time_in_range(range)
|
394
|
+
Time.at number_in_range(Range.new(range.first.to_i, range.last.to_i, rangee.exclude_end?))
|
395
|
+
end
|
396
|
+
|
397
|
+
def date_in_range(range)
|
398
|
+
Date.jd number_in_range(Range.new(range.first.jd, range.last.jd, range.exclude_end?))
|
399
|
+
end
|
400
|
+
|
401
|
+
def number_in_range(range)
|
402
|
+
if range.exclude_end?
|
403
|
+
rand(range.last - range.first) + range.first
|
404
|
+
else
|
405
|
+
rand((range.last+1) - range.first) + range.first
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
409
|
+
def format_date(date, date_format = '%d/%m/%Y')
|
410
|
+
date.strftime(date_format)
|
411
|
+
end
|
412
|
+
|
413
|
+
def date_format(format_argument)
|
414
|
+
if format_argument.nil? then
|
415
|
+
get_locale_date_format(default_locale)
|
416
|
+
elsif format_argument.class == Symbol then
|
417
|
+
get_locale_date_format(format_argument)
|
418
|
+
elsif format_argument.class == String then
|
419
|
+
format_argument
|
420
|
+
else
|
421
|
+
# invalid input, use default
|
422
|
+
get_locale_date_format(default_date_format)
|
423
|
+
end
|
424
|
+
|
425
|
+
end
|
426
|
+
|
427
|
+
def get_locale_date_format(locale)
|
428
|
+
case locale
|
429
|
+
when :us
|
430
|
+
"%m/%d/%Y"
|
431
|
+
when :au, :uk
|
432
|
+
"%d/%m/%Y"
|
433
|
+
else
|
434
|
+
"%Y-%m-%d"
|
435
|
+
end
|
436
|
+
end
|
437
|
+
|
438
|
+
def default_locale
|
439
|
+
return :au
|
440
|
+
end
|
441
|
+
|
442
|
+
|
443
|
+
def average_of(array)
|
444
|
+
array.inject(0.0) { |sum, e| sum + e } / array.length
|
445
|
+
end
|
446
|
+
|
447
|
+
# NOTE might cause issues
|
448
|
+
# why it is removed total
|
449
|
+
def sum_of(array)
|
450
|
+
array.inject(0.0) { |sum, e| sum + e }
|
451
|
+
end
|
452
|
+
|
453
|
+
## Data Driven Tests
|
454
|
+
#
|
455
|
+
# Processing each row in a CSV file, must have heading rows
|
456
|
+
#
|
457
|
+
# Usage:
|
458
|
+
#
|
459
|
+
# process_each_row_in_csv_file(@csv_file) { |row|
|
460
|
+
# goto_page("/")
|
461
|
+
# enter_text("username", row[1])
|
462
|
+
# enter_text("password", row[2])
|
463
|
+
# click_button("Sign in")
|
464
|
+
# page_text.should contain(row[3])
|
465
|
+
# failsafe{ click_link("Sign off") }
|
466
|
+
# }
|
467
|
+
#
|
468
|
+
def process_each_row_in_csv_file(csv_file, &block)
|
469
|
+
require 'faster_csv'
|
470
|
+
connect_to_testwise("CSV_START", csv_file) if $testwise_support
|
471
|
+
has_error = false
|
472
|
+
idx = 0
|
473
|
+
FasterCSV.foreach(csv_file, :headers => :first_row, :encoding => 'u') do |row|
|
474
|
+
connect_to_testwise("CSV_ON_ROW", idx.to_s) if $testwise_support
|
475
|
+
begin
|
476
|
+
yield row
|
477
|
+
connect_to_testwise("CSV_ROW_PASS", idx.to_s) if $testwise_support
|
478
|
+
rescue => e
|
479
|
+
connect_to_testwise("CSV_ROW_FAIL", idx.to_s) if $testwise_support
|
480
|
+
has_error = true
|
481
|
+
ensure
|
482
|
+
idx += 1
|
483
|
+
end
|
484
|
+
end
|
485
|
+
|
486
|
+
connect_to_testwise("CSV_END", "") if $testwise_support
|
487
|
+
raise "Test failed on data" if has_error
|
488
|
+
end
|
489
|
+
|
490
|
+
|
491
|
+
end
|
492
|
+
end
|
@@ -22,8 +22,12 @@ module RWebSpec
|
|
22
22
|
class AbstractWebPage
|
23
23
|
|
24
24
|
include RWebSpec::Assert
|
25
|
-
|
26
|
-
|
25
|
+
begin
|
26
|
+
include RWebSpec::Driver
|
27
|
+
rescue => e
|
28
|
+
puts "[WARN] Failed to load Driver, it will be reloaded. #{e.backtrace}"
|
29
|
+
end
|
30
|
+
include RWebSpec::Core
|
27
31
|
|
28
32
|
# browser: passed to do assertion within the page
|
29
33
|
# page_text: text used to identify the page, title will be the first candidate
|
@@ -29,7 +29,7 @@ module RWebSpec
|
|
29
29
|
# 1. pass as first argument
|
30
30
|
# 2. If running using TestWise, used as confiured
|
31
31
|
# 3. Use default value set
|
32
|
-
def
|
32
|
+
def open_browser_by_watir(options = {})
|
33
33
|
|
34
34
|
begin
|
35
35
|
support_unicode
|
@@ -83,7 +83,6 @@ module RWebSpec
|
|
83
83
|
return @web_browser
|
84
84
|
end
|
85
85
|
|
86
|
-
alias open_browser_with open_browser
|
87
86
|
|
88
87
|
# return the underlying RWebSpec::Browser object
|
89
88
|
def browser
|
@@ -214,9 +213,9 @@ module RWebSpec
|
|
214
213
|
|
215
214
|
# Reuse current an opened browser window instead of opening a new one
|
216
215
|
# example:
|
217
|
-
#
|
218
|
-
#
|
219
|
-
def
|
216
|
+
# use_current_watir_browser(:title, /.*/) # use what ever browser window
|
217
|
+
# use_current_watir_browser(:title, "TestWise") # use browser window with title "TestWise"
|
218
|
+
def use_current_watir_browser(how = :title, what = /.*/)
|
220
219
|
@web_browser = WebBrowser.attach_browser(how, what)
|
221
220
|
end
|
222
221
|
|
@@ -785,7 +784,6 @@ module RWebSpec
|
|
785
784
|
FileUtils.rm_f(screenshot_image_filepath) if File.exist?(screenshot_image_filepath)
|
786
785
|
end
|
787
786
|
|
788
|
-
if RWebSpec.framework == "Watir"
|
789
787
|
begin
|
790
788
|
if is_firefox? then
|
791
789
|
Win32::Screenshot::Take.of(:window, :title => /mozilla\sfirefox/i).write(screenshot_image_filepath)
|
@@ -800,11 +798,7 @@ module RWebSpec
|
|
800
798
|
rescue => e
|
801
799
|
puts "error on taking screenshot: #{e}"
|
802
800
|
end
|
803
|
-
|
804
|
-
# save screenshot with selenium
|
805
|
-
@web_browser.driver.save_screenshot(screenshot_image_filepath)
|
806
|
-
notify_screenshot_location(screenshot_image_filepath)
|
807
|
-
end
|
801
|
+
|
808
802
|
|
809
803
|
end
|
810
804
|
|
@@ -2,6 +2,9 @@
|
|
2
2
|
#* Copyright (c) 2006, Zhimin Zhan.
|
3
3
|
#* Distributed open-source, see full license in MIT-LICENSE
|
4
4
|
#***********************************************************
|
5
|
+
|
6
|
+
=begin
|
7
|
+
|
5
8
|
begin
|
6
9
|
require 'watir'
|
7
10
|
# require 'watir/contrib/enabled_popup'
|
@@ -20,6 +23,8 @@ if RUBY_PLATFORM =~ /mingw/
|
|
20
23
|
raise "You have must at least Watir installed" unless $watir_loaded
|
21
24
|
end
|
22
25
|
|
26
|
+
=end
|
27
|
+
|
23
28
|
module RWebSpec
|
24
29
|
|
25
30
|
##
|
@@ -29,7 +29,7 @@ module RWebSpec
|
|
29
29
|
#
|
30
30
|
# New Options:
|
31
31
|
# :browser => :ie | :firefox | :chrome
|
32
|
-
def
|
32
|
+
def open_browser_by_selenium(options = {})
|
33
33
|
# puts "[DEBUG] [SeleniumDriver] Callling open_browser #{options.inspect}"
|
34
34
|
|
35
35
|
begin
|
@@ -99,7 +99,6 @@ module RWebSpec
|
|
99
99
|
return @web_browser
|
100
100
|
end
|
101
101
|
|
102
|
-
alias open_browser_with open_browser
|
103
102
|
|
104
103
|
# return the underlying RWebSpec::WebDriver::Browser object
|
105
104
|
def browser
|
@@ -228,9 +227,9 @@ module RWebSpec
|
|
228
227
|
|
229
228
|
# Reuse current an opened browser window instead of opening a new one
|
230
229
|
# example:
|
231
|
-
#
|
232
|
-
#
|
233
|
-
def
|
230
|
+
# use_current_selenium_browser(:title, /.*/) # use what ever browser window
|
231
|
+
# use_current_selenium_browser(:title, "TestWise") # use browser window with title "TestWise"
|
232
|
+
def use_current_selenium_browser(how = :title, what = /.*/)
|
234
233
|
@web_browser = $browser || WebBrowser.attach_browser(how, what)
|
235
234
|
end
|
236
235
|
|
@@ -784,26 +783,9 @@ module RWebSpec
|
|
784
783
|
FileUtils.rm_f(screenshot_image_filepath) if File.exist?(screenshot_image_filepath)
|
785
784
|
end
|
786
785
|
|
787
|
-
if RWebSpec.framework == "Watir"
|
788
|
-
begin
|
789
|
-
if is_firefox? then
|
790
|
-
Win32::Screenshot::Take.of(:window, :title => /mozilla\sfirefox/i).write(screenshot_image_filepath)
|
791
|
-
elsif ie
|
792
|
-
Win32::Screenshot::Take.of(:window, :title => /internet\sexplorer/i).write(screenshot_image_filepath)
|
793
|
-
else
|
794
|
-
Win32::Screenshot::Take.of(:foreground).write(screenshot_image_filepath)
|
795
|
-
end
|
796
|
-
notify_screenshot_location(screenshot_image_filepath)
|
797
|
-
rescue ::DL::DLTypeError => de
|
798
|
-
puts "No screenshot libray found: #{de}"
|
799
|
-
rescue => e
|
800
|
-
puts "error on taking screenshot: #{e}"
|
801
|
-
end
|
802
|
-
else
|
803
786
|
# save screenshot with selenium
|
804
787
|
@web_browser.driver.save_screenshot(screenshot_image_filepath)
|
805
788
|
notify_screenshot_location(screenshot_image_filepath)
|
806
|
-
end
|
807
789
|
|
808
790
|
end
|
809
791
|
|
@@ -3,11 +3,11 @@
|
|
3
3
|
#* Distributed open-source, see full license in MIT-LICENSE
|
4
4
|
#***********************************************************
|
5
5
|
|
6
|
-
begin
|
7
|
-
|
8
|
-
rescue LoadError => e
|
9
|
-
|
10
|
-
end
|
6
|
+
# begin
|
7
|
+
# require "selenium-webdriver"
|
8
|
+
# rescue LoadError => e
|
9
|
+
# raise "You have must at least WebDriver installed"
|
10
|
+
# end
|
11
11
|
|
12
12
|
require File.join(File.dirname(__FILE__), "element_locator.rb")
|
13
13
|
|
data/lib/rwebspec.rb
CHANGED
@@ -16,7 +16,7 @@ end
|
|
16
16
|
require 'rspec'
|
17
17
|
|
18
18
|
unless defined? RWEBSPEC_VERSION
|
19
|
-
RWEBSPEC_VERSION = RWEBUNIT_VERSION = "4.
|
19
|
+
RWEBSPEC_VERSION = RWEBUNIT_VERSION = "4.3.1"
|
20
20
|
end
|
21
21
|
|
22
22
|
$testwise_polling_interval = 1 # seconds
|
@@ -24,7 +24,7 @@ $testwise_polling_interval = 1 # seconds
|
|
24
24
|
$testwise_polling_timeout = 30 # seconds
|
25
25
|
|
26
26
|
|
27
|
-
if RUBY_PLATFORM =~ /
|
27
|
+
if RUBY_PLATFORM =~ /mingw/
|
28
28
|
$screenshot_supported = false
|
29
29
|
begin
|
30
30
|
require 'win32/screenshot'
|
@@ -33,6 +33,13 @@ if RUBY_PLATFORM =~ /mswin/ or RUBY_PLATFORM =~ /mingw/
|
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
|
+
begin
|
37
|
+
require 'selenium-webdriver'
|
38
|
+
rescue LoadError => e
|
39
|
+
$selenium_loaded = false
|
40
|
+
end
|
41
|
+
|
42
|
+
|
36
43
|
module RWebSpec
|
37
44
|
class << self
|
38
45
|
def version
|
@@ -41,7 +48,8 @@ module RWebSpec
|
|
41
48
|
|
42
49
|
def framework
|
43
50
|
@_framework ||= begin
|
44
|
-
ENV["RWEBSPEC_FRAMEWORK"]
|
51
|
+
ENV["RWEBSPEC_FRAMEWORK"]
|
52
|
+
# ||= (RUBY_PLATFORM =~ /mingw/ ? "Watir" : "Selenium-WebDriver")
|
45
53
|
end
|
46
54
|
@_framework
|
47
55
|
end
|
@@ -57,6 +65,8 @@ module RWebSpec
|
|
57
65
|
|
58
66
|
def load_watir
|
59
67
|
# puts "Loading Watir"
|
68
|
+
require 'watir'
|
69
|
+
require 'watir-classic/ie'
|
60
70
|
load(File.dirname(__FILE__) + "/rwebspec-watir/web_browser.rb")
|
61
71
|
load(File.dirname(__FILE__) + "/rwebspec-watir/driver.rb")
|
62
72
|
require File.dirname(__FILE__) + "/extensions/watir_extensions"
|
@@ -64,6 +74,7 @@ module RWebSpec
|
|
64
74
|
end
|
65
75
|
|
66
76
|
def load_selenium
|
77
|
+
require 'selenium-webdriver'
|
67
78
|
# puts "Loading Selenium"
|
68
79
|
load(File.dirname(__FILE__) + "/rwebspec-webdriver/web_browser.rb")
|
69
80
|
load(File.dirname(__FILE__) + "/rwebspec-webdriver/driver.rb")
|
@@ -74,7 +85,18 @@ module RWebSpec
|
|
74
85
|
if @_framework.nil?
|
75
86
|
framework
|
76
87
|
end
|
77
|
-
|
88
|
+
|
89
|
+
if RWebSpec.framework =~ /watir/i
|
90
|
+
load_watir
|
91
|
+
return
|
92
|
+
end
|
93
|
+
|
94
|
+
if RWebSpec.framework =~ /selenium/i
|
95
|
+
load_selenium
|
96
|
+
return
|
97
|
+
end
|
98
|
+
|
99
|
+
puts "[WARN] not framework loaded yet"
|
78
100
|
end
|
79
101
|
|
80
102
|
end
|
@@ -83,16 +105,17 @@ end
|
|
83
105
|
# Watir 3 API Changes, no Watir/Container
|
84
106
|
require File.dirname(__FILE__) + "/plugins/testwise_plugin.rb"
|
85
107
|
|
86
|
-
RWebSpec.load_framework
|
108
|
+
#RWebSpec.load_framework
|
87
109
|
|
88
110
|
# Extra full path to load libraries
|
89
111
|
require File.dirname(__FILE__) + "/rwebspec-common/using_pages"
|
90
|
-
require File.dirname(__FILE__) + "/rwebspec-common/
|
112
|
+
require File.dirname(__FILE__) + "/rwebspec-common/core"
|
91
113
|
require File.dirname(__FILE__) + "/rwebspec-common/web_page"
|
92
114
|
require File.dirname(__FILE__) + "/rwebspec-common/assert"
|
93
|
-
require File.dirname(__FILE__) + "/rwebspec-common/test_script"
|
94
115
|
require File.dirname(__FILE__) + "/rwebspec-common/context"
|
95
|
-
require File.dirname(__FILE__) + "/rwebspec-common/
|
116
|
+
require File.dirname(__FILE__) + "/rwebspec-common/test_script.rb"
|
117
|
+
require File.dirname(__FILE__) + "/rwebspec-common/rspec_helper.rb"
|
118
|
+
|
96
119
|
require File.dirname(__FILE__) + "/rwebspec-common/load_test_helper"
|
97
120
|
require File.dirname(__FILE__) + "/rwebspec-common/matchers/contains_text"
|
98
121
|
require File.dirname(__FILE__) + "/extensions/rspec_extensions"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rwebspec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.3.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire: rwebspec
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-07-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -126,13 +126,13 @@ files:
|
|
126
126
|
- lib/rwebspec-common/assert.rb
|
127
127
|
- lib/rwebspec-common/clickJSDialog.rb
|
128
128
|
- lib/rwebspec-common/context.rb
|
129
|
+
- lib/rwebspec-common/core.rb
|
129
130
|
- lib/rwebspec-common/database_checker.rb
|
130
131
|
- lib/rwebspec-common/load_test_helper.rb
|
131
132
|
- lib/rwebspec-common/matchers/contains_text.rb
|
132
133
|
- lib/rwebspec-common/popup.rb
|
133
134
|
- lib/rwebspec-common/rspec_helper.rb
|
134
135
|
- lib/rwebspec-common/test_script.rb
|
135
|
-
- lib/rwebspec-common/test_utils.rb
|
136
136
|
- lib/rwebspec-common/using_pages.rb
|
137
137
|
- lib/rwebspec-common/web_page.rb
|
138
138
|
- lib/rwebspec-common/web_testcase.rb
|