diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..08750bd --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,14 @@ +Metrics/LineLength: + Max: 150 + +Metrics/AbcSize: + Max: 21 + +Metrics/MethodLength: + Max: 25 + +Metrics/ClassLength: + Max: 250 + +Metrics/CyclomaticComplexity: + Max: 10 \ No newline at end of file diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 0000000..68b3a4c --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +1.9.3-p551 diff --git a/Gemfile.lock b/Gemfile.lock index 04e1404..498937a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,65 +1,84 @@ PATH remote: . specs: - frameworks-capybara (2.3.1) - capybara + frameworks-capybara (3.0.0) + capybara (~> 2.5) capybara-mechanize cucumber json + logging mechanize + poltergeist selenium-webdriver + show_me_the_cookies w3c_validators GEM remote: https://rubygems.org/ specs: builder (3.2.2) - capybara (2.4.4) + capybara (2.5.0) mime-types (>= 1.16) nokogiri (>= 1.3.3) rack (>= 1.0.0) rack-test (>= 0.5.4) xpath (~> 2.0) - capybara-mechanize (1.4.0) - capybara (~> 2.4.4) - mechanize (~> 2.7.0) - childprocess (0.5.5) + capybara-mechanize (1.0.1) + capybara (~> 2.0, >= 2.0.1) + mechanize (~> 2.5) + childprocess (0.5.9) ffi (~> 1.0, >= 1.0.11) - cucumber (1.3.17) + cliver (0.3.2) + cucumber (2.3.0) builder (>= 2.1.2) + cucumber-core (~> 1.4.0) + cucumber-wire (~> 0.0.1) diff-lcs (>= 1.1.3) - gherkin (~> 2.12) + event-bus (~> 0.1.0) + gherkin (~> 3.2.0) multi_json (>= 1.7.5, < 2.0) - multi_test (>= 0.1.1) + multi_test (>= 0.1.2) + cucumber-core (1.4.0) + gherkin (~> 3.2.0) + cucumber-wire (0.0.1) diff-lcs (1.2.5) - domain_name (0.5.22) + domain_name (0.5.25) unf (>= 0.0.5, < 1.0.0) - ffi (1.9.6) - gherkin (2.12.2) - multi_json (~> 1.3) + event-bus (0.1.0) + ffi (1.9.10) + gherkin (3.2.0) http-cookie (1.0.2) domain_name (~> 0.5) - json (1.8.1) - mechanize (2.7.3) + json (1.8.3) + little-plugger (1.1.4) + logging (2.0.0) + little-plugger (~> 1.1) + multi_json (~> 1.10) + mechanize (2.7.4) domain_name (~> 0.5, >= 0.5.1) http-cookie (~> 1.0) - mime-types (~> 2.0) + mime-types (>= 1.17.2, < 3) net-http-digest_auth (~> 1.1, >= 1.1.1) net-http-persistent (~> 2.5, >= 2.5.2) - nokogiri (~> 1.4) + nokogiri (~> 1.6) ntlm-http (~> 0.1, >= 0.1.1) webrobots (>= 0.0.9, < 0.2) - mime-types (2.4.3) - mini_portile (0.6.0) - multi_json (1.10.1) - multi_test (0.1.1) + mime-types (2.99) + mini_portile2 (2.0.0) + multi_json (1.11.2) + multi_test (0.1.2) net-http-digest_auth (1.4) net-http-persistent (2.9.4) - nokogiri (1.6.3.1) - mini_portile (= 0.6.0) + nokogiri (1.6.7.1) + mini_portile2 (~> 2.0.0.rc2) ntlm-http (0.1.1) - rack (1.5.2) - rack-test (0.6.2) + poltergeist (1.8.1) + capybara (~> 2.1) + cliver (~> 0.3.1) + multi_json (~> 1.0) + websocket-driver (>= 0.2.0) + rack (1.6.4) + rack-test (0.6.3) rack (>= 1.0) rake (10.1.1) rspec (2.13.0) @@ -70,20 +89,25 @@ GEM rspec-expectations (2.13.0) diff-lcs (>= 1.1.3, < 2.0) rspec-mocks (2.13.1) - rubyzip (1.1.6) - selenium-webdriver (2.43.0) + rubyzip (1.1.7) + selenium-webdriver (2.49.0) childprocess (~> 0.5) multi_json (~> 1.0) rubyzip (~> 1.0) websocket (~> 1.0) + show_me_the_cookies (3.1.0) + capybara (~> 2.0) unf (0.1.4) unf_ext - unf_ext (0.0.6) + unf_ext (0.0.7.1) w3c_validators (1.2) json nokogiri - webrobots (0.1.1) - websocket (1.2.1) + webrobots (0.1.2) + websocket (1.2.2) + websocket-driver (0.6.3) + websocket-extensions (>= 0.1.0) + websocket-extensions (0.1.2) xpath (2.0.0) nokogiri (~> 1.3) @@ -94,3 +118,6 @@ DEPENDENCIES frameworks-capybara! rake rspec + +BUNDLED WITH + 1.10.6 diff --git a/README.rdoc b/README.rdoc index 4b27ae6..a0ef305 100644 --- a/README.rdoc +++ b/README.rdoc @@ -10,18 +10,20 @@ The principle behind this gem is to factor out all the common setup code for reg Below are the current drivers that can be registered: -* Selenium-Webdriver (Selenium2) - LOCAL: This can be used to drive 'in-browser' tests runnong on your local machine in IE, Firefox and Chrome (and any other browsers as and when they are added into the Selenium-Webdriver project) +* Selenium-Webdriver (Selenium2) - LOCAL: This can be used to drive 'in-browser' tests running on your local machine in IE, Firefox and Chrome (and any other browsers as and when they are added into the Selenium-Webdriver project) -* Selenium-Webdriver (Selenium2) - REMOTE: This can be used to drive 'in-browser' tests on a remote macine, this could be another macine on your local network which is running a Selenium-Webdriver server or indeed a cloud service such as 'Sauce Labs' +* Selenium-Webdriver (Selenium2) - REMOTE: This can be used to drive 'in-browser' tests on a remote machine, this could be another machine on your local network which is running a Selenium-Webdriver server or indeed a cloud service such as 'Sauce Labs' * Mechanize-Caybara: This can be used, by setting BROWSER=mechanize +* Poltergeist: This can be used, by setting BROWSER=poltergeist + How to use this gem in your project: In your env.rb simply add: - - require 'frameworks-capybara' + + require 'frameworks-capybara' The following environment variables can be set to configure your tests: @@ -37,12 +39,12 @@ The following environment variables can be set to configure your tests: FIREFOX_PREFS - specify a json string of additional preferences e.g. FIREFOX_PREFS='{"javascript.enabled": false}' FIREFOX_CERT_PATH - specify optional directory containing Firefox profile certificate (.db) files FIREFOX_CERT_PREFIX - specify optional prefix for locating Firefox profile certificate files (e.g. -.db) - CREATE_NEW_FF_PROFILE - create a new Firefox profile with name provided by FIREFOX_PROFILE + CREATE_NEW_FF_PROFILE - create a new Firefox profile with name provided by FIREFOX_PROFILE XVFB - (string - 'true', 'false') - determines whether XVFB is used to run browser (i.e. headless Firefox on *nix platform) FW_CERT_LOCATION - path to client certificate (combined pem) CHROME_SWITCHES - pass in any allowed switches for the Selenium chrome driver (http://peter.sh/experiments/chromium-command-line-switches/) e.g. CHROME_SWITCHES="--user-agent=Mozilla/5.0 (PLAYSTATION 3; 3.55)" - PROJECT_NAME - optional project name description which gets displayed in Cucumber html reports - TEAM_NAME - optional team name description which gets displayed in Cucumber html reports + PROJECT_NAME - optional project name description which gets displayed in Cucumber html reports + TEAM_NAME - optional team name description which gets displayed in Cucumber html reports BROWSER_CLI_ARGS - optional additional arguments to pass to local browser processes (individual arguments should be separated with spaces) The following environment variables are specific to running tests against a BrowserStack remote grid: @@ -54,6 +56,13 @@ The following environment variables are specific to running tests against a Brow BS_PROJECT - allows the user to specify a name for a logical group of builds e.g. 'Project X' BS_RESOLUTION - set the browser resolution e.g. '1024x768' +The following environment variables are specific to running tests against an Appium server: + + APPIUM_PLATFORM - one of iOS, Android, or FirefoxOS + APPIUM_DEVICE - e.g. iPhone Simulator, iPad Simulator, iPhone Retina 4-inch, Android Emulator + APPIUM_BROWSER - e.g. chrome, safari + APPIUM_UDID - the device id, note you can find this by doing +adb devices+ if you are working on a local machine + Here is a sample cucumber.yml: <%intenv='ENVIRONMENT=int'%> @@ -80,13 +89,37 @@ Here is a sample cucumber.yml: This gem also sets up a number of 'base urls' for you to use in your tests, these are set based on the ENVIRONMENT variable you set when running cucumber tests (either from the comand line or in cucumber.yml), the following URLs are set: - + @base_url @base_static_url @base_open_url Finally this gem contains some useful monkey-patches to core libraries e.g. Capybara-Mechanize, Selenium-Webdriver and Cucumber. +== Wait Helpers + +This gem provides some default wait helpers useful for when the 'out of the box' mechanisms provided by Capybara and/or SitePrism aren't quite enough. + +To use these include the +FrameworksCapybara+::+Wait+ module in your class. + ++wait_for+ - simple wait for boolean condition + wait_for { (Random.rand(2) % 2) } + + ++wait_for_assertion+ - wait for rspec assertion to pass without raising exceptions + + wait_for_assertion('Cannot find foo on page') do + expect(page).to have_content 'foo' + end + + ++wait_for_no_exception+ - wait for block to NOT raise provided exception + + wait_for_no_exception('Author image not visible', SitePrism::TimeOutWaitingForElementVisibility) do + article.wait_until_author_image_visible + end + + == Release instructions * Run tests - 'rake' @@ -105,7 +138,7 @@ You should see something like: Pushed frameworks-capybara 0.2.23 to rubygems.org == Contributing to frameworks-capybara - + * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it * Fork the project @@ -117,4 +150,3 @@ You should see something like: == Copyright See LICENSE.txt for further details. - diff --git a/Rakefile b/Rakefile index ed6c73a..89db265 100644 --- a/Rakefile +++ b/Rakefile @@ -5,8 +5,8 @@ require 'cucumber/rake/task' Bundler::GemHelper.install_tasks -desc "Run all examples" +desc 'Run all examples' RSpec::Core::RakeTask.new(:spec) do |t| - t.rspec_opts = %w[--color] + t.rspec_opts = %w(--color) end -task :default => [:spec] +task default: [:spec] diff --git a/frameworks-capybara.gemspec b/frameworks-capybara.gemspec index 45a7c21..7779a09 100644 --- a/frameworks-capybara.gemspec +++ b/frameworks-capybara.gemspec @@ -1,32 +1,34 @@ # -*- encoding: utf-8 -*- + lib = File.expand_path('../lib/', __FILE__) -$:.unshift lib unless $:.include?(lib) +$LOAD_PATH.unshift lib unless $LOAD_PATH.include?(lib) require 'version' Gem::Specification.new do |s| - s.name = "frameworks-capybara" + s.name = 'frameworks-capybara' s.version = FrameworksCapybara::VERSION - s.authors = ["matt robbins"] - s.email = ["mcrobbins@gmail.com"] - s.description = "Gem to ease the pain of managing capybara driver config and provide a home for common utils and patches" - - s.files = Dir.glob("{features,lib,bin,config,vendor,.bundle}/**/*") + %w(Gemfile Gemfile.lock) - - s.require_paths = ["lib"] - s.rubygems_version = "2.4.2" - s.summary = "Gem to ease the pain of managing capybara driver config and provide a home for common utils and patches" + s.authors = ['Radio and Music Test team'] + s.email = [''] + s.description = 'Gem to ease the pain of managing capybara driver config and provide a home for common utils and patches' - s.files = `git ls-files`.split("\n") + s.files = Dir.glob('{features,lib,bin,config,vendor,.bundle}/**/*') + %w(Gemfile Gemfile.lock) - s.add_runtime_dependency("selenium-webdriver") - s.add_runtime_dependency("capybara") - s.add_runtime_dependency("mechanize") - s.add_runtime_dependency("capybara-mechanize") - s.add_runtime_dependency("json") - s.add_runtime_dependency("cucumber") - s.add_runtime_dependency("w3c_validators") - s.add_development_dependency("rake") - s.add_development_dependency("rspec") + s.require_paths = ['lib'] + s.rubygems_version = '2.4.2' + s.summary = 'Gem to ease the pain of managing capybara driver config and provide a home for common utils and patches' + s.files = `git ls-files`.split("\n") + s.add_runtime_dependency('selenium-webdriver') + s.add_runtime_dependency('capybara', '~> 2.5') + s.add_runtime_dependency('mechanize') + s.add_runtime_dependency('capybara-mechanize') + s.add_runtime_dependency('poltergeist') + s.add_runtime_dependency('json') + s.add_runtime_dependency('cucumber', '~> 2.4.0') + s.add_runtime_dependency('logging') + s.add_runtime_dependency('show_me_the_cookies') + s.add_runtime_dependency('w3c_validators') + s.add_development_dependency('rake') + s.add_development_dependency('rspec') end diff --git a/lib/extensions/capybara-extensions.rb b/lib/extensions/capybara-extensions.rb deleted file mode 100644 index f910d31..0000000 --- a/lib/extensions/capybara-extensions.rb +++ /dev/null @@ -1,69 +0,0 @@ -require 'selenium-webdriver' - -# -# Cookie utility methods -# -class Capybara::Selenium::Driver - def cookies - browser.manage.all_cookies - end - - def cookie_named(name) - browser.manage.cookie_named(name) - end - - def delete_cookie(cookie) - browser.manage.delete_cookie(cookie) - end - - def delete_all_cookies - browser.manage.delete_all_cookies - end - - def add_cookie(attribs) - browser.manage.add_cookie(attribs) - end - - def delete_cookies_in_domain(domain) - browser.manage.delete_cookies_in_domain(domain) - end -end - -module Capybara - class Session - ## - # Get all cookies - # - # @return [Array] list of cookies - # - def cookies - driver.cookies - end - - ## - # Get the cookie with the given name - # - # @param [String] name the name of the cookie - # @return [Hash, nil] the cookie, or nil if it wasn't found. - # - def cookie_named(name) - driver.cookie_named(name) - end - - def delete_cookie(cookie) - driver.delete_cookie(cookie) - end - - def delete_all_cookies - driver.delete_all_cookies - end - - def add_cookie(attribs) - driver.add_cookie(attribs) - end - - def delete_cookies_in_domain(domain) - driver.delete_cookies_in_domain(domain) - end - end -end \ No newline at end of file diff --git a/lib/extensions/capybara-mechanize-extensions.rb b/lib/extensions/capybara-mechanize-extensions.rb deleted file mode 100644 index 662d19b..0000000 --- a/lib/extensions/capybara-mechanize-extensions.rb +++ /dev/null @@ -1,70 +0,0 @@ -require 'capybara/mechanize/cucumber' - -# Cookie handling extensions -class Capybara::Mechanize::Driver - - def cookies - cookies = [] - - browser.agent.cookie_jar.jar.each do |domain| - domain[1].each do |path| - path[1].each do |cookie| - - cookies.push({ - :name => cookie[1].name, - :value => cookie[1].value, - :domain => cookie[1].domain, - :secure => cookie[1].secure, - :expires => cookie[1].expires, - :httponly => cookie[1].httponly, - :path => cookie[1].path - }) - end - end - end - cookies - end - - def cookie_named(name) - cookies.find { |c| c[:name] == name } - end - - def delete_cookie(cookie_name) - browser.agent.cookie_jar.jar.each do |domain| - domain[1].each do |path| - path[1].each do |cookie| - if cookie[0] == cookie_name - browser.agent.cookie_jar.jar[domain[0]][path[0]].delete(cookie[0]) - end - end - end - end - end - - def delete_all_cookies - browser.agent.cookie_jar.clear! - end - - def delete_cookies_in_domain(domain) - cookies.each do |cookie| - delete_cookie(cookie[:name]) if cookie[:domain].include?(domain) - end - end - - def add_cookie(attribs) - - cookie = HTTP::Cookie.new( - attribs[:name], - attribs[:value], - :domain => attribs[:domain], - :for_domain => true, - :path => '/', - :expires => attribs[:expires], - :secure => attribs[:secure], - :httponly => attribs[:httponly] - ) - - browser.agent.cookie_jar.add(cookie) - - end -end diff --git a/lib/frameworks-capybara.rb b/lib/frameworks-capybara.rb index c7d9b80..c85c97c 100644 --- a/lib/frameworks-capybara.rb +++ b/lib/frameworks-capybara.rb @@ -1,5 +1,7 @@ require 'frameworks/cucumber' require 'frameworks/capybara' require 'frameworks/wait' +require 'frameworks/utils' +require 'frameworks/logger' CapybaraSetup.new unless ENV['CAPYBARA_DISABLED'] diff --git a/lib/frameworks/capybara.rb b/lib/frameworks/capybara.rb index eb60f4c..84ea8e7 100644 --- a/lib/frameworks/capybara.rb +++ b/lib/frameworks/capybara.rb @@ -1,70 +1,80 @@ require 'capybara' require 'capybara/cucumber' require 'capybara/mechanize' +require 'capybara/poltergeist' require 'selenium-webdriver' -require 'extensions/capybara-extensions' -require 'extensions/capybara-mechanize-extensions' +# Register drivers class CapybaraSetup - attr_reader :driver def initialize - http_proxy = ENV['HTTP_PROXY'] || ENV['http_proxy'] browser_cli_args = ENV['BROWSER_CLI_ARGS'].split(/\s+/).compact if ENV['BROWSER_CLI_ARGS'] - capybara_opts = {:environment => ENV['ENVIRONMENT'], - :http_proxy => http_proxy, - :profile => ENV['FIREFOX_PROFILE'], - :browser => ENV['BROWSER'], - :webdriver_proxy_on => ENV['PROXY_ON'], - :url => ENV['REMOTE_URL'], - :chrome_switches => ENV['CHROME_SWITCHES'], - :firefox_prefs => ENV['FIREFOX_PREFS'], - :args => browser_cli_args + capybara_opts = { + environment: ENV['ENVIRONMENT'], + http_proxy: http_proxy, + profile: ENV['FIREFOX_PROFILE'], + browser: ENV['BROWSER'], + webdriver_proxy_on: ENV['PROXY_ON'], + url: ENV['REMOTE_URL'], + chrome_switches: ENV['CHROME_SWITCHES'], + firefox_prefs: ENV['FIREFOX_PREFS'], + args: browser_cli_args } - selenium_remote_opts = {:os => ENV['PLATFORM'], - :os_version => ENV['PLATFORM_VERSION'], - :browser_name => ENV['REMOTE_BROWSER'], - :browser_version => ENV['REMOTE_BROWSER_VERSION'], - :url => ENV['REMOTE_URL'] + selenium_remote_opts = { + os: ENV['PLATFORM'], + os_version: ENV['PLATFORM_VERSION'], + browser_name: ENV['REMOTE_BROWSER'], + browser_version: ENV['REMOTE_BROWSER_VERSION'], + url: ENV['REMOTE_URL'] } - custom_opts = {:job_name => ENV['SAUCE_JOB_NAME'], - :max_duration => ENV['SAUCE_MAX_DURATION'], - :firefox_cert_path => ENV['FIREFOX_CERT_PATH'], - :firefox_cert_prefix => ENV['FIREFOX_CERT_PREFIX'], - :browserstack_build => ENV['BS_BUILD'], - :browserstack_debug => ENV['BS_DEBUG'] || 'true', # BrowserStack debug mode on by default - :browserstack_device => ENV['BS_DEVICE'], - :browserstack_device_orientation => ENV['BS_DEVICE_ORIENTATION'], - :browserstack_project => ENV['BS_PROJECT'], - :browserstack_resolution => ENV['BS_RESOLUTION'] + custom_opts = { + job_name: ENV['SAUCE_JOB_NAME'], + max_duration: ENV['SAUCE_MAX_DURATION'], + firefox_cert_path: ENV['FIREFOX_CERT_PATH'], + firefox_cert_prefix: ENV['FIREFOX_CERT_PREFIX'], + browserstack_build: ENV['BS_BUILD'], + browserstack_debug: ENV['BS_DEBUG'] || 'true', # BrowserStack debug mode on by default + browserstack_device: ENV['BS_DEVICE'], + browserstack_device_orientation: ENV['BS_DEVICE_ORIENTATION'], + browserstack_project: ENV['BS_PROJECT'], + browserstack_resolution: ENV['BS_RESOLUTION'], + appium_platform: ENV['APPIUM_PLATFORM'], + appium_device: ENV['APPIUM_DEVICE'], + appium_browser: ENV['APPIUM_BROWSER'], + appium_udid: ENV['APPIUM_UDID'] } + # validate environment variables set using cucumber.yml or passed via command line + validate_env_vars(capybara_opts.merge(selenium_remote_opts), custom_opts) - validate_env_vars(capybara_opts.merge(selenium_remote_opts)) #validate environment variables set using cucumber.yml or passed via command line - - if(capybara_opts[:http_proxy]) + if capybara_opts[:http_proxy] proxy_uri = URI(capybara_opts[:http_proxy]) @proxy_host = proxy_uri.host @proxy_port = proxy_uri.port end - capybara_opts[:browser] = capybara_opts[:browser].intern #update :browser value to be a symbol, required for Selenium - selenium_remote_opts[:browser_name] = selenium_remote_opts[:browser_name].intern if selenium_remote_opts[:browser_name]#update :browser value to be a symbol, required for Selenium - - Capybara.run_server = false #Disable rack server - Capybara.ignore_hidden_elements = false - - [capybara_opts, selenium_remote_opts, custom_opts].each do |opts| #delete nil options and environment (which is only used for validation) - - opts.delete_if {|k,v| (v.nil? or k == :environment)} + # update :browser value to be a symbol, required for Selenium + capybara_opts[:browser] = capybara_opts[:browser].intern + # update :browser value to be a symbol, required for Selenium + selenium_remote_opts[:browser_name] = selenium_remote_opts[:browser_name].intern if selenium_remote_opts[:browser_name] + + Capybara.run_server = false # Disable rack server + # delete nil options and environment (which is only used for validation) + [capybara_opts, selenium_remote_opts, custom_opts].each do |opts| + opts.delete_if { |k, v| (v.nil? || k == :environment) } end - case capybara_opts[:browser] + # always register in case we are using a configuration that swaps between drivers + mech_driver = register_mechanize_driver(capybara_opts) + poltergeist_driver = register_poltergeist_driver(capybara_opts) + case capybara_opts[:browser] when :mechanize then - @driver = register_mechanize_driver(capybara_opts) + @driver = mech_driver + when :poltergeist then + @driver = poltergeist_driver else @driver = register_selenium_driver(capybara_opts, selenium_remote_opts, custom_opts) end @@ -74,49 +84,45 @@ def initialize private - def validate_env_vars(opts) - + def validate_env_vars(opts, custom_opts) msg1 = 'Please ensure following environment variables are set ENVIRONMENT [int|test|stage|live], BROWSER[headless|ie|chrome|firefox] and HTTP_PROXY (if required)' msg2 = 'Please ensure the following environment variables are set PLATFORM, REMOTE_URL, REMOTE_BROWSER (browser to use on remote machine), HTTP_PROXY (if required), REMOTE_BROWSER_PROXY (if required) and BROWSER_VERSION (if required)' - [:environment, :browser].each do |item| - !opts.has_key?(item) or opts[item]==nil ? raise(msg1) : '' - end + [:environment, :browser].each { |item| !opts.key?(item) || opts[item].nil? ? raise(msg1) : '' } - if opts[:browser]=='remote' - [:url, :browser_name].each do |item| - !opts.has_key?(item) or opts[item]==nil ? raise(msg2) : '' - end + if custom_opts[:appium_platform] + [:url].each { |item| !opts.key?(item) || opts[item].nil? ? raise(msg2) : '' } + elsif opts[:browser] == 'remote' + [:url, :browser_name].each { |item| !opts.key?(item) || opts[item].nil? ? raise(msg2) : '' } end end # WARNING: This modifies the Firefox profile passed in the parameters def update_firefox_profile_with_certificates(profile, certificate_path, certificate_prefix = '') profile_path = profile.layout_on_disk - + # Create links to the certificate files in the profile directory ['cert8.db', 'key3.db', 'secmod.db'].each do |cert_file| - source_file = "#{certificate_prefix}#{cert_file}" + source_file = '#{certificate_prefix}#{cert_file}' source_path = "#{certificate_path}" + File::SEPARATOR + source_file dest_path = profile_path + File::SEPARATOR + cert_file - if(! File.exist?(source_path)) - raise "Firefox cert db file #{source_path} does not exist." + unless File.exist?(source_path) + raise 'Firefox cert db file #{source_path} does not exist.' end FileUtils.cp(source_path, dest_path) - end + end # Force the certificates to get pulled into the profile profile = Selenium::WebDriver::Firefox::Profile.new(profile_path) # Avoid Firefox certificate alerts - profile["security.default_personal_cert"] = 'Select Automatically' - - return profile + profile['security.default_personal_cert'] = 'Select Automatically' + + # return profile end - def register_selenium_driver(opts,remote_opts,custom_opts) + def register_selenium_driver(opts, remote_opts, custom_opts) Capybara.register_driver :selenium do |app| - if opts[:firefox_prefs] || opts[:profile] opts[:profile] = create_profile(opts[:profile], opts[:firefox_prefs]) @@ -125,7 +131,7 @@ def register_selenium_driver(opts,remote_opts,custom_opts) end end - opts[:switches] = [opts.delete(:chrome_switches)] if(opts[:chrome_switches]) + opts[:switches] = [opts.delete(:chrome_switches)] if opts[:chrome_switches] if opts[:browser] == :remote client = Selenium::WebDriver::Remote::Http::Default.new @@ -134,25 +140,25 @@ def register_selenium_driver(opts,remote_opts,custom_opts) remote_opts[:firefox_profile] = opts.delete :profile if opts[:profile] remote_opts['chrome.switches'] = opts.delete :switches if opts[:switches] caps = Selenium::WebDriver::Remote::Capabilities.new(remote_opts) - - add_custom_caps(caps, custom_opts) if remote_opts[:url].include? 'saucelabs' #set sauce specific parameters - will this scupper other on sauce remote jobs? - - add_browserstack_caps(caps, custom_opts) if remote_opts[:url].include? 'browserstack' #set browserstack specific parameters + # set sauce specific parameters - will this scupper other on sauce remote jobs? + add_custom_caps(caps, custom_opts) if remote_opts[:url].include? 'saucelabs' + # set browserstack specific parameters + add_browserstack_caps(caps, custom_opts) if remote_opts[:url].include? 'browserstack' + # set appium specific parameters + add_appium_caps(caps, custom_opts) if custom_opts.keys.join.include?('appium') opts[:desired_capabilities] = caps opts[:http_client] = client end clean_opts(opts, :http_proxy, :webdriver_proxy_on, :firefox_prefs) - Capybara::Selenium::Driver.new(app,opts) - end + Capybara::Selenium::Driver.new(app, opts) + end :selenium end - def add_custom_caps(caps, custom_opts) - sauce_time_limit = custom_opts.delete(:max_duration).to_i #note nil.to_i == 0 - # This no longer works with the latest selenium-webdriver release - #caps.custom_capabilities({:'job-name' => (custom_opts[:job_name] or 'frameworks-unamed-job'), :'max-duration' => ((sauce_time_limit if sauce_time_limit != 0) or 1800)}) + def add_custom_caps(_caps, custom_opts) + custom_opts.delete(:max_duration).to_i # note nil.to_i == 0 end def add_browserstack_caps(caps, custom_opts) @@ -164,59 +170,86 @@ def add_browserstack_caps(caps, custom_opts) caps[:'resolution'] = custom_opts[:browserstack_resolution] if custom_opts[:browserstack_resolution] end + def add_appium_caps(caps, custom_opts) + caps[:platformName] = custom_opts[:appium_platform] if custom_opts[:appium_platform] + caps[:deviceName] = custom_opts[:appium_device] if custom_opts[:appium_device] + caps[:browserName] = custom_opts[:appium_browser] if custom_opts[:appium_browser] + caps[:udid] = custom_opts[:appium_udid] if custom_opts[:appium_udid] + end + def set_client_proxy(opts) - Selenium::WebDriver::Proxy.new(:http => opts[:http_proxy]) if opts[:http_proxy] && opts[:webdriver_proxy_on] != 'false' #set proxy on client connection if required, note you may use ENV['HTTP_PROXY'] for setting in browser (ff profile) but not for client conection, hence allow for PROXY_ON=false + # set proxy on client connection if required, note you may use ENV['HTTP_PROXY'] for setting in browser (ff profile) but not for client conection, hence allow for PROXY_ON=false + Selenium::WebDriver::Proxy.new(http: opts[:http_proxy]) if opts[:http_proxy] && opts[:webdriver_proxy_on] != 'false' end def create_profile(profile_name = nil, additional_prefs = nil) additional_prefs = JSON.parse(additional_prefs) if additional_prefs - if(additional_prefs && !profile_name) + if additional_prefs && !profile_name profile = Selenium::WebDriver::Firefox::Profile.new - profile.native_events = true - elsif(profile_name == 'BBC_INTERNAL') + elsif profile_name == 'BBC_INTERNAL' profile = Selenium::WebDriver::Firefox::Profile.new - if(@proxy_host && @proxy_port) - profile["network.proxy.type"] = 1 - profile["network.proxy.no_proxies_on"] = "*.sandbox.dev.bbc.co.uk,*.sandbox.bbc.co.uk" - profile["network.proxy.http"] = @proxy_host - profile["network.proxy.ssl"] = @proxy_host - profile["network.proxy.http_port"] = @proxy_port - profile["network.proxy.ssl_port"] = @proxy_port + if @proxy_host && @proxy_port + profile['network.proxy.type'] = 1 + profile['network.proxy.no_proxies_on'] = '*.sandbox.dev.bbc.co.uk,*.sandbox.bbc.co.uk' + profile['network.proxy.http'] = @proxy_host + profile['network.proxy.ssl'] = @proxy_host + profile['network.proxy.http_port'] = @proxy_port + profile['network.proxy.ssl_port'] = @proxy_port end - profile.native_events = true else profile = Selenium::WebDriver::Firefox::Profile.from_name profile_name - profile.native_events = true end + profile.native_events = true if additional_prefs additional_prefs.each do |k, v| profile[k] = v end end - profile end - def register_mechanize_driver(opts) + def register_mechanize_driver(_opts) # Mechanize needs a Rack application: create a dummy one app = Proc.new do |env| - ['200', {'Content-Type' => 'text/html'}, ['A barebones rack app.']] + ['200', { 'Content-Type' => 'text/html' }, ['A barebones rack app.']] end - Capybara.app = app + Capybara.app = app Capybara.run_server = false Capybara.register_driver :mechanize do |app| - Capybara.app_host = "http://www.bbc.co.uk" Capybara::Mechanize::Driver.new(app) end :mechanize end + def register_poltergeist_driver(opts) + # Poltergiest needs a Rack application: create a dummy one + app = Proc.new do + ['200', { 'Content-Type' => 'text/html' }, ['A barebones rack app.']] + end + phantom_opts = %w(--ignore-ssl-errors=true) + phantom_opts.push "--ssl-client-certificate-file=#{ENV['FW_CERT_LOCATION']}" if ENV['FW_CERT_LOCATION'] + phantom_opts.push "--proxy=#{@proxy_host}:#{@proxy_port}" if @proxy_host && @proxy_port + Capybara.app = app + Capybara.run_server = false + options = { + js_errors: false, + timeout: 120, + window_size: [1200, 1000], + phantomjs_options: phantom_opts, + default_wait_time: 30 + } + options[:phantomjs] = ENV['PHANTOMJS_PATH'] if ENV['PHANTOMJS_PATH'] && !ENV['PHANTOMJS_PATH'].empty? + Capybara.register_driver :poltergeist do |app| + Capybara.app_host = 'http://www.bbc.co.uk' + Capybara::Poltergeist::Driver.new(app, options) + end + :poltergeist + end def clean_opts(opts, *args) args.each do |arg| opts.delete arg end end - end diff --git a/lib/frameworks/cucumber.rb b/lib/frameworks/cucumber.rb index 915d125..11118d3 100644 --- a/lib/frameworks/cucumber.rb +++ b/lib/frameworks/cucumber.rb @@ -2,29 +2,30 @@ require 'w3c_validators' module Frameworks + # Generate base urls to use in Cucumber step defs module EnvHelper include W3CValidators - #Generate base urls to use in Cucumber step defs - def generate_base_urls - environment = ENV['ENVIRONMENT'].downcase #be defensive + # Generate base urls to use in Cucumber step defs + def generate_base_urls + environment = ENV['ENVIRONMENT'].downcase # be defensive prepare_host - if(environment =='sandbox') - @base_url = @sandbox + @bbc_domain - @pal_base_url = @sandbox + @bbc_domain + if environment == 'sandbox' + @base_url = @sandbox + @bbc_domain + @pal_base_url = @sandbox + @bbc_domain @ssl_base_url = @sslsandbox + @bbc_domain @static_base_url = @static_sandbox + @bbc_domain - @mobile_base_url = @mobiledot_prefix + "sandbox.dev" + @bbc_domain - @m_base_url = @mdot_prefix + "sandbox.dev" + @bbc_domain - elsif(environment =='sandbox6') - @base_url = @sandbox6 + @bbc_domain - @pal_base_url = @sandbox6 + @bbc_domain + @mobile_base_url = @mobiledot_prefix + 'sandbox.dev' + @bbc_domain + @m_base_url = @mdot_prefix + 'sandbox.dev' + @bbc_domain + elsif environment == 'sandbox6' + @base_url = @sandbox6 + @bbc_domain + @pal_base_url = @sandbox6 + @bbc_domain @ssl_base_url = @sslsandbox6 + @bbc_domain @static_base_url = @static_sandbox6 + @bbc_domain - @mobile_base_url = @mobiledot_prefix + "sandbox" + @bbc_domain - @m_base_url = @mdot_prefix + "sandbox" + @bbc_domain - elsif (environment =='live' && ENV['WWW_LIVE']=='false') + @mobile_base_url = @mobiledot_prefix + 'sandbox' + @bbc_domain + @m_base_url = @mdot_prefix + 'sandbox' + @bbc_domain + elsif environment == 'live' @base_url = @www_prefix.chop + @bbc_domain @pal_base_url = @pal_prefix + environment + @bbc_domain @ssl_base_url = @ssl_prefix.chop + @bbc_domain @@ -43,48 +44,43 @@ def generate_base_urls @m_base_url = @mdot_prefix + environment + @bbc_domain end - proxy = ENV['http_proxy'] || ENV['HTTP_PROXY'] - proxy_parts = proxy.scan(/(?:http:\/\/)?([^\:]+)(?::(\d+))?/) if proxy && !proxy.empty? + proxy = ENV['http_proxy'] || ENV['HTTP_PROXY'] + proxy_parts = proxy.scan(%r{(?:http://)?([^\:]+)(?::(\d+))?}) if proxy && !proxy.empty? if proxy_parts && !proxy_parts.empty? - @proxy_host = proxy_parts[0][0] - if proxy_parts[0][1] - @proxy_port = proxy_parts[0][1] - else - @proxy_port = "80" - end + @proxy_host = proxy_parts[0][0] + @proxy_port = if proxy_parts[0][1] + proxy_parts[0][1] + else + '80' + end end end def validate_online(src, validator_args = nil) - - args = {:proxy_host => @proxy_host,:proxy_port => @proxy_port} - if(validator_args != nil) - args = args.merge(validator_args) - end + args = { proxy_host: @proxy_host, proxy_port: @proxy_port } + args = args.merge(validator_args) unless validator_args.nil? @validator = MarkupValidator.new(args) @validator.set_doctype!(:xhtml) begin - results = @validator.validate_text(src) - if results.errors.length > 0 + unless results.errors.empty? results.errors.each do |err| puts err.to_s end - raise "W3C Validation failed." + raise 'W3C Validation failed.' end - rescue SystemCallError => e - puts "System error whilst performing request to W3C: #{e}" + puts "System error whilst performing request to W3C: #{e}" end end def prepare_host - ENV['SCHEME']=='https' ? scheme = 'https' : scheme = 'http' + scheme = ENV['SCHEME'] == 'https' ? 'https' : 'http' @www_prefix = "#{scheme}://www." @pal_prefix = "#{scheme}://pal." - @ssl_prefix = "https://ssl." + @ssl_prefix = 'https://ssl.' @static_prefix = "#{scheme}://static." @open_prefix = "#{scheme}://open." @bbc_domain = '.' + (ENV['FW_BBC_DOMAIN'] || 'bbc.co.uk') @@ -93,57 +89,55 @@ def prepare_host @sandbox6 = "#{scheme}://sandbox" @mobiledot_prefix = "#{scheme}://mobile." @mdot_prefix = "#{scheme}://m." - @sslsandbox = "https://ssl.sandbox.dev" - @sslsandbox6 = "https://ssl.sandbox" + @sslsandbox = 'https://ssl.sandbox.dev' + @sslsandbox6 = 'https://ssl.sandbox' @static_sandbox = "#{scheme}://static.sandbox.dev" - @static_sandbox6 = "#{scheme}://static.sandbox" + @static_sandbox6 = "#{scheme}://static.sandbox" end - def setup_mechanize(agent, http_proxy=nil) + def setup_mechanize(agent, http_proxy = nil) http_proxy = http_proxy || ENV['HTTP_PROXY'] || ENV['http_proxy'] if ENV['FW_CERT_LOCATION'] - agent.cert, agent.key = ENV['FW_CERT_LOCATION'], ENV['FW_CERT_LOCATION'] + agent.cert = ENV['FW_CERT_LOCATION'] + agent.key = ENV['FW_CERT_LOCATION'] end agent.ca_file = ENV['CA_CERT_LOCATION'] if ENV['CA_CERT_LOCATION'] - agent.set_proxy(http_proxy.scan(/http:\/\/(.*):80/)[0][0].to_s,80) if http_proxy && !http_proxy.empty? + agent.set_proxy(http_proxy.scan(%r{http://(.*):80})[0][0].to_s, 80) if http_proxy && !http_proxy.empty? # The above proxy setting ignores any no_proxy variable setting: # added the following to circumvent this - if(http_proxy) + if http_proxy no_proxy = ENV['NO_PROXY'] || ENV['no_proxy'] - if(no_proxy) + if no_proxy # The no_proxy query string argument must not contain spaces - no_proxy_qs = no_proxy.gsub(/[, ]+/,',') + no_proxy_qs = no_proxy.gsub(/[, ]+/, ',') agent.agent.http.proxy = URI(http_proxy + '?no_proxy=' + no_proxy_qs) end end - #This is necessary because Mech2 does not ship with root certs like Mech1 did and boxes may not have the OpenSSL set installed + # This is necessary because Mech2 does not ship with root certs like Mech1 did and boxes may not have the OpenSSL set installed agent.verify_mode = OpenSSL::SSL::VERIFY_NONE # This prevents Mechanize from raising a Mechanize::ResponseCodeError # when the HTTP Response Code is 404 or 503. This lets capybara continue the journey. - agent.agent.allowed_error_codes = ['404', '503'] + agent.agent.allowed_error_codes = %w(404 503) end - def new_mechanize(http_proxy=nil) + def new_mechanize(http_proxy = nil) require 'mechanize' agent = Mechanize.new setup_mechanize(agent, http_proxy) agent end + end # EnvHelper +end # Frameworks - end #EnvHelper -end #Frameworks - - -#Add module into world to ensure visibility of instance variables within Cucumber +# Add module into world to ensure visibility of instance variables within Cucumber World(Frameworks::EnvHelper) Before do setup_mechanize(page.driver.browser.agent) if page.driver.class == Capybara::Mechanize::Driver generate_base_urls end - diff --git a/lib/frameworks/extensions/patches.rb b/lib/frameworks/extensions/patches.rb new file mode 100644 index 0000000..ae29935 --- /dev/null +++ b/lib/frameworks/extensions/patches.rb @@ -0,0 +1,37 @@ +require 'show_me_the_cookies' +require 'capybara' +require 'frameworks/logger' + +# monkey patches live here - beware! +module Capybara + # override behaviour of visit to surpress bbc survey + class Session + include ShowMeTheCookies + include FrameworksCapybara::Logger + + alias old_visit visit + def visit(url) + Capybara.current_driver + old_visit url + return if [:mechanize, :poltergeist].include?(Capybara.current_driver) + surpress_cookies_prompt + # reload_if_survey_appears + end + + def surpress_cookies_prompt + create_cookie('ckns_policy_exp', '9999999999999') + create_cookie('ckns_policy', '111') + end + + def reload_if_survey_appears + reload = false + within_frame('edr_l_first') do + if has_selector?('#layer_wrap', wait: 1) + log.info 'Found survey, will now reload the page' + reload = true + end + end + visit current_url if reload + end + end +end diff --git a/lib/frameworks/logger.rb b/lib/frameworks/logger.rb new file mode 100644 index 0000000..813ef5f --- /dev/null +++ b/lib/frameworks/logger.rb @@ -0,0 +1,42 @@ +require 'logging' + +module FrameworksCapybara + # configure logging + module Logger + def log_level + log_levels = %w[warn info debug] + env_log_level = (ENV['LOG_LEVEL'] || '').downcase + log_levels.include?(env_log_level) ? env_log_level.to_sym : :debug + end + + def log + Logging.appenders.stdout( + 'stdout', + layout: Logging.layouts.pattern(pattern: '[%d] %-7l %c: %m\n', color_scheme: default_style) + ) + # rubocop:disable Style/GlobalVars + # global log acceptable + $log ||= new_log + # rubocop:enable Style/GlobalVars + end + + def default_style + scheme = 'pldefault' + Logging.color_scheme( + scheme, + levels: { info: :green, warn: :yellow, error: :red }, + date: :cyan, + logger: :cyan, + message: :cyan + ) + scheme + end + + def new_log + log = Logging.logger['Color::Log'] + log.add_appenders 'stdout' + log.level = :info + log + end + end +end diff --git a/lib/frameworks/utils.rb b/lib/frameworks/utils.rb new file mode 100644 index 0000000..002c873 --- /dev/null +++ b/lib/frameworks/utils.rb @@ -0,0 +1,135 @@ +# generic util methods +module FrameworksCapybara + # generic util methods + module Utils + def rubyize(english_string) + english_string.tr(' ', '_').downcase + end + + def loweralpha(str) + str.downcase.scan(/[a-z]/).join + end + + def clean_id_cookies + Capybara.current_session.delete_cookie 'IDENTITIY' + Capybara.current_session.delete_cookie 'IDENTITIY_ENV' + end + + def set_cookie_for_uk + page.execute_script 'document.cookie="ckns_orb_fig_cache={%22uk%22:1%2C%22ck%22:1%2C%22ad%22:0%2C%22ap%22:0%2C%22tb%22:0%2C%22mb%22:0%2C%22eu%22:1}; path=/; domain=.bbc.co.uk";' + visit current_url + end + + def browser + if Capybara.current_driver == :selenium + Capybara.current_session.driver.browser.manage + .instance_variable_get('@bridge') + .instance_variable_get('@capabilities')[:browser_name] + else + Capybara.current_driver + end + end + + def check_expected_page_items(page, table) + table.raw.flatten.each do |table_item| + page_method = "have_#{rubyize(table_item)}" + expect(page).to send page_method + end + end + + def check_expected_link_text(parent_body, table) + table.raw.flatten.each do |link_text| + expect(parent_body.has_link?(link_text)).to eq true + end + end + + def check_expected_section_items(sections, table) + sections.each do |section| + table.raw.flatten.each do |section_item| + section_method = "have_#{rubyize(section_item)}" + expect(section).to send(section_method) unless section_item.include? '(optional)' + end + end + end + + def check_expected_section_item(section, table) + table.raw.flatten.each do |section_item| + section_method = "have_#{rubyize(section_item)}" + expect(section).to send(section_method) unless section_item.include? '(optional)' + end + end + + def check_expected_section_translation(section, table) + table.rows_hash.each do |key, value| + element = key.downcase.tr(' ', '_').tr(',', '') + expect(section.send(element).text).to eql value + end + end + + def check_expected_element_translation(page, table) + table.rows_hash.each do |key, value| + element = key.downcase.tr(' ', '_').tr(',', '') + expect(page.send(element).text).to eql value + end + end + + def check_expected_section_translation_includes(page, table) + table.rows_hash.each do |key, value| + element = key.downcase.tr(' ', '_').tr(',', '') + expect(page.send(element).text).to include value + end + end + + def switch_to_last_opened_window + Capybara.page.switch_to_window(Capybara.page.windows.last) + Capybara.page.windows.first.close + end + + def wait_until_page_is_fully_loaded + Timeout.timeout(Capybara.default_max_wait_time) do + loop until (value = Capybara.page.evaluate_script('document.readyState').eql?('complete')) + value + end + end + + def scroll_to_element(element) + page.execute_script("arguments[0].scrollIntoView(true);", element) + end + + def save_and_link_screenshot + FileUtils.mkdir_p('reports') unless File.directory?('reports') + current_time = Time.new.strftime('%Y-%m-%d-%H-%M-%S') + Capybara.current_session.driver.save_screenshot("./reports/Screenshot_#{current_time}.png") + embed "./reports/Screenshot_#{current_time}.png", 'image/png', "Actual screenshot of the error at #{current_url}" + end + + def get_console_logs(type) + case type + when 'errors' + errors = page.driver.browser.manage.logs.get(:browser).select {|e| e.level == "SEVERE"}.map(&:message).to_a + if errors.present? + puts "Below are the errors found." + raise StandardError, errors.join("\n\n") + else + puts "No Error found in console" + end + when 'warnings' + warnings = page.driver.browser.manage.logs.get(:browser).select {|e| e.level != "SEVERE"}.map(&:message).to_a + if warnings.present? + puts "Below are the warnings found." + raise StandardError, warnings.join("\n\n") + else + puts "No warnings found in console" + end + when 'errors_and_warnings' + errors = page.driver.browser.manage.logs.get(:browser).map(&:message).join("\n\n") + if errors.present? + puts "Below are the errors/warnings found." + raise StandardError, errors + else + puts "No Error/warnings found in console" + end + end + end + end +end diff --git a/lib/frameworks/wait.rb b/lib/frameworks/wait.rb index 5b4b97f..3b6e59c 100644 --- a/lib/frameworks/wait.rb +++ b/lib/frameworks/wait.rb @@ -1,25 +1,74 @@ require 'time' -class Wait - ## - # Execute a block until it returns true. - # Optionally pass a timeout (by default 5 seconds). - # - # wait = Wait.new - # wait.until { - # (Random.rand(2) % 2) - # } - # - # wait.until(:timeout => 4) { - # (Random.rand(2) % 2) - # } - # - def Wait.until(options={:timeout => 5}) - timeout = Time.new + options[:timeout].to_f +module FrameworksCapybara + # wait for elements methods + module Wait + # Execute a block until it returns true. + # Optionally pass a message and timeout (default 10 seconds). + # + # wait_for('checking divide by 2', timeout: 5) { (Random.rand(2) % 2) } + # + def wait_for(message = '', options = { timeout: 5 }) + Timeout.timeout(options[:timeout]) do + puts "In wait helper message is: #{message}" + sleep 1 until yield + end + end + + # Execute a block containing RSpec assertion, catch failures and wait till it passes + # Pass an exception message to be outputted on failure and a block + # Optionally pass a timeout, sleep interval + # + # wait_for_assertion('Cannot find foo on page') do + # expect(page).to have_content 'foo' + # end + # + def wait_for_assertion(exception_message, timeout = Capybara.default_max_wait_time, sleep_interval = 0.5, &block) + wait_for_no_exception(exception_message, + RSpec::Expectations::ExpectationNotMetError, + timeout, sleep_interval, &block) + end - while (Time.new < timeout) - return if (yield) + ## + # Execute a block and catch a specific exception until timeout or no exception + # Pass an exception message to be outputted on failure and a block + # Optionally pass a timeout, sleep interval + # + # wait_for_no_exception('Author image not visible', SitePrism::TimeOutWaitingForElementVisibility) do + # article.wait_until_author_image_visible + # end + # + def wait_for_no_exception(exception_message, exception, timeout = Capybara.default_max_wait_time, sleep_interval = 1, &block) + raise 'You need to provide a block' unless block_given? + test_exception = 'check did not return within timeout window.' + begin + Timeout.timeout(timeout) do + loop do + begin + yield + return true + rescue exception => assertion_exception + puts "#{exception_message} - rescuing: #{exception.to_s} and trying to call block again!" + test_exception = assertion_exception + sleep sleep_interval + end + end + end + rescue Timeout::Error + puts '********************************************************************' + puts "Timed out after waiting for #{timeout} seconds." + puts exception_message + puts "#{test_exception}" + puts '********************************************************************' + raise test_exception + rescue => standard_error + puts '********************************************************************' + puts "Got an unexpected exception type: #{standard_error.class}" + puts "#{standard_error}" + puts 'Check your code for puts!' + puts '********************************************************************' + raise standard_error + end end - raise 'Timeout exceeded for wait until.' end -end \ No newline at end of file +end diff --git a/lib/tasks/confluence.erb b/lib/tasks/confluence.erb new file mode 100644 index 0000000..0ae79c4 --- /dev/null +++ b/lib/tasks/confluence.erb @@ -0,0 +1 @@ +
diff --git a/lib/tasks/frameworks-tasks.rb b/lib/tasks/frameworks-tasks.rb index 14296c4..e9832c2 100644 --- a/lib/tasks/frameworks-tasks.rb +++ b/lib/tasks/frameworks-tasks.rb @@ -1,13 +1,14 @@ +# Rake Tasks class RakeHelpers - INVOKE_CUCUMBER = "bin/cucumber -r features" + INVOKE_CUCUMBER = 'bin/cucumber -r features'.freeze class << self def install - system('bundle install --no-cache --binstubs --path vendor/bundle') + system('bundle install --no-cache --binstubs --path vendor/bundle') end def color(text, options = {}) - #ANSI color codes + # ANSI color codes case options[:color] when :red text = "\033[31m#{text}\033[0m" @@ -20,54 +21,53 @@ def color(text, options = {}) end def list_profiles - puts 'Available profiles:' + puts 'Available profiles:' f = File.open('config/cucumber.yml', 'r') linenum = 0 @profiles = {} f.readlines.each do |line| line.scan(/.*?: /) do |match| linenum += 1 - puts color(linenum.to_s + '. ', :color => :yellow) + color(match.gsub(':',''), :color => :green) - @profiles[linenum.to_s] = match.gsub(':','') + puts color(linenum.to_s + '. ', color: yellow) + color(match.delete(':', ''), color: green) + @profiles[linenum.to_s] = match.delete(':', '') end end end def update - system('bundle update') + system('bundle update') end - def run_feature(feature, profile='default') + def run_feature(feature, profile = 'default') system("#{INVOKE_CUCUMBER} -p #{profile} features/#{feature}.feature") end - def run_profile(profile='default') + def run_profile(profile = 'default') system("#{INVOKE_CUCUMBER} -p #{profile}") end - def start_app - $: << File.dirname( __FILE__) + $LOAD_PATH << File.dirname(__FILE__) require 'lib/spec/test_app' - Rack::Handler::WEBrick.run TestApp, :Port => 8070 + Rack::Handler::WEBrick.run TestApp, Port: 8070 end def run_local - if(RUBY_PLATFORM == 'java') - abort color("This script only works if you are running on MRI ('normal') Ruby....sorry....", :color => :red) + if RUBY_PLATFORM == 'java' + abort color("This script only works if you are running on MRI ('normal') Ruby....sorry....", color: red) end - puts color('*********************************************',:color => :green) - puts color('* *',:color => :green) - puts color('* Cucumber Acceptance Tests *',:color => :green) - puts color('* Pre-Requisites: *',:color => :green) - puts color('* ruby 1.8.7, bundler, rake *',:color => :green) - puts color('* *',:color => :green) - puts color('*********************************************',:color => :green) + puts color('*********************************************', color: green) + puts color('* *', color: green) + puts color('* Cucumber Acceptance Tests *', color: green) + puts color('* Pre-Requisites: *', color: green) + puts color('* ruby 1.8.7, bundler, rake *', color: green) + puts color('* *', color: green) + puts color('*********************************************', color: green) list_profiles puts 'Above is a list of the available profiles, please enter the number of the profile you wish to run: ' profile = STDIN.gets.chomp - #TODO: Add some input validation? - puts "The profile chosen is: #{color(@profiles[profile], :color => :red)}" + # TODO: Add some input validation? + puts "The profile chosen is: #{color(@profiles[profile], color: red)}" puts 'Preparing to bundle required gems...' install puts 'Preparing to run tests...' diff --git a/lib/tasks/merge_cucumber_json_reports.rb b/lib/tasks/merge_cucumber_json_reports.rb new file mode 100644 index 0000000..4e74eb1 --- /dev/null +++ b/lib/tasks/merge_cucumber_json_reports.rb @@ -0,0 +1,84 @@ +require 'json' + +# class to merge cucumber json report +class CucumberJSONMerger + attr_reader :master + + def initialize + @reports = Dir.glob('reports/report*.json').map { |f| JSON.parse(File.read(f)) } + @master = @reports.shift + end + + def run + @reports.each do |report| + report.each do |feature| + fname = feature.fetch 'uri' + update(fname, feature, report) + end + end + end + + def update(fname, feature, report) + if feature_exists? fname + scenarios(report, fname).each do |scenario| + sname = scenario.fetch 'name' + sline = scenario.fetch 'line' + scenario_exists?(sname, fname) ? replace_scenario(sname, sline, scenario, fname) : append_scenario(scenario, fname) + end + else + append_feature feature + end + end + + def rerun + puts 'Processing rerun json' + json_rerun = Dir.glob 'reports/rerun.json' + if json_rerun.empty? + puts 'no rerun file found' + else + @reports = [JSON.parse(File.read('reports/rerun.json'))] + run + end + end + + private + + def feature_names(report) + report.map { |f| f['uri'] } + end + + def scenario_names(report, fname) + scenarios(report, fname).map { |s| s['name'] } + end + + def scenarios(report, fname) + report.find { |f| f['uri'] == fname }['elements'].select { |e| e['keyword'].include? 'Scenario' }.flatten + end + + def feature_exists?(name) + feature_names(@master).include? name + end + + def scenario_exists?(scenario, fname) + scenario_names(@master, fname).include? scenario + end + + def replace_scenario(sname, sline, scenario, feature) + @master.find { |f| f['uri'] == feature }['elements'].delete_if do |e| + exists = e['keyword'].include?('Scenario') && e['name'] == sname && e['line'] == sline + puts "Replacing #{sname} on line #{sline} in #{feature} in master" if exists + exists + end + append_scenario(scenario, feature) + end + + def append_scenario(scenario, feature) + puts "Need to append SCENARIO: #{scenario['name']} to FEATURE: #{feature} in master" + @master.find { |f| f['uri'] == feature }['elements'] << scenario + end + + def append_feature(feature) + puts "Need to append FEATURE: '#{feature['name']}' in master" + @master.push feature + end +end diff --git a/lib/tasks/parallel-tasks.rb b/lib/tasks/parallel-tasks.rb new file mode 100644 index 0000000..1632126 --- /dev/null +++ b/lib/tasks/parallel-tasks.rb @@ -0,0 +1,144 @@ +# parallel tasks +class ParallelTasks + include Rake::DSL if defined? Rake::DSL + + def install_tasks + require 'bundler/setup' + require 'parallel' + require 'rspec/core/rake_task' + require 'rubocop/rake_task' + require 'cucumber/rake/task' + require 'yard' + require_relative 'merge_cucumber_json_reports' + + def run_rake_task(name) + puts "name is #{name}" + begin + Rake::Task[name].invoke + rescue Exception => e + puts "Exception running rake task: #{e}" + return false + end + true + end + + def reports(name) + "--format pretty --format junit --out=reports/junit_#{name} --strict --format html " \ + "--out=reports/#{name}.html --format json --out=reports/#{name}.json" + end + + def bundle_exec + ENV['BUNDLE_EXEC'] || 'bundle exec ' + end + + def env + ENV['ENVIRONMENT'] ? "ENVIRONMENT=#{ENV['ENVIRONMENT']}" : 'ENVIRONMENT=live' + end + + def tags + ENV['TAGS'] || '' + end + + def features_dir + ENV['FEATURES_DIR'] || 'features' + end + + def get_thread_count + ENV['THREAD_COUNT'] ? ENV['THREAD_COUNT'].to_i : 2 + end + + def write_confluence_report(passfail) + require 'erb' + green = '#4CD672' + red = '#EA4D61' + template = File.read(File.dirname(__FILE__) + '/confluence.erb') + @result = passfail == 'pass' ? green : red + File.open('reports/confluence.html', 'w+').puts ERB.new(template).result(binding) + end + + desc 'Run all examples' + RSpec::Core::RakeTask.new(:spec) do |t| + t.rspec_opts = %w(--color -fprogress -fhtml -oreports/rspec.html) + end + + desc 'Create some docs' + YARD::Rake::YardocTask.new do |t| + t.files = ['lib/**/*.rb'] + t.options = %w(--markup=markdown) + end + + desc 'Feature documentation' + YARD::Rake::YardocTask.new(:yarddoc) do |t| + t.files = ['features/*.feature', 'features/**/*.rb'] + end + + desc 'Make sure we are good rubyists' + RuboCop::RakeTask.new(:rubocop) do |t| + t.formatters = ['progress'] + t.options = ['-fhtml', '-oreports/rubocop.html'] + # don't abort rake on failure + t.fail_on_error = false + end + + desc 'Run cukes on production in parallel with browserstack chrome' + task :parallel_cuke do + sh "#{bundle_exec}parallel_cucumber -n #{get_thread_count} -o '#{tags} #{env}' #{features_dir}" + end + + desc 'Rerun failed cukes on production with browserstack chrome' + task :rerun do + sh "#{bundle_exec}cucumber -p rerun #{env} @reports/rerun.txt #{reports('rerun')}" + end + + desc 'Run selenium and rerun failed tests' + task :tests_with_retry do + selenium_successful = run_rake_task('parallel_cuke') + rerun_successful = true + rerun_successful = run_rake_task('rerun') unless selenium_successful + result = (selenium_successful || rerun_successful) == true ? 'pass' : 'fail' + puts "Overall result is #{result}" + write_confluence_report(result) + raise 'Cucumber Failure' if result == 'fail' + end + + desc 'Remove all files from the ./reports and ./doc directory' + task :clean do + require 'fileutils' + FileUtils.rm_rf Dir.glob('reports/*') + FileUtils.rm_rf Dir.glob('doc/*') + end + + desc 'Use Junit Merge to merge results from multiple threads' + task :junit_merge do + require 'fileutils' + + report_dir = 'reports' + junit_dir = "#{report_dir}/junit_results" + + (2..get_thread_count).each do |thread| + original_reports = Dir.entries junit_dir + thread_reports = Dir.entries "#{junit_dir}#{thread}" + thread_reports.reject { |f| File.directory?(f) }.each do |report| + if original_reports.include?(report) + sh "#{bundle_exec}junit_merge #{junit_dir}#{thread}/#{report} #{junit_dir}/#{report}" + else + puts "copy #{junit_dir}#{thread}/#{report} to #{junit_dir}" + FileUtils.cp "#{junit_dir}#{thread}/#{report}", junit_dir + end + end + end + junit_rerun = Dir.glob "#{report_dir}/junit_rerun/*xml" + sh "#{bundle_exec}junit_merge #{report_dir}/junit_rerun #{junit_dir}" unless junit_rerun.empty? + end + + desc 'Merge Cucumber JSON reports' + task :json_merge do + c = CucumberJSONMerger.new + c.run + c.rerun + File.open('combined.json', 'w+').write c.master.to_json + end + end +end + +ParallelTasks.new.install_tasks diff --git a/lib/version.rb b/lib/version.rb index 95020c5..4514fc7 100644 --- a/lib/version.rb +++ b/lib/version.rb @@ -1,3 +1,3 @@ module FrameworksCapybara - VERSION = '2.3.1' + VERSION = '3.0.0'.freeze end diff --git a/spec/frameworks_capybara_spec.rb b/spec/frameworks_capybara_spec.rb old mode 100644 new mode 100755 index e310dec..97416e1 --- a/spec/frameworks_capybara_spec.rb +++ b/spec/frameworks_capybara_spec.rb @@ -1,12 +1,12 @@ require 'spec_helper' require 'securerandom' -## -#Monkey Patch -#This is required because Capybara has module methods (singletons) which create -#a session and then re-use this whenever Capybara is referenced in the current process. -#Therefore even creating new instances of CapybaraSetup will use the same session and driver instance -#...not picking up changes in the different tests below. -#Hence the only option is to clean out the session before each test. + +# Monkey Patch +# This is required because Capybara has module methods (singletons) which create +# a session and then re-use this whenever Capybara is referenced in the current process. +# Therefore even creating new instances of CapybaraSetup will use the same session and driver instance +# not picking up changes in the different tests below. +# Hence the only option is to clean out the session before each test. module Capybara class << self def delete_session @@ -15,105 +15,104 @@ def delete_session end end -shared_examples_for "Selenium Driver Options Array" do - it "should contain no nil values for unset options" do - #TODO: Test for nil elements in options - there shouldn't be any that we insert - #i.e. anything in our ENV options should not end up being nil in Selenium - Capybara.current_session.driver.options[:environment].should == nil - Capybara.current_session.driver.options[:http_proxy].should == nil - Capybara.current_session.driver.options[:webdriver_proxy_on].should == nil - Capybara.current_session.driver.options[:platform].should == nil - Capybara.current_session.driver.options[:browser_name].should == nil - Capybara.current_session.driver.options[:version].should == nil - Capybara.current_session.driver.options[:job_name].should == nil - Capybara.current_session.driver.options[:chrome_switches].should == nil - Capybara.current_session.driver.options[:firefox_prefs].should == nil - Capybara.current_session.driver.options[:max_duration].should == nil +shared_examples_for 'Selenium Driver Options Array' do + it 'should contain no nil values for unset options' do + # TODO: Test for nil elements in options - there shouldn't be any that we insert + # i.e. anything in our ENV options should not end up being nil in Selenium + Capybara.current_session.driver.options[:environment].should eq nil + Capybara.current_session.driver.options[:http_proxy].should eq nil + Capybara.current_session.driver.options[:webdriver_proxy_on].should eq nil + Capybara.current_session.driver.options[:platform].should eq nil + Capybara.current_session.driver.options[:browser_name].should eq nil + Capybara.current_session.driver.options[:version].should eq nil + Capybara.current_session.driver.options[:job_name].should eq nil + Capybara.current_session.driver.options[:chrome_switches].should eq nil + Capybara.current_session.driver.options[:firefox_prefs].should eq nil + Capybara.current_session.driver.options[:max_duration].should eq nil Capybara.current_session.driver.options[:profile].should_not be_a_kind_of String Capybara.current_session.driver.options[:browser].should_not be_a_kind_of String end end describe CapybaraSetup do - before(:each) do home = ENV['HOME'] appdata = ENV['APPDATA'] ENV.clear - ENV['HOME'] = home #Want to clear some env variables but HOME is used by Webdriver, therefore need to preserve it + ENV['HOME'] = home # Want to clear some env variables but HOME is used by Webdriver, therefore need to preserve it ENV['APPDATA'] = appdata end - describe "should validate options" do + describe 'should validate options' do before(:each) do Capybara.delete_session end - it "should require as a minimum ENVIRONMENT and BROWSER" do - lambda {CapybaraSetup.new}.should raise_error(RuntimeError,'Please ensure following environment variables are set ENVIRONMENT [int|test|stage|live], BROWSER[headless|ie|chrome|firefox] and HTTP_PROXY (if required)') + it 'should require as a minimum ENVIRONMENT and BROWSER' do + lambda { CapybaraSetup.new }.should raise_error(RuntimeError, 'Please ensure following environment variables are set ENVIRONMENT [int|test|stage|live], BROWSER[headless|ie|chrome|firefox] and HTTP_PROXY (if required)') end - it "should require as a minimum ENVIRONMENT, BROWSER and REMOTE_BROWSER if running a Remote Selenium Instance" do + it 'should require as a minimum ENVIRONMENT, BROWSER and REMOTE_BROWSER if running a Remote Selenium Instance' do ENV['BROWSER'] = 'remote' ENV['ENVIRONMENT'] = 'test' - lambda {CapybaraSetup.new}.should raise_error(RuntimeError,'Please ensure the following environment variables are set PLATFORM, REMOTE_URL, REMOTE_BROWSER (browser to use on remote machine), HTTP_PROXY (if required), REMOTE_BROWSER_PROXY (if required) and BROWSER_VERSION (if required)') + lambda { CapybaraSetup.new }.should raise_error(RuntimeError, 'Please ensure the following environment variables are set PLATFORM, REMOTE_URL, REMOTE_BROWSER (browser to use on remote machine), HTTP_PROXY (if required), REMOTE_BROWSER_PROXY (if required) and BROWSER_VERSION (if required)') end - it "should not error if ENVIRONMENT and BROWSER are provided" do + it 'should not error if ENVIRONMENT and BROWSER are provided' do ENV['BROWSER'] = 'headless' ENV['ENVIRONMENT'] = 'test' - lambda {CapybaraSetup.new}.should_not raise_error + lambda { CapybaraSetup.new }.should_not raise_error end - it "should not error if ENVIRONMENT, BROWSER and REMOTE_BROSWER are provided if running a Remote Selenium Instance" do + it 'should not error if ENVIRONMENT, BROWSER and REMOTE_BROSWER are provided if running a Remote Selenium Instance' do ENV['BROWSER'] = 'remote' ENV['ENVIRONMENT'] = 'test' ENV['REMOTE_BROWSER'] = 'test' ENV['REMOTE_URL'] = 'test' - lambda {CapybaraSetup.new}.should_not raise_error + lambda { CapybaraSetup.new }.should_not raise_error end end - describe "should allow Capybara drivers to be created" do + describe 'should allow Capybara drivers to be created' do before do ENV['ENVIRONMENT'] = 'test' end - describe "should allow Selenium driver to be created" do - context "with minimal Selenium driver" do + describe 'should allow Selenium driver to be created' do + context 'with minimal Selenium driver' do before do ENV['BROWSER'] = 'firefox' end - it "should be initialized correctly" do + it 'should be initialized correctly' do Capybara.delete_session - CapybaraSetup.new.driver.should == :selenium + CapybaraSetup.new.driver.should eq :selenium Capybara.current_session.driver.should be_a_kind_of Capybara::Selenium::Driver - Capybara.current_session.driver.options[:browser].should == :firefox + Capybara.current_session.driver.options[:browser].should eq :firefox end - it_behaves_like "Selenium Driver Options Array" + it_behaves_like 'Selenium Driver Options Array' end - context "with no command-line arguments supplied" do + context 'with no command-line arguments supplied' do before do ENV['BROWSER'] = 'phantomjs' end - it "should be initialized correctly" do + it 'should be initialized correctly' do Capybara.delete_session expect(CapybaraSetup.new.driver).to eq :selenium expect(Capybara.current_session.driver.options[:args]).to be nil end end - context "with single command-line argument supplied" do + context 'with single command-line argument supplied' do before do ENV['BROWSER'] = 'phantomjs' ENV['BROWSER_CLI_ARGS'] = '--ignore-ssl-errors=true' end - it "should be initialized correctly" do + it 'should be initialized correctly' do Capybara.delete_session expect(CapybaraSetup.new.driver).to eq :selenium args = Capybara.current_session.driver.options[:args] @@ -123,13 +122,13 @@ def delete_session end end - context "with multiple command-line arguments supplied" do + context 'with multiple command-line arguments supplied' do before do ENV['BROWSER'] = 'phantomjs' ENV['BROWSER_CLI_ARGS'] = '--ignore-ssl-errors=true --remote-debugger-port=9000' end - it "should be initialized correctly" do + it 'should be initialized correctly' do Capybara.delete_session expect(CapybaraSetup.new.driver).to eq :selenium args = Capybara.current_session.driver.options[:args] @@ -140,25 +139,24 @@ def delete_session end end - context "with Selenium driver and default firefox profile (from profiles.ini)" do + context 'with Selenium driver and default firefox profile (from profiles.ini)' do before do ENV['BROWSER'] = 'firefox' ENV['FIREFOX_PROFILE'] = 'default' end - it "should be initialized correctly" do + it 'should be initialized correctly' do Capybara.delete_session - CapybaraSetup.new.driver.should == :selenium + CapybaraSetup.new.driver.should eq :selenium Capybara.current_session.driver.should be_a_kind_of Capybara::Selenium::Driver - Capybara.current_session.driver.options[:browser].should == :firefox + Capybara.current_session.driver.options[:browser].should eq :firefox Capybara.current_session.driver.options[:profile].should be_a_kind_of Selenium::WebDriver::Firefox::Profile - Capybara.current_session.driver.options[:profile].instance_variable_get(:@model).should include "default" + Capybara.current_session.driver.options[:profile].instance_variable_get(:@model).should include 'default' end - it_behaves_like "Selenium Driver Options Array" - + it_behaves_like 'Selenium Driver Options Array' end - context "with Selenium driver and programtically created profile" do + context 'with Selenium driver and programtically created profile' do before do ENV['BROWSER'] = 'firefox' ENV['FIREFOX_PROFILE'] = 'BBC_INTERNAL' @@ -166,40 +164,39 @@ def delete_session ENV['PROXY_ON'] = 'false' end - it "should be initialized correctly" do + it 'should be initialized correctly' do Capybara.delete_session - CapybaraSetup.new.driver.should == :selenium + CapybaraSetup.new.driver.should eq :selenium Capybara.current_session.driver.should be_a_kind_of Capybara::Selenium::Driver - Capybara.current_session.driver.options[:browser].should == :firefox + Capybara.current_session.driver.options[:browser].should eq :firefox Capybara.current_session.driver.options[:profile].should be_a_kind_of Selenium::WebDriver::Firefox::Profile - Capybara.current_session.driver.options[:profile].instance_variable_get(:@additional_prefs)['network.proxy.type'].should == 1 - Capybara.current_session.driver.options[:profile].instance_variable_get(:@additional_prefs)['network.proxy.no_proxies_on'].should == '*.sandbox.dev.bbc.co.uk,*.sandbox.bbc.co.uk' - Capybara.current_session.driver.options[:profile].instance_variable_get(:@additional_prefs)['network.proxy.http'].should == 'example.cache.co.uk' - Capybara.current_session.driver.options[:profile].instance_variable_get(:@additional_prefs)['network.proxy.http_port'].should == 80 - Capybara.current_session.driver.options[:profile].instance_variable_get(:@additional_prefs)['network.proxy.ssl'].should == 'example.cache.co.uk' - Capybara.current_session.driver.options[:profile].instance_variable_get(:@additional_prefs)['network.proxy.ssl_port'].should == 80 - end - it_behaves_like "Selenium Driver Options Array" + Capybara.current_session.driver.options[:profile].instance_variable_get(:@additional_prefs)['network.proxy.type'].should eq 1 + Capybara.current_session.driver.options[:profile].instance_variable_get(:@additional_prefs)['network.proxy.no_proxies_on'].should eq '*.sandbox.dev.bbc.co.uk,*.sandbox.bbc.co.uk' + Capybara.current_session.driver.options[:profile].instance_variable_get(:@additional_prefs)['network.proxy.http'].should eq 'example.cache.co.uk' + Capybara.current_session.driver.options[:profile].instance_variable_get(:@additional_prefs)['network.proxy.http_port'].should eq 80 + Capybara.current_session.driver.options[:profile].instance_variable_get(:@additional_prefs)['network.proxy.ssl'].should eq 'example.cache.co.uk' + Capybara.current_session.driver.options[:profile].instance_variable_get(:@additional_prefs)['network.proxy.ssl_port'].should eq 80 + end + it_behaves_like 'Selenium Driver Options Array' end - context "with Selenium driver and custom chrome options" do + context 'with Selenium driver and custom chrome options' do before do ENV['BROWSER'] = 'chrome' ENV['CHROME_SWITCHES'] = '--user-agent=Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10' end - it "should be initialized correctly" do + it 'should be initialized correctly' do Capybara.delete_session - CapybaraSetup.new.driver.should == :selenium + CapybaraSetup.new.driver.should eq :selenium Capybara.current_session.driver.should be_a_kind_of Capybara::Selenium::Driver - Capybara.current_session.driver.options[:browser].should == :chrome - Capybara.current_session.driver.options[:switches].should == ['--user-agent=Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10'] + Capybara.current_session.driver.options[:browser].should eq :chrome + Capybara.current_session.driver.options[:switches].should eq ['--user-agent=Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10'] end - it_behaves_like "Selenium Driver Options Array" + it_behaves_like 'Selenium Driver Options Array' end - - context "with Remote Selenium driver" do + context 'with Remote Selenium driver' do before do ENV['BROWSER'] = 'remote' ENV['REMOTE_BROWSER'] = 'firefox' @@ -207,23 +204,23 @@ def delete_session ENV['REMOTE_URL'] = 'http://example.com' end - it "should be initialized correctly" do + it 'should be initialized correctly' do Capybara.delete_session - CapybaraSetup.new.driver.should == :selenium + CapybaraSetup.new.driver.should eq :selenium Capybara.current_session.driver.should be_a_kind_of Capybara::Selenium::Driver - Capybara.current_session.driver.options[:browser].should == :remote - Capybara.current_session.driver.options[:url].should == 'http://example.com' - Capybara.current_session.driver.options[:http_client].should be_a_kind_of Selenium::WebDriver::Remote::Http::Default - Capybara.current_session.driver.options[:http_client].instance_variable_get(:@proxy).should == nil - Capybara.current_session.driver.options[:desired_capabilities].should be_a_kind_of Selenium::WebDriver::Remote::Capabilities - Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:browser_name].should == :firefox + Capybara.current_session.driver.options[:browser].should eq :remote + Capybara.current_session.driver.options[:url].should eq 'http://example.com' + Capybara.current_session.driver.options[:http_client].should be_a_kind_of Selenium::WebDriver::Remote::Http::Default + Capybara.current_session.driver.options[:http_client].instance_variable_get(:@proxy).should eq nil + Capybara.current_session.driver.options[:desired_capabilities].should be_a_kind_of Selenium::WebDriver::Remote::Capabilities + Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:browser_name].should eq :firefox Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:firefox_profile].should be_a_kind_of Selenium::WebDriver::Firefox::Profile Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:firefox_profile].instance_variable_get(:@model).should include 'default' end - it_behaves_like "Selenium Driver Options Array" + it_behaves_like 'Selenium Driver Options Array' end - context "with Remote Selenium driver and client proxy" do + context 'with Remote Selenium driver and client proxy' do before do ENV['BROWSER'] = 'remote' ENV['REMOTE_BROWSER'] = 'firefox' @@ -232,20 +229,20 @@ def delete_session ENV['HTTP_PROXY'] = 'http://example.cache.co.uk:80' end - it "should be initialized correctly" do + it 'should be initialized correctly' do Capybara.delete_session - CapybaraSetup.new.driver.should == :selenium + CapybaraSetup.new.driver.should eq :selenium Capybara.current_session.driver.should be_a_kind_of Capybara::Selenium::Driver - Capybara.current_session.driver.options[:browser].should == :remote - Capybara.current_session.driver.options[:url].should == 'http://example.com' - Capybara.current_session.driver.options[:http_client].should be_a_kind_of Selenium::WebDriver::Remote::Http::Default + Capybara.current_session.driver.options[:browser].should eq :remote + Capybara.current_session.driver.options[:url].should eq 'http://example.com' + Capybara.current_session.driver.options[:http_client].should be_a_kind_of Selenium::WebDriver::Remote::Http::Default Capybara.current_session.driver.options[:http_client].instance_variable_get(:@proxy).should be_a_kind_of Selenium::WebDriver::Proxy Capybara.current_session.driver.options[:http_client].instance_variable_get(:@proxy).instance_variable_get(:@http).should == 'http://example.cache.co.uk:80' end - it_behaves_like "Selenium Driver Options Array" + it_behaves_like 'Selenium Driver Options Array' end - context "with Remote Selenium driver, programtically cretated Firefox profile using proxy but client not using proxy" do + context 'with Remote Selenium driver, programtically cretated Firefox profile using proxy but client not using proxy' do before do ENV['BROWSER'] = 'remote' ENV['REMOTE_BROWSER'] = 'firefox' @@ -255,25 +252,25 @@ def delete_session ENV['PROXY_ON'] = 'false' end - it "should be initialized correctly" do + it 'should be initialized correctly' do Capybara.delete_session - CapybaraSetup.new.driver.should == :selenium + CapybaraSetup.new.driver.should eq :selenium Capybara.current_session.driver.should be_a_kind_of Capybara::Selenium::Driver - Capybara.current_session.driver.options[:browser].should == :remote + Capybara.current_session.driver.options[:browser].should eq :remote Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:firefox_profile].should be_a_kind_of Selenium::WebDriver::Firefox::Profile - Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:firefox_profile].instance_variable_get(:@additional_prefs)['network.proxy.type'].should == 1 - Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:firefox_profile].instance_variable_get(:@additional_prefs)['network.proxy.no_proxies_on'].should == '*.sandbox.dev.bbc.co.uk,*.sandbox.bbc.co.uk' - Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:firefox_profile].instance_variable_get(:@additional_prefs)['network.proxy.http'].should == 'example.cache.co.uk' - Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:firefox_profile].instance_variable_get(:@additional_prefs)['network.proxy.http_port'].should == 80 - Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:firefox_profile].instance_variable_get(:@additional_prefs)['network.proxy.ssl'].should == 'example.cache.co.uk' - Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:firefox_profile].instance_variable_get(:@additional_prefs)['network.proxy.ssl_port'].should == 80 - Capybara.current_session.driver.options[:http_client].should be_a_kind_of Selenium::WebDriver::Remote::Http::Default - Capybara.current_session.driver.options[:http_client].instance_variable_get(:@proxy).should == nil - end - it_behaves_like "Selenium Driver Options Array" + Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:firefox_profile].instance_variable_get(:@additional_prefs)['network.proxy.type'].should eq 1 + Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:firefox_profile].instance_variable_get(:@additional_prefs)['network.proxy.no_proxies_on'].should eq '*.sandbox.dev.bbc.co.uk,*.sandbox.bbc.co.uk' + Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:firefox_profile].instance_variable_get(:@additional_prefs)['network.proxy.http'].should eq 'example.cache.co.uk' + Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:firefox_profile].instance_variable_get(:@additional_prefs)['network.proxy.http_port'].should eq 80 + Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:firefox_profile].instance_variable_get(:@additional_prefs)['network.proxy.ssl'].should eq 'example.cache.co.uk' + Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:firefox_profile].instance_variable_get(:@additional_prefs)['network.proxy.ssl_port'].should eq 80 + Capybara.current_session.driver.options[:http_client].should be_a_kind_of Selenium::WebDriver::Remote::Http::Default + Capybara.current_session.driver.options[:http_client].instance_variable_get(:@proxy).should eq nil + end + it_behaves_like 'Selenium Driver Options Array' end - context "with Remote Selenium driver (specifying platform and browser version) and default Custom Capabilites (e.g. for Sauce Labs)" do + context 'with Remote Selenium driver (specifying platform and browser version) and default Custom Capabilites (e.g. for Sauce Labs)' do before do ENV['BROWSER'] = 'remote' ENV['REMOTE_BROWSER'] = 'firefox' @@ -283,27 +280,25 @@ def delete_session ENV['REMOTE_URL'] = 'http://saucelabs.com' end - it "should be initialized correctly" do + it 'should be initialized correctly' do Capybara.delete_session - CapybaraSetup.new.driver.should == :selenium + CapybaraSetup.new.driver.should eq :selenium Capybara.current_session.driver.should be_a_kind_of Capybara::Selenium::Driver - Capybara.current_session.driver.options[:browser].should == :remote - Capybara.current_session.driver.options[:url].should == 'http://saucelabs.com' - Capybara.current_session.driver.options[:http_client].should be_a_kind_of Selenium::WebDriver::Remote::Http::Default - Capybara.current_session.driver.options[:http_client].instance_variable_get(:@proxy).should == nil - Capybara.current_session.driver.options[:desired_capabilities].should be_a_kind_of Selenium::WebDriver::Remote::Capabilities - #Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@custom_capabilities)[:'job-name'].should == 'frameworks-unamed-job' - #Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@custom_capabilities)[:'max-duration'].should == 1800 - Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:browser_name].should == :firefox - Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:browser_version].should == '4' - Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:os].should == 'windows' + Capybara.current_session.driver.options[:browser].should eq :remote + Capybara.current_session.driver.options[:url].should eq 'http://saucelabs.com' + Capybara.current_session.driver.options[:http_client].should be_a_kind_of Selenium::WebDriver::Remote::Http::Default + Capybara.current_session.driver.options[:http_client].instance_variable_get(:@proxy).should eq nil + Capybara.current_session.driver.options[:desired_capabilities].should be_a_kind_of Selenium::WebDriver::Remote::Capabilities + Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:browser_name].should eq :firefox + Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:browser_version].should eq '4' + Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:os].should eq 'windows' Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:firefox_profile].should be_a_kind_of Selenium::WebDriver::Firefox::Profile Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:firefox_profile].instance_variable_get(:@model).should include 'default' end - it_behaves_like "Selenium Driver Options Array" + it_behaves_like 'Selenium Driver Options Array' end - context "with Selenium driver and hardcoded bbc internal profile and additional firefox preferences" do + context 'with Selenium driver and hardcoded bbc internal profile and additional firefox preferences' do before do ENV['BROWSER'] = 'firefox' ENV['HTTP_PROXY'] = 'http://example.cache.co.uk:80' @@ -311,55 +306,53 @@ def delete_session ENV['FIREFOX_PREFS'] = '{"javascript.enabled":false}' end - it "should be initialized correctly" do + it 'should be initialized correctly' do Capybara.delete_session - CapybaraSetup.new.driver.should == :selenium + CapybaraSetup.new.driver.should eq :selenium Capybara.current_session.driver.should be_a_kind_of Capybara::Selenium::Driver - Capybara.current_session.driver.options[:browser].should == :firefox + Capybara.current_session.driver.options[:browser].should eq :firefox Capybara.current_session.driver.options[:profile].should be_a_kind_of Selenium::WebDriver::Firefox::Profile - Capybara.current_session.driver.options[:profile].instance_variable_get(:@additional_prefs)['javascript.enabled'].should == false + Capybara.current_session.driver.options[:profile].instance_variable_get(:@additional_prefs)['javascript.enabled'].should eq false end - it_behaves_like "Selenium Driver Options Array" + it_behaves_like 'Selenium Driver Options Array' end - - context "with Selenium driver and additional firefox preferences" do + context 'with Selenium driver and additional firefox preferences' do before do ENV['BROWSER'] = 'firefox' ENV['FIREFOX_PROFILE'] = 'default' ENV['FIREFOX_PREFS'] = '{"javascript.enabled":false}' end - it "should be initialized correctly" do + it 'should be initialized correctly' do Capybara.delete_session - CapybaraSetup.new.driver.should == :selenium + CapybaraSetup.new.driver.should eq :selenium Capybara.current_session.driver.should be_a_kind_of Capybara::Selenium::Driver - Capybara.current_session.driver.options[:browser].should == :firefox + Capybara.current_session.driver.options[:browser].should eq :firefox Capybara.current_session.driver.options[:profile].should be_a_kind_of Selenium::WebDriver::Firefox::Profile - Capybara.current_session.driver.options[:profile].instance_variable_get(:@additional_prefs)['javascript.enabled'].should == false + Capybara.current_session.driver.options[:profile].instance_variable_get(:@additional_prefs)['javascript.enabled'].should eq false end - it_behaves_like "Selenium Driver Options Array" + it_behaves_like 'Selenium Driver Options Array' end - - context "with Selenium driver and new profile and custom prefs" do + context 'with Selenium driver and new profile and custom prefs' do before do ENV['BROWSER'] = 'firefox' ENV['FIREFOX_PREFS'] = '{"javascript.enabled":false}' end - it "should be initialized correctly" do + it 'should be initialized correctly' do Capybara.delete_session - CapybaraSetup.new.driver.should == :selenium + CapybaraSetup.new.driver.should eq :selenium Capybara.current_session.driver.should be_a_kind_of Capybara::Selenium::Driver - Capybara.current_session.driver.options[:browser].should == :firefox + Capybara.current_session.driver.options[:browser].should eq :firefox Capybara.current_session.driver.options[:profile].should be_a_kind_of Selenium::WebDriver::Firefox::Profile - Capybara.current_session.driver.options[:profile].instance_variable_get(:@additional_prefs)['javascript.enabled'].should == false + Capybara.current_session.driver.options[:profile].instance_variable_get(:@additional_prefs)['javascript.enabled'].should eq false end - it_behaves_like "Selenium Driver Options Array" + it_behaves_like 'Selenium Driver Options Array' end - context "with Remote Selenium driver and specified Chrome Switches" do + context 'with Remote Selenium driver and specified Chrome Switches' do before do ENV['BROWSER'] = 'remote' ENV['REMOTE_BROWSER'] = 'chrome' @@ -367,23 +360,23 @@ def delete_session ENV['CHROME_SWITCHES'] = '--user-agent=Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10' end - it "should be initialized correctly" do + it 'should be initialized correctly' do Capybara.delete_session - CapybaraSetup.new.driver.should == :selenium + CapybaraSetup.new.driver.should eq :selenium Capybara.current_session.driver.should be_a_kind_of Capybara::Selenium::Driver - Capybara.current_session.driver.options[:browser].should == :remote - Capybara.current_session.driver.options[:switches].should == nil - Capybara.current_session.driver.options[:url].should == 'http://saucelabs.com' - Capybara.current_session.driver.options[:http_client].should be_a_kind_of Selenium::WebDriver::Remote::Http::Default - Capybara.current_session.driver.options[:http_client].instance_variable_get(:@proxy).should == nil - Capybara.current_session.driver.options[:desired_capabilities].should be_a_kind_of Selenium::WebDriver::Remote::Capabilities - Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:browser_name].should == :chrome - Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)['chrome.switches'].should == ['--user-agent=Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10'] - end - it_behaves_like "Selenium Driver Options Array" + Capybara.current_session.driver.options[:browser].should eq :remote + Capybara.current_session.driver.options[:switches].should eq nil + Capybara.current_session.driver.options[:url].should eq 'http://saucelabs.com' + Capybara.current_session.driver.options[:http_client].should be_a_kind_of Selenium::WebDriver::Remote::Http::Default + Capybara.current_session.driver.options[:http_client].instance_variable_get(:@proxy).should eq nil + Capybara.current_session.driver.options[:desired_capabilities].should be_a_kind_of Selenium::WebDriver::Remote::Capabilities + Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:browser_name].should eq :chrome + Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)['chrome.switches'].should eq ['--user-agent=Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10'] + end + it_behaves_like 'Selenium Driver Options Array' end - context "with Remote Selenium driver and specified Custom Capabilites (e.g. for Sauce Labs)" do + context 'with Remote Selenium driver and specified Custom Capabilites (e.g. for Sauce Labs)' do before do ENV['BROWSER'] = 'remote' ENV['REMOTE_BROWSER'] = 'firefox' @@ -394,44 +387,42 @@ def delete_session ENV['REMOTE_URL'] = 'http://saucelabs.com' end - it "should be initialized correctly" do + it 'should be initialized correctly' do Capybara.delete_session - CapybaraSetup.new.driver.should == :selenium + CapybaraSetup.new.driver.should eq :selenium Capybara.current_session.driver.should be_a_kind_of Capybara::Selenium::Driver - Capybara.current_session.driver.options[:browser].should == :remote - Capybara.current_session.driver.options[:url].should == 'http://saucelabs.com' - Capybara.current_session.driver.options[:http_client].should be_a_kind_of Selenium::WebDriver::Remote::Http::Default - Capybara.current_session.driver.options[:http_client].instance_variable_get(:@proxy).should == nil - Capybara.current_session.driver.options[:desired_capabilities].should be_a_kind_of Selenium::WebDriver::Remote::Capabilities - #Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@custom_capabilities)[:'job-name'].should == 'myjobname' - #Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@custom_capabilities)[:'max-duration'].should == 2000 - Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:browser_name].should == :firefox + Capybara.current_session.driver.options[:browser].should eq :remote + Capybara.current_session.driver.options[:url].should eq 'http://saucelabs.com' + Capybara.current_session.driver.options[:http_client].should be_a_kind_of Selenium::WebDriver::Remote::Http::Default + Capybara.current_session.driver.options[:http_client].instance_variable_get(:@proxy).should eq nil + Capybara.current_session.driver.options[:desired_capabilities].should be_a_kind_of Selenium::WebDriver::Remote::Capabilities + Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:browser_name].should eq :firefox Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:firefox_profile].should be_a_kind_of Selenium::WebDriver::Firefox::Profile Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:firefox_profile].instance_variable_get(:@model).should include 'default' end - it_behaves_like "Selenium Driver Options Array" + it_behaves_like 'Selenium Driver Options Array' end - context "with Remote Selenium driver and most minimal Capabilites for BrowserStack" do + context 'with Remote Selenium driver and most minimal Capabilites for BrowserStack' do before do ENV['BROWSER'] = 'remote' ENV['REMOTE_BROWSER'] = 'ie' ENV['REMOTE_URL'] = 'http://hub.browserstack.com' end - it "should be initialized correctly" do + it 'should be initialized correctly' do Capybara.delete_session - CapybaraSetup.new.driver.should == :selenium + CapybaraSetup.new.driver.should eq :selenium Capybara.current_session.driver.should be_a_kind_of Capybara::Selenium::Driver - Capybara.current_session.driver.options[:browser].should == :remote - Capybara.current_session.driver.options[:url].should == ENV['REMOTE_URL'] + Capybara.current_session.driver.options[:browser].should eq :remote + Capybara.current_session.driver.options[:url].should eq ENV['REMOTE_URL'] Capybara.current_session.driver.options[:desired_capabilities].should be_a_kind_of Selenium::WebDriver::Remote::Capabilities - Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:'browserstack.debug'].should == 'true' + Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:'browserstack.debug'].should eq 'true' end - it_behaves_like "Selenium Driver Options Array" + it_behaves_like 'Selenium Driver Options Array' end - context "with Remote Selenium driver and specified Custom Capabilites for BrowserStack" do + context 'with Remote Selenium driver and specified Custom Capabilites for BrowserStack' do before do ENV['BROWSER'] = 'remote' ENV['BS_BUILD'] = 'browserstack build 1' @@ -447,68 +438,117 @@ def delete_session ENV['REMOTE_URL'] = 'http://hub.browserstack.com' end - it "should be initialized correctly" do + it 'should be initialized correctly' do + Capybara.delete_session + CapybaraSetup.new.driver.should eq :selenium + Capybara.current_session.driver.should be_a_kind_of Capybara::Selenium::Driver + Capybara.current_session.driver.options[:browser].should eq :remote + Capybara.current_session.driver.options[:url].should eq ENV['REMOTE_URL'] + Capybara.current_session.driver.options[:http_client].should be_a_kind_of Selenium::WebDriver::Remote::Http::Default + Capybara.current_session.driver.options[:http_client].instance_variable_get(:@proxy).should eq nil + Capybara.current_session.driver.options[:desired_capabilities].should be_a_kind_of Selenium::WebDriver::Remote::Capabilities + Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:build].should eq ENV['BS_BUILD'] + Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:'browserstack.debug'].should eq ENV['BS_DEBUG'] + Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:device].should eq ENV['BS_DEVICE'] + Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:deviceOrientation].should eq ENV['BS_DEVICE_ORIENTATION'] + Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:project].should eq ENV['BS_PROJECT'] + Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:resolution].should eq ENV['BS_RESOLUTION'] + Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:os].should eq ENV['PLATFORM'] + Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:os_version].should eq ENV['PLATFORM_VERSION'] + Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:browser_name].should eq :iPhone + Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:browser_version].should eq ENV['REMOTE_BROWSER_VERSION'] + end + it_behaves_like 'Selenium Driver Options Array' + end + + context 'with Remote Selenium driver and specified Custom Capabilites for Appium' do + before do + ENV['BROWSER'] = 'remote' + ENV['REMOTE_URL'] = 'http://127.0.0.1:4273' + ENV['APPIUM_PLATFORM'] = 'Android' + ENV['APPIUM_DEVICE'] = 'android' + ENV['APPIUM_BROWSER'] = 'chrome' + ENV['APPIUM_UDID'] = 'abd234' + end + + it 'should be initialized correctly' do Capybara.delete_session - CapybaraSetup.new.driver.should == :selenium + CapybaraSetup.new.driver.should eq :selenium Capybara.current_session.driver.should be_a_kind_of Capybara::Selenium::Driver - Capybara.current_session.driver.options[:browser].should == :remote + Capybara.current_session.driver.options[:browser].should eq :remote Capybara.current_session.driver.options[:url].should == ENV['REMOTE_URL'] Capybara.current_session.driver.options[:http_client].should be_a_kind_of Selenium::WebDriver::Remote::Http::Default - Capybara.current_session.driver.options[:http_client].instance_variable_get(:@proxy).should == nil + Capybara.current_session.driver.options[:http_client].instance_variable_get(:@proxy).should eq nil Capybara.current_session.driver.options[:desired_capabilities].should be_a_kind_of Selenium::WebDriver::Remote::Capabilities - Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:build].should == ENV['BS_BUILD'] - Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:'browserstack.debug'].should == ENV['BS_DEBUG'] - Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:device].should == ENV['BS_DEVICE'] - Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:deviceOrientation].should == ENV['BS_DEVICE_ORIENTATION'] - Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:project].should == ENV['BS_PROJECT'] - Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:resolution].should == ENV['BS_RESOLUTION'] - Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:os].should == ENV['PLATFORM'] - Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:os_version].should == ENV['PLATFORM_VERSION'] - Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:browser_name].should == :iPhone - Capybara.current_session.driver.options[:desired_capabilities].instance_variable_get(:@capabilities)[:browser_version].should == ENV['REMOTE_BROWSER_VERSION'] - end - it_behaves_like "Selenium Driver Options Array" + end + it_behaves_like 'Selenium Driver Options Array' end end - describe "should allow Mechanize driver to be created" do - context "with minimal Mechanize driver" do + describe 'should allow Mechanize driver to be created' do + context 'with minimal Mechanize driver' do before do ENV['BROWSER'] = 'mechanize' end - it "should be initialized correctly" do + it 'should be initialized correctly' do Capybara.delete_session CapybaraSetup.new.driver.should == :mechanize Capybara.current_session.driver.should be_a_kind_of Capybara::Mechanize::Driver end - context "with maximal Mechanize driver" do + context 'with maximal Mechanize driver' do before do ENV['BROWSER'] = 'mechanize' ENV['ENVIRONMENT'] = 'test' ENV['HTTP_PROXY'] = 'http://example.cache.co.uk:80' end - it "should be initialized correctly" do + it 'should be initialized correctly' do Capybara.delete_session - CapybaraSetup.new.driver.should == :mechanize + CapybaraSetup.new.driver.should eq :mechanize Capybara.current_session.driver.should be_a_kind_of Capybara::Mechanize::Driver - #note can no longer unit test this due to change in Capybara wiping brower instance - #Capybara.current_session.driver.browser.agent.proxy_addr.should == 'example.cache.co.uk' - #Capybara.current_session.driver.browser.agent.proxy_port.should == 80 - + # note can no longer unit test this due to change in Capybara wiping brower instance + # Capybara.current_session.driver.browser.agent.proxy_addr.should == 'example.cache.co.uk' + # Capybara.current_session.driver.browser.agent.proxy_port.should == 80 end end end - describe "should permit certificate files to be incorporated into firefox profiles" do + describe 'should allow Poltergeist driver to be created' do + context 'with minimal Poltergeist driver' do + before do + ENV['BROWSER'] = 'poltergeist' + end + + it 'should be initialized correctly' do + Capybara.delete_session + CapybaraSetup.new.driver.should eq :poltergeist + Capybara.current_session.driver.should be_a_kind_of Capybara::Poltergeist::Driver + end - context "integration tests for update_firefox_profile_with_certificates() method" do + context 'with maximal Poltergeist driver' do before do - def write_random_data(file_path) + ENV['BROWSER'] = 'poltergeist' + ENV['ENVIRONMENT'] = 'test' + ENV['HTTP_PROXY'] = 'http://example.cache.co.uk:80' + end + + it 'should be initialized correctly' do + Capybara.delete_session + CapybaraSetup.new.driver.should eq :poltergeist + Capybara.current_session.driver.should be_a_kind_of Capybara::Poltergeist::Driver + end + end + end + end + + describe 'should permit certificate files to be incorporated into firefox profiles' do + context 'integration tests for update_firefox_profile_with_certificates() method' do + before do + def write_random_data(file_path) file_data = SecureRandom.hex - File.open(file_path, "w") { |a_file| + File.open(file_path, 'w') { |a_file| a_file.write(file_data) } file_data @@ -517,10 +557,10 @@ def write_random_data(file_path) def compare_file_data(profile_path, file_name, expected_data) profile_file = profile_path + File::SEPARATOR + file_name actual_data = nil - File.open(profile_file, "r") { |a_file| + File.open(profile_file, 'r') { |a_file| actual_data = a_file.read } - expected_data.should == actual_data + expected_data.should == actual_data end ENV['BROWSER'] = 'firefox' @@ -536,16 +576,16 @@ def compare_file_data(profile_path, file_name, expected_data) FileUtils.remove_entry @cert_dir end - it "should raise an exception if the cert8.db file is missing in the source directory" do + it 'should raise an exception if the cert8.db file is missing in the source directory' do profile = Selenium::WebDriver::Firefox::Profile.new - key3_data = write_random_data(@key3_db) - secmod_data = write_random_data(@secmod_db) - + write_random_data(@key3_db) + write_random_data(@secmod_db) + an_exception = nil - begin + begin CapybaraSetup.new.instance_exec(profile, @cert_dir) { |profile, certificate_path| - update_firefox_profile_with_certificates(profile, certificate_path) + update_firefox_profile_with_certificates(profile, certificate_path) } rescue RuntimeError => e an_exception = e @@ -554,16 +594,15 @@ def compare_file_data(profile_path, file_name, expected_data) an_exception.should_not be_nil end - it "should raise an exception if the key3.db file is missing in the source directory" do + it 'should raise an exception if the key3.db file is missing in the source directory' do profile = Selenium::WebDriver::Firefox::Profile.new - cert8_data = write_random_data(@cert8_db) - secmod_data = write_random_data(@secmod_db) - + write_random_data(@cert8_db) + write_random_data(@secmod_db) an_exception = nil - begin + begin CapybaraSetup.new.instance_exec(profile, @cert_dir) { |profile, certificate_path| - update_firefox_profile_with_certificates(profile, certificate_path) + update_firefox_profile_with_certificates(profile, certificate_path) } rescue RuntimeError => e an_exception = e @@ -571,17 +610,16 @@ def compare_file_data(profile_path, file_name, expected_data) an_exception.should_not be_nil end - - it "should raise an exception if the secmod.db file is missing in the source directory" do + + it 'should raise an exception if the secmod.db file is missing in the source directory' do profile = Selenium::WebDriver::Firefox::Profile.new - cert8_data = write_random_data(@cert8_db) - key3_data = write_random_data(@key3_db) - + write_random_data(@cert8_db) + write_random_data(@key3_db) an_exception = nil - begin + begin CapybaraSetup.new.instance_exec(profile, @cert_dir) { |profile, certificate_path| - update_firefox_profile_with_certificates(profile, certificate_path) + update_firefox_profile_with_certificates(profile, certificate_path) } rescue RuntimeError => e an_exception = e @@ -590,8 +628,7 @@ def compare_file_data(profile_path, file_name, expected_data) an_exception.should_not be_nil end - it "should update a firefox profile with valid references to certificate db files" do - + it 'should update a firefox profile with valid references to certificate db files' do profile = Selenium::WebDriver::Firefox::Profile.new cert8_data = write_random_data(@cert8_db) @@ -600,7 +637,7 @@ def compare_file_data(profile_path, file_name, expected_data) setup = CapybaraSetup.new result = setup.instance_exec(profile, @cert_dir) { |profile, certificate_path| - update_firefox_profile_with_certificates(profile, certificate_path) + update_firefox_profile_with_certificates(profile, certificate_path) } profile_path = result.layout_on_disk compare_file_data(profile_path, 'cert8.db', cert8_data) @@ -608,41 +645,36 @@ def compare_file_data(profile_path, file_name, expected_data) compare_file_data(profile_path, 'secmod.db', secmod_data) end - it "should update a firefox profile with references to certificate db files with prefixes" do - + it 'should update a firefox profile with references to certificate db files with prefixes' do profile = Selenium::WebDriver::Firefox::Profile.new cert_prefix = 'a' @cert8_db = @cert_dir + File::SEPARATOR + cert_prefix + 'cert8.db' @key3_db = @cert_dir + File::SEPARATOR + cert_prefix + 'key3.db' @secmod_db = @cert_dir + File::SEPARATOR + cert_prefix + 'secmod.db' - cert8_data = write_random_data(@cert8_db) key3_data = write_random_data(@key3_db) secmod_data = write_random_data(@secmod_db) setup = CapybaraSetup.new - result = setup.instance_exec(profile, @cert_dir, cert_prefix) { |profile, certificate_path, certificate_prefix, result| - update_firefox_profile_with_certificates(profile, certificate_path, certificate_prefix) + result = setup.instance_exec(profile, @cert_dir, cert_prefix) { |profile, certificate_path, certificate_prefix, _result| + update_firefox_profile_with_certificates(profile, certificate_path, certificate_prefix) } profile_path = result.layout_on_disk compare_file_data(profile_path, 'cert8.db', cert8_data) compare_file_data(profile_path, 'key3.db', key3_data) compare_file_data(profile_path, 'secmod.db', secmod_data) end - end - end - describe "The BBC-INTERNAL firefox profile should be set up with the correct proxy settings whether working behind a proxy or not" do - - context "no proxy settings provided" do + describe 'The BBC-INTERNAL firefox profile should be set up with the correct proxy settings whether working behind a proxy or not' do + context 'no proxy settings provided' do before do ENV['BROWSER'] = 'firefox' ENV['ENVIRONMENT'] = 'test' end - it "should create the firefox profile settings correctly" do + it 'should create the firefox profile settings correctly' do setup = CapybaraSetup.new profile = setup.instance_exec('BBC_INTERNAL', nil) { |profile_name, additional_prefs| create_profile(profile_name, additional_prefs) @@ -654,24 +686,24 @@ def compare_file_data(profile_path, file_name, expected_data) end end - context "proxy settings provided" do + context 'proxy settings provided' do before do @proxy_host = 'example.cache.co.uk' @proxy_port = 6789 ENV['BROWSER'] = 'firefox' ENV['ENVIRONMENT'] = 'test' - ENV['HTTP_PROXY'] = "http://#{@proxy_host}:#{@proxy_port}" + ENV['HTTP_PROXY'] = 'http://#{@proxy_host}:#{@proxy_port}' end - it "should create the firefox profile correctly" do + it 'should create the firefox profile correctly' do setup = CapybaraSetup.new profile = setup.instance_exec('BBC_INTERNAL', nil) { |profile_name, additional_prefs| create_profile(profile_name, additional_prefs) } - profile.instance_variable_get('@additional_prefs')['network.proxy.type'].should == 1 - profile.instance_variable_get('@additional_prefs')['network.proxy.http'].should == @proxy_host - profile.instance_variable_get('@additional_prefs')['network.proxy.http_port'].should == @proxy_port + profile.instance_variable_get('@additional_prefs')['network.proxy.type'].should eq 1 + profile.instance_variable_get('@additional_prefs')['network.proxy.http'].should eq @proxy_host + profile.instance_variable_get('@additional_prefs')['network.proxy.http_port'].should eq @proxy_port end end end diff --git a/spec/frameworks_cucumber_spec.rb b/spec/frameworks_cucumber_spec.rb old mode 100644 new mode 100755 index 1d10a6a..cdfbd62 --- a/spec/frameworks_cucumber_spec.rb +++ b/spec/frameworks_cucumber_spec.rb @@ -1,162 +1,158 @@ require 'spec_helper' describe Frameworks::EnvHelper do - before do ENV.clear - ENV['BROWSER'] = 'test' #mandatory data to prevent validation exception + ENV['BROWSER'] = 'test' # mandatory data to prevent validation exception end - describe "set base url correctly" do + describe 'set base url correctly' do include Frameworks::EnvHelper - it "should be able to set a local url" do + it 'should be able to set a local url' do ENV['ENVIRONMENT'] = 'sandbox' generate_base_urls - @base_url.should == 'http://pal.sandbox.dev.bbc.co.uk' - @ssl_base_url.should == 'https://ssl.sandbox.dev.bbc.co.uk' - @static_base_url.should == 'http://static.sandbox.dev.bbc.co.uk' - @m_base_url.should == 'http://m.sandbox.dev.bbc.co.uk' - @mobile_base_url.should == 'http://mobile.sandbox.dev.bbc.co.uk' + @base_url.should eq('http://pal.sandbox.dev.bbc.co.uk') + @ssl_base_url.should eq('https://ssl.sandbox.dev.bbc.co.uk') + @static_base_url.should eq('http://static.sandbox.dev.bbc.co.uk') + @m_base_url.should eq('http://m.sandbox.dev.bbc.co.uk') + @mobile_base_url.should eq('http://mobile.sandbox.dev.bbc.co.uk') end - it "should be able to set a local system6 url" do + it 'should be able to set a local system6 url' do ENV['ENVIRONMENT'] = 'sandbox6' generate_base_urls - @base_url.should == 'http://sandbox.bbc.co.uk' - @ssl_base_url.should == 'https://ssl.sandbox.bbc.co.uk' - @static_base_url.should == 'http://static.sandbox.bbc.co.uk' - @m_base_url.should == 'http://m.sandbox.bbc.co.uk' - @mobile_base_url.should == 'http://mobile.sandbox.bbc.co.uk' + @base_url.should eq('http://sandbox.bbc.co.uk') + @ssl_base_url.should eq('https://ssl.sandbox.bbc.co.uk') + @static_base_url.should eq('http://static.sandbox.bbc.co.uk') + @m_base_url.should eq('http://m.sandbox.bbc.co.uk') + @mobile_base_url.should eq('http://mobile.sandbox.bbc.co.uk') end - it "should be able to set a base url" do + it 'should be able to set a base url' do ENV['ENVIRONMENT'] = 'foo' generate_base_urls - @base_url.should == 'http://www.foo.bbc.co.uk' - @ssl_base_url.should == 'https://ssl.foo.bbc.co.uk' - @static_base_url.should == 'http://static.foo.bbci.co.uk' - @open_base_url.should == 'http://open.foo.bbc.co.uk' - @m_base_url.should == 'http://m.foo.bbc.co.uk' - @mobile_base_url.should == 'http://mobile.foo.bbc.co.uk' + @base_url.should eq('http://www.foo.bbc.co.uk') + @ssl_base_url.should eq('https://ssl.foo.bbc.co.uk') + @static_base_url.should eq('http://static.foo.bbci.co.uk') + @open_base_url.should eq('http://open.foo.bbc.co.uk') + @m_base_url.should eq('http://m.foo.bbc.co.uk') + @mobile_base_url.should eq('http://mobile.foo.bbc.co.uk') end - it "should set correct static base for www.live.bbc.co.uk" do + it 'should set correct static base for www.live.bbc.co.uk' do ENV['ENVIRONMENT'] = 'live' generate_base_urls - @base_url.should == 'http://www.live.bbc.co.uk' - @ssl_base_url.should == 'https://ssl.live.bbc.co.uk' - @static_base_url.should == 'http://static.bbci.co.uk' - @open_base_url.should == 'http://open.live.bbc.co.uk' - @m_base_url.should == 'http://m.live.bbc.co.uk' - @mobile_base_url.should == 'http://mobile.live.bbc.co.uk' + @base_url.should eq('http://www.live.bbc.co.uk') + @ssl_base_url.should eq('https://ssl.live.bbc.co.uk') + @static_base_url.should eq('http://static.bbci.co.uk') + @open_base_url.should eq('http://open.live.bbc.co.uk') + @m_base_url.should eq('http://m.live.bbc.co.uk') + @mobile_base_url.should eq('http://mobile.live.bbc.co.uk') end - it "should be able to set a base url and not be case sensitive" do + it 'should be able to set a base url and not be case sensitive' do ENV['ENVIRONMENT'] = 'fOo' generate_base_urls - @base_url.should == 'http://www.foo.bbc.co.uk' - @ssl_base_url.should == 'https://ssl.foo.bbc.co.uk' - @static_base_url.should == 'http://static.foo.bbci.co.uk' - @open_base_url.should == 'http://open.foo.bbc.co.uk' - @m_base_url.should == 'http://m.foo.bbc.co.uk' - @mobile_base_url.should == 'http://mobile.foo.bbc.co.uk' + @base_url.should eq('http://www.foo.bbc.co.uk') + @ssl_base_url.should eq('https://ssl.foo.bbc.co.uk') + @static_base_url.should eq('http://static.foo.bbci.co.uk') + @open_base_url.should eq('http://open.foo.bbc.co.uk') + @m_base_url.should eq('http://m.foo.bbc.co.uk') + @mobile_base_url.should eq('http://mobile.foo.bbc.co.uk') end - it "should set correct static base for www.live.bbc.co.uk and not be case sensitive" do + it 'should set correct static base for www.live.bbc.co.uk and not be case sensitive' do ENV['ENVIRONMENT'] = 'LiVe' generate_base_urls - @base_url.should == 'http://www.live.bbc.co.uk' - @ssl_base_url.should == 'https://ssl.live.bbc.co.uk' - @static_base_url.should == 'http://static.bbci.co.uk' - @open_base_url.should == 'http://open.live.bbc.co.uk' - @m_base_url.should == 'http://m.live.bbc.co.uk' - @mobile_base_url.should == 'http://mobile.live.bbc.co.uk' + @base_url.should eq('http://www.live.bbc.co.uk') + @ssl_base_url.should eq('https://ssl.live.bbc.co.uk') + @static_base_url.should eq('http://static.bbci.co.uk') + @open_base_url.should eq('http://open.live.bbc.co.uk') + @m_base_url.should eq('http://m.live.bbc.co.uk') + @mobile_base_url.should eq('http://mobile.live.bbc.co.uk') end - it "should be able to set a 'classic' live url and not be case sensitive" do ENV['ENVIRONMENT'] = 'Live' - ENV['WWW_LIVE'] = 'false' + ENV['WWW_LIVE'] = 'false' generate_base_urls - @base_url.should == 'http://www.bbc.co.uk' - @ssl_base_url.should == 'https://ssl.bbc.co.uk' - @static_base_url.should == 'http://static.bbci.co.uk' - @open_base_url.should == 'http://open.bbc.co.uk' - @m_base_url.should == 'http://m.bbc.co.uk' - @mobile_base_url.should == 'http://mobile.bbc.co.uk' + @base_url.should eq('http://www.bbc.co.uk') + @ssl_base_url.should eq('https://ssl.bbc.co.uk') + @static_base_url.should eq('http://static.bbci.co.uk') + @open_base_url.should eq('http://open.bbc.co.uk') + @m_base_url.should eq('http://m.bbc.co.uk') + @mobile_base_url.should eq('http://mobile.bbc.co.uk') end - it "should be able to set pal url and not be case sensitive" do + it 'should be able to set pal url and not be case sensitive' do ENV['ENVIRONMENT'] = 'Live' generate_base_urls - @base_url.should == 'http://www.live.bbc.co.uk' - @pal_base_url.should == 'http://pal.live.bbc.co.uk' - @ssl_base_url.should == 'https://ssl.live.bbc.co.uk' - @static_base_url.should == 'http://static.bbci.co.uk' - @open_base_url.should == 'http://open.live.bbc.co.uk' - @m_base_url.should == 'http://m.live.bbc.co.uk' - @mobile_base_url.should == 'http://mobile.live.bbc.co.uk' + @base_url.should eq('http://www.live.bbc.co.uk') + @pal_base_url.should eq('http://pal.live.bbc.co.uk') + @ssl_base_url.should eq('https://ssl.live.bbc.co.uk') + @static_base_url.should eq('http://static.bbci.co.uk') + @open_base_url.should eq('http://open.live.bbc.co.uk') + @m_base_url.should eq('http://m.live.bbc.co.uk') + @mobile_base_url.should eq('http://mobile.live.bbc.co.uk') end - it "pal url should still have environment even if asking for classic live url" do + it 'pal url should still have environment even if asking for classic live url' do ENV['ENVIRONMENT'] = 'Live' - ENV['WWW_LIVE'] = 'false' + ENV['WWW_LIVE'] = 'false' generate_base_urls - @base_url.should == 'http://www.bbc.co.uk' - @pal_base_url.should == 'http://pal.live.bbc.co.uk' - @ssl_base_url.should == 'https://ssl.bbc.co.uk' - @static_base_url.should == 'http://static.bbci.co.uk' - @open_base_url.should == 'http://open.bbc.co.uk' - @m_base_url.should == 'http://m.bbc.co.uk' - @mobile_base_url.should == 'http://mobile.bbc.co.uk' + @base_url.should eq('http://www.bbc.co.uk') + @pal_base_url.should eq('http://pal.live.bbc.co.uk') + @ssl_base_url.should eq('https://ssl.bbc.co.uk') + @static_base_url.should eq('http://static.bbci.co.uk') + @open_base_url.should eq('http://open.bbc.co.uk') + @m_base_url.should eq('http://m.bbc.co.uk') + @mobile_base_url.should eq('http://mobile.bbc.co.uk') end - - - it "should be able to set scheme to ssl" do + it 'should be able to set scheme to ssl' do ENV['SCHEME'] = 'https' ENV['ENVIRONMENT'] = 'foo' generate_base_urls - @base_url.should == 'https://www.foo.bbc.co.uk' - @ssl_base_url.should == 'https://ssl.foo.bbc.co.uk' - @static_base_url.should == 'https://static.foo.bbci.co.uk' - @open_base_url.should == 'https://open.foo.bbc.co.uk' + @base_url.should eq('https://www.foo.bbc.co.uk') + @ssl_base_url.should eq('https://ssl.foo.bbc.co.uk') + @static_base_url.should eq('https://static.foo.bbci.co.uk') + @open_base_url.should eq('https://open.foo.bbc.co.uk') end - it "should be able to set proxy host and port correctly to use in tests using HTTP_PROXY env variable" do + it 'should be able to set proxy host and port correctly to use in tests using HTTP_PROXY env variable' do ENV['ENVIRONMENT'] = 'foo' ENV['HTTP_PROXY'] = 'http://mycache.co.uk:8080' generate_base_urls - @proxy_host.should == "mycache.co.uk" - @proxy_port.should == "8080" + @proxy_host.should eq('mycache.co.uk') + @proxy_port.should eq('8080') end - it "should be able to set proxy host correctly to use in tests using http_proxy env variable" do + it 'should be able to set proxy host correctly to use in tests using http_proxy env variable' do ENV['ENVIRONMENT'] = 'foo' ENV['http_proxy'] = 'http://mycache.co.uk:8080' generate_base_urls - @proxy_host.should == "mycache.co.uk" - @proxy_port.should == "8080" + @proxy_host.should eq('mycache.co.uk') + @proxy_port.should eq('8080') end - it "should be able to use 80 as default proxy port when none specified" do + it 'should be able to use 80 as default proxy port when none specified' do ENV['ENVIRONMENT'] = 'foo' ENV['http_proxy'] = 'http://mycache.co.uk' generate_base_urls - @proxy_host.should == "mycache.co.uk" - @proxy_port.should == "80" + @proxy_host.should eq('mycache.co.uk') + @proxy_port.should eq('80') end it "should be able to handle an environment variable which doesn't have the protocol" do ENV['ENVIRONMENT'] = 'foo' ENV['http_proxy'] = 'mycache.co.uk' generate_base_urls - @proxy_host.should == "mycache.co.uk" - @proxy_port.should == "80" + @proxy_host.should eq('mycache.co.uk') + @proxy_port.should eq('80') end - it "should be able to have an empty http_proxy environment variable" do + it 'should be able to have an empty http_proxy environment variable' do ENV['ENVIRONMENT'] = 'foo' ENV['http_proxy'] = '' generate_base_urls @@ -164,115 +160,96 @@ @proxy_port.should be_nil end - it "should be able to set a local url with expected domain" do + it 'should be able to set a local url with expected domain' do ENV['ENVIRONMENT'] = 'sandbox' ENV['FW_BBC_DOMAIN'] = 'bbc.com' generate_base_urls - @base_url.should == 'http://pal.sandbox.dev.bbc.com' - @ssl_base_url.should == 'https://ssl.sandbox.dev.bbc.com' - @static_base_url.should == 'http://static.sandbox.dev.bbc.com' - @m_base_url.should == 'http://m.sandbox.dev.bbc.com' - @mobile_base_url.should == 'http://mobile.sandbox.dev.bbc.com' + @base_url.should eq('http://pal.sandbox.dev.bbc.com') + @ssl_base_url.should eq('https://ssl.sandbox.dev.bbc.com') + @static_base_url.should eq('http://static.sandbox.dev.bbc.com') + @m_base_url.should eq('http://m.sandbox.dev.bbc.com') + @mobile_base_url.should eq('http://mobile.sandbox.dev.bbc.com') end - it "should be able to set a local system6 url with expected domain" do + it 'should be able to set a local system6 url with expected domain' do ENV['ENVIRONMENT'] = 'sandbox6' ENV['FW_BBC_DOMAIN'] = 'bbc.com' generate_base_urls - @base_url.should == 'http://sandbox.bbc.com' - @ssl_base_url.should == 'https://ssl.sandbox.bbc.com' - @static_base_url.should == 'http://static.sandbox.bbc.com' - @m_base_url.should == 'http://m.sandbox.bbc.com' - @mobile_base_url.should == 'http://mobile.sandbox.bbc.com' + @base_url.should eq('http://sandbox.bbc.com') + @ssl_base_url.should eq('https://ssl.sandbox.bbc.com') + @static_base_url.should eq('http://static.sandbox.bbc.com') + @m_base_url.should eq('http://m.sandbox.bbc.com') + @mobile_base_url.should eq('http://mobile.sandbox.bbc.com') end - it "should be able to set a base url with expected domain" do + it 'should be able to set a base url with expected domain' do ENV['ENVIRONMENT'] = 'foo' ENV['FW_BBC_DOMAIN'] = 'bbc.com' generate_base_urls - @base_url.should == 'http://www.foo.bbc.com' - @ssl_base_url.should == 'https://ssl.foo.bbc.com' - @static_base_url.should == 'http://static.foo.bbci.co.uk' - @open_base_url.should == 'http://open.foo.bbc.com' - @m_base_url.should == 'http://m.foo.bbc.com' - @mobile_base_url.should == 'http://mobile.foo.bbc.com' + @base_url.should eq('http://www.foo.bbc.com') + @ssl_base_url.should eq('https://ssl.foo.bbc.com') + @static_base_url.should eq('http://static.foo.bbci.co.uk') + @open_base_url.should eq('http://open.foo.bbc.com') + @m_base_url.should eq('http://m.foo.bbc.com') + @mobile_base_url.should eq('http://mobile.foo.bbc.com') end - it "should set public facing live domain" do + it 'should set public facing live domain' do ENV['ENVIRONMENT'] = 'live' ENV['WWW_LIVE'] = 'false' ENV['FW_BBC_DOMAIN'] = 'bbc.com' generate_base_urls - @base_url.should == 'http://www.bbc.com' - @ssl_base_url.should == 'https://ssl.bbc.com' - @static_base_url.should == 'http://static.bbci.co.uk' - @open_base_url.should == 'http://open.bbc.com' - @m_base_url.should == 'http://m.bbc.com' - @mobile_base_url.should == 'http://mobile.bbc.com' - end - -=begin -#don't want to push proxy addr online - it "should be able to validate xhtml online" do - @proxy_host = '' - @proxy_port = '' - xhtml = 'a

a

' - validate_online(xhtml) - end - - it "should be able to report errors for invalid markup" do - @proxy_host = '' - @proxy_port = '' - xhtml = 'a

a

' - expect { - validate_online(xhtml) - }.to raise_error(RuntimeError) + @base_url.should eq('http://www.bbc.com') + @ssl_base_url.should eq('https://ssl.bbc.com') + @static_base_url.should eq('http://static.bbci.co.uk') + @open_base_url.should eq('http://open.bbc.com') + @m_base_url.should eq('http://m.bbc.com') + @mobile_base_url.should eq('http://mobile.bbc.com') end -=end end - describe "independent mechanize agent" do + describe 'independent mechanize agent' do include Frameworks::EnvHelper - it "should allow you to create an independent, configured mechanize object" do + it 'should allow you to create an independent, configured mechanize object' do ENV['HTTP_PROXY'] = 'http://mycache.co.uk:80' agent = new_mechanize agent.should be_a_kind_of Mechanize - agent.proxy_addr.should == 'mycache.co.uk' + agent.proxy_addr.should eq('mycache.co.uk') end - it "the proxy should be separately configurable" do - agent = new_mechanize(http_proxy='http://mycache.co.uk:80') + it 'the proxy should be separately configurable' do + agent = new_mechanize('http://mycache.co.uk:80') agent.should be_a_kind_of Mechanize - agent.proxy_addr.should == 'mycache.co.uk' + agent.proxy_addr.should eq('mycache.co.uk') end - it "the proxy should be ignored if the no_proxy exclusion is set" do + it 'the proxy should be ignored if the no_proxy exclusion is set' do proxy_host = 'mycache.co.uk' proxy_port = '80' - proxy_uri = 'http://' + proxy_host + ':' + proxy_port + proxy_uri = 'http://' + proxy_host + ':' + proxy_port no_proxy = 'ignore_this_host' ENV['NO_PROXY'] = no_proxy - agent = new_mechanize(http_proxy=proxy_uri) + agent = new_mechanize(proxy_uri) expect(agent).to be_a_kind_of Mechanize expect(agent.agent.http.proxy_uri.host).to eq(proxy_host) expect(agent.agent.http.proxy_uri.port).to eq(proxy_port.to_i) - no_proxy_array = [ no_proxy ] + no_proxy_array = [no_proxy] expect(agent.agent.http.no_proxy).to eq(no_proxy_array) end - it "the proxy should be ignored if the no_proxy exclusion is set with multiple values" do + it 'the proxy should be ignored if the no_proxy exclusion is set with multiple values' do proxy_host = 'mycache.co.uk' proxy_port = '80' - proxy_uri = 'http://' + proxy_host + ':' + proxy_port + proxy_uri = 'http://' + proxy_host + ':' + proxy_port no_proxy1 = 'ignore_this_host' no_proxy2 = '.and.this.domain' ENV['NO_PROXY'] = no_proxy1 + ', ' + no_proxy2 - agent = new_mechanize(http_proxy=proxy_uri) + agent = new_mechanize(proxy_uri) expect(agent).to be_a_kind_of Mechanize expect(agent.agent.http.proxy_uri.host).to eq(proxy_host) expect(agent.agent.http.proxy_uri.port).to eq(proxy_port.to_i) - no_proxy_array = [ no_proxy1, no_proxy2 ] + no_proxy_array = [no_proxy1, no_proxy2] expect(agent.agent.http.no_proxy).to eq(no_proxy_array) end end diff --git a/spec/logger_spec.rb b/spec/logger_spec.rb new file mode 100755 index 0000000..0738a01 --- /dev/null +++ b/spec/logger_spec.rb @@ -0,0 +1,27 @@ +require 'rspec' +require_relative '../lib/frameworks/logger' + +describe FrameworksCapybara::Logger do + describe 'log levels' do + let(:test) { Class.new { include FrameworksCapybara::Logger }.new } + + it 'sets a default log level of debug' do + expect(test.log_level).to eql :debug + end + + it 'allows_log_level to be overwritten uppercase' do + ENV['LOG_LEVEL'] = 'WARN' + expect(test.log_level).to eql :warn + end + + it 'allows_log_level to be overwritten lowercase' do + ENV['LOG_LEVEL'] = 'info' + expect(test.log_level).to eql :info + end + + it 'ignores invalid log levels' do + ENV['LOG_LEVEL'] = 'FOOBAR' + expect(test.log_level).to eql :debug + end + end +end diff --git a/spec/mock.default/prefs.js b/spec/mock.default/prefs.js old mode 100644 new mode 100755 diff --git a/spec/profiles.ini b/spec/profiles.ini old mode 100644 new mode 100755 diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb old mode 100644 new mode 100755 index 5c6076d..02cc03a --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,7 +1,6 @@ require 'rubygems' require 'bundler/setup' -require 'gherkin' -require 'cucumber/language_support/language_methods' +require 'cucumber/configuration' require 'cucumber/rb_support/rb_language' require 'cucumber/runtime' require 'rspec' @@ -9,7 +8,8 @@ dir = File.dirname(__FILE__) $LOAD_PATH.unshift "#{dir}/../lib" -Cucumber::RbSupport::RbLanguage.new(Cucumber::Runtime.new) #Need to load Cucumber runtime, so World is available +c = Cucumber::Configuration.new +Cucumber::RbSupport::RbLanguage.new(Cucumber::Runtime.new, c) # Need to load Cucumber runtime, so World is available require 'frameworks/capybara' require 'frameworks/cucumber' diff --git a/spec/unit_test_monkeypatches.rb b/spec/unit_test_monkeypatches.rb old mode 100644 new mode 100755 index 56dcc88..b721543 --- a/spec/unit_test_monkeypatches.rb +++ b/spec/unit_test_monkeypatches.rb @@ -4,17 +4,14 @@ module Selenium module WebDriver module Firefox - # @api private module Util module_function def app_data_path - File.dirname(__FILE__) + File.dirname(__FILE__) end - end # Util end # Firefox end # WebDriver end # Selenium - diff --git a/spec/utils_spec.rb b/spec/utils_spec.rb new file mode 100755 index 0000000..c573339 --- /dev/null +++ b/spec/utils_spec.rb @@ -0,0 +1,11 @@ +require 'rspec' +require_relative '../lib/frameworks/utils' + +describe FrameworksCapybara::Utils do + describe 'generic util methods' do + let(:test) { Class.new { include FrameworksCapybara::Utils }.new } + it 'converts english to ruby method name' do + expect(test.rubyize('Hello Matt')).to eql 'hello_matt' + end + end +end diff --git a/spec/wait_spec.rb b/spec/wait_spec.rb old mode 100644 new mode 100755 index c39cac0..bf87887 --- a/spec/wait_spec.rb +++ b/spec/wait_spec.rb @@ -1,27 +1,47 @@ require 'frameworks/wait' -describe Wait do - it "should exit silently if the block returns true" do - Wait.until(){ - true - } +describe FrameworksCapybara::Wait do + let(:test) { Class.new { include FrameworksCapybara::Wait }.new } + + describe 'wait_for' do + it 'should exit silently if the block returns true' do + test.wait_for { true } + end + + it 'should raise an exception if the default timeout expires' do + expect { test.wait_for('foo') { true == false } }.to raise_error + end + + it 'should raise an exception if the specified timeout expires' do + start_time = Time.now + expect { + test.wait_for('', timeout: 1) do + Time.now > (start_time + (2 * 60)) + end + }.to raise_error + end end - it "should raise an exception if the default timeout expires" do - start_time = Time.now - expect { - Wait.until(){ - Time.now > (start_time + (6 * 60)) - } - }.to raise_error + describe 'wait for an rspec assertion' do + it 'should allow us to wait for assertions' do + expect(test.wait_for_assertion('msg') { expect(true).to eql true }).to be true + end + + it 'should raise rspec expectation error when condition is not met' do + error = RSpec::Expectations::ExpectationNotMetError + expect { test.wait_for_assertion('msg') { expect(true).to eql false } }.to raise_error(error) + end end - it "should raise an exception if the specified timeout expires" do - start_time = Time.now - expect { - Wait.until(options={:timeout => 1}) do - Time.now > (start_time + (2 * 60)) - end - }.to raise_error + describe 'wait for an arbitrary assertion' do + it 'should catch provided exception until block no longer raises it' do + error = ZeroDivisionError + expect(test.wait_for_no_exception('msg', error) { 1 / 1 == 1 }).to eql true + end + + it 'should catch provided exception until block no longer raises it or timeout' do + error = ZeroDivisionError + expect { test.wait_for_no_exception('msg', error) { expect(1 / 0).to eql 1 } }.to raise_error(error) + end end -end \ No newline at end of file +end