rwebspec 1.4.0

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