Change Default Timeout and Wait Time of Capybara
set large enough to tolerate network related problems. For Selenium based automation frameworks, like Capybara, default Webdriver timeout is set to
Changing ReadTimeoutIf you have timeout problem for Capybara, it gives an error like above. This means that the page is not fully loaded in given timeout period. Even you can see that page is loaded correctly but webdriver wait until the Ajax calls finish.
class BufferedIO #:nodoc: internal use only def initialize(io) @io = io @read_timeout = 60 @continue_timeout = nil @debug_output = nil @rbuf = '' end . . ... def rbuf_fill begin @rbuf << @io.read_nonblock(BUFSIZE) rescue IO::WaitReadable if IO.select([@io], nil, nil, @read_timeout) retry else raise Net::ReadTimeout end rescue IO::WaitWritable # OpenSSL::Buffering#read_nonblock may fail with IO::WaitWritable. # http://www.openssl.org/support/faq.html#PROG10 if IO.select(nil, [@io], nil, @read_timeout) retry else raise Net::ReadTimeout end end end end
If you need more or less time than predefined time 60 seconds you can change the read_timeout variable in the source code from the following module as in the shown above source code.
Editing source code may be dangerous, which may let you do unnecessary changing and the update may be overwritten by incoming source code update. Instead of doing this, you can simply set this value by overriding creating new instance of driver. The followings are new instances for Chrome and Firefox:
# Firefox instance with timeout is set to 100 secondsCapybara.register_driver :firefox_timeout do |app| client = Selenium::WebDriver::Remote::Http::Default.new client.timeout = 100 Capybara::Selenium::Driver.new(app, :browser => :firefox, :http_client => client) end # Chrome instance with timeout is set to 100 seconds Capybara.register_driver :chrome_timeout do |app| client = Selenium::WebDriver::Remote::Http::Default.new client.timeout = 100 Capybara::Selenium::Driver.new(app, :browser => :chrome, :http_client => client) end
You also need to use one of these driver instance, to do this change the following lines in your features/support/env.rb:
#Capybara.default_driver = :firefox_timeout Capybara.default_driver = :chrome_timeout
If you still have problem with loading test pages you get the following error:
Net::ReadTimeout: Net::ReadTimeout from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/protocol.rb:158:in `rescue in rbuf_fill' from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/protocol.rb:152:in `rbuf_fill' from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/protocol.rb:134:in `readuntil' from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/protocol.rb:144:in `readline' from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/http/response.rb:39:in `read_status_line' from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/http/response.rb:28:in `read_new' from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/http.rb:1412:in `block in transport_request' from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/http.rb:1409:in `catch' from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/http.rb:1409:in `transport_request' from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/http.rb:1382:in `request' from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/http.rb:1375:in `block in request' from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/http.rb:852:in `start' from /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/net/http.rb:1373:in `request' from /Library/Ruby/Gems/2.0.0/gems/selenium-webdriver-2.52.0/lib/selenium/webdriver/remote/http/default.rb:107:in `response_for' from /Library/Ruby/Gems/2.0.0/gems/selenium-webdriver-2.52.0/lib/selenium/webdriver/remote/http/default.rb:58:in `request' from /Library/Ruby/Gems/2.0.0/gems/selenium-webdriver-2.52.0/lib/selenium/webdriver/remote/http/common.rb:59:in `call' from /Library/Ruby/Gems/2.0.0/gems/selenium-webdriver-2.52.0/lib/selenium/webdriver/remote/bridge.rb:645:in `raw_execute' from /Library/Ruby/Gems/2.0.0/gems/selenium-webdriver-2.52.0/lib/selenium/webdriver/remote/bridge.rb:623:in `execute' from /Library/Ruby/Gems/2.0.0/gems/selenium-webdriver-2.52.0/lib/selenium/webdriver/remote/bridge.rb:134:in `get' from /Library/Ruby/Gems/2.0.0/gems/selenium-webdriver-2.52.0/lib/selenium/webdriver/common/navigation.rb:33:in `to' from /Library/Ruby/Gems/2.0.0/gems/capybara-2.6.2/lib/capybara/selenium/driver.rb:45:in `visit' from /Library/Ruby/Gems/2.0.0/gems/capybara-2.6.2/lib/capybara/session.rb:232:in `visit' from /Library/Ruby/Gems/2.0.0/gems/capybara-2.6.2/lib/capybara/dsl.rb:51:in `block (2 levels) in <module:DSL>'
Changing Wait Time
If you are searching an element on the page, Capybara is clever enough to search element repeatedly with given parameters until the Capybara.default_max_wait_time (before Capybara version 2.5.0, it is Capybara.default_wait_time) finishes. In such a case you need more or less time for finding an element you can Capybara.using_wait_time that is added with Capybara version 2.1. It requires time paremeter and a block of what you want. See the example below:
Capybara.using_wait_time 5 do find("#password").set("12qw34") end Capybara.using_wait_time 5 do page.has_css? "#comment" end