Capybara doesn't close browser when Net::ReadTimeout error happens - ruby

I am running tests for a Rails app with Capybara, Cucumber and Selenium Webdriver (Ruby). I have a question: why Capybara doesn't close browser when Net::ReadTimeout happens even I had a hook which asked browser to quit after each test scenario? How can I force it to close the browser when Net::ReadTimeout occurs?
This is my hooks.rb
after do |scenario|
if scenario.failed?
page.driver.browser.save_screenshot("#{scenario.__id__}.png")
end
Capybara.current_session.driver.browser.manage.delete_all_cookies
Capybara.current_session.driver.quit
end

I have another solution that works for me.
add gem capybara-screenshot
configure your spec_helper.rb in such way:
Capybara::Screenshot.autosave_on_failure = true
Capybara::Screenshot.prune_strategy = :keep_last_run
Capybara.default_wait_time = 60

Related

How do I open a chrome browser using ruby, cucumber, capybara and bddfire gem?

I am very new at BDD testing and I am trying to figure out how to open a chrome browser in a specific URL using these technologies. I already installed bddfire gem and already ran it.
Now I have a feature:
#openingChrome
Scenario: Opening Chrome on facebook page
Given I open chrome and write "url"
bddfir_steps.rb
Given(/^I open chrome and write "([^"]*)"$/) do |arg1|
$session.visit("https://www.facebook.com.br")
end
In the hooks file I wrote
Before do
$session = Capybara::Session.new(:selenium, browser: :chrome)
end
And in the env.rb file that came with bddfire gem there is this
Capybara.register_driver :chrome do |app|
Capybara::Selenium::Driver.new(app, browser: :chrome)
end
So chrome is already added and I already installed chrome webdriver. Unfortunately this line of code is not working: $session = Capybara::Session.new(:selenium, browser: :chrome)
it throws this error: The second parameter to Session::new should be a rack app if passed. (TypeError)
does anyone know why?
Session#new takes the name of the driver and optionally a rack app instance to start. Since you don't seem to be starting an app and you're registering your driver with a name of :chrome you want
Before do
$session = Capybara::Session.new(:chrome)
end

Net::ReadTimeout: Net::ReadTimeout using selenium-webdriver with Ruby

I use selenium-webdriver gem, Ruby 2.4.4, Rails 4.2 to run Jasmine tests using Firefox.
But unfortunately in most cases I have this error : Net::ReadTimeout: Net::ReadTimeout.
Logs from Selenium show me that test run, but then there is a huge delay after running tests before closing browser.
Could you please advise how to fix that? Or maybe someone had the same issue?
Maybe I can add some code fix this in jasmine_helper.rb ?
The above error was thrown when the page load time exceeds 60 seconds so write the following code for page load
client = Selenium::WebDriver::Remote::Http::Default.new
client.read_timeout = 120 # seconds
driver = Selenium::WebDriver.for :firefox,http_client: client
Now your code would wait for 120 seconds for any page load which has been caused by #click and also wait to load the url by goto method.

Why capybara codes don't work with selenium webdriver?

I am new to Capybara. I have a question about why my Capybara doesn't work when I use it together with Selenium Webdriver.
This is my sample code:
Given(/^I am on the Youtube homepage$/) do
# visit 'http://www.youtube.com'
driver = Selenium::WebDriver.for :firefox
driver.navigate.to('http://www.youtube.com')
end
When(/^I search for "([^"]*)"$/) do |search_term|
fill_in 'search_query', :with => search_term
click_on 'search-btn'
end
Then(/^videos of large rodents are returned$/) do
expect(page).to have_content 'Making Friends with a Capybara'
end
When I run it, it just open Firefox and go to Youtube homepage. But it gets error:
Capybara::ElementNotFound: Unable to find field "search_query".
Everything works with visit 'http://www.youtube.com' command.
You're creating a driver, telling it to navigate to a page and then it's going out of scope so it's getting deleted. the visit line works because it's using the current capybara driver which stays around between test steps. Rather than creating a driver manually you should be registering a driver with Capybara and then specifying which driver to use for the specific test. See drivers
Since capybara sets up a selenium driver by default for use with firefox you can just do
Capybara.default_driver = :selenium
somewhere before running your tests to make all your tests run using selenium with firefox, or since capybara registers selenium as the default javascript driver you can tag any scenarios you want to run in firefox with #javascript as shown here
#javascript
Scenario: do something something
Given ...

How to use same browser window for automated test using selenium-webdriver (ruby)?

I am automating test cases for a website using selenium-webdriver and cucumber in ruby. I need each feature to run in a particular order and using the same browser window. Atm each feature creates a new window to run test in. Though in some test cases this behavior is desired- in many cases it is not. From my research so far it seems there are mixed answers about whether or not it is possible to drive the same browser window with selenium throughout test cases. Most answers I have run into were for other languages and were work arounds specific to a browser (I am developing my test while testing IE but will be expected to run these test in other browsers). I am working in Ruby and from what I have read it seems as though I'd have to make a class for the page? I'm confused as to why I would have to do this or how that helps.
my env.rb file:
require 'selenium-webdriver'
require 'rubygems'
require 'nokogiri'
require 'rspec/expectations'
Before do
#driver ||= Selenium::WebDriver.for :ie
#accept_next_alert = true
#driver.manage.timeouts.implicit_wait = 30
#driver.manage.timeouts.script_timeout = 30
#verification_errors = []
end
After do
##driver.quit
##verification_errors.should == []
end
Some information I've gathered so far of people with similar problems:
https://code.google.com/p/selenium/issues/detail?id=18
Is there any way to attach an already running browser to selenium webdriver in java?
Please ask me questions if anything about my question is not clear. I have many more test to create but I do not want to move on creating test if my foundation is sloppy and missing requested capabilities. (If you notice any other issues within my code please point them out in a comment)
The Before hook is run before each scenario. This is why a new browser is opened each time.
Do the following instead (in the env.rb):
require "selenium-webdriver"
driver = Selenium::WebDriver.for :ie
accept_next_alert = true
driver.manage.timeouts.implicit_wait = 30
driver.manage.timeouts.script_timeout = 30
verification_errors = []
Before do
#driver = driver
end
at_exit do
driver.close
end
In this case, a browser will be opened at the start (before any tests). Then each test will grab that browser and continue using it.
Note: While it is usually okay to re-use the browser across tests. You should be careful about tests that need to be run in a specific order (ie become dependent). Dependent tests can be hard to debug and maintain.
I had a similar problem in creating a spec_helper file. I did the following (simplified for locally-run firefox) for my purposes and it works very, very reliably. RSpec will use the same browser window for all it blocks in your _spec.rb file.
Rspec.configure do |config|
config.before(:all) do
#driver = Selenium::WebDriver.for :firefox
end
config.after(:all) do
#driver.quit
end
end
If you switch to :each instead of :all, you can use a separate browser instance for each assertion block... again, with :each RSpec will give a new browser instance for each it. Both are useful depending on the circumstance.
As the answers solve the problem but do not answer the question "How to connect to an existing session".
I managed to do this with the following code since it is not officially supported.
# monkey-patch 2 methods
module Selenium
module WebDriver
class Driver
# Be able to set the driver
def set_bridge_to(b)
#bridge = b
end
# bridge is a private method, simply create a public version
def public_bridge
#bridge
end
end
end
end
caps = Selenium::WebDriver::Remote::Capabilities.send("chrome")
driver = Selenium::WebDriver.for(
:remote,
url: "http://chrome:4444/wd/hub",
desired_capabilities: caps
)
used_bridge = driver.bridge
driver.get('https://www.google.com')
# opens a new unused chrome window
driver2 = Selenium::WebDriver.for(
:remote,
url: "http://chrome:4444/wd/hub",
desired_capabilities: caps
)
driver2.close() # close unused chrome window
driver2.set_bridge_to(used_bridge)
driver2.title # => "Google"
Sadly this did not test work between 2 rescue jobs, will update this in the future when I made it work for my own use case.

Watir script timeout problems with Firefox browser

I am new to Watir and I have this weird situation with AJAX based webapp. Application might render a notification window over the page. This notification is a JS based modal window. If I click or mouse-over the notification it vanishes.. So somewhere in my script I have:
#browser = Watir::Browser.new :firefox
...
notf = notification
notf.click if notf
and the method to get notification is this:
def notification
if browser.div(:class => "popupContent").present?
Notification.new(browser.div(:class => "popupContent"))
end
end
Script is running fine with IE and Chrome but with Firefox I get after 60sec 'Timeout:Error' for the if statement.. When I changed code this way:
def notification
begin
browser.div(:class => "popupContent").wait_until_present(1)
Notification.new(browser.div(:class => "popupContent"))
rescue Exception
puts "timeout..."
end
end
Chrome and IE work fine are working fine - just adding up 1 sec delay in case notification is not present.. But Firefox is still having 60sec timeouts in case notification is not present?!? What am I doing wrong - do I need to set/check some Firefox settings?
I have this configuration:
- Win7 OS with Firefox 17.0.1
- Ruby 1.9.3p125
- watir-webdriver (0.6.1)
- selenium-webdriver (2.26.0)
Thank you for your help!
As mentioned in the comments, the solution is to upgrade to the latest version of selenium-webdriver (2.27.2).

Resources