Automated testing with Cucumber on BrowserStack of site behind VPN - ruby

I am trying to get my Cucumber tests to work on BrowserStack. The problem is that our test environments are all behind a VPN. BrowserStack's docs say, just set up local testing and it will just work!. It doesn't. The tests start up, but they are not being rerouted through my local machine to pick up my vpn credentials.
I downloaded the binary as instructed by BrowserStack. I started it up with the command
~ ./BrowserStackLocal <my BS key> -forcelocal
Then I run my test with (in a different terminal window):
bundle exec cucumber CURRENT_BROWSER=browserstack features/01_login.feature
my env.rb looks like this:
require 'cucumber/rails'
Capybara.default_selector = :css
cb = ENV['CURRENT_BROWSER']
testbrowser = cb ? cb.downcase.to_sym : :firefox
puts "-------------- current browser: #{testbrowser}........."
Capybara.register_driver :selenium do |app|
if RbConfig::CONFIG['host_os'][/linux/] && testbrowser.to_s.eql?("CHROME".downcase)
Capybara::Selenium::Driver.new(app, {:browser => :remote, :url => "http://127.0.0.1:9515"})
else
if testbrowser.eql?(:chrome)
prefs = {
:download => {
:prompt_for_download => false,
:default_directory => DownloadHelpers::PATH.to_s
}
}
Capybara::Selenium::Driver.new(app, :browser => :chrome, :prefs => prefs, :switches => %w[--test-type])
elsif testbrowser.eql?(:browserstack)
stackToUse = ENV['BS_STACK'] || 'ie_9'
json = JSON.load(open(File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'browsers.json'))))
config = json[stackToUse]
unless config
puts "invalid BS_STACK specified. Was '#{stackToUse}'"
return
end
# Add default config
config['name'] = "#{config['os']} #{config['os_version']} - #{Time.now.strftime '%Y-%m-%d %H:%M'}"
config['acceptSslCert'] = true
config['browserstack.debug'] = true
Capybara::Selenium::Driver.new(app, :browser => :remote, :desired_capabilities => config, :url => "http://<BS_USERNAME>:<BS_PASSKEY>#hub.browserstack.com/wd/hub")
elsif testbrowser.eql?(:internetexplorer)
Capybara::Selenium::Driver.new(app, :browser => :internetexplorer, :switches => %w[--test-type])
else
profile = Selenium::WebDriver::Firefox::Profile.new
profile
profile["browser.download.dir"] = DownloadHelpers::PATH.to_s
profile["browser.download.folderList"] = 2 # 2 - save to user defined location
profile["browser.download.manager.alertOnEXEOpen"] = false
profile["browser.helperApps.neverAsk.saveToDisk"] = "application/msword, application/csv, application/ris, text/csv, image/png, application/pdf, text/html, text/plain, application/zip, application/x-zip, application/x-zip-compressed, application/download, application/octet-stream, data:application/csv"
profile["browser.helperApps.alwaysAsk.force"] = false
profile["browser.download.manager.showWhenStarting"] = false
profile["browser.download.manager.focusWhenStarting"] = false
profile["browser.download.useDownloadDir"] = true
profile["browser.download.manager.alertOnEXEOpen"] = false
profile["browser.download.manager.closeWhenDone"] = true
profile["browser.download.manager.showAlertOnComplete"] = false
profile["browser.download.manager.useWindow"] = false
profile["services.sync.prefs.sync.browser.download.manager.showWhenStarting"] = false
profile["pdfjs.disabled"] = true
Capybara::Selenium::Driver.new(app, :browser => testbrowser, :profile => profile)
end
end
end
ActionController::Base.allow_rescue = false
# Remove/comment out the lines below if your app doesn't have a database.
# For some databases (like MongoDB and CouchDB) you may need to use :truncation instead.
begin
DatabaseCleaner.strategy = :transaction
rescue NameError
raise "You need to add database_cleaner to your Gemfile (in the :test group) if you wish to use it."
end
# You may also want to configure DatabaseCleaner to use different strategies for certain features and scenarios.
# See the DatabaseCleaner documentation for details. Example:
#
# Before('#no-txn,#selenium,#culerity,#celerity,#javascript') do
# # { :except => [:widgets] } may not do what you expect here
# # as tCucumber::Rails::Database.javascript_strategy overrides
# # this setting.
# DatabaseCleaner.strategy = :truncation
# end
#
# Before('~#no-txn', '~#selenium', '~#culerity', '~#celerity', '~#javascript') do
# DatabaseCleaner.strategy = :transaction
# end
#
# Possible values are :truncation and :transaction
# The :transaction strategy is faster, but might give you threading problems.
# See https://github.com/cucumber/cucumber-rails/blob/master/features/choose_javascript_database_strategy.feature
Cucumber::Rails::Database.javascript_strategy = :truncation
Other people use these same tests and we have written dozens, so making sure that I can still run these tests locally is paramount.
When I do run the tests, it begins to run on browserstack, but it can't reach any of the sites I have tried telling it to reach. Including http://localhost:3000/login I have contacted BrowserStack support and they asked if I had set up local testing.
The only error I am getting is that the test can't find the CSS element to login. When I watched the automated test through browserstack I can see that it isn't reaching the page. It just says "Oops! This link appears to be broken." Any suggestions would be most appreciated.

The support at BrowserStack got back to me. I had to had another config property like so to the env.rb:
config['browserstack.local'] = true
Now my only problem is that none of the features that we wrote seem to work on IE. So I can test chrome or firefox on browserstack, but I already had that capability set up.

Related

Debug in headless Chrome

After switching from capybara_webkit to headless_chrome, I'm trying to find a way to replicate
Capybara::Webkit.configure do |config|
config.debug = true
end
or
Capybara.javascript_driver = :webkit_debug
with the new driver.
The goal is to be able to see the log of everything happening when running rspec my_spec.rb: for example, all GET requests.
Is there a way to achieve that?
There is no option when using Selenium like the capybara_webkit debug option that outputs the debug info in realtime, however you can get access to the Chrome logs and output those at the end of each test (or you could write a helper to output them whenever you call it of course).
First you'd need to configure your selenium driver for logging
Capybara.register_driver :logging_chrome do |app|
caps = Selenium::WebDriver::Remote::Capabilities.chrome(
# customize this based on which and what level logs your prefer
loggingPrefs: {
browser: 'ALL',
driver: 'ALL',
performance: 'ALL'
}
)
browser_options = ::Selenium::WebDriver::Chrome::Options.new()
browser_options.headless!
Capybara::Selenium::Driver.new(
app,
browser: :chrome,
desired_capabilities: caps,
options: browser_options
)
end
Then you'd set up to use that driver
Capybara.javascript_driver = :logging_chrome # possibly default_driver = depending on your config
and then add an after block that gets the logs and displays them
after(:each) do
# customize based on which type of logs you want displayed
log_types = page.driver.browser.manage.logs.available_types
log_types.each do |t|
puts t.to_s + ": " + page.driver.browser.manage.logs.get(t).join("\n")
end
end

Ruby & Selenium - how to pass arguments to browser?

My search has only turned up answers for Java - this and this
The selenium gem doesn't include addCommandLineOptions as far as I can tell, but it does have WebDriver::Remote::Capabilities.
How do I use it to add arguments? I know you pass it as desired_capabilities: to the driver constructor, but in what format?
Unfortunately the documentation has been especially useless
You can set --start-maximizedby following for Chrome. See this post for more details.
Capybara.register_driver :chrome_maximize do |app|
caps = Selenium::WebDriver::Remote::Capabilities.chrome(
'chromeOptions' => {
"args" => [ "--start-maximized", "--otherthings" ]
}
)
$driver = Capybara::Selenium::Driver.new(app, {:browser => :chrome, :desired_capabilities => caps})
end
I finally figured out!!! Here is a working example for gem "selenium-webdriver". Should work too for Capybara as well.
First line is if you want to run a custom binary. In case of --headless command line argument, support starts from firefox version 55. Don't forget to make firefox-nightly available to $PATH Env Var.
Selenium::WebDriver::Firefox.path = "/home/user/bin/firefox-nightly"
caps = Selenium::WebDriver::Remote::Capabilities.firefox(
"moz:firefoxOptions" => {
args: ["--headless"] # and other arguments...
}
)
driver = Selenium::WebDriver.for :firefox, desired_capabilities: caps
# do stuff here ....
driver.quit

Ruby, cucumber, capybaras: is it possible to switch between sauce labs and local runs when running parallel tests?

Currently I am working on an environment that should be able to run both locally and on sauce labs but I have the following issue:
When using Cucumber the tag "#selenium" is needed for the sauce integration with parallel tests. However this tag also forces the test to run on sauce labs (I want to be able to switch between sauce and local). Is there a way I can use an environment variable or tag to change this behavior?
OS: OSX Yosemite
Testing Stack: Ruby, Capybara, Cucumber, Rake.
Note: Without the Selenium tag I can run both sauce labs and local for a single test run or sequential all test run. I am new to ruby/capybara/cucumber so any general tips greatly appreciated)
Approach that works with a single feature and the cucumber feature:
if (ENV["RUN_ON_SAUCE"] == "true")
puts('TRUE: ENV["RUN_ON_SAUCE"] = ' + ENV["RUN_ON_SAUCE"])
Capybara.default_driver = :sauce
Capybara.javascript_driver = :sauce
else
puts('FALSE: ENV["RUN_ON_SAUCE"] = ' + ENV["RUN_ON_SAUCE"])
Capybara.default_driver = :selenium
Capybara.javascript_driver = :selenium
end
The below code works for me. I'm using cucumber with capybara and my features are marked with #selenium and couple of other tags(#core) which I use for filtering.
Command to execute the suite on sauce labs-
RUN_ON_SAUCE=true
SC_EXECUTABLE=path/to/sauce/connect/executable
START_TUNNEL=true ENVIRONMENT=staging parallel_cucumber features -o
"-t #core" -n 8
Command to execute the suite locally-
parallel_cucumber features -o
"-t #core" -n 8
if ENV['HEADLESS']
require 'capybara/poltergeist'
Capybara.default_driver = :poltergeist
Capybara.register_driver :poltergeist do |app|
Capybara::Poltergeist::Driver.new(app, {:debug => false, :default_wait_time => 60, :timeout => 120, :js_errors => false, :window_size => [1024, 768]})
end
Capybara.javascript_driver = :poltergeist
elsif ENV['RUN_ON_SAUCE']
require 'sauce'
require 'sauce/capybara'
require 'sauce/cucumber'
Capybara.default_driver = :sauce
Capybara.javascript_driver = :sauce
Sauce.config do |c|
if ENV['START_TUNNEL']
c[:start_tunnel] = ENV['START_TUNNEL']
c[:sauce_connect_4_executable] = ENV['SC_EXECUTABLE']
c[:connect_options] = {tunnel_domains: "'*.example.com'", max_logsize: "10485760"}
end
c[:browsers] = [
["Windows 8", "Internet Explorer", "10"],
["Windows 10", "Internet Explorer", "11"],
["Windows XP", "Internet Explorer", "8"]
]
c[:'max-duration'] = 300
end
else
Capybara.default_driver = :selenium
Capybara.default_max_wait_time = 120
Capybara.page.driver.browser.manage.window.maximize
end

How to run multiple firefox browser parallely having different proxy in Watir

The code is given Below , where it is launching three firefox browser
, all browser has different proxy settings. Using watir how launch all three browser same time using tread in watir???
require 'selenium-webdriver'
require 'rubygems'
require 'watir'
require 'rautomation'
require './CLReport.class'
require 'win32ole'
# TO INITIATE FIRST FIREFOX BROWSER
# THE PROXY DATA CAN BE parameterized from Excel sheet
profile = Selenium::WebDriver::Firefox::Profile.new
profile.proxy = Selenium::WebDriver::Proxy.new :http => 'myproxy.com:8080', :ssl => 'myproxy.com:8080'
$b1 = Watir::Browser.new :firefox, :profile => profile
$b1.goto("https://google.com")
# TO INITIATE SECOND FIREFOX BROWSER
# THE PROXY DATA CAN BE parameterized from Excel sheet
profile = Selenium::WebDriver::Firefox::Profile.new
profile.proxy = Selenium::WebDriver::Proxy.new :http => 'myproxy.com:8081', :ssl => 'myproxy.com:8081'
$b2 = Watir::Browser.new :firefox, :profile => profile
$b2.goto("https://google.com")
# TO INITIATE THORD FIREFOX BROWSER
# THE PROXY DATA CAN BE parameterized from Excel sheet
profile = Selenium::WebDriver::Firefox::Profile.new
profile.proxy = Selenium::WebDriver::Proxy.new :http => 'myproxy.com:8082', :ssl => 'myproxy.com:8082'
$b3 = Watir::Browser.new :firefox, :profile => profile
$b3.goto("https://google.com")
Now my question is how to join $b1,$b2,$b3 in a single browser using thread so that
only $browser.link(:text, "form application")click should work for all three browser parallely insted of writing
$b1.link(:text, "form application").click
$b2.link(:text, "form application").click
$b3.link(:text, "form application").click
i.e single line of code work work in three firefox browser same time parallely.
It is not possible because $b1,$b2,$b3 are instances of different browser,You can not make them equal.What are you doing is right. Or You can do some thing like that.
array = [$b1,$b2,$b3]
array.each { |browser|
browser.link(:text, "form application").click
}

How to enable SSL for a standalone Sinatra app?

I want to write a quick server app in Sinatra. It has to be self-contained (i.e. not use apache/nginx/passenger) but also has to support SSL.
Is there an easy way to enable SSL support for Sinatra (using WEBRick for example)?
To do this with MRI ruby, use the following monkeypatch:
sinatra_ssl.rb:
require 'webrick/https'
module Sinatra
class Application
def self.run!
certificate_content = File.open(ssl_certificate).read
key_content = File.open(ssl_key).read
server_options = {
:Host => bind,
:Port => port,
:SSLEnable => true,
:SSLCertificate => OpenSSL::X509::Certificate.new(certificate_content),
:SSLPrivateKey => OpenSSL::PKey::RSA.new(key_content)
}
Rack::Handler::WEBrick.run self, server_options do |server|
[:INT, :TERM].each { |sig| trap(sig) { server.stop } }
server.threaded = settings.threaded if server.respond_to? :threaded=
set :running, true
end
end
end
end
Then, in your standalone application:
app.rb
require 'sinatra'
require 'sinatra_ssl'
set :port, 8443
set :ssl_certificate, "server.crt"
set :ssl_key, "server.key"
get "/" do
"Hello world!"
end
Use JRuby interpreter + jetty-rackup gem (http://github.com/geekq/jetty-rackup)
Edit jetty-rackup file in the jetty-rackup gem and add a SslSocketConnector, some code to help you:
security_connector = Jetty::Security::SslSocketConnector.new
security_connector.set_acceptors(config[:acceptor_size])
security_connector.port = config[:port]
security_connector.confidential_port = config[:port]
security_connector.keystore = keystore
security_connector.password = config[:password]
security_connector.key_password = config[:key_password].nil? ? config[:password] : config[:key_password]
security_connector.truststore = truststore
security_connector.trust_password = config[:trust_pasword].nil? ? config[:password] : config[:trust_pasword]
server.add_connector(security_connector)
Sample config:
# Config
:acceptor_size: 10
:ssl: true
:keystore: keystore.jks
:password: your_pass
# :key_password: your_pass # if different
# :truststore: truststore.jks # if different
# :trust_pasword: your_pass # if different
Generating keystore.jks : http://docs.codehaus.org/display/JETTY/How+to+configure+SSL

Resources