rwebunit 0.2.0 → 0.7.2
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.
- 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
|