rwebunit 0.2.0 → 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +110 -35
- data/Rakefile +6 -5
- data/lib/rwebunit/assert.rb +249 -0
- data/lib/rwebunit/driver.rb +296 -0
- data/lib/rwebunit/rspec_helper.rb +108 -0
- data/lib/rwebunit/test_context.rb +15 -10
- data/lib/rwebunit/test_utils.rb +81 -72
- data/lib/rwebunit/web_page.rb +58 -66
- data/lib/rwebunit/web_testcase.rb +20 -201
- data/lib/rwebunit/web_tester.rb +365 -399
- data/lib/rwebunit.rb +5 -0
- data/test/test_test_utils.rb +76 -73
- metadata +45 -43
@@ -0,0 +1,296 @@
|
|
1
|
+
# The Mixin is normally included in the spec/tests and pages, provide
|
2
|
+
# convenient methods to drive the browser.
|
3
|
+
#
|
4
|
+
# Instead of
|
5
|
+
# browser.click_button("submit")
|
6
|
+
# You can just use
|
7
|
+
# click_button("submit")
|
8
|
+
#
|
9
|
+
|
10
|
+
module RWebUnit
|
11
|
+
module Driver
|
12
|
+
|
13
|
+
# Verify the next page following an operation.
|
14
|
+
#
|
15
|
+
# Typical usage:
|
16
|
+
# login_page.click_login
|
17
|
+
# expect_page HomePage
|
18
|
+
def expect_page(page_clazz)
|
19
|
+
page_clazz.new(@web_tester)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Using Ruby block syntax to create interesting domain specific language,
|
23
|
+
# may be appeal to someone.
|
24
|
+
|
25
|
+
# Example:
|
26
|
+
# on @page do |i|
|
27
|
+
# i.enter_text('btn1')
|
28
|
+
# i.click_button('btn1')
|
29
|
+
# end
|
30
|
+
def on(page, &block)
|
31
|
+
yield page
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_context
|
35
|
+
@web_tester.test_context
|
36
|
+
end
|
37
|
+
|
38
|
+
def begin_at(url)
|
39
|
+
@web_tester.begin_at(url)
|
40
|
+
end
|
41
|
+
|
42
|
+
def ie; @web_tester.ie; end
|
43
|
+
|
44
|
+
def close_browser
|
45
|
+
@web_tester.close_browser
|
46
|
+
end
|
47
|
+
alias close_ie close_browser
|
48
|
+
|
49
|
+
# browser navigation
|
50
|
+
def go_back; @web_tester.go_back; end
|
51
|
+
def go_forward; @web_tester.go_forward; end
|
52
|
+
def goto_page(page); @web_tester.goto_page(page); end
|
53
|
+
def refresh; @web_tester.refresh; end
|
54
|
+
alias refresh_page refresh
|
55
|
+
|
56
|
+
def attach_browser(how, what); WebTester.attach_browser(how, what); end
|
57
|
+
|
58
|
+
##
|
59
|
+
# Delegate to WebTester
|
60
|
+
#
|
61
|
+
|
62
|
+
# Depends on which object type, you can use following attribute
|
63
|
+
# More details: http://wiki.openqa.org/display/WTR/Methods+supported+by+Element
|
64
|
+
#
|
65
|
+
# :id Used to find an element that has an "id=" attribute. Since each id should be unique, according to the XHTML specification, this is recommended as the most reliable method to find an object. *
|
66
|
+
# :name Used to find an element that has a "name=" attribute. This is useful for older versions of HTML, but "name" is deprecated in XHTML. *
|
67
|
+
# :value Used to find a text field with a given default value, or a button with a given caption, or a text field
|
68
|
+
# :text Used for links, spans, divs and other element that contain text.
|
69
|
+
# :index Used to find the nth element of the specified type on a page. For example, button(:index, 2) finds the second button. Current versions of WATIR use 1-based indexing, but future versions will use 0-based indexing.
|
70
|
+
# :class Used for an element that has a "class=" attribute.
|
71
|
+
# :title Used for an element that has a "title=" attribute.
|
72
|
+
# :xpath Finds the item using xpath query.
|
73
|
+
# :method Used only for forms, the method attribute of a form is either GET or POST.
|
74
|
+
# :action Used only for form elements, specifies the URL where the form is to be submitted.
|
75
|
+
# :href Used to identify a link by its "href=" attribute.
|
76
|
+
# :src Used to identify an image by its URL.
|
77
|
+
#
|
78
|
+
|
79
|
+
# area <area> tags
|
80
|
+
# button <input> tags with type=button, submit, image or reset
|
81
|
+
# check_box <input> tags with type=checkbox
|
82
|
+
# div <div> tags
|
83
|
+
# form <form> tags
|
84
|
+
# frame frames, including both the <frame> elements and the corresponding pages
|
85
|
+
# h1 - h6 <h1>, <h2>, <h3>, <h4>, <h5>, <h6> tags
|
86
|
+
# hidden <input> tags with type=hidden
|
87
|
+
# image <img> tags
|
88
|
+
# label <label> tags (including "for" attribute)
|
89
|
+
# li <li> tags
|
90
|
+
# link <a> (anchor) tags
|
91
|
+
# map <map> tags
|
92
|
+
# radio <input> tags with the type=radio; known as radio buttons
|
93
|
+
# select_list <select> tags, known as drop-downs or drop-down lists
|
94
|
+
# span <span> tags
|
95
|
+
# table <table> tags, including row and cell methods for accessing nested elements
|
96
|
+
# text_field <input> tags with the type=text (single-line), type=textarea (multi-line), and type=password
|
97
|
+
# p <p> (paragraph) tags, because
|
98
|
+
def area(*args); @web_tester.area(*args); end
|
99
|
+
def button(*args); @web_tester.button(*args); end
|
100
|
+
def cell(*args); @web_tester.cell(*args); end
|
101
|
+
alias td cell
|
102
|
+
def checkbox(*args); @web_tester.checkbox(*args); end
|
103
|
+
alias check_box checkbox # seems watir doc is wrong, checkbox not check_box
|
104
|
+
def div(*args); @web_tester.div(*args); end
|
105
|
+
def form(*args); @web_tester.form(*args); end
|
106
|
+
def frame(*args); @web_tester.frame(*args); end
|
107
|
+
def h1(*args); @web_tester.h1(*args); end
|
108
|
+
def h2(*args); @web_tester.h2(*args); end
|
109
|
+
def h3(*args); @web_tester.h3(*args); end
|
110
|
+
def h4(*args); @web_tester.h4(*args); end
|
111
|
+
def h5(*args); @web_tester.h5(*args); end
|
112
|
+
def h6(*args); @web_tester.h6(*args); end
|
113
|
+
def hidden(*args); @web_tester.hidden(*args); end
|
114
|
+
def image(*args); @web_tester.image(*args); end
|
115
|
+
def li(*args); @web_tester.li(*args); end
|
116
|
+
def link(*args); @web_tester.link(*args); end
|
117
|
+
def map(*args); @web_tester.map(*args); end
|
118
|
+
def pre(*args); @web_tester.pre(*args); end
|
119
|
+
def row(*args); @web_tester.row(*args); end
|
120
|
+
alias tr row
|
121
|
+
def radio(*args); @web_tester.radio(*args); end
|
122
|
+
def select_list(*args); @web_tester.select_list(*args); end
|
123
|
+
def span(*args); @web_tester.span(*args); end
|
124
|
+
def table(*args); @web_tester.table(*args); end
|
125
|
+
def text_field(*args); @web_tester.text_field(*args); end
|
126
|
+
|
127
|
+
def paragraph(*args); @web_tester.paragraph(*args); end
|
128
|
+
def file_field(*args); @web_tester.file_field(*args); end
|
129
|
+
def label(*args); @web_tester.span(*args); end
|
130
|
+
|
131
|
+
def contains_text(text); @web_tester.contains_text(text); end
|
132
|
+
|
133
|
+
|
134
|
+
def links; @web_tester.links; end
|
135
|
+
def buttons; @web_tester.buttons; end
|
136
|
+
def select_lists; @web_tester.select_lists; end
|
137
|
+
def checkboxes; @web_tester.checkboxes; end
|
138
|
+
def radios; @web_tester.radios; end
|
139
|
+
def text_fields; @web_tester.text_fields; end
|
140
|
+
|
141
|
+
|
142
|
+
# enter text into a text field
|
143
|
+
def enter_text(elementName, elementValue)
|
144
|
+
@web_tester.set_form_element(elementName, elementValue)
|
145
|
+
end
|
146
|
+
alias set_form_element enter_text
|
147
|
+
|
148
|
+
|
149
|
+
#links
|
150
|
+
def click_link_with_text(linkText)
|
151
|
+
@web_tester.click_link_with_text(linkText)
|
152
|
+
end
|
153
|
+
|
154
|
+
def click_link_with_id(link_id)
|
155
|
+
@web_tester.click_link_with_id(link_id)
|
156
|
+
end
|
157
|
+
alias click_link click_link_with_id
|
158
|
+
|
159
|
+
##
|
160
|
+
# buttons
|
161
|
+
|
162
|
+
# submit the form using the first (index) submit button
|
163
|
+
def submit()
|
164
|
+
@web_tester.submit()
|
165
|
+
end
|
166
|
+
|
167
|
+
# click a form submit button with specified button id
|
168
|
+
def submit(button_id)
|
169
|
+
@web_tester.submit(button_id)
|
170
|
+
end
|
171
|
+
|
172
|
+
def click_button(button_id)
|
173
|
+
@web_tester.click_button(button_id)
|
174
|
+
end
|
175
|
+
alias click_button_with_id click_button
|
176
|
+
|
177
|
+
def click_button_with_caption(caption)
|
178
|
+
@web_tester.click_button_with_caption(caption)
|
179
|
+
end
|
180
|
+
alias click_button_with_text click_button_with_caption
|
181
|
+
|
182
|
+
def click_button_with_value(value)
|
183
|
+
@web_tester.click_button_with_value(value)
|
184
|
+
end
|
185
|
+
|
186
|
+
# Radios
|
187
|
+
def click_radio_option(name, value)
|
188
|
+
@web_tester.click_radio_option(name, value)
|
189
|
+
end
|
190
|
+
alias click_radio_button click_radio_option
|
191
|
+
|
192
|
+
def clear_radio_option(name, value)
|
193
|
+
@web_tester.clear_radio_option(name, value)
|
194
|
+
end
|
195
|
+
alias clear_radio_button clear_radio_option
|
196
|
+
|
197
|
+
# Filefield
|
198
|
+
def select_file_for_upload(file_field, file_path)
|
199
|
+
@web_tester.select_file_for_upload(file_field, file_path)
|
200
|
+
end
|
201
|
+
|
202
|
+
# Check one or more checkboxes with same name, can accept a string or an array of string as values checkbox, pass array as values will try to set mulitple checkboxes.
|
203
|
+
#
|
204
|
+
# page.check_checkbox('bad_ones', 'Chicken Little')
|
205
|
+
# page.check_checkbox('good_ones', ['Cars', 'Toy Story'])
|
206
|
+
def check_checkbox(name, value=nil)
|
207
|
+
@web_tester.check_checkbox(name, value)
|
208
|
+
end
|
209
|
+
|
210
|
+
# Uncheck one or more checkboxes with same name
|
211
|
+
def uncheck_checkbox(name, value=nil)
|
212
|
+
@web_tester.uncheck_checkbox(name, value)
|
213
|
+
end
|
214
|
+
|
215
|
+
# combo box
|
216
|
+
def select_option(selectName, option)
|
217
|
+
@web_tester.select_option(selectName, option)
|
218
|
+
end
|
219
|
+
|
220
|
+
def new_popup_window(options)
|
221
|
+
@web_tester.new_popup_window(options)
|
222
|
+
end
|
223
|
+
|
224
|
+
|
225
|
+
# Wait for specific seconds for an Ajax update finish.
|
226
|
+
# Trick: In your Rails application,
|
227
|
+
# :loading => "Element.show('search_indicator');
|
228
|
+
# :complete => "Element.hide('search_indicator');
|
229
|
+
#
|
230
|
+
# <%= image_tag("indicator.gif", :id => 'search_indicator', :style => 'display:none') %>
|
231
|
+
#
|
232
|
+
# Typical usage:
|
233
|
+
# ajax_wait_for_element("search_indicator", 30)
|
234
|
+
# ajax_wait_for_element("search_indicator", 30, "show")
|
235
|
+
# ajax_wait_for_element("search_indicator", 30, "hide")
|
236
|
+
# ajax_wait_for_element("search_indicator", 30, "show", 5) # check every 5 seconds
|
237
|
+
#
|
238
|
+
# Warning: this method has not been fully tested, if you are not using Rails, change your parameter accordingly.
|
239
|
+
#
|
240
|
+
def ajax_wait_for_element(element_id, seconds, status='show', check_interval=2)
|
241
|
+
count = 0
|
242
|
+
check_interval = 2 if check_interval < 1 or check_interval > seconds
|
243
|
+
while count < (seconds / check_interval) do
|
244
|
+
search_indicator = @web_tester.element_by_id(element_id)
|
245
|
+
search_indicator_outer_html = search_indicator.outerHtml if search_indicator
|
246
|
+
if status == 'hide'
|
247
|
+
return true if search_indicator_outer_html and !search_indicator_outer_html.include?('style="DISPLAY: none"')
|
248
|
+
else
|
249
|
+
return true if search_indicator_outer_html and search_indicator_outer_html.include?('style="DISPLAY: none"')
|
250
|
+
end
|
251
|
+
sleep check_interval if check_interval > 0 and check_interval < 5 * 60 # wait max 5 minutes
|
252
|
+
count += 1
|
253
|
+
end
|
254
|
+
return false
|
255
|
+
end
|
256
|
+
|
257
|
+
def wait_for_element(element_id, timeout = 30, interval = 0.5)
|
258
|
+
start_time = Time.now
|
259
|
+
until @web_tester.element_by_id(element_id) do
|
260
|
+
sleep(interval)
|
261
|
+
if (Time.now - start_time) > timeout
|
262
|
+
raise RuntimeError, "failed to find element: #{element_id} for max #{timeout}"
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
def element_text(elem_id)
|
268
|
+
@web_tester.element_value(elem_id)
|
269
|
+
end
|
270
|
+
|
271
|
+
# fail the test if user can perform the operation
|
272
|
+
def shall_not_allow
|
273
|
+
operation_performed_ok = false
|
274
|
+
begin
|
275
|
+
yield
|
276
|
+
operation_performed_ok = true
|
277
|
+
rescue
|
278
|
+
end
|
279
|
+
|
280
|
+
raise "Operation shall not be allowed" if operation_performed_ok
|
281
|
+
end
|
282
|
+
alias do_not_allow shall_not_allow
|
283
|
+
|
284
|
+
# ---
|
285
|
+
# For debugging
|
286
|
+
# ---
|
287
|
+
def dump_response(stream = nil)
|
288
|
+
@web_tester.dump_response(stream)
|
289
|
+
end
|
290
|
+
|
291
|
+
def click_popup_window(button, waitTime= 9, user_input=nil )
|
292
|
+
@web_tester.start_clicker(button, waitTime, user_input)
|
293
|
+
end
|
294
|
+
|
295
|
+
end
|
296
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
# example
|
4
|
+
# should link_by_text(text, options).size > 0
|
5
|
+
|
6
|
+
module RWebUnit
|
7
|
+
module RSpecHelper
|
8
|
+
include RWebUnit::Driver
|
9
|
+
include RWebUnit::Utils
|
10
|
+
include RWebUnit::Assert
|
11
|
+
|
12
|
+
def browser
|
13
|
+
@web_tester
|
14
|
+
end
|
15
|
+
|
16
|
+
def open_browser_preconfigured(options = {})
|
17
|
+
open_browser(ENV['ITEST_PROJECT_BASE_URL'], options)
|
18
|
+
end
|
19
|
+
|
20
|
+
# open a browser, and set base_url via hash, but does not acually
|
21
|
+
#
|
22
|
+
# example:
|
23
|
+
# open_browser :base_url => http://localhost:8080
|
24
|
+
def open_browser(base_url = nil, options = {})
|
25
|
+
raise "base_url must be set" if base_url .nil?
|
26
|
+
|
27
|
+
default_options = {:speed => "fast",
|
28
|
+
:visible => true,
|
29
|
+
:highlight_colour => 'yellow',
|
30
|
+
:close_others => true,
|
31
|
+
:start_new => false, # start a new browser always
|
32
|
+
:go => true}
|
33
|
+
|
34
|
+
options = default_options.merge options
|
35
|
+
options[:firefox] = true if "Firefox" == ENV['ITEST_BROWSER']
|
36
|
+
|
37
|
+
uri = URI.parse(base_url)
|
38
|
+
uri_base = "#{uri.scheme}://#{uri.host}:#{uri.port}"
|
39
|
+
if options[:start_new]
|
40
|
+
@web_tester = WebTester.new(uri_base, options)
|
41
|
+
else
|
42
|
+
@web_tester ||= WebTester.new(uri_base, options)
|
43
|
+
end
|
44
|
+
|
45
|
+
if options[:go]
|
46
|
+
(uri.path.length == 0) ? begin_at("/") : begin_at(uri.path)
|
47
|
+
end
|
48
|
+
return @web_tester
|
49
|
+
end
|
50
|
+
alias open_browser_with open_browser
|
51
|
+
|
52
|
+
# --
|
53
|
+
# Content
|
54
|
+
# --
|
55
|
+
def page_title
|
56
|
+
@web_tester.page_title
|
57
|
+
end
|
58
|
+
|
59
|
+
def page_source
|
60
|
+
@web_tester.page_source
|
61
|
+
end
|
62
|
+
|
63
|
+
def table_source(table_id)
|
64
|
+
elem = @@browser.document.getElementById(table_id)
|
65
|
+
raise "The element '#{table_id}' is not a table or there are multple elements with same id" unless elem.name.uppercase == "TABLE"
|
66
|
+
elem.innerHTML
|
67
|
+
end
|
68
|
+
alias table_source_by_id table_source
|
69
|
+
|
70
|
+
def element_text(elem_id)
|
71
|
+
@web_tester.element_value(elem_id)
|
72
|
+
end
|
73
|
+
alias element_text_by_id element_text
|
74
|
+
|
75
|
+
#TODO: is it working?
|
76
|
+
def element_source(elem_id)
|
77
|
+
@web_tester.get_html_in_element(elem_id)
|
78
|
+
end
|
79
|
+
|
80
|
+
def element_by_id(elem_id)
|
81
|
+
@web_tester.element_by_id(elem_id)
|
82
|
+
end
|
83
|
+
|
84
|
+
def button_by_id(button_id)
|
85
|
+
button(:id, button_id)
|
86
|
+
end
|
87
|
+
|
88
|
+
def buttons_by_caption(text)
|
89
|
+
button(:text, text)
|
90
|
+
end
|
91
|
+
alias buttons_by_text buttons_by_caption
|
92
|
+
|
93
|
+
def link_by_id(link_id)
|
94
|
+
link(:id, link_id)
|
95
|
+
end
|
96
|
+
|
97
|
+
# default options: exact => true
|
98
|
+
def links_by_text(link_text, options = {})
|
99
|
+
options.merge!({:exact=> true})
|
100
|
+
links.select { |link|
|
101
|
+
options[:exact] ? link.text == link_text : link.text.include?(link_text)
|
102
|
+
}
|
103
|
+
end
|
104
|
+
alias links_with_text links_by_text
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
@@ -1,19 +1,24 @@
|
|
1
1
|
#***********************************************************
|
2
|
-
#* Copyright (c) 2006, Zhimin Zhan.
|
2
|
+
#* Copyright (c) 2006, 2007 Zhimin Zhan.
|
3
3
|
#* Distributed open-source, see full license in MIT-LICENSE
|
4
4
|
#***********************************************************
|
5
5
|
|
6
6
|
module RWebUnit
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
##
|
9
|
+
# Store test optionns
|
10
|
+
#
|
11
|
+
class TestContext
|
12
|
+
attr_accessor :base_url
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
def initialize(base_url)
|
15
|
+
set_base_url(base_url)
|
16
|
+
end
|
17
|
+
|
18
|
+
def set_base_url(baseUrl)
|
19
|
+
@base_url = baseUrl
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
18
23
|
|
19
24
|
end
|
data/lib/rwebunit/test_utils.rb
CHANGED
@@ -3,78 +3,87 @@
|
|
3
3
|
#* Distributed open-source, see full license in MIT-LICENSE
|
4
4
|
#***********************************************************
|
5
5
|
|
6
|
+
# useful hekoer methods for testing
|
7
|
+
#
|
6
8
|
module RWebUnit
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
def getDaysBefore(days)
|
20
|
-
nil if !(days.instance_of?(Fixnum))
|
21
|
-
format_date(Time.now - days * 24 * 3600)
|
22
|
-
end
|
23
|
-
|
24
|
-
def getYesterday
|
25
|
-
getDaysBefore(1)
|
26
|
-
end
|
27
|
-
|
28
|
-
def getDaysAfter(days)
|
29
|
-
nil if !(days.instance_of?(Fixnum))
|
30
|
-
format_date(Time.now + days * 24 * 3600)
|
31
|
-
end
|
32
|
-
|
33
|
-
def getTomorrow
|
34
|
-
getDaysAfter(1)
|
35
|
-
end
|
36
|
-
|
37
|
-
#TODO: getDaysBefore, getDaysAfter, getYesterday, getTomorrow
|
38
|
-
|
39
|
-
# return a random number >= min, but <= max
|
40
|
-
def randomNumber(min, max)
|
41
|
-
rand(max-min+1)+min
|
9
|
+
module Utils
|
10
|
+
|
11
|
+
# default date format returned is 29/12/2007.
|
12
|
+
# if supplied parameter is not '%m/%d/%Y' -> 12/29/2007
|
13
|
+
# Otherwise, "2007-12-29", which is most approiate date format
|
14
|
+
def today(format = '%d/%m/%y')
|
15
|
+
if format.downcase == '%d/%m/%y'
|
16
|
+
format_date(Time.now, "%02d/%02d/%04d")
|
17
|
+
elsif format.downcase == '%m/%d/%y'
|
18
|
+
sprintf("%02d/%02d/%04d", Time.now.month, Time.now.day, Time.now.year)
|
19
|
+
else
|
20
|
+
sprintf("%04d-%02d-%02d", Time.now.year, Time.now.month, Time.now.day)
|
42
21
|
end
|
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
|
-
|
22
|
+
end
|
23
|
+
alias getToday_AU today
|
24
|
+
alias getToday_US today
|
25
|
+
alias getToday today
|
26
|
+
|
27
|
+
|
28
|
+
def days_before(days)
|
29
|
+
nil if !(days.instance_of?(Fixnum))
|
30
|
+
format_date(Time.now - days * 24 * 3600)
|
31
|
+
end
|
32
|
+
|
33
|
+
def yesterday
|
34
|
+
days_before(1)
|
35
|
+
end
|
36
|
+
|
37
|
+
def days_from_now(days)
|
38
|
+
nil if !(days.instance_of?(Fixnum))
|
39
|
+
format_date(Time.now + days * 24 * 3600)
|
40
|
+
end
|
41
|
+
alias days_after days_from_now
|
42
|
+
|
43
|
+
def tomorrow
|
44
|
+
days_from_now(1)
|
45
|
+
end
|
46
|
+
|
47
|
+
# return a random number >= min, but <= max
|
48
|
+
def random_number(min, max)
|
49
|
+
rand(max-min+1)+min
|
50
|
+
end
|
51
|
+
|
52
|
+
def random_boolean
|
53
|
+
return random_number(0, 1) == 1
|
54
|
+
end
|
55
|
+
|
56
|
+
def random_char(lowercase = true)
|
57
|
+
sprintf("%c", random_number(97, 122)) if lowercase
|
58
|
+
sprintf("%c", random_number(65, 90)) unless lowercase
|
59
|
+
end
|
60
|
+
alias randomChar random_char
|
61
|
+
|
62
|
+
def random_digit()
|
63
|
+
sprintf("%c", random_number(48, 57))
|
64
|
+
end
|
65
|
+
|
66
|
+
def random_str(length, lowercase = true)
|
67
|
+
randomStr = ""
|
68
|
+
length.times {
|
69
|
+
randomStr += random_char(lowercase)
|
70
|
+
}
|
71
|
+
randomStr
|
72
|
+
end
|
73
|
+
|
74
|
+
# Return a random string in a rangeof pre-defined strings
|
75
|
+
def random_string_in(arr)
|
76
|
+
return nil if arr.empty?
|
77
|
+
index = random_number(0, arr.length-1)
|
78
|
+
arr[index]
|
79
|
+
end
|
80
|
+
alias random_string_in_collection random_string_in
|
81
|
+
|
82
|
+
private
|
83
|
+
def format_date(date, date_format = nil)
|
84
|
+
date_format ||= "%02d/%02d/%04d"
|
85
|
+
sprintf(date_format, date.day, date.month, date.year)
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
80
89
|
end
|