rwebspec 1.4.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.
@@ -0,0 +1,528 @@
1
+ #***********************************************************
2
+ #* Copyright (c) 2006, Zhimin Zhan.
3
+ #* Distributed open-source, see full license in MIT-LICENSE
4
+ #***********************************************************
5
+
6
+ begin
7
+ require 'watir'
8
+ require 'watir/ie'
9
+ require 'watir/contrib/enabled_popup'
10
+ require 'watir/contrib/visible'
11
+ require 'watir/close_all'
12
+ $watir_loaded = true
13
+ rescue LoadError => e
14
+ $watir_loaded = false
15
+ end
16
+
17
+ begin
18
+ require "rubygems";
19
+ require "firewatir";
20
+ $firewatir_loaded = true
21
+ rescue LoadError => e
22
+ $firewatir_loaded = false
23
+ end
24
+
25
+ begin
26
+ require "rubygems";
27
+ require "celerity";
28
+ $celerity_loaded = true
29
+ rescue LoadError => e
30
+ $celerity_loaded = false
31
+ end
32
+
33
+ raise "You have must at least Watir or Firewatir installed" unless $watir_loaded || $firewatir_loaded || $celerity_loaded
34
+
35
+ module RWebSpec
36
+
37
+ ##
38
+ # Wrapping WATIR IE and FireWatir Firefox
39
+ #
40
+ class WebBrowser
41
+
42
+ attr_accessor :context
43
+
44
+ def initialize(base_url = nil, existing_browser = nil, options = {})
45
+ default_options = {:speed => "zippy",
46
+ :visible => true,
47
+ :highlight_colour => 'yellow',
48
+ :close_others => true
49
+ }
50
+ options = default_options.merge options
51
+ options[:existing_browser] = existing_browser
52
+ @context = Context.new base_url if base_url
53
+
54
+ case RUBY_PLATFORM
55
+ when /java/i
56
+ # Java, maybe firewatir or celerity
57
+ puts "Ruby java platform"
58
+ raise "Not supported, no FireWatir or Celerity detected" unless $firewatir_loaded || $celerity_loaded
59
+ if $firewatir_loaded && $celerity_loaded then
60
+ # choose one out of two, :default to celerity
61
+ if options[:firefox] then
62
+ initialize_firefox_browser(base_url, options)
63
+ else
64
+ initialize_celerity_browser(base_url, options)
65
+ end
66
+ elsif $firewatir_loaded
67
+ initialize_firefox_browser(base_url, options)
68
+ else
69
+ initialize_celerity_browser(base_url, options)
70
+ end
71
+
72
+ when /mswin|windows|mingw/i
73
+ puts "Ruby windows platform"
74
+ raise "Not supported, no Watir or FireWatir detected" unless $watir_loaded || $firewatir_loaded
75
+ if $firewatir_loaded && options[:firefox] then
76
+ initialize_firefox_browser(base_url, options)
77
+ else
78
+ initialize_ie_browser(options)
79
+ end
80
+ else
81
+ raise "Not supported, no FireWatirdetected" unless $firewatir_loaded
82
+ puts "Ruby Linux or Mac platform: firefox"
83
+ initialize_firefox_browser(base_url, options)
84
+ end
85
+ end
86
+
87
+ def initialize_firefox_browser(base_url, options)
88
+ if options[:existing_browser] then
89
+ @browser = existing_browser
90
+ return
91
+ end
92
+ # JSSH is running, 9997
93
+ begin
94
+ require 'net/telnet'
95
+ firefox_jssh = Net::Telnet::new("Host" => "127.0.0.1", "Port" => 9997)
96
+ FireWatir::Firefox.firefox_started = true
97
+ rescue => e
98
+ # puts "debug: XXX #{e}"
99
+ sleep 1
100
+ end
101
+ @browser = FireWatir::Firefox.start(base_url)
102
+ end
103
+
104
+ def initialize_celerity_browser(base_url, options)
105
+ default_celerity_options = { :proxy => nil, :browser => :firefox, :resynchronize => true, :log_level => :off }
106
+ options = default_celerity_options.merge options
107
+ options.each { |k, v| options.delete(k) unless default_celerity_options.keys.include?(k)}
108
+ puts "Starting Celerity: #{options.inspect}"
109
+ @browser = Celerity::Browser.new(options)
110
+ @browser.goto(base_url)
111
+ end
112
+
113
+ def initialize_ie_browser(options)
114
+ if options[:existing_browser] then
115
+ @browser = existing_browser
116
+ return
117
+ end
118
+
119
+ @browser = Watir::IE.new
120
+ if $ITEST2_EMULATE_TYPING && $ITEST2_TYPING_SPEED then
121
+ @browser.set_slow_speed if $ITEST2_TYPING_SPEED == 'slow'
122
+ @browser.set_fast_speed if $ITEST2_TYPING_SPEED == 'fast'
123
+ else
124
+ @browser.speed = :zippy
125
+ end
126
+ @browser.activeObjectHighLightColor = options[:highlight_colour]
127
+ @browser.visible = options[:visible] unless $HIDE_IE
128
+ #NOTE: close_others fails
129
+ if RUBY_VERSION =~ /^1\.8/ && options[:close_others] then
130
+ puts "close other browser instances not working yet in Ruby 1.9.1 version of Watir"
131
+ @browser.close_others
132
+ end
133
+ end
134
+
135
+ def self.reuse(base_url, options)
136
+ if RUBY_PLATFORM.downcase.include?("mswin") && $ITEST2_BROWSER != "Firefox"
137
+ Watir::IE.each do |browser_window|
138
+ return WebBrowser.new(base_url, browser_window, options)
139
+ end
140
+ puts "no browser instance found"
141
+ WebBrowser.new(base_url, nil, options)
142
+ else
143
+ WebBrowser.new(base_url, nil, options)
144
+ end
145
+ end
146
+
147
+ # for popup windows
148
+ def self.new_from_existing(underlying_browser, web_context = nil)
149
+ return WebBrowser.new(web_context ? web_context.base_url : nil, underlying_browser, {:close_others => false})
150
+ end
151
+
152
+
153
+ ##
154
+ # Delegate to Watir
155
+ #
156
+ [: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|
157
+ define_method method do |*args|
158
+ @browser.send(method, *args)
159
+ end
160
+ end
161
+ alias td cell
162
+ alias check_box checkbox # seems watir doc is wrong, checkbox not check_box
163
+ alias tr row
164
+
165
+ # FireWatir does not support area directly, treat it as text_field
166
+ def area(*args)
167
+ if is_firefox?
168
+ text_field(*args)
169
+ else
170
+ @browser.send("area", *args)
171
+ end
172
+ end
173
+
174
+ def contains_text(text)
175
+ @browser.contains_text(text);
176
+ end
177
+
178
+ def page_source
179
+ @browser.html()
180
+ #@browser.document.body
181
+ end
182
+
183
+ alias html_body page_source
184
+
185
+ def html
186
+ @browser.html
187
+ end
188
+
189
+ def text
190
+ @browser.text
191
+ end
192
+
193
+ def page_title
194
+ case @browser.class.to_s
195
+ when "FireWatir::Firefox"
196
+ @browser.title
197
+ when "Watir::IE"
198
+ @browser.document.title
199
+ else
200
+ @browser.title
201
+ end
202
+ end
203
+
204
+ [:images, :links, :buttons, :select_lists, :checkboxes, :radios, :text_fields].each do |method|
205
+ define_method method do
206
+ @browser.send(method)
207
+ end
208
+ end
209
+
210
+ # current url
211
+ def url
212
+ @browser.url
213
+ end
214
+
215
+ def base_url=(new_base_url)
216
+ if @context
217
+ @conext.base_url = new_base_url
218
+ return
219
+ end
220
+ @context = Context.new base_url
221
+ end
222
+
223
+ def is_firefox?
224
+ return false unless $firewatir_loaded
225
+ begin
226
+ @browser.class == FireWatir::Firefox
227
+ rescue => e
228
+ return false
229
+ end
230
+ end
231
+
232
+ # Close the browser window. Useful for automated test suites to reduce
233
+ # test interaction.
234
+ def close_browser
235
+ case @browser.class.to_s
236
+ when "FireWatir::Firefox"
237
+ @browser.close
238
+ when "Watir::IE"
239
+ @browser.getIE.quit
240
+ else
241
+ puts "#{@browser.class} can't close, ignore"
242
+ end
243
+ sleep 2
244
+ end
245
+
246
+ alias close close_browser
247
+
248
+ #TODO determine browser type, check FireWatir support or not
249
+ def self.close_all_browsers
250
+ if RUBY_PLATFORM.downcase.include?("mswin")
251
+ Watir::IE.close_all
252
+ else
253
+ # raise "not supported in FireFox yet."
254
+ end
255
+ end
256
+
257
+ def full_url(relative_url)
258
+ if @context && @context.base_url
259
+ @context.base_url + relative_url
260
+ else
261
+ relative_url
262
+ end
263
+ end
264
+
265
+ def begin_at(relative_url)
266
+ @browser.goto full_url(relative_url)
267
+ end
268
+
269
+ def browser_opened?
270
+ begin
271
+ @browser != nil
272
+ rescue => e
273
+ return false
274
+ end
275
+ end
276
+
277
+ # Some browsers (i.e. IE) need to be waited on before more actions can be
278
+ # performed. Most action methods in Watir::Simple already call this before
279
+ # and after.
280
+ def wait_for_browser
281
+ if $celerity_loaded then
282
+ # puts "ignore, using celerity"
283
+ else
284
+ @browser.waitForIE unless is_firefox?
285
+ end
286
+ end
287
+
288
+
289
+ # A convenience method to wait at both ends of an operation for the browser
290
+ # to catch up.
291
+ def wait_before_and_after
292
+ wait_for_browser
293
+ yield
294
+ wait_for_browser
295
+ end
296
+
297
+
298
+ [:back, :forward, :refresh, :focus, :close_others].each do |method|
299
+ define_method(method) do
300
+ @browser.send(method)
301
+ end
302
+ end
303
+ alias refresh_page refresh
304
+ alias go_back back
305
+ alias go_forward forward
306
+
307
+ def goto_page(page)
308
+ @browser.goto full_url(page);
309
+ end
310
+
311
+ def goto_url(url)
312
+ @browser.goto url
313
+ end
314
+
315
+ # text fields
316
+ def enter_text_into_field_with_name(name, text)
317
+ if is_firefox?
318
+ wait_before_and_after { text_field(:name, name).value = text }
319
+ sleep 0.3
320
+ else
321
+ wait_before_and_after { text_field(:name, name).set(text) }
322
+ end
323
+ end
324
+
325
+ alias set_form_element enter_text_into_field_with_name
326
+ alias enter_text enter_text_into_field_with_name
327
+
328
+ #links
329
+ def click_link_with_id(link_id)
330
+ wait_before_and_after { link(:id, link_id).click }
331
+ end
332
+
333
+ def click_link_with_text(text)
334
+ wait_before_and_after { link(:text, text).click }
335
+ end
336
+
337
+ ##
338
+ # buttons
339
+
340
+ def click_button_with_id(id)
341
+ wait_before_and_after { button(:id, id).click }
342
+ end
343
+
344
+ def click_button_with_name(name)
345
+ wait_before_and_after { button(:name, name).click }
346
+ end
347
+
348
+ def click_button_with_caption(caption)
349
+ wait_before_and_after { button(:caption, caption).click }
350
+ end
351
+
352
+ def click_button_with_value(value)
353
+ wait_before_and_after { button(:value, value).click }
354
+ end
355
+
356
+ def select_option(selectName, option)
357
+ select_list(:name, selectName).select(option)
358
+ end
359
+
360
+ # submit first submit button
361
+ def submit(buttonName = nil)
362
+ if (buttonName.nil?) then
363
+ buttons.each { |button|
364
+ next if button.type != 'submit'
365
+ button.click
366
+ return
367
+ }
368
+ else
369
+ click_button_with_name(buttonName)
370
+ end
371
+ end
372
+
373
+ # checkbox
374
+ def check_checkbox(checkBoxName, values=nil)
375
+ if values
376
+ values.class == Array ? arys = values : arys = [values]
377
+ arys.each {|cbx_value|
378
+ checkbox(:name, checkBoxName, cbx_value).set
379
+ }
380
+ else
381
+ checkbox(:name, checkBoxName).set
382
+ end
383
+ end
384
+
385
+ def uncheck_checkbox(checkBoxName, values = nil)
386
+ if values
387
+ values.class == Array ? arys = values : arys = [values]
388
+ arys.each {|cbx_value|
389
+ checkbox(:name, checkBoxName, cbx_value).clear
390
+ }
391
+ else
392
+ checkbox(:name, checkBoxName).clear
393
+ end
394
+ end
395
+
396
+
397
+ # the method is protected in JWebUnit
398
+ def click_radio_option(radio_group, radio_option)
399
+ radio(:name, radio_group, radio_option).set
400
+ end
401
+
402
+ def clear_radio_option(radio_group, radio_option)
403
+ radio(:name, radio_group, radio_option).clear
404
+ end
405
+
406
+ def element_by_id(elem_id)
407
+ if is_firefox?
408
+ # elem = @browser.document.getElementById(elem_id)
409
+ elem = div(:id, elem_id) || label(:id, elem_id) || button(:id, elem_id) || span(:id, elem_id) || hidden(:id, elem_id) || link(:id, elem_id) || radio(:id, elem_id)
410
+ else
411
+ elem = @browser.document.getElementById(elem_id)
412
+ end
413
+ end
414
+
415
+ def element_value(elementId)
416
+ if is_firefox? then
417
+ elem = element_by_id(elementId)
418
+ elem ? elem.invoke('innerText') : nil
419
+ else
420
+ elem = element_by_id(elementId)
421
+ elem ? elem.invoke('innerText') : nil
422
+ end
423
+ end
424
+
425
+ def element_source(elementId)
426
+ elem = element_by_id(elementId)
427
+ assert_not_nil(elem, "HTML element: #{elementId} not exists")
428
+ elem.innerHTML
429
+ end
430
+
431
+ def select_file_for_upload(file_field, file_path)
432
+ normalized_file_path = RUBY_PLATFORM.downcase.include?("mswin") ? file_path.gsub("/", "\\") : file_path
433
+ file_field(:name, file_field).set(normalized_file_path)
434
+ end
435
+
436
+ def start_window(url = nil)
437
+ @browser.start_window(url);
438
+ end
439
+
440
+ # Attach to existing browser
441
+ #
442
+ # Usage:
443
+ # WebBrowser.attach_browser(:title, "iTest2")
444
+ # WebBrowser.attach_browser(:url, "http://www.itest2.com")
445
+ # WebBrowser.attach_browser(:url, "http://www.itest2.com", {:browser => "Firefox", :base_url => "http://www.itest2.com"})
446
+ # WebBrowser.attach_browser(:title, /agileway\.com\.au\/attachment/) # regular expression
447
+ def self.attach_browser(how, what, options={})
448
+ default_options = {:browser => "IE"}
449
+ options = default_options.merge(options)
450
+ site_context = Context.new(options[:base_url]) if options[:base_url]
451
+ if (options[:browser] == "Firefox")
452
+ return WebBrowser.new_from_existing(FireWatir::Firefox.new.attach(how, what), site_context)
453
+ else
454
+ return WebBrowser.new_from_existing(Watir::IE.attach(how, what), site_context)
455
+ end
456
+ end
457
+
458
+ # Attach a Watir::IE instance to a popup window.
459
+ #
460
+ # Typical usage
461
+ # new_popup_window(:url => "http://www.google.com/a.pdf")
462
+ def new_popup_window(options, browser = "ie")
463
+ if is_firefox?
464
+ raise "not implemented"
465
+ else
466
+ if options[:url]
467
+ Watir::IE.attach(:url, options[:url])
468
+ elsif options[:title]
469
+ Watir::IE.attach(:title, options[:title])
470
+ else
471
+ raise 'Please specify title or url of new pop up window'
472
+ end
473
+ end
474
+ end
475
+
476
+ # ---
477
+ # For deubgging
478
+ # ---
479
+ def dump_response(stream = nil)
480
+ stream.nil? ? puts(page_source) : stream.puts(page_source)
481
+ end
482
+
483
+ # A Better Popup Handler using the latest Watir version. Posted by Mark_cain@rl.gov
484
+ #
485
+ # http://wiki.openqa.org/display/WTR/FAQ#FAQ-HowdoIattachtoapopupwindow%3F
486
+ #
487
+ def start_clicker( button, waitTime= 9, user_input=nil)
488
+ # get a handle if one exists
489
+ hwnd = @browser.enabled_popup(waitTime)
490
+ if (hwnd) # yes there is a popup
491
+ w = WinClicker.new
492
+ if ( user_input )
493
+ w.setTextValueForFileNameField( hwnd, "#{user_input}" )
494
+ end
495
+ # I put this in to see the text being input it is not necessary to work
496
+ sleep 3
497
+ # "OK" or whatever the name on the button is
498
+ w.clickWindowsButton_hwnd( hwnd, "#{button}" )
499
+ #
500
+ # this is just cleanup
501
+ w = nil
502
+ end
503
+ end
504
+
505
+ # return underlying browser
506
+ def ie
507
+ raise "can't call this as it is configured to use Firefox" if is_firefox?
508
+ @browser
509
+ end
510
+
511
+ def firefox
512
+ raise "can't call this as it is configured to use IE" unless is_firefox?
513
+ @browser
514
+ end
515
+
516
+ def save_page(file_name = nil)
517
+ file_name ||= Time.now.strftime("%Y%m%d%H%M%S") + ".html"
518
+ puts "about to save page: #{File.expand_path(file_name)}"
519
+ File.open(file_name, "w").puts page_source
520
+ end
521
+
522
+
523
+ def self.is_windows?
524
+ RUBY_PLATFORM.downcase.include?("mswin") or RUBY_PLATFORM.downcase.include?("mingw")
525
+ end
526
+
527
+ end
528
+ end
@@ -0,0 +1,94 @@
1
+ #***********************************************************
2
+ #* Copyright (c) 2006, Zhimin Zhan.
3
+ #* Distributed open-source, see full license in MIT-LICENSE
4
+ #***********************************************************
5
+ require File.join(File.dirname(__FILE__), 'assert')
6
+ require File.join(File.dirname(__FILE__), 'driver')
7
+ require 'fileutils'
8
+
9
+ module RWebSpec
10
+
11
+ # WebPage (children of AbstractWebPage) encapsulates a real web page.
12
+ # For example,
13
+ # beginAt("/home")
14
+ # @web_browser.clickLinkWithText("/login")
15
+ # @web_browser.setFormElement("username", "sa")
16
+ # Can be rewritten to
17
+ # begin_at("/home")
18
+ # home_page = HomePage.new
19
+ # login_page = home_page.clickLoginLink
20
+ # login_page.enterUserName("sa")
21
+ #
22
+ # So you only need change in LoingPage class if UI changes, which happen quite often.
23
+ class AbstractWebPage
24
+
25
+ include RWebSpec::Assert
26
+ include RWebSpec::Driver
27
+
28
+ # browser: passed to do assertion within the page
29
+ # page_text: text used to identify the page, title will be the first candidate
30
+ attr_accessor :page_text
31
+
32
+ def initialize(the_browser, page_text = nil)
33
+ @web_browser = the_browser
34
+ @web_tester = the_browser
35
+ @page_text = page_text
36
+ begin
37
+ snapshot if $ITEST2_DUMP_PAGE
38
+ delay = $ITEST2_PAGE_DELAY
39
+ sleep(delay)
40
+ rescue => e
41
+ end
42
+ assert_on_page
43
+ end
44
+
45
+ def browser
46
+ @web_browser
47
+ end
48
+
49
+ def assert_on_page()
50
+ assert_text_present(@page_text) if @page_text
51
+ end
52
+
53
+ def assert_not_on_page()
54
+ assert_text_not_present(@page_text) if @page_text
55
+ end
56
+
57
+ def dump(stream = nil)
58
+ @web_browser.dump_response(stream)
59
+ end
60
+
61
+
62
+ def source
63
+ @web_browser.page_source
64
+ end
65
+ alias html source
66
+
67
+ # return current page title
68
+ def title
69
+ @web_browser.page_title
70
+ end
71
+
72
+ # return current page text
73
+ def text
74
+ @web_browser.text
75
+ end
76
+
77
+ # TO validate
78
+ def contains?(ary)
79
+ return true if ary.nil?
80
+ the_page_source = source
81
+ found = false
82
+ ary.each_line do |str|
83
+ found ||= the_page_source.include?(str)
84
+ end
85
+ return found
86
+ end
87
+
88
+ def snapshot(replace_css = false)
89
+ save_current_page(:filename => Time.now.strftime("%m%d%H%M%S") + "_" + self.class.name.gsub(" ", "") + ".html" )
90
+ end
91
+
92
+ end
93
+
94
+ end
@@ -0,0 +1,36 @@
1
+ #***********************************************************
2
+ #* Copyright (c) 2006, Zhimin Zhan.
3
+ #* Distributed open-source, see full license in MIT-LICENSE
4
+ #***********************************************************
5
+
6
+ require 'test/unit'
7
+ require File.join(File.dirname(__FILE__), 'assert')
8
+ require File.join(File.dirname(__FILE__), 'driver')
9
+
10
+ module RWebSpec
11
+
12
+ class WebTestCase < Test::Unit::TestCase
13
+ include RWebSpec::Driver
14
+ include RWebSpec::Assert
15
+ include RWebSpec::Utils
16
+
17
+ attr_reader :web_tester
18
+
19
+ def initialize(name=nil)
20
+ super(name) if name
21
+ @web_browser = WebBrowser.new
22
+ end
23
+
24
+ def default_test
25
+ super unless (self.class == WebTestCase)
26
+ end
27
+
28
+ def open_browser(baseUrl, relativeUrl)
29
+ context.base_url = baseUrl
30
+ begin_at(relativeUrl)
31
+ end
32
+ alias open_ie open_browser
33
+
34
+ end
35
+
36
+ end
data/lib/rwebspec.rb ADDED
@@ -0,0 +1,31 @@
1
+ #***********************************************************
2
+ #* Copyright (c) 2006 - 2009, Zhimin Zhan.
3
+ #* Distributed open-source, see full license in MIT-LICENSE
4
+ #***********************************************************
5
+
6
+ # Load active_support, so that we can use 1.days.ago
7
+ begin
8
+ require 'active_support/basic_object'
9
+ require 'active_support/duration'
10
+ rescue LoadError => no_as1_err
11
+ # active_support 2.0 loaded error
12
+ end
13
+ require 'active_support/core_ext'
14
+ require 'spec'
15
+
16
+ RWEBUNIT_VERSION = "1.4.0"
17
+
18
+ # Extra full path to load libraries
19
+ require File.dirname(__FILE__) + "/rwebspec/using_pages"
20
+ require File.dirname(__FILE__) + "/rwebspec/test_utils"
21
+ require File.dirname(__FILE__) + "/rwebspec/web_page"
22
+ require File.dirname(__FILE__) + "/rwebspec/assert"
23
+ require File.dirname(__FILE__) + "/rwebspec/itest_plugin"
24
+ require File.dirname(__FILE__) + "/rwebspec/web_browser"
25
+ require File.dirname(__FILE__) + "/rwebspec/driver"
26
+ require File.dirname(__FILE__) + "/rwebspec/test_script"
27
+ require File.dirname(__FILE__) + "/rwebspec/context"
28
+ require File.dirname(__FILE__) + "/rwebspec/rspec_helper"
29
+ require File.dirname(__FILE__) + "/rspec_extensions"
30
+ require File.dirname(__FILE__) + "/watir_extensions"
31
+ require File.dirname(__FILE__) + "/rwebspec/matchers/contains_text"
data/lib/rwebunit.rb ADDED
@@ -0,0 +1,3 @@
1
+ # legacy code to support old 'require rwebunit'
2
+ require File.dirname(__FILE__) + "/rwebspec"
3
+ RWebUnit = RWebSpec