diff --git a/examples/cucumber-capybara/Gemfile b/examples/cucumber-capybara/Gemfile index e6c3812..c498e88 100644 --- a/examples/cucumber-capybara/Gemfile +++ b/examples/cucumber-capybara/Gemfile @@ -4,3 +4,4 @@ gem 'cucumber' gem 'rspec' gem 'capybara' gem 'sauce', :path => '../../' +gem 'sauce-cucumber', :path => '../../gems/sauce-cucumber' diff --git a/examples/cucumber-capybara/features/support/env.rb b/examples/cucumber-capybara/features/support/env.rb index 1a93983..0a0c4ab 100644 --- a/examples/cucumber-capybara/features/support/env.rb +++ b/examples/cucumber-capybara/features/support/env.rb @@ -1,6 +1,5 @@ require 'capybara/cucumber' -require 'sauce/capybara' -require 'sauce/capybara/cucumber' +require 'sauce/cucumber' Capybara.current_driver = :sauce diff --git a/gems/sauce-cucumber/lib/sauce/cucumber.rb b/gems/sauce-cucumber/lib/sauce/cucumber.rb index cd41341..a27792a 100644 --- a/gems/sauce-cucumber/lib/sauce/cucumber.rb +++ b/gems/sauce-cucumber/lib/sauce/cucumber.rb @@ -1,5 +1,122 @@ +require 'capybara' +require 'cucumber' +require 'sauce/job' +require 'sauce/capybara' + module Sauce - module Cucumber - # Your code goes here... + 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: + 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 diff --git a/lib/sauce/capybara/cucumber.rb b/lib/sauce/capybara/cucumber.rb deleted file mode 100644 index a4078fa..0000000 --- a/lib/sauce/capybara/cucumber.rb +++ /dev/null @@ -1,121 +0,0 @@ -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: - 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 diff --git a/spec/sauce/capybara/spec_helper.rb b/spec/cucumber_helper.rb similarity index 100% rename from spec/sauce/capybara/spec_helper.rb rename to spec/cucumber_helper.rb diff --git a/spec/sauce/capybara_spec.rb b/spec/sauce/capybara_spec.rb index 73160be..ebcaf15 100644 --- a/spec/sauce/capybara_spec.rb +++ b/spec/sauce/capybara_spec.rb @@ -1,6 +1,5 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper') require 'sauce/capybara' -require 'sauce/capybara/cucumber' describe Sauce::Capybara do describe '#connect_tunnel' do diff --git a/spec/sauce/capybara/cucumber_spec.rb b/spec/sauce/cucumber_spec.rb similarity index 94% rename from spec/sauce/capybara/cucumber_spec.rb rename to spec/sauce/cucumber_spec.rb index 4f4ed88..ea25b12 100644 --- a/spec/sauce/capybara/cucumber_spec.rb +++ b/spec/sauce/cucumber_spec.rb @@ -1,9 +1,8 @@ -require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper') -require 'sauce/capybara' -require 'sauce/capybara/cucumber' +require 'spec_helper' -# We need to pull in our local spec_helper.rb to test cucumbery things -require File.dirname(__FILE__) + '/spec_helper' +require 'sauce/cucumber' +# We need to pull in the cucumber_helper to effectively test cucumbery things +require 'cucumber_helper' module Sauce::Capybara describe Cucumber do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index ca255e8..b2f86d7 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,5 +1,6 @@ $:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib') $:.unshift File.expand_path(File.dirname(__FILE__) + '/../gems/sauce-jasmine/lib') +$:.unshift File.expand_path(File.dirname(__FILE__) + '/../gems/sauce-cucumber/lib') require 'sauce'