module Capybara::Webmock

Constants

SEPARATOR
VERSION

Attributes

allowed_hosts[RW]
kill_timeout[RW]
pid_file[RW]
port_number[RW]
start_timeout[RW]

Public Class Methods

chrome_headless_options() click to toggle source
# File lib/capybara/webmock.rb, line 82
def chrome_headless_options
  chrome_options.tap { |options| options.headless! }
end
chrome_options() click to toggle source
# File lib/capybara/webmock.rb, line 76
def chrome_options
  ::Selenium::WebDriver::Chrome::Options.new.tap do |options|
    options.add_argument "--proxy-server=127.0.0.1:#{port_number}"
  end
end
firefox_profile() click to toggle source
# File lib/capybara/webmock.rb, line 65
def firefox_profile
  proxy_host = '127.0.0.1'
  profile = ::Selenium::WebDriver::Firefox::Profile.new
  profile["network.proxy.type"] = 1
  profile["network.proxy.http"] = proxy_host
  profile["network.proxy.http_port"] = port_number
  profile["network.proxy.ssl"] = proxy_host
  profile["network.proxy.ssl_port"] = port_number
  profile
end
phantomjs_options() click to toggle source
# File lib/capybara/webmock.rb, line 86
def phantomjs_options
  ["--proxy=127.0.0.1:#{port_number}"]
end
proxied_requests() click to toggle source
# File lib/capybara/webmock.rb, line 42
def proxied_requests
  @output_buf += get_output_nonblocking

  matches = @output_buf.sub(/\n[^\n]+\z/, '').split("\n").map do |line|
    match = /\A(.+) -> (.+)\Z/.match(line)
    next nil unless match
    match.captures
  end

  matches.compact.map{ |raw_referrer, raw_uri| ProxiedRequest.new(raw_referrer, raw_uri) }
end
reset() click to toggle source
# File lib/capybara/webmock.rb, line 37
def reset
  get_output_nonblocking
  @output_buf = ""
end
start() click to toggle source
# File lib/capybara/webmock.rb, line 17
def start
  if @pid.nil?
    kill_old_process
    gem_path   = File.dirname(__FILE__)
    proxy_file = File.join(gem_path, 'webmock', 'config.ru')
    env_config = {
      "CAPYBARA_WEBMOCK_PROXY_PORT_NUMBER" => port_number.to_s,
      "CAPYBARA_WEBMOCK_ADDED_HOSTS" => allowed_hosts.to_a.join(SEPARATOR)
    }
    stdin, stdout, wait_thr = Open3.popen2e(env_config, "rackup", proxy_file)
    stdin.close
    @stdout = stdout
    @pid = wait_thr[:pid]
    write_pid_file
    wait_for_proxy_start
  end

  reset
end
stop() click to toggle source
# File lib/capybara/webmock.rb, line 54
def stop
  return if @pid.nil?

  @stdout.close
  kill_process(@pid)
  remove_pid_file

  @pid = nil
  @stdout = nil
end

Private Class Methods

get_output_nonblocking() click to toggle source
# File lib/capybara/webmock.rb, line 109
def get_output_nonblocking
  buf = ""

  while true
    begin
      output = @stdout.read_nonblock(1024)
      break if output == ""
      buf += output
    rescue IO::WaitReadable
      break
    end
  end

  buf
end
kill_old_process() click to toggle source
# File lib/capybara/webmock.rb, line 125
def kill_old_process
  return unless File.exists?(pid_file)
  old_pid = File.read(pid_file).to_i
  kill_process(old_pid) if old_pid > 1
  remove_pid_file
end
kill_process(pid) click to toggle source
# File lib/capybara/webmock.rb, line 132
def kill_process(pid)
  Process.kill('HUP', pid) if process_alive?(pid)

  (1..kill_timeout).each do
    sleep(1) if process_alive?(pid)
  end

  Process.kill('KILL', pid) if process_alive?(pid)

  (1..kill_timeout).each do
    sleep(1) if process_alive?(pid)
  end

  if process_alive?(pid)
    raise "Unable to kill capybara-webmock process with PID #{pid}"
  end
end
process_alive?(pid) click to toggle source
# File lib/capybara/webmock.rb, line 150
def process_alive?(pid)
  !!Process.kill(0, pid) rescue false
end
remove_pid_file() click to toggle source
# File lib/capybara/webmock.rb, line 160
def remove_pid_file
  File.delete(pid_file) if File.exists?(pid_file)
end
wait_for_proxy_start() click to toggle source
# File lib/capybara/webmock.rb, line 92
def wait_for_proxy_start
  connected = false
  (1..start_timeout).each do
    begin
      Socket.tcp("127.0.0.1", port_number, connect_timeout: 1) {}
      connected = true
      break
    rescue => e
      sleep 1
    end
  end

  unless connected
    raise "Unable to connect to capybara-webmock proxy on #{port_number}"
  end
end
write_pid_file() click to toggle source
# File lib/capybara/webmock.rb, line 154
def write_pid_file
  raise "Pid file #{pid_file} already exists" if File.exists?(pid_file)
  FileUtils.mkdir_p(File.dirname(pid_file))
  File.write(pid_file, @pid.to_s)
end