sauce_ruby/lib/sauce/capybara/cucumber.rb

122 lines
4.2 KiB
Ruby

require 'capybara'
require 'cucumber'
require 'sauce/job'
module Sauce
module Capybara
module Cucumber
def use_sauce_driver
::Capybara.current_driver = :sauce
end
module_function :use_sauce_driver
def name_from_scenario(scenario)
# Special behavior to handle Scenario Outlines
if scenario.instance_of? ::Cucumber::Ast::OutlineTable::ExampleRow
table = scenario.instance_variable_get(:@table)
outline = table.instance_variable_get(:@scenario_outline)
return "#{outline.feature.file} - #{outline.title} - #{table.headers} -> #{scenario.name}"
end
scenario, feature = _scenario_and_feature_name(scenario)
return "#{feature} - #{scenario}"
end
module_function :name_from_scenario
def jenkins_name_from_scenario(scenario)
# Special behavior to handle Scenario Outlines
if scenario.instance_of? ::Cucumber::Ast::OutlineTable::ExampleRow
table = scenario.instance_variable_get(:@table)
outline = table.instance_variable_get(:@scenario_outline)
return "#{outline.feature.short_name}.#{outline.title}.#{outline.title} (outline example: #{scenario.name})"
end
scenario, feature = _scenario_and_feature_name(scenario)
return "#{feature}.#{scenario}.#{scenario}"
end
module_function :jenkins_name_from_scenario
def _scenario_and_feature_name(scenario)
scenario_name = scenario.name.split("\n").first
feature_name = scenario.feature.short_name
return scenario_name, feature_name
end
module_function :_scenario_and_feature_name
def before_hook
Sauce::Capybara::Cucumber.use_sauce_driver
end
module_function :before_hook
def using_jenkins?
# JENKINS_SERVER_COOKIE seems to be as good as any sentinel value to
# determine whether we're running under Jenkins or not.
ENV['JENKINS_SERVER_COOKIE']
end
module_function :using_jenkins?
def around_hook(scenario, block)
::Capybara.current_driver = :sauce
driver = ::Capybara.current_session.driver
# This session_id is the job ID used by Sauce Labs, we're pulling it
# off of the driver now to make sure we have it after `block.call`
session_id = driver.browser.session_id
job_name = Sauce::Capybara::Cucumber.name_from_scenario(scenario)
custom_data = {}
if using_jenkins?
custom_data.merge!({:commit => ENV['GIT_COMMIT'] || ENV['SVN_COMMIT'],
:jenkins_node => ENV['NODE_NAME'],
:jenkins_job => ENV['JOB_NAME']})
end
job = Sauce::Job.new('id' => session_id,
'name' => job_name,
'custom-data' => custom_data)
job.save unless job.nil?
Sauce.config do |c|
c[:name] = Sauce::Capybara::Cucumber.name_from_scenario(scenario)
end
if using_jenkins?
# If we're running under Jenkins, we should dump the
# `SauceOnDemandSessionID` into the Console Output for the Sauce OnDemand
# Jenkins plugin.
# See: <https://github.com/saucelabs/sauce_ruby/issues/48>
output = []
output << "\nSauceOnDemandSessionID=#{session_id}"
# The duplication in the scenario_name comes from the fact that the
# JUnit formatter seems to do the same, so in order to get the sauce
# OnDemand plugin for Jenkins to co-operate, we need to double it up as
# well
output << "job-name=#{Sauce::Capybara::Cucumber.jenkins_name_from_scenario(scenario)}"
puts output.join(' ')
end
block.call
# Quit the driver to allow for the generation of a new session_id
driver.browser.quit
driver.instance_variable_set(:@browser, nil)
unless job.nil?
job.passed = !scenario.failed?
job.save
end
end
module_function :around_hook
end
end
end
begin
Before('@selenium') do
Sauce::Capybara::Cucumber.before_hook
end
Around('@selenium') do |scenario, block|
Sauce::Capybara::Cucumber.around_hook(scenario, block)
end
rescue NoMethodError # This makes me sad
end