module SauceRSpec

Constants

DATE
MUTEX
VERSION

Attributes

driver[R]

Public Class Methods

config(&block) click to toggle source
# File lib/sauce_rspec/config.rb, line 70
def config &block
  return @config unless block_given?
  block.call @config

  # Set test-queue-split workers to the Sauce concurrency limit by default
  test_queue_workers = 'TEST_QUEUE_WORKERS'
  if SauceRSpec.config.sauce? && (!ENV[test_queue_workers] || ENV[test_queue_workers].empty?)
    user                = SauceRSpec.config.user
    hurley_client       = SauceRSpec.hurley_client
    concurrency_url     = "users/#{user}/concurrency"
    concurrency_timeout = SauceRSpec.config.concurrency_timeout || 2 * 60

    wait_true(concurrency_timeout) do
      body = hurley_client.get(concurrency_url).body
      concurrency = body['concurrency'][user]['remaining']['overall'] rescue false
      ENV[test_queue_workers] = concurrency.to_s if concurrency

      concurrency ? true : fail(body)
    end
  end

  @config
end
driver=(driver) click to toggle source

Fully initialized Selenium Webdriver.

# File lib/sauce_rspec/sauce_rspec.rb, line 12
def driver= driver
  fail 'Driver must not be nil' unless driver
  @driver                    = driver

  # Attach session_id to the current RSpec example.
  sauce_test_link            = "https://saucelabs.com/beta/tests/#{driver.session_id}"
  metadata                   = RSpec.current_example.metadata
  metadata[:sauce_test_link] = sauce_test_link
  # don't attach sauce link to description because it messes up formatters
  # the formatters don't expect a link in the test name.
end
hurley_client() click to toggle source
# File lib/sauce_rspec/sauce_rspec.rb, line 67
def hurley_client
  mutex do
    return @hurley_client if @hurley_client
    client                              = @hurley_client = Hurley::Client.new 'https://saucelabs.com/rest/v1/'
    client.header[:content_type]        = 'application/json'
    client.request_options.timeout      = 2 * 60
    client.request_options.open_timeout = 2 * 60

    config              = SauceRSpec.config
    client.url.user     = config.user
    client.url.password = config.key

    # Ensure body JSON string is parsed into a hash
    # Detect errors and fail so wait_true will retry the request
    client.after_call do |response|
      response.body = Oj.load(response.body) rescue {}

      client_server_error = %i(client_error server_error).include? response.status_type
      body_error          = response.body['error']

      if client_server_error || body_error
        response_error = body_error || ''
        fail(::Errno::ECONNREFUSED, response_error)
      end
    end

    @hurley_client
  end
end
mutex() click to toggle source

from: github.com/lostisland/hurley/blob/b61f4c96bcfa4fcd51c6718bc05f13e1c2ba01e6/lib/hurley.rb#L17

# File lib/sauce_rspec/sauce_rspec.rb, line 7
def mutex
  MUTEX.synchronize(&Proc.new)
end
run_after_test_hooks(timeout: 60, stdout: $stdout) click to toggle source
# File lib/sauce_rspec/sauce_rspec.rb, line 24
def run_after_test_hooks timeout: 60, stdout: $stdout
  jenkins(stdout) if jenkins?
  update_job_status_on_sauce(timeout) if SauceRSpec.config.sauce?
end
update_example_caps() click to toggle source

Returns the caps for the current RSpec example with the Sauce Labs job name set.

# File lib/sauce_rspec/sauce_rspec.rb, line 31
def update_example_caps
  example                     = RSpec.current_example
  meta                        = example.metadata

  # Must update the test description / full_description because we are
  # duplicating the tests and the only difference is the capabilities.
  #
  # Store a copy of the original description if it's not already saved.
  meta[:old_description]      = example.description unless meta[:old_description]
  meta[:old_full_description] = example.full_description unless meta[:old_full_description]

  # Reset the description to ensure previous runs don't mess with the value
  meta[:description]          = meta[:old_description]
  meta[:full_description]     = meta[:old_full_description]

  caps             = example.caps
  fail 'Example has no caps' unless caps
  full_description = example.full_description

  browser                  = caps[:browserName].capitalize
  version                  = caps[:platformVersion] || caps[:version]
  platform                 = caps[:platformName] || caps[:platform]

  # Set Sauce Labs job_name
  browser_version_platform = [browser, version, '-', platform].join ' '
  caps[:name]              = [full_description, '-', browser_version_platform].join ' '

  # Add browser info to description to ensure test names are unique
  # Otherwise the same test run on multiple browsers will not have a different name
  extra_description        = " - #{browser_version_platform}"
  meta[:full_description]  += extra_description
  meta[:description]       += extra_description

  caps
end

Private Class Methods

jenkins(stdout) click to toggle source
# File lib/sauce_rspec/sauce_rspec.rb, line 116
def jenkins stdout
  session_id = driver.session_id
  job_name   = RSpec.current_example.full_description
  # https://github.com/jenkinsci/sauce-ondemand-plugin/blob/2dbf9cf057d03480d020050a842aa23f595e4a3d/src/main/java/hudson/plugins/sauce_ondemand/SauceOnDemandBuildAction.java#L44
  stdout.puts "SauceOnDemandSessionID=#{session_id} job-name=#{job_name}"
end
update_job_status_on_sauce(timeout) click to toggle source

@param timeout <Integer> timeout in seconds to wait for sauce labs response

# File lib/sauce_rspec/sauce_rspec.rb, line 100
def update_job_status_on_sauce timeout
  # PUT https://saucelabs.com/rest/v1/:username/jobs/:job_id
  # https://docs.saucelabs.com/reference/rest-api/#update-job
  user           = SauceRSpec.config.user
  passed         = RSpec.current_example.exception.nil?
  passed         = { passed: passed }
  passed_json    = Oj.dump(passed)
  fail 'driver is nil' unless driver
  update_job_url = "#{user}/jobs/#{driver.session_id}"

  wait_true(timeout) do
    body = hurley_client.put(update_job_url, passed_json).body
    body['passed'] == passed[:passed] ? true : fail(body)
  end
end