rwebunit 1.0.3 → 1.3.0

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