Allow JavaScript errors to be raised as exceptions (#988)

When configured, all driver commands (except reading console messages) will
check for JavaScript errors. 

The ConsoleMessages command is excluded from the check to prevent recursion, and
maintain the ease of debugging JavaScript errors interactively.
This commit is contained in:
Oliver Peate 2017-03-17 14:54:36 +00:00 committed by GitHub
parent 56e244e074
commit 2e869bb9b7
8 changed files with 108 additions and 2 deletions

View File

@ -129,6 +129,9 @@ Capybara::Webkit.configure do |config|
user: "proxy", user: "proxy",
pass: "secret" pass: "secret"
) )
# Raise JavaScript errors as exceptions
config.raise_javascript_errors = true
end end
``` ```

View File

@ -5,6 +5,7 @@ module Capybara::Webkit
class Browser class Browser
def initialize(connection) def initialize(connection)
@connection = connection @connection = connection
apply_defaults
end end
def authenticate(username, password) def authenticate(username, password)
@ -36,6 +37,7 @@ module Capybara::Webkit
end end
def reset! def reset!
apply_defaults
command("Reset") command("Reset")
end end
@ -99,6 +101,14 @@ module Capybara::Webkit
command("SetSkipImageLoading", skip_image_loading) command("SetSkipImageLoading", skip_image_loading)
end end
def set_raise_javascript_errors(is_enabled)
@raise_javascript_errors = is_enabled
end
def raise_javascript_errors?
@raise_javascript_errors
end
def window_focus(selector) def window_focus(selector)
command("WindowFocus", selector) command("WindowFocus", selector)
end end
@ -209,7 +219,9 @@ module Capybara::Webkit
@connection.print arg.to_s @connection.print arg.to_s
end end
check check
read_response response = read_response
check_javascript_errors(name)
response
rescue SystemCallError => exception rescue SystemCallError => exception
@connection.restart @connection.restart
raise(Capybara::Webkit::CrashError, <<-MESSAGE.strip) raise(Capybara::Webkit::CrashError, <<-MESSAGE.strip)
@ -295,6 +307,10 @@ https://github.com/thoughtbot/capybara-webkit/wiki/Reporting-Crashes
private private
def apply_defaults
@raise_javascript_errors = false
end
def check def check
result = @connection.gets result = @connection.gets
result.strip! if result result.strip! if result
@ -308,6 +324,14 @@ https://github.com/thoughtbot/capybara-webkit/wiki/Reporting-Crashes
result result
end end
def check_javascript_errors(command_name)
return if command_name == "ConsoleMessages"
if raise_javascript_errors? && error_messages.any?
raise JavaScriptError, error_messages
end
end
def read_response def read_response
response_length = @connection.gets.to_i response_length = @connection.gets.to_i
if response_length > 0 if response_length > 0

View File

@ -30,6 +30,7 @@ module Capybara
attr_accessor :stderr attr_accessor :stderr
attr_accessor :timeout attr_accessor :timeout
attr_writer :skip_image_loading attr_writer :skip_image_loading
attr_accessor :raise_javascript_errors
def initialize def initialize
@allowed_urls = [] @allowed_urls = []
@ -41,6 +42,7 @@ module Capybara
@skip_image_loading = false @skip_image_loading = false
@stderr = $stderr @stderr = $stderr
@timeout = -1 @timeout = -1
@raise_javascript_errors = false
end end
def allow_url(url) def allow_url(url)
@ -93,7 +95,8 @@ module Capybara
proxy: proxy, proxy: proxy,
skip_image_loading: skip_image_loading?, skip_image_loading: skip_image_loading?,
stderr: stderr, stderr: stderr,
timeout: timeout timeout: timeout,
raise_javascript_errors: raise_javascript_errors,
} }
end end
end end

View File

@ -398,6 +398,10 @@ module Capybara::Webkit
@browser.timeout = @options[:timeout] @browser.timeout = @options[:timeout]
end end
if @options.has_key? :raise_javascript_errors
@browser.set_raise_javascript_errors(@options[:raise_javascript_errors])
end
Array(@options[:allowed_urls]).each { |url| @browser.allow_url(url) } Array(@options[:allowed_urls]).each { |url| @browser.allow_url(url) }
Array(@options[:blocked_urls]).each { |url| @browser.block_url(url) } Array(@options[:blocked_urls]).each { |url| @browser.block_url(url) }
end end

View File

@ -44,4 +44,13 @@ module Capybara::Webkit
Capybara::Webkit.const_get @class_name Capybara::Webkit.const_get @class_name
end end
end end
class JavaScriptError < StandardError
def initialize(errors)
@javascript_errors = errors
super(errors.join(","))
end
attr_reader :javascript_errors
end
end end

View File

@ -43,4 +43,20 @@ describe Capybara::Webkit::Browser do
end end
end end
end end
describe "#reset!" do
it "resets to the default state" do
connection = double("connection", puts: nil, print: nil)
allow(connection).to receive(:gets).and_return("ok\n", "{}\n")
browser = Capybara::Webkit::Browser.new(connection)
browser.set_raise_javascript_errors(true)
expect(browser.raise_javascript_errors?).to be true
browser.reset!
expect(browser.raise_javascript_errors?).to be false
end
end
end end

View File

@ -3440,4 +3440,50 @@ CACHE MANIFEST
def driver_url(driver, path) def driver_url(driver, path)
URI.parse(driver.current_url).merge(path).to_s URI.parse(driver.current_url).merge(path).to_s
end end
context "page with JavaScript errors" do
let(:driver) do
driver_for_app do
get "/" do
<<-HTML
<!DOCTYPE html>
<html>
<body>
<script type="text/javascript">
undefinedFunc();
</script>
</body>
</html>
HTML
end
end
end
it "raises errors as an exception, when configured" do
configure do |config|
config.raise_javascript_errors = true
end
expected_error = Capybara::Webkit::JavaScriptError
expected_message = "ReferenceError: Can't find variable: undefinedFunc"
expect { visit("/") }.to raise_error(expected_error) do |error|
expect(error.javascript_errors.first[:message]).to eq expected_message
end
expect { driver.find_css("h1") }.to raise_error(expected_error)
end
it "does not raise an exception when fetching the error messages" do
configure do |config|
config.raise_javascript_errors = true
end
expect { driver.error_messages }.to_not raise_error
end
it "does not raise errors as an exception by default" do
expect { visit("/") }.to_not raise_error
expect(driver.error_messages).to_not be_empty
end
end
end end

View File

@ -21,6 +21,7 @@ module AppRunner
end end
self.browser = $webkit_browser self.browser = $webkit_browser
self.browser.reset!
self.configuration = Capybara::Webkit::Configuration.new self.configuration = Capybara::Webkit::Configuration.new
end end