rwebunit 1.0.3 → 1.3.0

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.
@@ -6,113 +6,163 @@
6
6
  # click_button("submit")
7
7
  #
8
8
  require File.join(File.dirname(__FILE__), 'itest_plugin')
9
+ require File.join(File.dirname(__FILE__), 'popup')
9
10
  require 'timeout'
11
+ require 'uri'
10
12
 
11
13
  module RWebUnit
12
14
  module Driver
13
15
  include RWebUnit::ITestPlugin
16
+ include RWebUnit::Popup
14
17
 
15
- def browser
16
- @web_browser
17
- end
18
+ @@default_polling_interval = 1 # second
19
+ @@default_timeout = 30 # seconds
18
20
 
19
- # Verify the next page following an operation.
21
+ # open a browser, and set base_url via hash, but does not acually
20
22
  #
21
- # Typical usage:
22
- # login_page.click_login
23
- # expect_page HomePage
24
- def expect_page(page_clazz, argument = nil)
25
- if argument
26
- page_clazz.new(@web_browser, argument)
23
+ # example:
24
+ # open_browser :base_url => http://localhost:8080
25
+ #
26
+ # There are 3 ways to set base url
27
+ # 1. pass as first argument
28
+ # 2. If running using iTest2, used as confiured
29
+ # 3. Use default value set
30
+ def open_browser(base_url = nil, options = {})
31
+ base_url ||= $ITEST2_PROJECT_BASE_URL
32
+ base_url ||= $BASE_URL
33
+ raise "base_url must be set" if base_url.nil?
34
+
35
+ default_options = {:speed => "fast",
36
+ :visible => true,
37
+ :highlight_colour => 'yellow',
38
+ :close_others => true,
39
+ :start_new => false, # start a new browser always
40
+ :go => true}
41
+
42
+ options = default_options.merge options
43
+ options[:firefox] = true if "Firefox" == $ITEST2_BROWSER || "Firefox" == $BROWSER
44
+ ($ITEST2_HIDE_BROWSER) ? $HIDE_IE = true : $HIDE_IE = false
45
+
46
+ if base_url =~ /^file:/
47
+ uri_base = base_url
27
48
  else
28
- page_clazz.new(@web_browser)
49
+ uri = URI.parse(base_url)
50
+ uri_base = "#{uri.scheme}://#{uri.host}:#{uri.port}"
29
51
  end
30
- end
31
52
 
32
- # Using Ruby block syntax to create interesting domain specific language,
33
- # may be appeal to someone.
53
+ if options[:start_new]
54
+ @web_browser = WebBrowser.new(uri_base, nil, options)
55
+ else
56
+ @web_browser = WebBrowser.reuse(uri_base, options) # Reuse existing browser
57
+ end
34
58
 
35
- # Example:
36
- # on @page do |i|
37
- # i.enter_text('btn1')
38
- # i.click_button('btn1')
39
- # end
40
- def on(page, &block)
41
- yield page
59
+ if base_url =~ /^file:/
60
+ goto_url(base_url) # for files, no base url
61
+ else
62
+ (uri.path.length == 0) ? begin_at("/") : begin_at(uri.path) if options[:go]
63
+ end
64
+
65
+ return @web_browser
42
66
  end
67
+ alias open_browser_with open_browser
43
68
 
44
- # fail the test if user can perform the operation
69
+ # return the underlying RWebUnit::Browser object
70
+ def browser
71
+ @web_browser
72
+ end
73
+
74
+
75
+ # Close the current browser window (started by the script). If no browser started, then close
76
+ # all browser windows.
45
77
  #
46
- # Example:
47
- # shall_not_allow { 1/0 }
48
- def shall_not_allow(&block)
49
- operation_performed_ok = false
50
- begin
51
- yield
52
- operation_performed_ok = true
53
- rescue
78
+ def close_browser
79
+ if @web_browser
80
+ # Old iTest2 version
81
+ # @web_browser.close_browser unless $ITEST2_LEAVE_BROWSER_OPEN_AFTER_RUN
82
+ @web_browser.close_browser
83
+ else
84
+ WebBrowser.close_all_browsers
54
85
  end
55
- raise "Operation shall not be allowed" if operation_performed_ok
56
86
  end
57
- alias do_not_allow shall_not_allow
87
+ alias close_ie close_browser
58
88
 
59
- def allow(&block)
60
- operation_performed_ok = false
61
- begin
62
- yield
63
- operation_performed_ok = true
64
- rescue
89
+
90
+ # Close all opening browser windows
91
+ #
92
+ def close_all_browsers
93
+ if is_firefox?
94
+ FireWatir::Firefox.close_all
95
+ else
96
+ Watir::IE.close_all
65
97
  end
66
- operation_performed_ok
67
98
  end
68
99
 
69
- # try operation, ignore if errors occur
100
+ # Verify the next page following an operation.
70
101
  #
71
- # Example:
72
- # failsafe { click_link("Logout") } # try logout, but it still OK if not being able to (already logout))
73
- def failsafe(&block)
74
- begin
75
- yield
76
- rescue =>e
102
+ # Typical usage:
103
+ # login_page.click_login
104
+ # expect_page HomePage
105
+ def expect_page(page_clazz, argument = nil)
106
+ if argument
107
+ page_clazz.new(@web_browser, argument)
108
+ else
109
+ page_clazz.new(@web_browser)
77
110
  end
78
111
  end
79
- alias fail_safe failsafe
80
112
 
81
113
  def context
82
114
  @web_browser.context
83
115
  end
84
116
 
117
+ # Starting browser with a URL
118
+ #
119
+ # Example:
120
+ # begin_at("http://www.itest2.com")
85
121
  def begin_at(url)
86
122
  dump_caller_stack
87
123
  @web_browser.begin_at(url)
88
124
  end
89
125
 
126
+ # Return the Watir::IE instance
127
+ #
90
128
  def ie
91
129
  @web_browser.ie
92
130
  end
93
131
 
94
- def is_firefox?
95
- @web_browser.is_firefox?
96
- end
97
-
132
+ # Return the FireWatir::Firefox instance
133
+ #
98
134
  def firefox
99
135
  @web_browser.firefox
100
136
  end
101
137
 
102
- def close_browser
103
- dump_caller_stack
104
- @web_browser.close_browser unless $ITEST2_LEAVE_BROWSER_OPEN_AFTER_RUN
138
+ def is_firefox?
139
+ @web_browser.is_firefox? if @web_browser
105
140
  end
106
- alias close_ie close_browser
107
141
 
108
142
 
143
+ # Go to another page on the testing site.
144
+ #
145
+ # open_browser("http://www.itest2.com")
146
+ # goto_page("/demo") # visit page http://www.itest2.com/demo
147
+ #
109
148
  def goto_page(page)
110
149
  operation_delay
111
150
  dump_caller_stack
112
- @web_browser.goto_page(page);
151
+ @web_browser.goto_page(page) if @web_browser
113
152
  end
114
153
  alias visit goto_page
115
154
 
155
+ # Go to another web site, normally different site being tested on
156
+ #
157
+ # open_browser("http://www.itest2.com")
158
+ # goto_url("http://myorganized.info")
159
+ def goto_url(url)
160
+ @web_browser.goto_url url
161
+ end
162
+
163
+ # Attach to existinb browser window
164
+ #
165
+ # attach_browser(:title, )
116
166
  def attach_browser(how, what, options = {})
117
167
  options.merge!(:browser => is_firefox? ? "Firefox" : "IE")
118
168
  begin
@@ -123,10 +173,21 @@ module RWebUnit
123
173
  WebBrowser.attach_browser(how, what, options)
124
174
  end
125
175
 
176
+ # Reuse current an opened browser window instead of opening a new one
177
+ # example:
178
+ # use_current_browser(:title, /.*/) # use what ever browser window
179
+ # use_current_browser(:title, "iTest2") # use browser window with title "iTest2"
180
+ def use_current_browser(how = :title, what = /.*/)
181
+ @web_browser = WebBrowser.attach_browser(how, what)
182
+ end
183
+
126
184
  ##
127
185
  # Delegate to WebTester
128
186
  #
129
-
187
+ # Note:
188
+ # label(:id, "abc") # OK
189
+ # label(:id, :abc) # Error
190
+ #
130
191
  # Depends on which object type, you can use following attribute
131
192
  # More details: http://wiki.openqa.org/display/WTR/Methods+supported+by+Element
132
193
  #
@@ -166,7 +227,8 @@ module RWebUnit
166
227
  [:area, :button, :cell, :checkbox, :div, :form, :frame, :h1, :h2, :h3, :h4, :h5, :h6, :hidden, :image, :li, :link, :map, :pre, :row, :radio, :select_list, :span, :table, :text_field, :paragraph, :file_field, :label].each do |method|
167
228
  define_method method do |*args|
168
229
  dump_caller_stack
169
- @web_browser.send(method, *args)
230
+ # add check for @web_browser, in case the moudule included without init browser
231
+ @web_browser.send(method, *args) if @web_browser
170
232
  end
171
233
  end
172
234
  alias td cell
@@ -176,7 +238,8 @@ module RWebUnit
176
238
  [:back, :forward, :refresh].each do |method|
177
239
  define_method(method) do
178
240
  dump_caller_stack
179
- @web_browser.send(method)
241
+ operation_delay
242
+ @web_browser.send(method) if @web_browser
180
243
  end
181
244
  end
182
245
  alias refresh_page refresh
@@ -186,7 +249,7 @@ module RWebUnit
186
249
  [:images, :links, :buttons, :select_lists, :checkboxes, :radios, :text_fields].each do |method|
187
250
  define_method method do
188
251
  dump_caller_stack
189
- @web_browser.send(method)
252
+ @web_browser.send(method) if @web_browser
190
253
  end
191
254
  end
192
255
 
@@ -195,15 +258,16 @@ module RWebUnit
195
258
  # page.check_checkbox('bad_ones', 'Chicken Little')
196
259
  # page.check_checkbox('good_ones', ['Cars', 'Toy Story'])
197
260
  #
198
- [:set_form_element, :click_link_with_text, :click_link_with_id, :submit, :click_button_with_id, :click_button_with_caption, :click_button_with_value, :click_radio_option, :clear_radio_option, :select_file_for_upload, :check_checkbox, :uncheck_checkbox, :select_option].each do |method|
261
+ [:set_form_element, :click_link_with_text, :click_link_with_id, :submit, :click_button_with_id, :click_button_with_name, :click_button_with_caption, :click_button_with_value, :click_radio_option, :clear_radio_option, :select_file_for_upload, :check_checkbox, :uncheck_checkbox, :select_option].each do |method|
199
262
  define_method method do |*args|
200
263
  dump_caller_stack
201
264
  operation_delay
202
- @web_browser.send(method, *args)
265
+ @web_browser.send(method, *args) if @web_browser
203
266
  end
204
267
  end
205
268
 
206
269
  alias enter_text set_form_element
270
+ alias set_hidden_field set_form_element
207
271
  alias click_link click_link_with_text
208
272
  alias click_button_with_text click_button_with_caption
209
273
  alias click_button click_button_with_caption
@@ -218,9 +282,13 @@ module RWebUnit
218
282
  end
219
283
 
220
284
  def contains_text(text)
221
- @web_browser.contains_text(text);
285
+ @web_browser.contains_text(text)
222
286
  end
223
287
 
288
+ # Click image buttion with image source name
289
+ #
290
+ # For an image submit button <input name="submit" type="image" src="/images/search_button.gif">
291
+ # click_button_with_image("search_button.gif")
224
292
  def click_button_with_image_src_contains(image_filename)
225
293
  dump_caller_stack
226
294
  operation_delay
@@ -241,6 +309,251 @@ module RWebUnit
241
309
  @web_browser.new_popup_window(options)
242
310
  end
243
311
 
312
+
313
+ # Warning: this does not work well with Firefox yet.
314
+ def element_text(elem_id)
315
+ @web_browser.element_value(elem_id)
316
+ end
317
+
318
+ # Identify DOM element by ID
319
+ # Warning: it is only supported on IE
320
+ def element_by_id(elem_id)
321
+ @web_browser.element_by_id(elem_id)
322
+ end
323
+
324
+ # ---
325
+ # For debugging
326
+ # ---
327
+ def dump_response(stream = nil)
328
+ @web_browser.dump_response(stream)
329
+ end
330
+
331
+ # For current page souce to a file in specified folder for inspection
332
+ #
333
+ # save_current_page(:dir => "C:\\mysite", filename => "abc", :replacement => true)
334
+ def save_current_page(options = {})
335
+ default_options = {:replacement => true}
336
+ options = default_options.merge(options)
337
+ if options[:dir]
338
+ # already defined the dir
339
+ to_dir = options[:dir]
340
+ elsif $ITEST2_RUNNING_SPEC_ID
341
+
342
+ $ITEST2_DUMP_DIR = File.join($ITEST2_WORKING_DIR, "dump")
343
+ FileUtils.mkdir($ITEST2_DUMP_DIR) unless File.exists?($ITEST2_DUMP_DIR)
344
+
345
+ spec_run_id = $ITEST2_RUNNING_SPEC_ID
346
+ spec_run_dir_name = spec_run_id.to_s.rjust(4, "0") unless spec_run_id == "unknown"
347
+ to_dir = File.join($ITEST2_DUMP_DIR, spec_run_dir_name)
348
+ else
349
+ to_dir = ENV['TEMP_DIR'] || "C:\\temp"
350
+ end
351
+
352
+ if options[:filename]
353
+ file_name = options[:filename]
354
+ else
355
+ file_name = Time.now.strftime("%m%d%H%M%S") + ".html"
356
+ end
357
+
358
+ Dir.mkdir(to_dir) unless File.exists?(to_dir)
359
+ file = File.join(to_dir, file_name)
360
+
361
+ content = page_source
362
+ base_url = @web_browser.context.base_url
363
+ current_url = @web_browser.url
364
+ current_url =~ /(.*\/).*$/
365
+ current_url_parent = $1
366
+ if options[:replacement] && base_url =~ /^http:/
367
+
368
+ # <link rel="stylesheet" type="text/css" href="/stylesheets/default.css" />
369
+ # '<script type="text/javascript" src="http://www.jeroenwijering.com/embed/swfobject.js"></script>'
370
+ # <script type="text/javascript" src="/javascripts/prototype.js"></script>
371
+ # <script type="text/javascript" src="/javascripts/scriptaculous.js?load=effects,builder"></script>
372
+ # <script type="text/javascript" src="/javascripts/extensions/gallery/lightbox.js"></script>
373
+ # <link href="/stylesheets/extensions/gallery/lightbox.css" rel="stylesheet" type="text/css" />
374
+ # <img src="images/mission_48.png" />
375
+
376
+ modified_content = ""
377
+
378
+ content.each_line do |line|
379
+ if line =~ /<script\s+.*src=["'']?(.*)["'].*/i then
380
+ script_src = $1
381
+ substitute_relative_path_in_src_line(line, script_src, base_url, current_url_parent)
382
+ elsif line =~ /<link\s+.*href=["'']?(.*)["'].*/i then
383
+ link_href = $1
384
+ substitute_relative_path_in_src_line(line, link_href, base_url, current_url_parent)
385
+ elsif line =~ /<img\s+.*src=["'']?(.*)["'].*/i then
386
+ img_src = $1
387
+ substitute_relative_path_in_src_line(line, img_src, base_url, current_url_parent)
388
+ end
389
+
390
+ modified_content += line
391
+ end
392
+
393
+ File.new(file, "w").puts modified_content
394
+ else
395
+ File.new(file, "w").puts content
396
+
397
+ end
398
+
399
+
400
+ end
401
+
402
+ # substut
403
+ def substitute_relative_path_in_src_line(line, script_src, host_url, page_parent_url)
404
+ unless script_src =~ /^["']?http:/
405
+ host_url.slice!(-1) if ends_with?(host_url, "/")
406
+ if script_src =~ /^\s*\// # absolute_path
407
+ line.gsub!(script_src, "#{host_url}#{script_src}")
408
+ else #relative_path
409
+ line.gsub!(script_src, "#{page_parent_url}#{script_src}")
410
+ end
411
+ end
412
+ end
413
+
414
+ def ends_with?(str, suffix)
415
+ suffix = suffix.to_s
416
+ str[-suffix.length, suffix.length] == suffix
417
+ end
418
+
419
+ # current web page title
420
+ def page_title
421
+ @web_browser.page_title
422
+ end
423
+
424
+ # current page source (in HTML)
425
+ def page_source
426
+ @web_browser.page_source
427
+ end
428
+
429
+ # return plain text view of page
430
+ def page_text
431
+ @web_browser.text
432
+ end
433
+
434
+ # return the text of specific (identified by attribute "id") label tag
435
+ # For page containing
436
+ # <label id="preferred_ide">iTest2</label>
437
+ # label_with_id("preferred_ids") # => iTest2
438
+ def label_with_id(label_id)
439
+ label(:id, label_id.to_s).text
440
+ end
441
+
442
+ # return the text of specific (identified by attribute "id") span tag
443
+ # For page containing
444
+ # <span id="preferred_recorder">iTest2/Watir Recorder</span>
445
+ # span_with_id("preferred_recorder") # => iTest2/Watir Recorder
446
+ def span_with_id(span_id)
447
+ span(:id, span_id).text
448
+ end
449
+
450
+ # return the text of specific (identified by attribute "id") ta tag
451
+ # For page containing
452
+ # <td id="preferred_recorder">iTest2/Watir Recorder</span>
453
+ # td_with_id("preferred_recorder") # => iTest2/Watir Recorder
454
+ def cell_with_id(cell_id)
455
+ cell(:id, cell_id).text
456
+ end
457
+ alias table_data_with_id cell_with_id
458
+
459
+
460
+ def is_mac?
461
+ RUBY_PLATFORM.downcase.include?("darwin")
462
+ end
463
+
464
+ def is_windows?
465
+ RUBY_PLATFORM.downcase.include?("mswin") or RUBY_PLATFORM.downcase.include?("mingw32")
466
+ end
467
+
468
+ # Support browser (IE) operations using unicode
469
+ # Example:
470
+ # click_button("Google 搜索")
471
+ def support_utf8
472
+ if is_windows?
473
+ require 'win32ole'
474
+ WIN32OLE.codepage = WIN32OLE::CP_UTF8
475
+ end
476
+ end
477
+ alias support_unicode support_utf8
478
+
479
+ def is_linux?
480
+ RUBY_PLATFORM.downcase.include?("linux")
481
+ end
482
+
483
+ #= Convenient functions
484
+ #
485
+
486
+ # Using Ruby block syntax to create interesting domain specific language,
487
+ # may be appeal to someone.
488
+
489
+ # Example:
490
+ # on @page do |i|
491
+ # i.enter_text('btn1')
492
+ # i.click_button('btn1')
493
+ # end
494
+ def on(page, &block)
495
+ yield page
496
+ end
497
+
498
+ # fail the test if user can perform the operation
499
+ #
500
+ # Example:
501
+ # shall_not_allow { 1/0 }
502
+ def shall_not_allow(&block)
503
+ operation_performed_ok = false
504
+ begin
505
+ yield
506
+ operation_performed_ok = true
507
+ rescue
508
+ end
509
+ raise "Operation shall not be allowed" if operation_performed_ok
510
+ end
511
+ alias do_not_allow shall_not_allow
512
+
513
+ # Does not provide real function, other than make enhancing test syntax
514
+ #
515
+ # Example:
516
+ # allow { click_button('Register') }
517
+ def allow(&block)
518
+ operation_performed_ok = false
519
+ begin
520
+ yield
521
+ operation_performed_ok = true
522
+ rescue
523
+ end
524
+ operation_performed_ok
525
+ end
526
+ alias shall_allow allow
527
+ alias allowing allow
528
+
529
+ # try operation, ignore if errors occur
530
+ #
531
+ # Example:
532
+ # failsafe { click_link("Logout") } # try logout, but it still OK if not being able to (already logout))
533
+ def failsafe(&block)
534
+ begin
535
+ yield
536
+ rescue =>e
537
+ end
538
+ end
539
+ alias fail_safe failsafe
540
+
541
+
542
+ # Execute the provided block until either (1) it returns true, or
543
+ # (2) the timeout (in seconds) has been reached. If the timeout is reached,
544
+ # a TimeOutException will be raised. The block will always
545
+ # execute at least once.
546
+ #
547
+ # This does not handle error, if the given block raise error, the statement finish with error
548
+ # Examples:
549
+ # wait_until {puts 'hello'}
550
+ # wait_until { div(:id, :receipt_date).exists? }
551
+ #
552
+ def wait_until(timeout = @@default_timeout || 30, polling_interval = @@default_polling_interval || 1, &block)
553
+ waiter = Watir::Waiter.new(timeout, polling_interval)
554
+ waiter.wait_until { yield }
555
+ end
556
+
244
557
  # Wait for specific seconds for an Ajax update finish.
245
558
  # Trick: In your Rails application,
246
559
  # :loading => "Element.show('search_indicator');
@@ -256,7 +569,7 @@ module RWebUnit
256
569
  #
257
570
  # Warning: this method has not been fully tested, if you are not using Rails, change your parameter accordingly.
258
571
  #
259
- def ajax_wait_for_element(element_id, seconds, status='show', check_interval=2)
572
+ def ajax_wait_for_element(element_id, seconds, status='show', check_interval = @@default_polling_interval)
260
573
  count = 0
261
574
  check_interval = 1 if check_interval < 1 or check_interval > seconds
262
575
  while count < (seconds / check_interval) do
@@ -273,8 +586,12 @@ module RWebUnit
273
586
  return false
274
587
  end
275
588
 
276
- def wait_for_element(element_id, timeout = 30, interval = 0.5)
589
+ #Wait the element with given id to be present in web page
590
+ #
591
+ # Warning: this not working in Firefox, try use wait_util or try instead
592
+ def wait_for_element(element_id, timeout = @@default_timeout, interval = @@default_polling_interval)
277
593
  start_time = Time.now
594
+ #TODO might not work with Firefox
278
595
  until @web_browser.element_by_id(element_id) do
279
596
  sleep(interval)
280
597
  if (Time.now - start_time) > timeout
@@ -282,6 +599,7 @@ module RWebUnit
282
599
  end
283
600
  end
284
601
  end
602
+ =begin
285
603
 
286
604
  # TODO: Firewatir does not suport retrieving style or outerHtml
287
605
  # http://jira.openqa.org/browse/WTR-260
@@ -313,231 +631,78 @@ module RWebUnit
313
631
  end
314
632
  end
315
633
 
316
- # Warning: this does not work well with Firefox yet.
317
- def element_text(elem_id)
318
- @web_browser.element_value(elem_id)
319
- end
320
-
321
- def element_by_id(elem_id)
322
- @web_browser.element_by_id(elem_id)
323
- end
324
-
325
- # ---
326
- # For debugging
327
- # ---
328
- def dump_response(stream = nil)
329
- @web_browser.dump_response(stream)
330
- end
331
-
332
- def save_current_page(to_dir = ENV['TEMP_DIR'] || "C:\\temp")
333
- Dir.mkdir(to_dir) unless File.exists?(to_dir)
334
- file_name = Time.now.strftime("%m%d%H%M%S") + ".html"
335
- file = File.join(to_dir, file_name)
336
- File.new(file, "w").puts page_source
337
- end
338
-
339
- def click_popup_window(button, wait_time= 9, user_input=nil )
340
- @web_browser.start_clicker(button, wait_time, user_input)
341
- sleep 0.5
342
- end
343
-
344
- # return plain text view of page
345
- def page_text
346
- Hpricot(page_source).to_plain_text
347
- end
348
-
349
- def label_with_id(label_id)
350
- label(:id, label_id).text
351
- end
352
-
353
- def span_with_id(span_id)
354
- span(:id, span_id).text
355
- end
356
-
357
- def cell_with_id(cell_id)
358
- cell(:id, cell_id).text
359
- end
360
- alias table_data_with_id cell_with_id
361
-
362
- # run a separate process waiting for the popup window to click
363
- #
364
- #
365
- def prepare_to_click_button_in_popup(button = "OK", wait_time = 3)
366
- # !@web_browser.is_firefox?
367
- # TODO: firefox is OK
368
- if RUBY_PLATFORM =~ /mswin/ then
369
- start_checking_js_dialog(button, wait_time)
370
- else
371
- raise "this only support on Windows and on IE"
372
- end
373
- end
374
-
375
- # Start a background process to click the button on a javascript popup window
376
- def start_checking_js_dialog(button = "OK", wait_time = 3)
377
- w = WinClicker.new
378
- longName = File.expand_path(File.dirname(__FILE__)).gsub("/", "\\" )
379
- shortName = w.getShortFileName(longName)
380
- c = "start ruby #{shortName}\\clickJSDialog.rb #{button} #{wait_time} "
381
- w.winsystem(c)
382
- w = nil
383
- end
384
-
385
- # Click the button in javascript popup dialog
386
- # Usage:
387
- # click_button_in_popup_after { click_link('Cancel')}
388
- # click_button_in_popup_after("OK") { click_link('Cancel')}
389
- #
390
- def click_button_in_popup_after(options = {:button => "OK", :wait_time => 3}, &block)
391
- if RUBY_PLATFORM =~ /mswin/ then
392
- start_checking_js_dialog(options[:button], options[:wait_time])
393
- yield
394
- else
395
- raise "this only support on Windows and on IE"
634
+ =end
635
+
636
+ # Try the operation up to specified times, and sleep given interval (in seconds)
637
+ # Error will be ignored until timeout
638
+ # Example
639
+ # repeat_try(3, 2) { click_button('Search' } # 3 times, 6 seconds in total
640
+ # repeat_try { click_button('Search' } # using default 5 tries, 2 second interval
641
+ def repeat_try(num_tries = @@default_timeout || 30, interval = @@default_polling_interval || 1, &block)
642
+ num_tries ||= 1
643
+ (num_tries - 1).times do |num|
644
+ begin
645
+ yield
646
+ return
647
+ rescue => e
648
+ # puts "debug: #{num} failed: #{e}"
649
+ sleep interval
650
+ end
396
651
  end
397
- end
398
652
 
399
-
400
- # Support of iTest to ajust the intervals between keystroke/mouse operations
401
- def operation_delay
653
+ # last try, throw error if still fails
402
654
  begin
403
- if $ITEST2_OPERATION_DELAY && $ITEST2_OPERATION_DELAY > 0 &&
404
- $ITEST2_OPERATION_DELAY && $ITEST2_OPERATION_DELAY < 30000 then # max 30 seconds
405
- sleep($ITEST2_OPERATION_DELAY / 1000)
406
- end
407
-
408
- while $ITEST2_PAUSE
409
- debug("Paused, waiting ...")
410
- sleep 1
411
- end
655
+ yield
412
656
  rescue => e
413
- puts "Error on delaying: #{e}"
414
- # ignore
657
+ raise e.to_s + " after trying #{num_tries} times every #{interval} seconds"
415
658
  end
659
+ yield
416
660
  end
417
661
 
662
+ # TODO: syntax
418
663
 
419
- def close_all_browsers
420
- Watir::IE.close_all
421
- end
422
-
423
- def is_mac?
424
- RUBY_PLATFORM.downcase.include?("darwin")
425
- end
426
-
427
- def is_windows?
428
- RUBY_PLATFORM.downcase.include?("mswin")
429
- end
430
-
431
- def is_linux?
432
- RUBY_PLATFORM.downcase.include?("linux")
433
- end
434
-
435
- # Start background thread to click popup windows
436
- # Warning:
437
- # Make browser window active
438
- # Don't mouse your mouse to focus other window during test execution
439
- def check_for_popups
440
- autoit = WIN32OLE.new('AutoItX3.Control')
441
- #
442
- # Do forever - assumes popups could occur anywhere/anytime in your
443
- # application.
444
- loop do
445
- # Look for window with given title. Give up after 1 second.
446
- ret = autoit.WinWait('Windows Internet Explorer', '', 1)
447
- #
448
- # If window found, send appropriate keystroke (e.g. {enter}, {Y}, {N}).
449
- if (ret==1) then
450
- autoit.Send('{enter}')
451
- end
452
- #
453
- # Take a rest to avoid chewing up cycles and give another thread a go.
454
- # Then resume the loop.
455
- sleep(3)
456
- end
457
- end
664
+ # Try the operation up to specified timeout (in seconds), and sleep given interval (in seconds).
665
+ # Error will be ignored until timeout
666
+ # Example
667
+ # try { click_link('waiting')}
668
+ # try(10, 2) { click_button('Search' } # try to click the 'Search' button upto 10 seconds, try every 2 seconds
669
+ # try { click_button('Search' }
670
+ def try(timeout = @@default_timeout, polling_interval = @@default_polling_interval || 1, &block)
671
+ start_time = Time.now
458
672
 
459
- ##
460
- # Check for "Security Information" and "Security Alert" alert popup, click 'Yes'
461
- #
462
- # Usage: For individual test suite
463
- #
464
- # before(:all) do
465
- # $popup = Thread.new { check_for_alerts }
466
- # open_in_browser
467
- # ...
468
- # end
469
- #
470
- # after(:all) do
471
- # close_browser
472
- # Thread.kill($popup)
473
- # end
474
- #
475
- # or for all tests,
476
- # $popup = Thread.new { check_for_alerts }
477
- # at_exit{ Thread.kill($popup) }
478
- def check_for_security_alerts
479
- autoit = WIN32OLE.new('AutoItX3.Control')
480
- loop do
481
- ["Security Alert", "Security Information"].each do |win_title|
482
- ret = autoit.WinWait(win_title, '', 1)
483
- if (ret==1) then
484
- autoit.Send('{Y}')
485
- end
673
+ last_error = nil
674
+ until (duration = Time.now - start_time) > timeout
675
+ begin
676
+ return if yield
677
+ last_error = nil
678
+ rescue => e
679
+ last_error = e
486
680
  end
487
- sleep(3)
488
- end
489
- end
490
-
491
- def verify_alert(title = "Microsoft Internet Explorer", button = "OK")
492
- if is_windows? && !is_firefox?
493
- WIN32OLE.new('AutoItX3.Control').ControlClick(title, '', button)
494
- else
495
- raise "This function only supports IE"
681
+ sleep polling_interval
496
682
  end
497
- end
498
-
499
- def click_button_in_security_information_popup(button = "&Yes")
500
- verify_alert("Security Information", "", button)
501
- end
502
- alias click_security_information_popup click_button_in_security_information_popup
503
-
504
- def click_button_in_security_alert_popup(button = "&Yes")
505
- verify_alert("Security Alert", "", button)
506
- end
507
- alias click_security_alert_popup click_button_in_security_alert_popup
508
683
 
509
- def click_button_in_javascript_popup(button = "OK")
510
- verify_alert()
511
- end
512
- alias click_javascript_popup click_button_in_javascript_popup
513
-
514
- ##
515
- # This only works for IEs
516
- # Cons:
517
- # - Slow
518
- # - only works in IE
519
- # - does not work for security alert ?
520
- def ie_popup_clicker(button_name = "OK", max_wait = 15)
521
- require 'watir/contrib/enabled_popup'
522
- require 'win32ole'
523
- hwnd = ie.enabled_popup(15)
524
- if (hwnd) #yeah! a popup
525
- popup = WinClicker.new
526
- popup.makeWindowActive(hwnd) #Activate the window.
527
- popup.clickWindowsButton_hwnd(hwnd, button_name) #Click the button
528
- #popup.clickWindowsButton(/Internet/,button_name,30)
529
- popup = nil
530
- end
684
+ raise "Timeout after #{duration.to_i} seconds with error: #{last_error}." if last_error
685
+ raise "Timeout after #{duration.to_i} seconds."
531
686
  end
687
+ alias try_upto try
532
688
 
533
689
  ##
534
690
  # Convert :first to 1, :second to 2, and so on...
535
691
  def symbol_to_sequence(symb)
536
- value = { :zero => 0, :first => 1, :second => 2, :third => 3,
537
- :fourth => 4, :fifth => 5, :sixth => 6, :seventh => 7,
538
- :eighth => 8, :ninth => 9, :tenth => 10 }[symb]
692
+ value = { :zero => 0,
693
+ :first => 1,
694
+ :second => 2,
695
+ :third => 3,
696
+ :fourth => 4,
697
+ :fifth => 5,
698
+ :sixth => 6,
699
+ :seventh => 7,
700
+ :eighth => 8,
701
+ :ninth => 9,
702
+ :tenth => 10 }[symb]
539
703
  return value || symb.to_i
540
704
  end
541
705
 
542
706
  end
707
+
543
708
  end