2013-10-20 13:29:22 -04:00
require " uri "
2011-04-11 01:24:00 -04:00
class Capybara :: Selenium :: Driver < Capybara :: Driver :: Base
2011-02-22 09:53:14 -05:00
DEFAULT_OPTIONS = {
:browser = > :firefox
}
2012-02-01 08:23:17 -05:00
SPECIAL_OPTIONS = [ :browser ]
2011-02-22 09:53:14 -05:00
2012-07-13 07:29:02 -04:00
attr_reader :app , :options
2009-11-07 10:30:16 -05:00
2010-08-30 03:19:44 -04:00
def browser
unless @browser
2011-02-22 09:53:14 -05:00
@browser = Selenium :: WebDriver . for ( options [ :browser ] , options . reject { | key , val | SPECIAL_OPTIONS . include? ( key ) } )
2011-05-13 08:22:50 -04:00
main = Process . pid
2009-11-14 04:44:46 -05:00
at_exit do
2011-08-22 04:15:03 -04:00
# Store the exit status of the test run since it goes away after calling the at_exit proc...
@exit_status = $! . status if $! . is_a? ( SystemExit )
2011-05-13 08:22:50 -04:00
quit if Process . pid == main
2011-08-22 04:15:03 -04:00
exit @exit_status if @exit_status # Force exit with stored status
2009-11-14 04:44:46 -05:00
end
end
2010-08-30 03:19:44 -04:00
@browser
2009-11-07 10:30:16 -05:00
end
2010-09-07 12:35:55 -04:00
def initialize ( app , options = { } )
2013-03-18 18:43:48 -04:00
begin
require 'selenium-webdriver'
rescue LoadError = > e
if e . message =~ / selenium-webdriver /
raise LoadError , " Capybara's selenium driver is unable to load `selenium-webdriver`, please install the gem and add `gem 'selenium-webdriver'` to your Gemfile if you are using bundler. "
else
raise e
end
end
2009-11-07 10:30:16 -05:00
@app = app
2012-01-08 09:01:46 -05:00
@browser = nil
2012-01-08 09:02:24 -05:00
@exit_status = nil
2013-02-22 15:12:09 -05:00
@frame_handles = { }
2011-02-22 09:53:14 -05:00
@options = DEFAULT_OPTIONS . merge ( options )
2009-11-07 10:30:16 -05:00
end
2009-11-14 04:44:46 -05:00
2009-11-07 10:30:16 -05:00
def visit ( path )
2012-07-13 07:29:02 -04:00
browser . navigate . to ( path )
2009-11-07 10:30:16 -05:00
end
2009-11-14 04:44:46 -05:00
2013-10-05 14:23:51 -04:00
def go_back
browser . navigate . back
end
def go_forward
browser . navigate . forward
end
2012-09-09 21:05:17 -04:00
def html
2010-01-01 14:13:54 -05:00
browser . page_source
2009-11-07 10:30:16 -05:00
end
2009-11-14 04:44:46 -05:00
2013-02-06 14:36:55 -05:00
def title
browser . title
end
2013-02-24 12:54:39 -05:00
2009-12-16 09:16:52 -05:00
def current_url
2010-01-01 14:13:54 -05:00
browser . current_url
2009-12-16 09:16:52 -05:00
end
2013-02-19 12:03:26 -05:00
def find_xpath ( selector )
browser . find_elements ( :xpath , selector ) . map { | node | Capybara :: Selenium :: Node . new ( self , node ) }
end
2013-02-24 12:54:39 -05:00
2013-02-19 12:03:26 -05:00
def find_css ( selector )
browser . find_elements ( :css , selector ) . map { | node | Capybara :: Selenium :: Node . new ( self , node ) }
2009-11-07 10:30:16 -05:00
end
2013-02-24 12:54:39 -05:00
2009-12-12 15:46:08 -05:00
def wait? ; true ; end
2012-07-13 07:29:02 -04:00
def needs_server? ; true ; end
2009-11-07 10:30:16 -05:00
2010-06-29 16:41:33 -04:00
def execute_script ( script )
browser . execute_script script
end
2009-12-11 16:41:12 -05:00
def evaluate_script ( script )
2010-01-01 14:13:54 -05:00
browser . execute_script " return #{ script } "
end
2010-01-01 16:46:05 -05:00
2012-07-10 00:50:15 -04:00
def save_screenshot ( path , options = { } )
browser . save_screenshot ( path )
end
2010-07-29 09:25:45 -04:00
def reset!
2010-09-07 12:35:09 -04:00
# Use instance variable directly so we avoid starting the browser just to reset the session
2011-04-07 11:08:32 -04:00
if @browser
2012-02-01 08:23:17 -05:00
begin @browser . manage . delete_all_cookies
2012-01-08 08:53:45 -05:00
rescue Selenium :: WebDriver :: Error :: UnhandledError
2011-04-10 13:25:39 -04:00
# delete_all_cookies fails when we've previously gone
# to about:blank, so we rescue this error and do nothing
# instead.
end
2013-10-20 13:29:22 -04:00
uri = URI ( Capybara :: EMPTY_HTML_FILE_PATH )
uri . scheme = " file "
@browser . navigate . to ( uri . to_s )
2011-04-07 11:08:32 -04:00
end
2010-01-23 06:58:30 -05:00
end
2013-01-08 03:40:12 -05:00
##
#
# Webdriver supports frame name, id, index(zero-based) or {Capybara::Element} to find iframe
#
# @overload within_frame(index)
# @param [Integer] index index of a frame
# @overload within_frame(name_or_id)
# @param [String] name_or_id name or id of a frame
# @overload within_frame(element)
# @param [Capybara::Node::Base] a_node frame element
#
def within_frame ( frame_handle )
2013-02-22 15:12:09 -05:00
@frame_handles [ browser . window_handle ] || = [ ]
2013-01-08 03:40:12 -05:00
frame_handle = frame_handle . native if frame_handle . is_a? ( Capybara :: Node :: Base )
2013-02-22 15:12:09 -05:00
@frame_handles [ browser . window_handle ] << frame_handle
a = browser . switch_to . frame ( frame_handle )
2010-04-28 19:03:13 -04:00
yield
2012-04-25 05:43:56 -04:00
ensure
2013-02-22 15:12:09 -05:00
# There doesnt appear to be any way in Webdriver to move back to a parent frame
# other than going back to the root and then reiterating down
@frame_handles [ browser . window_handle ] . pop
browser . switch_to . default_content
@frame_handles [ browser . window_handle ] . each { | fh | browser . switch_to . frame ( fh ) }
2010-01-12 14:40:10 -05:00
end
2010-04-28 19:03:13 -04:00
2011-02-22 09:53:14 -05:00
def find_window ( selector )
original_handle = browser . window_handle
browser . window_handles . each do | handle |
browser . switch_to . window handle
if ( selector == browser . execute_script ( " return window.name " ) ||
browser . title . include? ( selector ) ||
browser . current_url . include? ( selector ) ||
( selector == handle ) )
browser . switch_to . window original_handle
return handle
end
end
raise Capybara :: ElementNotFound , " Could not find a window identified by #{ selector } "
end
def within_window ( selector , & blk )
handle = find_window ( selector )
2010-08-28 12:50:34 -04:00
browser . switch_to . window ( handle , & blk )
2010-08-27 15:00:08 -04:00
end
2011-05-13 08:22:50 -04:00
def quit
2013-05-23 07:06:05 -04:00
@browser . quit if @browser
2011-05-13 08:22:50 -04:00
rescue Errno :: ECONNREFUSED
# Browser must have already gone
2013-11-22 18:59:51 -05:00
ensure
@browser = nil
2011-05-13 08:22:50 -04:00
end
2011-07-13 09:39:17 -04:00
def invalid_element_errors
2012-11-13 08:25:45 -05:00
[ Selenium :: WebDriver :: Error :: StaleElementReferenceError , Selenium :: WebDriver :: Error :: UnhandledError , Selenium :: WebDriver :: Error :: ElementNotVisibleError ]
2011-07-13 09:39:17 -04:00
end
2013-02-24 12:54:39 -05:00
2009-11-07 10:30:16 -05:00
end