rwebunit 0.2.0 → 0.7.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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