Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Add ability to query for console messages and errors #201

Merged
merged 3 commits into from

9 participants

@joefiorini
  • This changes the format of console message output to use "|" as the delimiter instead of ":"; ":" is no good for splitting when there are URLs and error messages in the output
  • WebPage tracks all console messages and clears them out on reset
@joefiorini

Also added a matcher to be able to say:

page.should_not have_errors
@mike-burns
Owner

A tab character seems more canonical than a pipe.

@joefiorini

All console messages are printed to the screen in raw format (with delimiters). Wouldn't using tabs would make this harder to read? I'm happy to change it something more canonical, but I'd prefer to use a printed character for that reason.

@seanami

Awesome. Excited to use page.should_not have_errors in my tests.

@joefiorini

Is there something I can do to help move this along?

@morenocarullo

+1 this pull request would be very useful.

@jferris
Owner

Thanks for putting this together. I'll try to have a look at this soon.

joefiorini added some commits
@joefiorini joefiorini Add ability to query for console messages & errors
- This changes the format of console message output to use "|" as the
delimiter instead of ":"; ":" is no good for splitting when there are
URLs and error messages in the output
- WebPage tracks all console messages and clears them out on reset
62b4991
@joefiorini joefiorini Add matcher for javascript error checking 741261c
@joefiorini joefiorini Fix spec broken in previous commit 24ccd1f
@joefiorini

It's been almost a month-and-a-half since I submitted this. I'm working on a screencast and would like to use this feature in it, but I don't want to point people to my personal fork. Are there problems with this I can fix or there anything else I can do to help get this through? Thanks!

@jferris jferris commented on the diff
spec/driver_spec.rb
((14 lines not shown))
+ <script type="text/javascript">
+ console.log("hello");
+ console.log("hello again");
+ oops
+ </script>
+ </body>
+ </html>
+ HTML
+ [200,
+ { 'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s },
+ [body]]
+ end
+ end
+
+ it "collects messages logged to the console" do
+ puts subject.console_messages.inspect
@jferris Owner
jferris added a note

Was this left in unintentionally?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@jferris jferris merged commit 24ccd1f into thoughtbot:master
@jferris
Owner

Thanks for the patch; this is merged into master.

@joefiorini

Thanks for accepting this Joe, sorry about my stray puts :)

@nuc-gr

I cannot make this to work :(

I'm pretty sure I have the latest version, but when I try page.should_not have_errors I get:

NoMethodError Exception: undefined method 'has_errors?' for #<Capybara::Session>
@joefiorini
@adsummos

There seems to be a race condition somewhere. Sometimes I get
|15|TypeError: Result of expression 'b' [undefined] is not an object.
in the console running my tests, but nothing ends up in console_messages. Other times it does end up there.

@chrisnicola

@joefiorini page.browser is undefined and while page.driver.browser is the error is still:

NoMethodError Exception: undefined method 'has_errors?' for #<Capybara::Driver::Webkit::Browser:0x00000003181750>
@chrisnicola

Possible that the RSpec API changed. I've fixed it in #297.

@KurtPreston

I'm getting the same error trying to test for JavaScript errors:

     Failure/Error: expect(page).not_to have_errors
     NoMethodError:
       undefined method `has_errors?' for #<Capybara::Session>

I have the following versions installed:

  • capybara 2.2.0
  • capybara-webkit 1.1.0
  • rspec-rails 2.14.0
  • rspec-core 2.14.7

Any ideas?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Nov 16, 2011
  1. @joefiorini

    Add ability to query for console messages & errors

    joefiorini authored
    - This changes the format of console message output to use "|" as the
    delimiter instead of ":"; ":" is no good for splitting when there are
    URLs and error messages in the output
    - WebPage tracks all console messages and clears them out on reset
  2. @joefiorini
  3. @joefiorini
This page is out of date. Refresh to see the latest.
View
8 lib/capybara/driver/webkit.rb
@@ -59,6 +59,14 @@ def evaluate_script(script)
browser.evaluate_script script
end
+ def console_messages
+ browser.console_messages
+ end
+
+ def error_messages
+ browser.error_messages
+ end
+
def response_headers
browser.response_headers
end
View
13 lib/capybara/driver/webkit/browser.rb
@@ -45,6 +45,19 @@ def status_code
command("Status").to_i
end
+ def console_messages
+ command("ConsoleMessages").split("\n").map do |messages|
+ parts = messages.split("|", 3)
+ { source: parts.first, line_number: Integer(parts[1]), message: parts.last }
+ end
+ end
+
+ def error_messages
+ console_messages.select do |message|
+ message[:message] =~ /Error:/
+ end
+ end
+
def response_headers
Hash[command("Headers").split("\n").map { |header| header.split(": ") }]
end
View
39 lib/capybara/webkit/matchers.rb
@@ -0,0 +1,39 @@
+module Capybara
+ module Webkit
+ module RspecMatchers
+ extend RSpec::Matchers::DSL
+
+ matcher :have_errors do |expected|
+ match do |actual|
+ actual = resolve(actual)
+ actual.error_messages.any?
+ end
+
+ failure_message_for_should do |actual|
+ "Expected Javascript errors, but there were none."
+ end
+ failure_message_for_should_not do |actual|
+ actual = resolve(actual)
+ "Expected no Javascript errors, got:\n#{error_messages_for(actual)}"
+ end
+
+ def error_messages_for(obj)
+ obj.error_messages.map do |m|
+ " - #{m[:message]}"
+ end.join("\n")
+ end
+
+ def resolve(actual)
+ if actual.respond_to? :page
+ actual.page.driver
+ elsif actual.respond_to? :driver
+ actual.driver
+ else
+ actual
+ end
+ end
+ end
+
+ end
+ end
+end
View
2  spec/browser_spec.rb
@@ -35,7 +35,7 @@
new_browser = Capybara::Driver::Webkit::Browser.new(:stdout => io)
new_browser.execute_script('console.log("hello world")')
sleep(0.5)
- io.string.should == "hello world\n"
+ io.string.should include "hello world\n"
end
context 'handling of SSL validation errors' do
View
36 spec/driver_spec.rb
@@ -320,6 +320,42 @@
end
end
+ context "console messages app" do
+
+ before(:all) do
+ @app = lambda do |env|
+ puts "running"
+ body = <<-HTML
+ <html>
+ <head>
+ </head>
+ <body>
+ <script type="text/javascript">
+ console.log("hello");
+ console.log("hello again");
+ oops
+ </script>
+ </body>
+ </html>
+ HTML
+ [200,
+ { 'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s },
+ [body]]
+ end
+ end
+
+ it "collects messages logged to the console" do
+ puts subject.console_messages.inspect
@jferris Owner
jferris added a note

Was this left in unintentionally?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ subject.console_messages.first.should include :source, message: "hello", line_number: 6
+ subject.console_messages.length.should eq 3
+ end
+
+ it "logs errors to the console" do
+ subject.error_messages.length.should eq 1
+ end
+
+ end
+
context "form app" do
before(:all) do
@app = lambda do |env|
View
1  src/CommandFactory.cpp
@@ -18,6 +18,7 @@
#include "ClearCookies.h"
#include "GetCookies.h"
#include "SetProxy.h"
+#include "ConsoleMessages.h"
CommandFactory::CommandFactory(WebPage *page, QObject *parent) : QObject(parent) {
m_page = page;
View
11 src/ConsoleMessages.cpp
@@ -0,0 +1,11 @@
+#include "ConsoleMessages.h"
+#include "WebPage.h"
+
+ConsoleMessages::ConsoleMessages(WebPage *page, QObject *parent) : Command(page, parent) {
+}
+
+void ConsoleMessages::start(QStringList &arguments) {
+ Q_UNUSED(arguments);
+ emit finished(new Response(true, page()->consoleMessages()));
+}
+
View
12 src/ConsoleMessages.h
@@ -0,0 +1,12 @@
+#include "Command.h"
+
+class WebPage;
+
+class ConsoleMessages : public Command {
+ Q_OBJECT
+
+ public:
+ ConsoleMessages(WebPage *page, QObject *parent = 0);
+ virtual void start(QStringList &arguments);
+};
+
View
1  src/Reset.cpp
@@ -15,6 +15,7 @@ void Reset::start(QStringList &arguments) {
page()->setCustomNetworkAccessManager();
page()->setUserAgent(NULL);
page()->resetResponseHeaders();
+ page()->resetConsoleMessages();
emit finished(new Response(true));
}
View
14 src/WebPage.cpp
@@ -58,6 +58,10 @@ QString WebPage::userAgentForUrl(const QUrl &url ) const {
}
}
+QString WebPage::consoleMessages() {
+ return m_consoleMessages.join("\n");
+}
+
void WebPage::setUserAgent(QString userAgent) {
m_userAgent = userAgent;
}
@@ -90,9 +94,11 @@ QVariant WebPage::invokeCapybaraFunction(QString &name, QStringList &arguments)
}
void WebPage::javaScriptConsoleMessage(const QString &message, int lineNumber, const QString &sourceID) {
+ QString fullMessage = QString::number(lineNumber) + "|" + message;
if (!sourceID.isEmpty())
- std::cout << qPrintable(sourceID) << ":" << lineNumber << " ";
- std::cout << qPrintable(message) << std::endl;
+ fullMessage = sourceID + "|" + fullMessage;
+ m_consoleMessages.append(fullMessage);
+ std::cout << qPrintable(fullMessage) << std::endl;
}
void WebPage::javaScriptAlert(QWebFrame *frame, const QString &message) {
@@ -217,6 +223,10 @@ void WebPage::resetResponseHeaders() {
m_pageHeaders = QString();
}
+void WebPage::resetConsoleMessages() {
+ m_consoleMessages.clear();
+}
+
QString WebPage::pageHeaders() {
return m_pageHeaders;
}
View
3  src/WebPage.h
@@ -17,6 +17,8 @@ class WebPage : public QWebPage {
virtual bool extension (Extension extension, const ExtensionOption *option=0, ExtensionReturn *output=0);
void setIgnoreSslErrors(bool ignore);
bool ignoreSslErrors();
+ QString consoleMessages();
+ void resetConsoleMessages();
public slots:
bool shouldInterruptJavaScript();
@@ -50,5 +52,6 @@ class WebPage : public QWebPage {
int m_lastStatus;
QString m_pageHeaders;
bool m_ignoreSslErrors;
+ QStringList m_consoleMessages;
};
View
1  src/find_command.h
@@ -22,3 +22,4 @@ CHECK_COMMAND(ClearCookies)
CHECK_COMMAND(GetCookies)
CHECK_COMMAND(Headers)
CHECK_COMMAND(SetProxy)
+CHECK_COMMAND(ConsoleMessages)
View
2  src/webkit_server.pro
@@ -2,6 +2,7 @@ TEMPLATE = app
TARGET = webkit_server
DESTDIR = .
HEADERS = \
+ ConsoleMessages.h \
WebPage.h \
Server.h \
Connection.h \
@@ -33,6 +34,7 @@ HEADERS = \
SetProxy.h \
SOURCES = \
+ ConsoleMessages.cpp \
main.cpp \
WebPage.cpp \
Server.cpp \
Something went wrong with that request. Please try again.