Introduce API for global configuration
Users were generally confused about where to configure things like allowed URLs. Because they were reset in between each sessions, they needed to be applied repeatedly in a before block. This introduces an API for global configuration, which will be applied for every session. It also deprecates the per-session configuration methods, as those are less likely to be useful.
This commit is contained in:
parent
bcbcdabd37
commit
519d90306b
72
README.md
72
README.md
|
@ -82,6 +82,60 @@ If you're using capybara-webkit with Sinatra, don't forget to set
|
|||
Capybara.app = MySinatraApp.new
|
||||
```
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
You can configure global options using `Capybara::Webkit.configure`:
|
||||
|
||||
``` ruby
|
||||
Capybara::Webkit.configure do |config|
|
||||
# Enable debug mode. Prints a log of everything the driver is doing.
|
||||
config.debug = true
|
||||
|
||||
# By default, requests to outside domains (anything besides localhost) will
|
||||
# result in a warning. Several methods allow you to change this behavior.
|
||||
|
||||
# Silently return an empty 200 response for any requests to unknown URLs.
|
||||
config.block_unknown_urls
|
||||
|
||||
# Allow pages to make requests to any URL without issuing a warning.
|
||||
config.allow_unknown_urls
|
||||
|
||||
# Allow a specifc domain without issuing a warning.
|
||||
config.allow_url("example.com")
|
||||
|
||||
# Allow a specifc URL and path without issuing a warning.
|
||||
config.allow_url("example.com/some/path")
|
||||
|
||||
# Wildcards are allowed in URL expressions.
|
||||
config.allow_url("*.example.com")
|
||||
|
||||
# Silently return an empty 200 response for any requests to the given URL.
|
||||
config.block_url("example.com")
|
||||
|
||||
# Timeout if requests take longer than 5 seconds
|
||||
config.timeout = 5
|
||||
|
||||
# Don't raise errors when SSL certificates can't be validated
|
||||
config.ignore_ssl_errors
|
||||
|
||||
# Don't load images
|
||||
config.skip_image_loading
|
||||
|
||||
# Use a proxy
|
||||
config.use_proxy(
|
||||
host: "example.com",
|
||||
port: 1234,
|
||||
user: "proxy",
|
||||
pass: "secret"
|
||||
)
|
||||
end
|
||||
```
|
||||
|
||||
These options will take effect for all future sessions and only need to be set
|
||||
once. It's recommended that you configure these in your `spec_helper.rb` or
|
||||
`test_helper.rb` rather than a `before` or `setup` block.
|
||||
|
||||
Offline Application Cache
|
||||
-------------------------
|
||||
|
||||
|
@ -127,24 +181,6 @@ page.driver.cookies["alpha"]
|
|||
page.driver.header 'Referer', 'https://www.thoughtbot.com'
|
||||
```
|
||||
|
||||
**block_unknown_urls**: By default, capybara-webkit will warn when a request is made to a URL other than 127.0.0.1 or localhost. This option will block such unknown URLs instead.
|
||||
|
||||
```ruby
|
||||
page.driver.block_unknown_urls
|
||||
```
|
||||
|
||||
**allow_url**: Allow requests to a URL. This will silence unknown URL warnings, or permit requests to a URL when `block_unknown_urls` is used. Allowed URLs are reset on `Driver#reset!`.
|
||||
|
||||
```ruby
|
||||
page.driver.allow_url 'example.com/*.js'
|
||||
```
|
||||
|
||||
**allow_unknown_urls**: Allow requests to all URLs. This will silence unknown URL warnings, or permit requests to all URLs when `block_unknown_urls` is used. Allowed URLs are reset on `Driver#reset!`.
|
||||
|
||||
```ruby
|
||||
page.driver.allow_unknown_urls
|
||||
```
|
||||
|
||||
Contributing
|
||||
------------
|
||||
|
||||
|
|
|
@ -2,17 +2,22 @@ require "capybara"
|
|||
|
||||
module Capybara
|
||||
module Webkit
|
||||
def self.configure(&block)
|
||||
Capybara::Webkit::Configuration.modify(&block)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
require "capybara/webkit/driver"
|
||||
require "capybara/webkit/configuration"
|
||||
|
||||
Capybara.register_driver :webkit do |app|
|
||||
Capybara::Webkit::Driver.new(app)
|
||||
Capybara::Webkit::Driver.new(app, Capybara::Webkit::Configuration.to_hash)
|
||||
end
|
||||
|
||||
Capybara.register_driver :webkit_debug do |app|
|
||||
driver = Capybara::Webkit::Driver.new(app)
|
||||
driver.enable_logging
|
||||
driver
|
||||
Capybara::Webkit::Driver.new(
|
||||
app,
|
||||
Capybara::Webkit::Configuration.to_hash.merge(debug: true)
|
||||
)
|
||||
end
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
module Capybara
|
||||
module Webkit
|
||||
class Configuration
|
||||
class << self
|
||||
private
|
||||
|
||||
def instance
|
||||
@instance ||= new
|
||||
end
|
||||
end
|
||||
|
||||
def self.to_hash
|
||||
instance.freeze.to_hash
|
||||
end
|
||||
|
||||
def self.modify
|
||||
if instance.frozen?
|
||||
raise "All configuration must take place before the driver starts"
|
||||
else
|
||||
yield instance
|
||||
end
|
||||
end
|
||||
|
||||
attr_accessor :allowed_urls
|
||||
attr_writer :block_unknown_urls
|
||||
attr_accessor :blocked_urls
|
||||
attr_accessor :debug
|
||||
attr_writer :ignore_ssl_errors
|
||||
attr_accessor :proxy
|
||||
attr_accessor :timeout
|
||||
attr_writer :skip_image_loading
|
||||
|
||||
def initialize
|
||||
@allowed_urls = []
|
||||
@blocked_urls = []
|
||||
@block_unknown_urls = false
|
||||
@debug = false
|
||||
@ignore_ssl_errors = false
|
||||
@proxy = nil
|
||||
@skip_image_loading = false
|
||||
@timeout = -1
|
||||
end
|
||||
|
||||
def allow_url(url)
|
||||
@allowed_urls << url
|
||||
end
|
||||
|
||||
def block_url(url)
|
||||
@blocked_urls << url
|
||||
end
|
||||
|
||||
def block_unknown_urls
|
||||
@block_unknown_urls = true
|
||||
end
|
||||
|
||||
def block_unknown_urls?
|
||||
@block_unknown_urls
|
||||
end
|
||||
|
||||
def allow_unknown_urls
|
||||
allow_url("*")
|
||||
end
|
||||
|
||||
def ignore_ssl_errors
|
||||
@ignore_ssl_errors = true
|
||||
end
|
||||
|
||||
def ignore_ssl_errors?
|
||||
@ignore_ssl_errors
|
||||
end
|
||||
|
||||
def skip_image_loading
|
||||
@skip_image_loading = true
|
||||
end
|
||||
|
||||
def skip_image_loading?
|
||||
@skip_image_loading
|
||||
end
|
||||
|
||||
def use_proxy(proxy)
|
||||
@proxy = proxy
|
||||
end
|
||||
|
||||
def to_hash
|
||||
{
|
||||
allowed_urls: allowed_urls,
|
||||
block_unknown_urls: block_unknown_urls?,
|
||||
blocked_urls: blocked_urls,
|
||||
debug: debug,
|
||||
ignore_ssl_errors: ignore_ssl_errors?,
|
||||
proxy: proxy,
|
||||
skip_image_loading: skip_image_loading?,
|
||||
timeout: timeout
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -12,25 +12,31 @@ module Capybara::Webkit
|
|||
@app = app
|
||||
@options = options
|
||||
@browser = options[:browser] || Browser.new(Connection.new(options))
|
||||
apply_options
|
||||
end
|
||||
|
||||
def enable_logging
|
||||
deprecate_and_replace_with_config "enable_logging", "debug = true"
|
||||
@browser.enable_logging
|
||||
end
|
||||
|
||||
def allow_url(url)
|
||||
deprecate_and_replace_with_config "allow_url", "allow_url(#{url.inspect})"
|
||||
@browser.allow_url(url)
|
||||
end
|
||||
|
||||
def block_url(url)
|
||||
deprecate_and_replace_with_config "block_url", "block_url(#{url.inspect})"
|
||||
@browser.block_url(url)
|
||||
end
|
||||
|
||||
def block_unknown_urls
|
||||
deprecate_and_replace_with_config "block_unknown_urls"
|
||||
@browser.block_unknown_urls
|
||||
end
|
||||
|
||||
def allow_unknown_urls
|
||||
deprecate_and_replace_with_config "allow_unknown_urls"
|
||||
@browser.allow_url("*")
|
||||
end
|
||||
|
||||
|
@ -254,6 +260,7 @@ module Capybara::Webkit
|
|||
|
||||
def reset!
|
||||
@browser.reset!
|
||||
apply_options
|
||||
end
|
||||
|
||||
def has_shortcircuit_timeout?
|
||||
|
@ -300,10 +307,15 @@ module Capybara::Webkit
|
|||
end
|
||||
|
||||
def timeout
|
||||
deprecate_and_replace_with_config "timeout"
|
||||
@browser.timeout
|
||||
end
|
||||
|
||||
def timeout=(timeout)
|
||||
deprecate_and_replace_with_config(
|
||||
"timeout=",
|
||||
"timeout = #{timeout.inspect}"
|
||||
)
|
||||
@browser.timeout = timeout
|
||||
end
|
||||
|
||||
|
@ -333,5 +345,44 @@ module Capybara::Webkit
|
|||
raise Capybara::ModalNotFound,
|
||||
"Timed out waiting for modal dialog#{" with #{options[:original_text]}" if options[:original_text]}"
|
||||
end
|
||||
|
||||
def apply_options
|
||||
if @options[:debug]
|
||||
@browser.enable_logging
|
||||
end
|
||||
|
||||
if @options[:block_unknown_urls]
|
||||
@browser.block_unknown_urls
|
||||
end
|
||||
|
||||
if @options[:ignore_ssl_errors]
|
||||
@browser.ignore_ssl_errors
|
||||
end
|
||||
|
||||
if @options[:skip_image_loading]
|
||||
@browser.set_skip_image_loading(true)
|
||||
end
|
||||
|
||||
if @options[:proxy]
|
||||
@browser.set_proxy(@options[:proxy])
|
||||
end
|
||||
|
||||
if @options[:timeout]
|
||||
@browser.timeout = @options[:timeout]
|
||||
end
|
||||
|
||||
Array(@options[:allowed_urls]).each { |url| @browser.allow_url(url) }
|
||||
Array(@options[:blocked_urls]).each { |url| @browser.block_url(url) }
|
||||
end
|
||||
|
||||
def deprecate_and_replace_with_config(deprecated_method, config_syntax = deprecated_method)
|
||||
warn "[DEPRECATION] #{deprecated_method} is deprecated. " \
|
||||
"Please use Capybara::Webkit.configure instead:\n\n" \
|
||||
" Capybara::Webkit.configure do |config|\n" \
|
||||
" config.#{config_syntax}\n" \
|
||||
" end\n\n" \
|
||||
"This option is global and can be configured once" \
|
||||
" (not in a `before` or `setup` block)."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -9,144 +9,6 @@ describe Capybara::Webkit::Browser do
|
|||
|
||||
let(:connection) { Capybara::Webkit::Connection.new }
|
||||
let(:browser) { Capybara::Webkit::Browser.new(connection) }
|
||||
let(:browser_ignore_ssl_err) do
|
||||
Capybara::Webkit::Browser.new(Capybara::Webkit::Connection.new).tap do |browser|
|
||||
browser.ignore_ssl_errors
|
||||
end
|
||||
end
|
||||
let(:browser_skip_images) do
|
||||
Capybara::Webkit::Browser.new(Capybara::Webkit::Connection.new).tap do |browser|
|
||||
browser.set_skip_image_loading(true)
|
||||
end
|
||||
end
|
||||
|
||||
context 'handling of SSL validation errors' do
|
||||
before do
|
||||
# set up minimal HTTPS server
|
||||
@host = "127.0.0.1"
|
||||
@server = TCPServer.new(@host, 0)
|
||||
@port = @server.addr[1]
|
||||
|
||||
# set up SSL layer
|
||||
ssl_serv = OpenSSL::SSL::SSLServer.new(@server, $openssl_self_signed_ctx)
|
||||
|
||||
@server_thread = Thread.new(ssl_serv) do |serv|
|
||||
while conn = serv.accept do
|
||||
# read request
|
||||
request = []
|
||||
until (line = conn.readline.strip).empty?
|
||||
request << line
|
||||
end
|
||||
|
||||
# write response
|
||||
html = "<html><body>D'oh!</body></html>"
|
||||
conn.write "HTTP/1.1 200 OK\r\n"
|
||||
conn.write "Content-Type:text/html\r\n"
|
||||
conn.write "Content-Length: %i\r\n" % html.size
|
||||
conn.write "\r\n"
|
||||
conn.write html
|
||||
conn.close
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
after do
|
||||
@server_thread.kill
|
||||
@server.close
|
||||
end
|
||||
|
||||
it "doesn't accept a self-signed certificate by default" do
|
||||
lambda { browser.visit "https://#{@host}:#{@port}/" }.should raise_error
|
||||
end
|
||||
|
||||
it 'accepts a self-signed certificate if configured to do so' do
|
||||
browser_ignore_ssl_err.visit "https://#{@host}:#{@port}/"
|
||||
end
|
||||
|
||||
it "doesn't accept a self-signed certificate in a new window by default" do
|
||||
browser.execute_script("window.open('about:blank')")
|
||||
browser.window_focus(browser.get_window_handles.last)
|
||||
lambda { browser.visit "https://#{@host}:#{@port}/" }.should raise_error
|
||||
end
|
||||
|
||||
it 'accepts a self-signed certificate in a new window if configured to do so' do
|
||||
browser_ignore_ssl_err.execute_script("window.open('about:blank')")
|
||||
browser_ignore_ssl_err.window_focus(browser_ignore_ssl_err.get_window_handles.last)
|
||||
browser_ignore_ssl_err.visit "https://#{@host}:#{@port}/"
|
||||
end
|
||||
end
|
||||
|
||||
context "skip image loading" do
|
||||
before(:each) do
|
||||
# set up minimal HTTP server
|
||||
@host = "127.0.0.1"
|
||||
@server = TCPServer.new(@host, 0)
|
||||
@port = @server.addr[1]
|
||||
@received_requests = []
|
||||
|
||||
@server_thread = Thread.new do
|
||||
while conn = @server.accept
|
||||
Thread.new(conn) do |thread_conn|
|
||||
# read request
|
||||
request = []
|
||||
until (line = thread_conn.readline.strip).empty?
|
||||
request << line
|
||||
end
|
||||
|
||||
@received_requests << request.join("\n")
|
||||
|
||||
# write response
|
||||
html = <<-HTML
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body {
|
||||
background-image: url(/path/to/bgimage);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<img src="/path/to/image"/>
|
||||
</body>
|
||||
</html>
|
||||
HTML
|
||||
thread_conn.write "HTTP/1.1 200 OK\r\n"
|
||||
thread_conn.write "Content-Type:text/html\r\n"
|
||||
thread_conn.write "Content-Length: %i\r\n" % html.size
|
||||
thread_conn.write "\r\n"
|
||||
thread_conn.write html
|
||||
thread_conn.write("\r\n\r\n")
|
||||
thread_conn.close
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
after(:each) do
|
||||
@server_thread.kill
|
||||
@server.close
|
||||
end
|
||||
|
||||
it "should load images in image tags by default" do
|
||||
browser.visit("http://#{@host}:#{@port}/")
|
||||
@received_requests.find {|r| r =~ %r{/path/to/image} }.should_not be_nil
|
||||
end
|
||||
|
||||
it "should load images in css by default" do
|
||||
browser.visit("http://#{@host}:#{@port}/")
|
||||
@received_requests.find {|r| r =~ %r{/path/to/image} }.should_not be_nil
|
||||
end
|
||||
|
||||
it "should not load images in image tags when skip_image_loading is true" do
|
||||
browser_skip_images.visit("http://#{@host}:#{@port}/")
|
||||
@received_requests.find {|r| r =~ %r{/path/to/image} }.should be_nil
|
||||
end
|
||||
|
||||
it "should not load images in css when skip_image_loading is true" do
|
||||
browser_skip_images.visit("http://#{@host}:#{@port}/")
|
||||
@received_requests.find {|r| r =~ %r{/path/to/bgimage} }.should be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe "forking", skip_on_windows: true, skip_on_jruby: true do
|
||||
it "only shuts down the server from the main process" do
|
||||
|
@ -157,97 +19,6 @@ describe Capybara::Webkit::Browser do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#set_proxy' do
|
||||
before do
|
||||
@host = '127.0.0.1'
|
||||
@user = 'user'
|
||||
@pass = 'secret'
|
||||
@url = "http://example.org/"
|
||||
|
||||
@server = TCPServer.new(@host, 0)
|
||||
@port = @server.addr[1]
|
||||
|
||||
@proxy_requests = []
|
||||
@proxy = Thread.new(@server, @proxy_requests) do |serv, proxy_requests|
|
||||
while conn = serv.accept do
|
||||
# read request
|
||||
request = []
|
||||
until (line = conn.readline.strip).empty?
|
||||
request << line
|
||||
end
|
||||
|
||||
# send response
|
||||
auth_header = request.find { |h| h =~ /Authorization:/i }
|
||||
if auth_header || request[0].split(/\s+/)[1] =~ /^\//
|
||||
html = "<html><body>D'oh!</body></html>"
|
||||
conn.write "HTTP/1.1 200 OK\r\n"
|
||||
conn.write "Content-Type:text/html\r\n"
|
||||
conn.write "Content-Length: %i\r\n" % html.size
|
||||
conn.write "\r\n"
|
||||
conn.write html
|
||||
conn.close
|
||||
proxy_requests << request if auth_header
|
||||
else
|
||||
conn.write "HTTP/1.1 407 Proxy Auth Required\r\n"
|
||||
conn.write "Proxy-Authenticate: Basic realm=\"Proxy\"\r\n"
|
||||
conn.write "\r\n"
|
||||
conn.close
|
||||
proxy_requests << request
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
browser.set_proxy(:host => @host,
|
||||
:port => @port,
|
||||
:user => @user,
|
||||
:pass => @pass)
|
||||
browser.visit @url
|
||||
@proxy_requests.size.should eq 2
|
||||
@request = @proxy_requests[-1]
|
||||
end
|
||||
|
||||
after do
|
||||
@proxy.kill
|
||||
@server.close
|
||||
end
|
||||
|
||||
it 'uses the HTTP proxy correctly' do
|
||||
@request[0].should match(/^GET\s+http:\/\/example.org\/\s+HTTP/i)
|
||||
@request.find { |header|
|
||||
header =~ /^Host:\s+example.org$/i }.should_not be nil
|
||||
end
|
||||
|
||||
it 'sends correct proxy authentication' do
|
||||
auth_header = @request.find { |header|
|
||||
header =~ /^Proxy-Authorization:\s+/i }
|
||||
auth_header.should_not be nil
|
||||
|
||||
user, pass = Base64.decode64(auth_header.split(/\s+/)[-1]).split(":")
|
||||
user.should eq @user
|
||||
pass.should eq @pass
|
||||
end
|
||||
|
||||
it "uses the proxies' response" do
|
||||
browser.body.should include "D'oh!"
|
||||
end
|
||||
|
||||
it 'uses original URL' do
|
||||
browser.current_url.should eq @url
|
||||
end
|
||||
|
||||
it 'uses URLs changed by javascript' do
|
||||
browser.execute_script "window.history.pushState('', '', '/blah')"
|
||||
browser.current_url.should eq 'http://example.org/blah'
|
||||
end
|
||||
|
||||
it 'is possible to disable proxy again' do
|
||||
@proxy_requests.clear
|
||||
browser.clear_proxy
|
||||
browser.visit "http://#{@host}:#{@port}/"
|
||||
@proxy_requests.size.should eq 0
|
||||
end
|
||||
end
|
||||
|
||||
it "doesn't try to read an empty response" do
|
||||
connection = double("connection")
|
||||
connection.stub(:puts)
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
require "spec_helper"
|
||||
|
||||
describe Capybara::Webkit::Configuration do
|
||||
it "returns a hash and then prevents future modification" do
|
||||
Capybara::Webkit.configure do |config|
|
||||
config.debug = true
|
||||
end
|
||||
|
||||
result = Capybara::Webkit::Configuration.to_hash
|
||||
|
||||
expect(result).to include(debug: true)
|
||||
expect { Capybara::Webkit.configure {} }.to raise_error(
|
||||
"All configuration must take place before the driver starts"
|
||||
)
|
||||
end
|
||||
end
|
|
@ -3,6 +3,7 @@
|
|||
require 'spec_helper'
|
||||
require 'capybara/webkit/driver'
|
||||
require 'base64'
|
||||
require 'self_signed_ssl_cert'
|
||||
|
||||
describe Capybara::Webkit::Driver do
|
||||
include AppRunner
|
||||
|
@ -1808,7 +1809,7 @@ describe Capybara::Webkit::Driver do
|
|||
|
||||
context "no response app" do
|
||||
let(:driver) do
|
||||
driver_for_html(<<-HTML, browser)
|
||||
driver_for_html(<<-HTML, browser: browser)
|
||||
<html><body>
|
||||
<form action="/error"><input type="submit"/></form>
|
||||
</body></html>
|
||||
|
@ -2657,10 +2658,12 @@ CACHE MANIFEST
|
|||
end
|
||||
|
||||
before do
|
||||
driver.block_url "http://example.org/path/to/file"
|
||||
driver.block_url "http://example.*/foo/*"
|
||||
driver.block_url "http://example.com"
|
||||
driver.block_url "#{AppRunner.app_host}/script"
|
||||
configure do |config|
|
||||
config.block_url "http://example.org/path/to/file"
|
||||
config.block_url "http://example.*/foo/*"
|
||||
config.block_url "http://example.com"
|
||||
config.block_url "#{AppRunner.app_host}/script"
|
||||
end
|
||||
end
|
||||
|
||||
it "should not fetch urls blocked by host" do
|
||||
|
@ -2707,7 +2710,7 @@ CACHE MANIFEST
|
|||
describe "url whitelisting", skip_if_offline: true do
|
||||
it_behaves_like "output writer" do
|
||||
let(:driver) do
|
||||
driver_for_html(<<-HTML, browser)
|
||||
driver_for_html(<<-HTML, browser: browser)
|
||||
<<-HTML
|
||||
<html>
|
||||
<body>
|
||||
|
@ -2727,8 +2730,11 @@ CACHE MANIFEST
|
|||
end
|
||||
|
||||
it "can allow specific hosts" do
|
||||
driver.allow_url("example.com")
|
||||
driver.allow_url("www.example.com")
|
||||
configure do |config|
|
||||
config.allow_url("example.com")
|
||||
config.allow_url("www.example.com")
|
||||
end
|
||||
|
||||
visit("/")
|
||||
|
||||
expect(stderr).not_to include("http://example.com/path")
|
||||
|
@ -2739,7 +2745,7 @@ CACHE MANIFEST
|
|||
end
|
||||
|
||||
it "can allow all hosts" do
|
||||
driver.allow_unknown_urls
|
||||
configure(&:allow_unknown_urls)
|
||||
visit("/")
|
||||
|
||||
expect(stderr).not_to include("http://example.com/path")
|
||||
|
@ -2759,7 +2765,7 @@ CACHE MANIFEST
|
|||
end
|
||||
|
||||
it "can block unknown hosts" do
|
||||
driver.block_unknown_urls
|
||||
configure(&:block_unknown_urls)
|
||||
visit("/")
|
||||
|
||||
expect(stderr).not_to include("http://example.com/path")
|
||||
|
@ -2770,7 +2776,7 @@ CACHE MANIFEST
|
|||
end
|
||||
|
||||
it "can allow urls with wildcards" do
|
||||
driver.allow_url("*/path")
|
||||
configure { |config| config.allow_url("*/path") }
|
||||
visit("/")
|
||||
|
||||
expect(stderr).to include("www.example.com")
|
||||
|
@ -2820,29 +2826,29 @@ CACHE MANIFEST
|
|||
end
|
||||
|
||||
it "should not raise a timeout error when zero" do
|
||||
driver.timeout = 0
|
||||
configure { |config| config.timeout = 0 }
|
||||
lambda { visit("/") }.should_not raise_error
|
||||
end
|
||||
|
||||
it "should raise a timeout error" do
|
||||
driver.timeout = 1
|
||||
configure { |config| config.timeout = 1 }
|
||||
lambda { visit("/") }.should raise_error(Timeout::Error, "Request timed out after 1 second(s)")
|
||||
end
|
||||
|
||||
it "should not raise an error when the timeout is high enough" do
|
||||
driver.timeout = 10
|
||||
configure { |config| config.timeout = 10 }
|
||||
lambda { visit("/") }.should_not raise_error
|
||||
end
|
||||
|
||||
it "should set the timeout for each request" do
|
||||
driver.timeout = 10
|
||||
configure { |config| config.timeout = 10 }
|
||||
lambda { visit("/") }.should_not raise_error
|
||||
driver.timeout = 1
|
||||
lambda { visit("/") }.should raise_error(Timeout::Error)
|
||||
end
|
||||
|
||||
it "should set the timeout for each request" do
|
||||
driver.timeout = 1
|
||||
configure { |config| config.timeout = 1 }
|
||||
lambda { visit("/") }.should raise_error(Timeout::Error)
|
||||
driver.reset!
|
||||
driver.timeout = 10
|
||||
|
@ -2850,7 +2856,7 @@ CACHE MANIFEST
|
|||
end
|
||||
|
||||
it "should raise a timeout on a slow form" do
|
||||
driver.timeout = 3
|
||||
configure { |config| config.timeout = 3 }
|
||||
visit("/")
|
||||
driver.status_code.should eq 200
|
||||
driver.timeout = 1
|
||||
|
@ -2859,26 +2865,25 @@ CACHE MANIFEST
|
|||
end
|
||||
|
||||
it "get timeout" do
|
||||
driver.timeout = 10
|
||||
driver.timeout.should eq 10
|
||||
driver.timeout = 3
|
||||
driver.timeout.should eq 3
|
||||
configure { |config| config.timeout = 10 }
|
||||
driver.browser.timeout.should eq 10
|
||||
end
|
||||
end
|
||||
|
||||
describe "logger app" do
|
||||
it_behaves_like "output writer" do
|
||||
let(:driver) do
|
||||
driver_for_html("<html><body>Hello</body></html>", browser)
|
||||
driver_for_html("<html><body>Hello</body></html>", browser: browser)
|
||||
end
|
||||
|
||||
it "logs nothing before turning on the logger" do
|
||||
it "logs nothing in normal mode" do
|
||||
configure { |config| config.debug = false }
|
||||
visit("/")
|
||||
stderr.should_not include logging_message
|
||||
end
|
||||
|
||||
it "logs its commands after turning on the logger" do
|
||||
driver.enable_logging
|
||||
it "logs its commands in debug mode" do
|
||||
configure { |config| config.debug = true }
|
||||
visit("/")
|
||||
stderr.should include logging_message
|
||||
end
|
||||
|
@ -3049,7 +3054,7 @@ CACHE MANIFEST
|
|||
it_behaves_like "output writer" do
|
||||
let(:driver) do
|
||||
count = 0
|
||||
driver_for_app browser do
|
||||
driver_for_app browser: browser do
|
||||
get "/" do
|
||||
count += 1
|
||||
<<-HTML
|
||||
|
@ -3094,7 +3099,7 @@ CACHE MANIFEST
|
|||
|
||||
context "when the driver process crashes" do
|
||||
let(:driver) do
|
||||
driver_for_app browser do
|
||||
driver_for_app browser: browser do
|
||||
get "/" do
|
||||
"<html><body>Relaunched</body></html>"
|
||||
end
|
||||
|
@ -3112,6 +3117,223 @@ CACHE MANIFEST
|
|||
end
|
||||
end
|
||||
|
||||
context "handling of SSL validation errors" do
|
||||
before do
|
||||
# set up minimal HTTPS server
|
||||
@host = "127.0.0.1"
|
||||
@server = TCPServer.new(@host, 0)
|
||||
@port = @server.addr[1]
|
||||
|
||||
# set up SSL layer
|
||||
ssl_serv = OpenSSL::SSL::SSLServer.new(@server, $openssl_self_signed_ctx)
|
||||
|
||||
@server_thread = Thread.new(ssl_serv) do |serv|
|
||||
while conn = serv.accept do
|
||||
# read request
|
||||
request = []
|
||||
until (line = conn.readline.strip).empty?
|
||||
request << line
|
||||
end
|
||||
|
||||
# write response
|
||||
html = "<html><body>D'oh!</body></html>"
|
||||
conn.write "HTTP/1.1 200 OK\r\n"
|
||||
conn.write "Content-Type:text/html\r\n"
|
||||
conn.write "Content-Length: %i\r\n" % html.size
|
||||
conn.write "\r\n"
|
||||
conn.write html
|
||||
conn.close
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
after do
|
||||
@server_thread.kill
|
||||
@server.close
|
||||
end
|
||||
|
||||
context "with default settings" do
|
||||
it "doesn't accept a self-signed certificate" do
|
||||
lambda { driver.visit "https://#{@host}:#{@port}/" }.should raise_error
|
||||
end
|
||||
|
||||
it "doesn't accept a self-signed certificate in a new window" do
|
||||
driver.execute_script("window.open('about:blank')")
|
||||
driver.switch_to_window(driver.window_handles.last)
|
||||
lambda { driver.visit "https://#{@host}:#{@port}/" }.should raise_error
|
||||
end
|
||||
end
|
||||
|
||||
context "ignoring SSL errors" do
|
||||
it "accepts a self-signed certificate if configured to do so" do
|
||||
configure(&:ignore_ssl_errors)
|
||||
driver.visit "https://#{@host}:#{@port}/"
|
||||
end
|
||||
|
||||
it "accepts a self-signed certificate in a new window when configured" do
|
||||
configure(&:ignore_ssl_errors)
|
||||
driver.execute_script("window.open('about:blank')")
|
||||
driver.switch_to_window(driver.window_handles.last)
|
||||
driver.visit "https://#{@host}:#{@port}/"
|
||||
end
|
||||
end
|
||||
|
||||
let(:driver) { driver_for_html("", browser: browser) }
|
||||
let(:browser) { Capybara::Webkit::Browser.new(connection) }
|
||||
let(:connection) { Capybara::Webkit::Connection.new }
|
||||
end
|
||||
|
||||
context "skip image loading" do
|
||||
let(:driver) do
|
||||
driver_for_app do
|
||||
requests = []
|
||||
|
||||
get "/" do
|
||||
<<-HTML
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body {
|
||||
background-image: url(/path/to/bgimage);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<img src="/path/to/image"/>
|
||||
</body>
|
||||
</html>
|
||||
HTML
|
||||
end
|
||||
|
||||
get "/requests" do
|
||||
<<-HTML
|
||||
<html>
|
||||
<body>
|
||||
#{requests.map { |path| "<p>#{path}</p>" }.join}
|
||||
</body>
|
||||
</html>
|
||||
HTML
|
||||
end
|
||||
|
||||
get %r{/path/to/(.*)} do |path|
|
||||
requests << path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "should load images by default" do
|
||||
visit("/")
|
||||
requests.should match_array %w(image bgimage)
|
||||
end
|
||||
|
||||
it "should not load images when disabled" do
|
||||
configure(&:skip_image_loading)
|
||||
visit("/")
|
||||
requests.should eq []
|
||||
end
|
||||
|
||||
let(:requests) do
|
||||
visit "/requests"
|
||||
driver.find("//p").map(&:text)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#set_proxy" do
|
||||
before do
|
||||
@host = "127.0.0.1"
|
||||
@user = "user"
|
||||
@pass = "secret"
|
||||
@url = "http://example.org/"
|
||||
|
||||
@server = TCPServer.new(@host, 0)
|
||||
@port = @server.addr[1]
|
||||
|
||||
@proxy_requests = []
|
||||
@proxy = Thread.new(@server, @proxy_requests) do |serv, proxy_requests|
|
||||
while conn = serv.accept do
|
||||
# read request
|
||||
request = []
|
||||
until (line = conn.readline.strip).empty?
|
||||
request << line
|
||||
end
|
||||
|
||||
# send response
|
||||
auth_header = request.find { |h| h =~ /Authorization:/i }
|
||||
if auth_header || request[0].split(/\s+/)[1] =~ /^\//
|
||||
html = "<html><body>D'oh!</body></html>"
|
||||
conn.write "HTTP/1.1 200 OK\r\n"
|
||||
conn.write "Content-Type:text/html\r\n"
|
||||
conn.write "Content-Length: %i\r\n" % html.size
|
||||
conn.write "\r\n"
|
||||
conn.write html
|
||||
conn.close
|
||||
proxy_requests << request if auth_header
|
||||
else
|
||||
conn.write "HTTP/1.1 407 Proxy Auth Required\r\n"
|
||||
conn.write "Proxy-Authenticate: Basic realm=\"Proxy\"\r\n"
|
||||
conn.write "\r\n"
|
||||
conn.close
|
||||
proxy_requests << request
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
configure do |config|
|
||||
config.allow_url("example.org")
|
||||
config.use_proxy host: @host, port: @port, user: @user, pass: @pass
|
||||
end
|
||||
|
||||
driver.visit @url
|
||||
@proxy_requests.size.should eq 2
|
||||
@request = @proxy_requests[-1]
|
||||
end
|
||||
|
||||
after do
|
||||
@proxy.kill
|
||||
@server.close
|
||||
end
|
||||
|
||||
let(:driver) do
|
||||
driver_for_html("", browser: nil)
|
||||
end
|
||||
|
||||
it "uses the HTTP proxy correctly" do
|
||||
@request[0].should match(/^GET\s+http:\/\/example.org\/\s+HTTP/i)
|
||||
@request.find { |header|
|
||||
header =~ /^Host:\s+example.org$/i }.should_not be nil
|
||||
end
|
||||
|
||||
it "sends correct proxy authentication" do
|
||||
auth_header = @request.find { |header|
|
||||
header =~ /^Proxy-Authorization:\s+/i }
|
||||
auth_header.should_not be nil
|
||||
|
||||
user, pass = Base64.decode64(auth_header.split(/\s+/)[-1]).split(":")
|
||||
user.should eq @user
|
||||
pass.should eq @pass
|
||||
end
|
||||
|
||||
it "uses the proxy's response" do
|
||||
driver.html.should include "D'oh!"
|
||||
end
|
||||
|
||||
it "uses original URL" do
|
||||
driver.current_url.should eq @url
|
||||
end
|
||||
|
||||
it "uses URLs changed by javascript" do
|
||||
driver.execute_script %{window.history.pushState("", "", "/blah")}
|
||||
driver.current_url.should eq "http://example.org/blah"
|
||||
end
|
||||
|
||||
it "is possible to disable proxy again" do
|
||||
@proxy_requests.clear
|
||||
driver.browser.clear_proxy
|
||||
driver.visit "http://#{@host}:#{@port}/"
|
||||
@proxy_requests.size.should eq 0
|
||||
end
|
||||
end
|
||||
|
||||
def driver_url(driver, path)
|
||||
URI.parse(driver.current_url).merge(path).to_s
|
||||
end
|
||||
|
|
|
@ -5,7 +5,7 @@ require 'sinatra/base'
|
|||
|
||||
module AppRunner
|
||||
class << self
|
||||
attr_accessor :app, :app_host
|
||||
attr_accessor :app, :app_host, :configuration
|
||||
end
|
||||
|
||||
def self.boot
|
||||
|
@ -19,12 +19,18 @@ module AppRunner
|
|||
self.app = lambda do |env|
|
||||
[200, { 'Content-Type' => 'html', 'Content-Length' => 0 }, []]
|
||||
end
|
||||
|
||||
self.configuration = Capybara::Webkit::Configuration.new
|
||||
end
|
||||
|
||||
def run_application(app)
|
||||
AppRunner.app = app
|
||||
end
|
||||
|
||||
def configure
|
||||
yield AppRunner.configuration
|
||||
end
|
||||
|
||||
def driver_for_app(*driver_args, &body)
|
||||
app = Class.new(ExampleApp, &body)
|
||||
run_application app
|
||||
|
@ -50,8 +56,12 @@ module AppRunner
|
|||
|
||||
private
|
||||
|
||||
def build_driver(browser = $webkit_browser)
|
||||
Capybara::Webkit::Driver.new(AppRunner.app, :browser => browser)
|
||||
def build_driver(overrides = {})
|
||||
options = AppRunner.configuration.
|
||||
to_hash.
|
||||
merge(browser: $webkit_browser).
|
||||
merge(overrides)
|
||||
Capybara::Webkit::Driver.new(AppRunner.app, options)
|
||||
end
|
||||
|
||||
def self.included(example_group)
|
||||
|
|
Loading…
Reference in New Issue