Raise errors in main thread when error in application occurs, closes #660

This commit is contained in:
Jonas Nicklas 2012-07-13 14:57:43 +02:00
parent b0364e6bd0
commit 6f145fb069
4 changed files with 61 additions and 4 deletions

View File

@ -4,7 +4,9 @@ require 'rack'
module Capybara
class Server
class Identify
class Middleware
attr_accessor :error
def initialize(app)
@app = app
end
@ -13,7 +15,12 @@ module Capybara
if env["PATH_INFO"] == "/__identify__"
[200, {}, [@app.object_id.to_s]]
else
@app.call(env)
begin
@app.call(env)
rescue StandardError => e
@error = e unless @error
raise e
end
end
end
end
@ -28,9 +35,18 @@ module Capybara
def initialize(app)
@app = app
@middleware = Middleware.new(@app)
@server_thread = nil # supress warnings
end
def reset_error!
@middleware.error = nil
end
def error
@middleware.error
end
def host
Capybara.server_host || "127.0.0.1"
end
@ -56,7 +72,7 @@ module Capybara
Capybara::Server.ports[@app.object_id] = @port
@server_thread = Thread.new do
Capybara.server.call(Identify.new(@app), @port)
Capybara.server.call(@middleware, @port)
end
Timeout.timeout(60) { @server_thread.join(0.1) until responsive? }

View File

@ -45,7 +45,7 @@ module Capybara
]
DSL_METHODS = NODE_METHODS + SESSION_METHODS
attr_reader :mode, :app
attr_reader :mode, :app, :server
def initialize(mode, app=nil)
@mode = mode
@ -72,6 +72,9 @@ module Capybara
def reset!
driver.reset! if @touched
@touched = false
raise @server.error if @server and @server.error
ensure
@server.reset_error! if @server
end
alias_method :cleanup!, :reset!
alias_method :reset_session!, :reset!

View File

@ -3,11 +3,32 @@ require 'nokogiri'
Dir[File.dirname(__FILE__)+'/session/*'].each { |group| require group }
module Quietly
def silence_stream(stream)
old_stream = stream.dup
stream.reopen(RbConfig::CONFIG['host_os'] =~ /rmswin|mingw/ ? 'NUL:' : '/dev/null')
stream.sync = true
yield
ensure
stream.reopen(old_stream)
end
def quietly
silence_stream(STDOUT) do
silence_stream(STDERR) do
yield
end
end
end
end
shared_examples_for "session" do
def extract_results(session)
YAML.load Nokogiri::HTML(session.body).xpath("//pre[@id='results']").first.text.lstrip
end
include Quietly
after do
@session.reset_session!
end
@ -82,6 +103,15 @@ shared_examples_for "session" do
@session.body.should_not include('This is a test')
@session.should have_no_selector('.//h1')
end
it "raises any errors caught inside the server" do
expect do
quietly { @session.visit("/error") }
@session.reset_session!
end.to raise_error(TestApp::TestAppError)
@session.visit("/")
@session.current_path.should == "/"
end
end
it_should_behave_like "node"

View File

@ -3,8 +3,12 @@ require 'rack'
require 'yaml'
class TestApp < Sinatra::Base
class TestAppError < StandardError; end
set :root, File.dirname(__FILE__)
set :static, true
set :raise_errors, true
set :show_exceptions, false
# Also check lib/capybara/spec/views/*.erb for pages not listed here
@ -114,6 +118,10 @@ class TestApp < Sinatra::Base
redirect '/get_header'
end
get '/error' do
raise TestAppError, "some error"
end
get '/:view' do |view|
erb view.to_sym
end