module RWebSpec::Driver
Public Instance Methods
change
<script type="text/javascript" src="/javascripts/prototype.js"></script>
to
<script type="text/javascript" src="http://itest2.com/javascripts/prototype.js"></script>
# File lib/rwebspec-watir/driver.rb, line 511 def absolutify_url(src, base_url, parent_url) if src.nil? || src.empty? || src == "//:" || src =~ /\s*http:\/\//i return src end return "#{base_url}#{src}" if src =~ /^\s*\// return "#{parent_url}#{src}" if parent_url return src end
Return page HTML with absolute references of images, stylesheets and javascripts
# File lib/rwebspec-watir/driver.rb, line 455 def absolutize_page(content, base_url, current_url_parent) modified_content = "" content.each_line do |line| if line =~ /<script\s+.*src=["'']?(.*)["'].*/i then script_src = $1 substitute_relative_path_in_src_line(line, script_src, base_url, current_url_parent) elsif line =~ /<link\s+.*href=["'']?(.*)["'].*/i then link_href = $1 substitute_relative_path_in_src_line(line, link_href, base_url, current_url_parent) elsif line =~ /<img\s+.*src=["'']?(.*)["'].*/i then img_src = $1 substitute_relative_path_in_src_line(line, img_src, base_url, current_url_parent) end modified_content += line end return modified_content end
absolutize_page
using hpricot
# File lib/rwebspec-watir/driver.rb, line 476 def absolutize_page_hpricot(content, base_url, parent_url) return absolutize_page(content, base_url, parent_url) if RUBY_PLATFORM == 'java' begin require 'hpricot' doc = Hpricot(content) base_url.slice!(-1) if ends_with?(base_url, "/") (doc/'link').each { |e| e['href'] = absolutify_url(e['href'], base_url, parent_url) || "" } (doc/'img').each { |e| e['src'] = absolutify_url(e['src'], base_url, parent_url) || "" } (doc/'script').each { |e| e['src'] = absolutify_url(e['src'], base_url, parent_url) || "" } return doc.to_html rescue => e absolutize_page(content, base_url, parent_url) end end
# File lib/rwebspec-watir/driver.rb, line 491 def absolutize_page_nokogiri(content, base_url, parent_url) return absolutize_page(content, base_url, parent_url) if RUBY_PLATFORM == 'java' begin require 'nokogiri' doc = Nokogiri::HTML(content) base_url.slice!(-1) if ends_with?(base_url, "/") (doc/'link').each { |e| e['href'] = absolutify_url(e['href'], base_url, parent_url) || "" } (doc/'img').each { |e| e['src'] = absolutify_url(e['src'], base_url, parent_url) || "" } (doc/'script').each { |e| e['src'] = absolutify_url(e['src'], base_url, parent_url) || "" } return doc.to_html rescue => e absolutize_page(content, base_url, parent_url) end end
Wait for specific seconds for an Ajax update finish. Trick: In your Rails application,
:loading => "Element.show('search_indicator'); :complete => "Element.hide('search_indicator'); <%= image_tag("indicator.gif", :id => 'search_indicator', :style => 'display:none') %>
Typical usage:
ajax_wait_for_element("search_indicator", 30) ajax_wait_for_element("search_indicator", 30, "show") ajax_wait_for_element("search_indicator", 30, "hide") ajax_wait_for_element("search_indicator", 30, "show", 5) # check every 5 seconds
Warning: this method has not been fully tested, if you are not using Rails, change your parameter accordingly.
# File lib/rwebspec-watir/driver.rb, line 650 def ajax_wait_for_element(element_id, seconds, status='show', check_interval = $testwise_polling_interval) count = 0 check_interval = 1 if check_interval < 1 or check_interval > seconds while count < (seconds / check_interval) do search_indicator = @web_browser.element_by_id(element_id) search_indicator_outer_html = search_indicator.outerHtml if search_indicator if status == 'hide' return true if search_indicator_outer_html and !search_indicator_outer_html.include?('style="DISPLAY: none"') else return true if search_indicator_outer_html and search_indicator_outer_html.include?('style="DISPLAY: none"') end sleep check_interval if check_interval > 0 and check_interval < 5 * 60 # wait max 5 minutes count += 1 end return false end
Attach to existing browser window
attach_browser(:title, "Page" ) attach_browser(:url, "http://wwww..." )
# File lib/rwebspec-watir/driver.rb, line 202 def attach_browser(how, what, options = {}) options.merge!(:browser => is_firefox? ? "Firefox" : "IE") unless options[:browser] begin options.merge!(:base_url => browser.context.base_url) rescue => e puts "failed to set base_url, ignore : #{e}" end WebBrowser.attach_browser(how, what, options) end
Go to specific url in background (i.e not via browwser, different from goto_url
) This won't share the session with what's currenlty in browser, proxy setting
One use example: resetting database
background_visit("/reset")
# File lib/rwebspec-watir/driver.rb, line 181 def background_visit(url, opts = {}) require 'httpclient' begin client = HTTPClient.new if url && url =~ /^http/ http_response = client.get(url).body else base_url = $TESTWISE_PROJECT_BASE_URL || $TESTWISE_PROJECT_BASE_URL || $BASE_URL http_response = client.get("#{base_url}#{url}").body end http_response = http_response.content if http_response.respond_to?("content") rescue => e raise e end end
# File lib/rwebspec-watir/driver.rb, line 767 def basic_authentication(username, password, options = {}) basic_authentication_ie(options[:title], username, password, options) end
Use AutoIT3 to send password title starts with “Connect to …”
# File lib/rwebspec-watir/driver.rb, line 746 def basic_authentication_ie(title, username, password, options = {}) default_options = {:textctrl_username => "Edit2", :textctrl_password => "Edit3", :button_ok => 'Button1' } options = default_options.merge(options) title ||= "" if title =~ /^Connect\sto/ full_title = title else full_title = "Connect to #{title}" end require 'rformspec' login_win = RFormSpec::Window.new(full_title) login_win.send_control_text(options[:textctrl_username], username) login_win.send_control_text(options[:textctrl_password], password) login_win.click_button("OK") end
Starting browser with a URL
Example:
begin_at("http://www.itest2.com")
# File lib/rwebspec-watir/driver.rb, line 133 def begin_at(url) dump_caller_stack @web_browser.begin_at(url) end
return the underlying RWebSpec::Browser object
# File lib/rwebspec-watir/driver.rb, line 86 def browser @web_browser end
return the text of specific (identified by attribute “id”) ta tag For page containing
<td id="preferred_recorder">iTest2/Watir Recorder</span>
td_with_id(“preferred_recorder”) # => iTest2/Watir Recorder
# File lib/rwebspec-watir/driver.rb, line 582 def cell_with_id(cell_id, options = {}) if options && options[:index] then cell(:id => cell_id.to_s, :index => options[:index]).text else cell(:id, cell_id).text end end
# File lib/rwebspec-watir/driver.rb, line 724 def check_ie_version if is_windows? && @ie_version.nil? begin cmd = 'reg query "HKLM\SOFTWARE\Microsoft\Internet Explorer" /v Version'; result = `#{cmd}` version_line = nil result.each do |line| if (line =~ /Version\s+REG_SZ\s+([\d\.]+)/) version_line = $1 end end if version_line =~ /^\s*(\d+)\./ @ie_version = $1.to_i end rescue => e end end end
Clear popup windows such as 'Security Alert' or 'Security Information' popup window,
Screenshot see kb2.adobe.com/cps/165/tn_16588.html
You can also by pass security alerts by change IE setting, kb.iu.edu/data/amuj.html
Example
clear_popup("Security Information", 5, true) # check for Security Information for 5 seconds, click Yes
# File lib/rwebspec-watir/driver.rb, line 689 def clear_popup(popup_win_title, seconds = 10, yes = true) # commonly "Security Alert", "Security Information" if is_windows? sleep 1 autoit = WIN32OLE.new('AutoItX3.Control') # Look for window with given title. Give up after 1 second. ret = autoit.WinWait(popup_win_title, '', seconds) # # If window found, send appropriate keystroke (e.g. {enter}, {Y}, {N}). if ret == 1 then puts "about to send click Yes" if debugging? button_id = yes ? "Button1" : "Button2" # Yes or No autoit.ControlClick(popup_win_title, '', button_id) end sleep(0.5) else raise "Currently supported only on Windows" end end
Close all opening browser windows
# File lib/rwebspec-watir/driver.rb, line 108 def close_all_browsers @web_browser.close_all_browsers end
Close the current browser window (started by the script). If no browser started, then close all browser windows.
# File lib/rwebspec-watir/driver.rb, line 94 def close_browser if @web_browser # Old TestWise version # @web_browser.close_browser unless $TESTWISE_LEAVE_BROWSER_OPEN_AFTER_RUN @web_browser.close_browser else close_all_browsers end end
In pages, can't use include, text.should include(“abc”) won't work Instead,
text.should contains("abc"
# File lib/rwebspec-watir/driver.rb, line 359 def contains(str) ContainsText.new(str) end
# File lib/rwebspec-watir/driver.rb, line 352 def contains_text(text) @web_browser.contains_text(text) end
# File lib/rwebspec-watir/driver.rb, line 125 def context @web_browser.context end
# File lib/rwebspec-watir/driver.rb, line 409 def default_dump_dir if ($TESTWISE_RUNNING_SPEC_ID && $TESTWISE_WORKING_DIR) || ($TESTWISE_RUNNING_SPEC_ID && $TESTWISE_WORKING_DIR) $TESTWISE_DUMP_DIR = $TESTWISE_DUMP_DIR = File.join($TESTWISE_WORKING_DIR, "dump") FileUtils.mkdir($TESTWISE_DUMP_DIR) unless File.exists?($TESTWISE_DUMP_DIR) spec_run_id = $TESTWISE_RUNNING_SPEC_ID || $TESTWISE_RUNNING_SPEC_ID spec_run_dir_name = spec_run_id.to_s.rjust(4, "0") unless spec_run_id == "unknown" to_dir = File.join($TESTWISE_DUMP_DIR, spec_run_dir_name) else to_dir = ENV['TEMP_DIR'] || (is_windows? ? "C:\\temp" : "/tmp") end end
For debugging
# File lib/rwebspec-watir/driver.rb, line 405 def dump_response(stream = nil) @web_browser.dump_response(stream) end
Identify DOM element by ID Warning: it is only supported on IE
# File lib/rwebspec-watir/driver.rb, line 398 def element_by_id(elem_id) @web_browser.element_by_id(elem_id) end
Warning: this does not work well with Firefox yet.
# File lib/rwebspec-watir/driver.rb, line 392 def element_text(elem_id) @web_browser.element_value(elem_id) end
# File lib/rwebspec-watir/driver.rb, line 533 def ends_with?(str, suffix) suffix = suffix.to_s str[-suffix.length, suffix.length] == suffix end
for text field can be easier to be identified by attribute “id” instead of “name”, not recommended though
params opts takes :appending => true or false, if true, won't clear the text field.
# File lib/rwebspec-watir/driver.rb, line 317 def enter_text_with_id(textfield_id, value, opts = {}) # For IE10, it seems unable to identify HTML5 elements # # However for IE10, the '.' is omitted. if opts.nil? || opts.empty? # for Watir, default is clear opts[:appending] = false end perform_operation { begin text_field(:id, textfield_id).set(value) rescue => e # However, this approach is not reliable with Watir (IE) # for example, for entering email, the dot cannot be entered, try ["a@b", :decimal, "com"] the_elem = element(:xpath, "//input[@id='#{textfield_id}']") the_elem.send_keys(:clear) unless opts[:appending] the_elem.send_keys(value) end } end
Verify the next page following an operation.
Typical usage:
login_page.click_login expect_page HomePage
# File lib/rwebspec-watir/driver.rb, line 117 def expect_page(page_clazz, argument = nil) if argument @web_browser.expect_page(page_clazz, argument) else @web_browser.expect_page(page_clazz) end end
# File lib/rwebspec-webdriver/driver.rb, line 109 def find_element(how, what) @web_browser.find_element(how, what) end
# File lib/rwebspec-webdriver/driver.rb, line 113 def find_elements(how, what) @web_browser.find_elements(how, what) end
Return the FireWatir::Firefox instance
# File lib/rwebspec-watir/driver.rb, line 146 def firefox @web_browser.firefox end
Go to another page on the testing site.
open_browser(:base_url => "http://www.itest2.com") goto_page("/demo") # visit page http://www.itest2.com/demo
# File lib/rwebspec-watir/driver.rb, line 159 def goto_page(page) perform_operation { @web_browser.goto_page(page) if @web_browser } end
Go to another web site, normally different site being tested on
open_browser(:base_url => "http://www.itest2.com") goto_url("http://myorganized.info")
# File lib/rwebspec-watir/driver.rb, line 171 def goto_url(url) @web_browser.goto_url url end
Return the Watir::IE instance
# File lib/rwebspec-watir/driver.rb, line 140 def ie @web_browser.ie end
# File lib/rwebspec-watir/driver.rb, line 150 def is_firefox? @web_browser.is_firefox? if @web_browser end
# File lib/rwebspec-webdriver/driver.rb, line 188 def is_htmlunit? RUBY_PLATFORM =~ /java/ && @web_browser end
# File lib/rwebspec-webdriver/driver.rb, line 184 def is_ie? @web_browser.is_ie? if @web_browser end
# File lib/rwebspec-watir/driver.rb, line 601 def is_linux? RUBY_PLATFORM.downcase.include?("linux") end
# File lib/rwebspec-watir/driver.rb, line 593 def is_mac? RUBY_PLATFORM.downcase.include?("darwin") end
# File lib/rwebspec-watir/driver.rb, line 597 def is_windows? RUBY_PLATFORM.downcase.include?("mswin") or RUBY_PLATFORM.downcase.include?("mingw") end
Watir 1.9 way of handling javascript dialog
# File lib/rwebspec-watir/driver.rb, line 710 def javascript_dialog @web_browser.javascript_dialog end
return the text of specific (identified by attribute “id”) label tag For page containing
<label id="preferred_ide">TestWise</label>
label_with_id
(“preferred_ids”) # => TestWise label_with_id
(“preferred_ids”, :index => 2) # => TestWise
# File lib/rwebspec-watir/driver.rb, line 558 def label_with_id(label_id, options = {}) if options && options[:index] then label(:id => label_id.to_s, :index => options[:index]).text else label(:id, label_id.to_s).text end end
# File lib/rwebspec-watir/driver.rb, line 386 def new_popup_window(options) @web_browser.new_popup_window(options) end
open a browser, and set base_url via hash, but does not acually
example:
open_browser :base_url => http://localhost:8080
There are 3 ways to set base url
1. pass as first argument 2. If running using TestWise, used as confiured 3. Use default value set
New Options:
:browser => :ie | :firefox | :chrome
# File lib/rwebspec-webdriver/driver.rb, line 29 def open_browser_by_selenium(options = {}) # puts "[DEBUG] [SeleniumDriver] Callling open_browser #{options.inspect}" begin support_unicode rescue => e puts "Unicode may not work in IE, #{e}" end if options && options.class == String options = {:base_url => options.to_s } end if options && options.class == Hash && options[:base_url] base_url ||= options[:base_url] end base_url = options[:base_url] rescue nil base_url ||= $TESTWISE_PROJECT_BASE_URL base_url ||= $BASE_URL base_url ||= options[:url] raise "base_url must be set" if base_url.nil? default_options = {:speed => "fast", :visible => true, :highlight_colour => 'yellow', :close_others => true, :start_new => true, # start a new browser always :go => true } options = default_options.merge options if ENV["BROWSER"] && !ENV["BROWSER"].empty? options[:browser] = ENV["BROWSER"].downcase end if options[:browser].nil? options[:browser] = "chrome" end if base_url =~ /^file:/ uri_base = base_url else uri = URI.parse(base_url) uri_base = "#{uri.scheme}://#{uri.host}:#{uri.port}" end # puts "[DEBUG] Starting a new browser #{uri_base} with options: #{options.inspect}" if options[:start_new] # puts "[DEBUG] [SeleniumBrowser] creating a new browser" @web_browser = WebBrowser.new(uri_base, nil, options) # puts "[DEBUG] [SeleniumBrowser] browser: #{@web_browser.inspect}" else @web_browser = WebBrowser.reuse(uri_base, options) # Reuse existing browser end if base_url =~ /^file:/ goto_url(base_url) # for files, no base url else (uri.path.length == 0) ? begin_at(base_url) : begin_at(uri.path) if options[:go] end # remembering browser handle for debugging need $browser = @web_browser return @web_browser end
open a browser, and set base_url via hash, but does not acually
example:
open_browser :base_url => http://localhost:8080
There are 3 ways to set base url
1. pass as first argument 2. If running using TestWise, used as confiured 3. Use default value set
# File lib/rwebspec-watir/driver.rb, line 30 def open_browser_by_watir(options = {}) begin support_unicode rescue => e puts "Unicode may not work in IE, #{e}" end if options && options.class == String options = {:base_url => options.to_s } end if options && options.class == Hash && options[:base_url] base_url ||= options[:base_url] end base_url = options[:base_url] rescue nil base_url ||= $TESTWISE_PROJECT_BASE_URL base_url ||= $BASE_URL raise "base_url must be set" if base_url.nil? default_options = {:speed => "fast", :visible => true, :highlight_colour => 'yellow', :close_others => true, :start_new => false, # start a new browser always :go => true} options = default_options.merge options ($TESTWISE_HIDE_BROWSER) ? $HIDE_IE = true : $HIDE_IE = false if base_url =~ /^file:/ uri_base = base_url else uri = URI.parse(base_url) uri_base = "#{uri.scheme}://#{uri.host}:#{uri.port}" end if options[:start_new] @web_browser = WebBrowser.new(uri_base, nil, options) else @web_browser = WebBrowser.reuse(uri_base, options) # Reuse existing browser end if base_url =~ /^file:/ goto_url(base_url) # for files, no base url else (uri.path.length == 0) ? begin_at("/") : begin_at(uri.path) if options[:go] end return @web_browser end
current page source (in HTML)
# File lib/rwebspec-watir/driver.rb, line 544 def page_source @web_browser.page_source end
return plain text view of page
# File lib/rwebspec-watir/driver.rb, line 549 def page_text @web_browser.text end
current web page title
# File lib/rwebspec-watir/driver.rb, line 539 def page_title @web_browser.page_title end
# File lib/rwebspec-watir/driver.rb, line 340 def perform_operation(& block) begin dump_caller_stack operation_delay yield rescue RuntimeError => re raise re # ensure # puts "[DEBUG] ensure #{perform_ok}" unless perform_ok end end
# File lib/rwebspec-webdriver/driver.rb, line 105 def quit @web_browser.quit end
For current page souce to a file in specified folder for inspection
save_current_page(:dir => "C:\\mysite", filename => "abc", :replacement => true)
# File lib/rwebspec-watir/driver.rb, line 426 def save_current_page(options = {}) default_options = {:replacement => true} options = default_options.merge(options) to_dir = options[:dir] || default_dump_dir if options[:filename] file_name = options[:filename] else file_name = Time.now.strftime("%m%d%H%M%S") + ".html" end Dir.mkdir(to_dir) unless File.exists?(to_dir) file = File.join(to_dir, file_name) content = page_source base_url = @web_browser.context.base_url current_url = @web_browser.url current_url =~ /(.*\/).*$/ current_url_parent = $1 if options[:replacement] && base_url =~ /^http:/ File.new(file, "w").puts absolutize_page_nokogiri(content, base_url, current_url_parent) else File.new(file, "w").puts content end end
# File lib/rwebspec-watir/driver.rb, line 714 def select_file_for_upload(file_field_name, file_path) if is_windows? normalized_file_path = file_path.gsub("/", "\\") file_field(:name, file_field_name).set(normalized_file_path) else # for firefox, just call file_field, it may fail file_field(:name, file_field_name).set(normalized_file_path) end end
return the text of specific (identified by attribute “id”) span tag For page containing
<span id="preferred_recorder">iTest2/Watir Recorder</span>
span_with_id
(“preferred_recorder”) # => iTest2/Watir Recorder
# File lib/rwebspec-watir/driver.rb, line 570 def span_with_id(span_id, options = {}) if options && options[:index] then span(:id => span_id.to_s, :index => options[:index]).text else span(:id, span_id).text end end
substut
# File lib/rwebspec-watir/driver.rb, line 522 def substitute_relative_path_in_src_line(line, script_src, host_url, page_parent_url) unless script_src =~ /^["']?http:/ host_url.slice!(-1) if ends_with?(host_url, "/") if script_src =~ /^\s*\// # absolute_path line.gsub!(script_src, "#{host_url}#{script_src}") else #relative_path line.gsub!(script_src, "#{page_parent_url}#{script_src}") end end end
Support browser (IE) operations using unicode
Example: click_button("Google 搜索")
Reference: jira.openqa.org/browse/WTR-219
# File lib/rwebspec-watir/driver.rb, line 609 def support_utf8 if is_windows? require 'win32ole' WIN32OLE.codepage = WIN32OLE::CP_UTF8 end end
use win32screenshot library or Selenium
to save curernt active window
opts => the direcotry to save image under
# File lib/rwebspec-watir/driver.rb, line 781 def take_screenshot(to_file = nil, opts = {}) # puts "calling new take screenshot: #{$screenshot_supported}" # unless $screenshot_supported # puts " [WARN] Screenhost not supported, check whether win32screenshot gem is installed" # return # end if to_file screenshot_image_filepath = to_file else screenshot_image_filename = "screenshot_" + Time.now.strftime("%m%d%H%M%S") + ".jpg" the_dump_dir = opts[:to_dir] || default_dump_dir FileUtils.mkdir_p(the_dump_dir) unless File.exists?(the_dump_dir) screenshot_image_filepath = File.join(the_dump_dir, screenshot_image_filename) screenshot_image_filepath.gsub!("/", "\\") if is_windows? FileUtils.rm_f(screenshot_image_filepath) if File.exist?(screenshot_image_filepath) end begin if is_firefox? then Win32::Screenshot::Take.of(:window, :title => /mozilla\sfirefox/i).write(screenshot_image_filepath) elsif ie Win32::Screenshot::Take.of(:window, :title => /internet\sexplorer/i).write(screenshot_image_filepath) else Win32::Screenshot::Take.of(:foreground).write(screenshot_image_filepath) end notify_screenshot_location(screenshot_image_filepath) rescue ::DL::DLTypeError => de puts "No screenshot libray found: #{de}" rescue => e puts "error on taking screenshot: #{e}" end end
Reuse current an opened browser window instead of opening a new one example:
use_current_selenium_browser(:title, /.*/) # use what ever browser window use_current_selenium_browser(:title, "TestWise") # use browser window with title "TestWise"
# File lib/rwebspec-webdriver/driver.rb, line 231 def use_current_selenium_browser(how = :title, what = /.*/) @web_browser = $browser || WebBrowser.attach_browser(how, what) end
Reuse current an opened browser window instead of opening a new one
example: use_current_watir_browser(:title, /.*/) # use what ever browser window use_current_watir_browser(:title, "TestWise") # use browser window with title "TestWise"
# File lib/rwebspec-watir/driver.rb, line 216 def use_current_watir_browser(how = :title, what = /.*/) @web_browser = WebBrowser.attach_browser(how, what) end
Wait the element with given id to be present in web page
Warning: this not working in Firefox, try use wait_util or try instead
# File lib/rwebspec-watir/driver.rb, line 670 def wait_for_element(element_id, timeout = $testwise_polling_timeout, interval = $testwise_polling_interval) start_time = Time.now #TODO might not work with Firefox until @web_browser.element_by_id(element_id) do sleep(interval) if (Time.now - start_time) > timeout raise RuntimeError, "failed to find element: #{element_id} for max #{timeout}" end end end
Execute the provided block until either (1) it returns true, or (2) the timeout (in seconds) has been reached. If the timeout is reached, a TimeOutException will be raised. The block will always execute at least once.
This does not handle error, if the given block raise error, the statement finish with error Examples:
wait_until {puts 'hello'} wait_until { div(:id, :receipt_date).exists? }
# File lib/rwebspec-watir/driver.rb, line 630 def wait_until(timeout = $testwise_polling_timeout || 30, polling_interval = $testwise_polling_interval || 1, & block) waiter = Watir::Waiter.new(timeout, polling_interval) waiter.wait_until { yield } end