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.
@@ -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
- # Store test optionns
10
- #
11
- class TestContext
12
- attr_accessor :base_url
8
+ ##
9
+ # Store test optionns
10
+ #
11
+ class TestContext
12
+ attr_accessor :base_url
13
13
 
14
- def setBaseUrl(baseUrl)
15
- @base_url = baseUrl
16
- end
17
- end
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
@@ -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
- module Utils
8
-
9
- #useful methods for test data
10
- def getToday_AU()
11
- format_date(Time.now, "%02d/%02d/%04d")
12
- end
13
- alias getToday getToday_AU
14
-
15
- def getToday_US()
16
- sprintf("%02d/%02d/%04d", Time.now.month, Time.now.day, Time.now.year)
17
- end
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
- def randomBoolean()
45
- return randomNumber(0, 1) == 1
46
- end
47
-
48
- def randomChar(lowercase)
49
- sprintf("%c", random_number(97, 122)) if lowercase
50
- sprintf("%c", random_number(65, 90)) unless lowercase
51
- end
52
-
53
- def randomDigit()
54
- sprintf("%c", randomNumber(48, 57))
55
- end
56
-
57
- def randomString(length, lowercase)
58
- randomStr = ""
59
- length.times {
60
- randomStr += randomChar(lowercase)
61
- }
62
- randomStr
63
- end
64
-
65
- # Return a random string in a rangeof pre-defined strings
66
- def randomStringInCollection(arr)
67
- return nil if arr.empty?
68
- index = random_number(0, arr.length-1)
69
- arr[index]
70
- end
71
-
72
- private
73
- def format_date(date, date_format = nil)
74
- date_format ||= "%02d/%02d/%04d"
75
- sprintf(date_format, date.day, date.month, date.year)
76
- end
77
-
78
-
79
- end
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