From d9b18985e12a38c9b0f9c664f4c528e9aa3e24c4 Mon Sep 17 00:00:00 2001 From: Joe Ferris Date: Fri, 29 Jun 2012 12:14:22 -0400 Subject: [PATCH] Command to enable a more useful debug log --- lib/capybara/driver/webkit.rb | 4 +++ lib/capybara/driver/webkit/browser.rb | 4 +++ lib/capybara/driver/webkit/connection.rb | 3 +- lib/capybara/webkit.rb | 7 ++--- spec/driver_spec.rb | 39 ++++++++++++++++++++++-- src/Command.cpp | 11 ++++--- src/Command.h | 7 +++-- src/CommandFactory.cpp | 1 + src/Connection.cpp | 12 ++++++-- src/EnableLogging.cpp | 10 ++++++ src/EnableLogging.h | 12 ++++++++ src/JavascriptInvocation.cpp | 2 +- src/JavascriptInvocation.h | 2 +- src/Node.cpp | 4 +++ src/Node.h | 1 + src/PageLoadingCommand.cpp | 4 +++ src/WebPage.cpp | 4 +-- src/WebPage.h | 4 +-- src/WebPageManager.cpp | 38 +++++++++++++++++++---- src/WebPageManager.h | 13 ++++++-- src/find_command.h | 1 + src/webkit_server.pro | 2 ++ templates/Command.cpp | 6 ++-- templates/Command.h | 4 +-- 24 files changed, 158 insertions(+), 37 deletions(-) create mode 100644 src/EnableLogging.cpp create mode 100644 src/EnableLogging.h diff --git a/lib/capybara/driver/webkit.rb b/lib/capybara/driver/webkit.rb index 9d977e3..59db5ff 100644 --- a/lib/capybara/driver/webkit.rb +++ b/lib/capybara/driver/webkit.rb @@ -26,6 +26,10 @@ class Capybara::Driver::Webkit @browser = options[:browser] || Browser.new(Connection.new(options)) end + def enable_logging + browser.enable_logging + end + def current_url browser.current_url end diff --git a/lib/capybara/driver/webkit/browser.rb b/lib/capybara/driver/webkit/browser.rb index c010993..1d103af 100644 --- a/lib/capybara/driver/webkit/browser.rb +++ b/lib/capybara/driver/webkit/browser.rb @@ -10,6 +10,10 @@ class Capybara::Driver::Webkit command("Authenticate", username, password) end + def enable_logging + command "EnableLogging" + end + def visit(url) command "Visit", url end diff --git a/lib/capybara/driver/webkit/connection.rb b/lib/capybara/driver/webkit/connection.rb index 366cc84..ac9b4c0 100644 --- a/lib/capybara/driver/webkit/connection.rb +++ b/lib/capybara/driver/webkit/connection.rb @@ -12,6 +12,7 @@ class Capybara::Driver::Webkit def initialize(options = {}) @socket_class = options[:socket_class] || TCPSocket @stdout = options.has_key?(:stdout) ? options[:stdout] : $stdout + @command = options[:command] || SERVER_PATH start_server connect end @@ -41,7 +42,7 @@ class Capybara::Driver::Webkit end def open_pipe - @pipe = IO.popen(SERVER_PATH) + @pipe = IO.popen(@command) @pid = @pipe.pid register_shutdown_hook end diff --git a/lib/capybara/webkit.rb b/lib/capybara/webkit.rb index 17b8b2e..408b0f1 100644 --- a/lib/capybara/webkit.rb +++ b/lib/capybara/webkit.rb @@ -6,8 +6,7 @@ Capybara.register_driver :webkit do |app| end Capybara.register_driver :webkit_debug do |app| - connection = Capybara::Driver::Webkit::Connection.new( - :socket_class => Capybara::Driver::Webkit::SocketDebugger) - browser = Capybara::Driver::Webkit::Browser.new(connection) - Capybara::Driver::Webkit.new(app, :browser => browser) + driver = Capybara::Driver::Webkit.new(app) + driver.enable_logging + driver end diff --git a/spec/driver_spec.rb b/spec/driver_spec.rb index a5673cd..bad2f6e 100644 --- a/spec/driver_spec.rb +++ b/spec/driver_spec.rb @@ -4,8 +4,10 @@ require 'base64' describe Capybara::Driver::Webkit do subject { Capybara::Driver::Webkit.new(@app, :browser => $webkit_browser) } - before { subject.visit("/hello/world?success=true") } - after { subject.reset! } + before do + subject.reset! + subject.visit("/hello/world?success=true") + end context "iframe app" do before(:all) do @@ -1767,4 +1769,37 @@ describe Capybara::Driver::Webkit do subject.body.should include("Basic "+Base64.encode64("user:password").strip) end end + + describe "logger app" do + before(:all) do + @app = lambda do |env| + [200, { "Content-Type" => "text/html", "Content-Length" => "0" }, [""]] + end + end + + it "logs nothing before turning on the logger" do + driver.visit("/") + log.should == "" + end + + it "logs its commands after turning on the logger" do + driver.enable_logging + driver.visit("/") + log.should_not == "" + end + + let(:driver) do + command = "#{Capybara::Driver::Webkit::Connection::SERVER_PATH} 2>&1" + connection = Capybara::Driver::Webkit::Connection.new(:command => command, :stdout => output) + browser = Capybara::Driver::Webkit::Browser.new(connection) + Capybara::Driver::Webkit.new(@app, :browser => browser) + end + + let(:output) { StringIO.new } + + def log + output.rewind + output.read + end + end end diff --git a/src/Command.cpp b/src/Command.cpp index c25c616..4bf32e4 100644 --- a/src/Command.cpp +++ b/src/Command.cpp @@ -10,15 +10,18 @@ Command::Command(WebPageManager *manager, QStringList &arguments, QObject *paren void Command::start() { } -WebPage *Command::page() { +QString Command::toString() const { + return metaObject()->className(); +} + +WebPage *Command::page() const { return m_manager->currentPage(); } -QStringList &Command::arguments() { +const QStringList &Command::arguments() const { return m_arguments; } -WebPageManager *Command::manager() { +WebPageManager *Command::manager() const { return m_manager; } - diff --git a/src/Command.h b/src/Command.h index 20cf096..f225728 100644 --- a/src/Command.h +++ b/src/Command.h @@ -14,14 +14,15 @@ class Command : public QObject { public: Command(WebPageManager *, QStringList &arguments, QObject *parent = 0); virtual void start(); + virtual QString toString() const; signals: void finished(Response *response); protected: - WebPage *page(); - QStringList &arguments(); - WebPageManager *manager(); + WebPage *page() const; + const QStringList &arguments() const; + WebPageManager *manager() const; private: QStringList m_arguments; diff --git a/src/CommandFactory.cpp b/src/CommandFactory.cpp index 3d1d921..cc23b31 100644 --- a/src/CommandFactory.cpp +++ b/src/CommandFactory.cpp @@ -30,6 +30,7 @@ #include "GetWindowHandle.h" #include "WebPageManager.h" #include "Authenticate.h" +#include "EnableLogging.h" CommandFactory::CommandFactory(WebPageManager *manager, QObject *parent) : QObject(parent) { m_manager = manager; diff --git a/src/Connection.cpp b/src/Connection.cpp index db40e41..2b6ef88 100644 --- a/src/Connection.cpp +++ b/src/Connection.cpp @@ -23,10 +23,13 @@ Connection::Connection(QTcpSocket *socket, WebPageManager *manager, QObject *par void Connection::commandReady(Command *command) { m_queuedCommand = command; - if (m_manager->isLoading()) + m_manager->logger() << "Received" << command->toString(); + if (m_manager->isLoading()) { + m_manager->logger() << command->toString() << "waiting for load to finish"; m_commandWaiting = true; - else + } else { startCommand(); + } } void Connection::startCommand() { @@ -42,8 +45,9 @@ void Connection::startCommand() { void Connection::pendingLoadFinished(bool success) { m_pageSuccess = m_pageSuccess && success; - if (m_commandWaiting) + if (m_commandWaiting) { startCommand(); + } } void Connection::writePageLoadFailure() { @@ -64,6 +68,8 @@ void Connection::writeResponse(Response *response) { else m_socket->write("failure\n"); + m_manager->logger() << "Wrote response" << response->isSuccess() << response->message(); + QByteArray messageUtf8 = response->message(); QString messageLength = QString::number(messageUtf8.size()) + "\n"; m_socket->write(messageLength.toAscii()); diff --git a/src/EnableLogging.cpp b/src/EnableLogging.cpp new file mode 100644 index 0000000..121a803 --- /dev/null +++ b/src/EnableLogging.cpp @@ -0,0 +1,10 @@ +#include "EnableLogging.h" +#include "WebPageManager.h" + +EnableLogging::EnableLogging(WebPageManager *manager, QStringList &arguments, QObject *parent) : Command(manager, arguments, parent) { +} + +void EnableLogging::start() { + manager()->enableLogging(); + emit finished(new Response(true)); +} diff --git a/src/EnableLogging.h b/src/EnableLogging.h new file mode 100644 index 0000000..1b70d52 --- /dev/null +++ b/src/EnableLogging.h @@ -0,0 +1,12 @@ +#include "Command.h" + +class WebPageManager; + +class EnableLogging : public Command { + Q_OBJECT + + public: + EnableLogging(WebPageManager *, QStringList &arguments, QObject *parent = 0); + virtual void start(); +}; + diff --git a/src/JavascriptInvocation.cpp b/src/JavascriptInvocation.cpp index b69c4b7..56446ff 100644 --- a/src/JavascriptInvocation.cpp +++ b/src/JavascriptInvocation.cpp @@ -1,6 +1,6 @@ #include "JavascriptInvocation.h" -JavascriptInvocation::JavascriptInvocation(QString &functionName, QStringList &arguments, QObject *parent) : QObject(parent) { +JavascriptInvocation::JavascriptInvocation(const QString &functionName, const QStringList &arguments, QObject *parent) : QObject(parent) { m_functionName = functionName; m_arguments = arguments; } diff --git a/src/JavascriptInvocation.h b/src/JavascriptInvocation.h index 7a1d5b9..b3722bd 100644 --- a/src/JavascriptInvocation.h +++ b/src/JavascriptInvocation.h @@ -8,7 +8,7 @@ class JavascriptInvocation : public QObject { Q_PROPERTY(QStringList arguments READ arguments) public: - JavascriptInvocation(QString &functionName, QStringList &arguments, QObject *parent = 0); + JavascriptInvocation(const QString &functionName, const QStringList &arguments, QObject *parent = 0); QString &functionName(); QStringList &arguments(); diff --git a/src/Node.cpp b/src/Node.cpp index 0b093e2..6c98b25 100644 --- a/src/Node.cpp +++ b/src/Node.cpp @@ -13,3 +13,7 @@ void Node::start() { emit finished(new Response(true, attributeValue)); } +QString Node::toString() const { + QStringList functionArguments(arguments()); + return QString("Node.") + functionArguments.takeFirst(); +} diff --git a/src/Node.h b/src/Node.h index 54fbaa2..1a6b6e5 100644 --- a/src/Node.h +++ b/src/Node.h @@ -7,5 +7,6 @@ class Node : public Command { public: Node(WebPageManager *manager, QStringList &arguments, QObject *parent = 0); virtual void start(); + virtual QString toString() const; }; diff --git a/src/PageLoadingCommand.cpp b/src/PageLoadingCommand.cpp index f2eb29b..6d7583a 100644 --- a/src/PageLoadingCommand.cpp +++ b/src/PageLoadingCommand.cpp @@ -14,6 +14,7 @@ PageLoadingCommand::PageLoadingCommand(Command *command, WebPageManager *manager } void PageLoadingCommand::start() { + m_manager->logger() << "Started" << m_command->toString(); connect(m_command, SIGNAL(finished(Response *)), this, SLOT(commandFinished(Response *))); m_command->start(); }; @@ -23,6 +24,7 @@ void PageLoadingCommand::pendingLoadFinished(bool success) { if (m_pageLoadingFromCommand) { m_pageLoadingFromCommand = false; if (m_pendingResponse) { + m_manager->logger() << "Page load from command finished"; if (m_pageSuccess) { emit finished(m_pendingResponse); } else { @@ -34,11 +36,13 @@ void PageLoadingCommand::pendingLoadFinished(bool success) { } void PageLoadingCommand::pageLoadingFromCommand() { + m_manager->logger() << m_command->toString() << "started page load"; m_pageLoadingFromCommand = true; } void PageLoadingCommand::commandFinished(Response *response) { disconnect(m_manager, SIGNAL(loadStarted()), this, SLOT(pageLoadingFromCommand())); + m_manager->logger() << "Finished" << m_command->toString(); m_command->deleteLater(); if (m_pageLoadingFromCommand) m_pendingResponse = response; diff --git a/src/WebPage.cpp b/src/WebPage.cpp index e5b7390..fff2e2e 100644 --- a/src/WebPage.cpp +++ b/src/WebPage.cpp @@ -116,7 +116,7 @@ bool WebPage::shouldInterruptJavaScript() { return false; } -QVariant WebPage::invokeCapybaraFunction(const char *name, QStringList &arguments) { +QVariant WebPage::invokeCapybaraFunction(const char *name, const QStringList &arguments) { QString qname(name); QString objectName("CapybaraInvocation"); JavascriptInvocation invocation(qname, arguments); @@ -125,7 +125,7 @@ QVariant WebPage::invokeCapybaraFunction(const char *name, QStringList &argument return currentFrame()->evaluateJavaScript(javascript); } -QVariant WebPage::invokeCapybaraFunction(QString &name, QStringList &arguments) { +QVariant WebPage::invokeCapybaraFunction(QString &name, const QStringList &arguments) { return invokeCapybaraFunction(name.toAscii().data(), arguments); } diff --git a/src/WebPage.h b/src/WebPage.h index de2dd95..0123b74 100644 --- a/src/WebPage.h +++ b/src/WebPage.h @@ -9,8 +9,8 @@ class WebPage : public QWebPage { public: WebPage(WebPageManager *, QObject *parent = 0); - QVariant invokeCapybaraFunction(const char *name, QStringList &arguments); - QVariant invokeCapybaraFunction(QString &name, QStringList &arguments); + QVariant invokeCapybaraFunction(const char *name, const QStringList &arguments); + QVariant invokeCapybaraFunction(QString &name, const QStringList &arguments); QString failureString(); QString userAgentForUrl(const QUrl &url ) const; void setUserAgent(QString userAgent); diff --git a/src/WebPageManager.cpp b/src/WebPageManager.cpp index 863e4c4..8282a1c 100644 --- a/src/WebPageManager.cpp +++ b/src/WebPageManager.cpp @@ -1,12 +1,13 @@ #include "WebPageManager.h" #include "WebPage.h" #include "NetworkCookieJar.h" -#include WebPageManager::WebPageManager(QObject *parent) : QObject(parent) { m_ignoreSslErrors = false; m_cookieJar = new NetworkCookieJar(this); m_success = true; + m_loggingEnabled = false; + m_ignoredOutput = new QString(); createPage(this)->setFocus(); } @@ -22,7 +23,7 @@ void WebPageManager::setCurrentPage(WebPage *page) { m_currentPage = page; } -WebPage *WebPageManager::currentPage() { +WebPage *WebPageManager::currentPage() const { return m_currentPage; } @@ -31,7 +32,7 @@ WebPage *WebPageManager::createPage(QObject *parent) { connect(page, SIGNAL(loadStarted()), this, SLOT(emitLoadStarted())); connect(page, SIGNAL(pageFinished(bool)), - this, SLOT(emitPageFinished(bool))); + this, SLOT(setPageStatus(bool))); connect(page, SIGNAL(requestCreated(QNetworkReply *)), this, SLOT(requestCreated(QNetworkReply *))); connect(page, SIGNAL(replyFinished(QNetworkReply *)), @@ -42,26 +43,40 @@ WebPage *WebPageManager::createPage(QObject *parent) { void WebPageManager::emitLoadStarted() { if (m_started.empty()) { + logger() << "Load started"; emit loadStarted(); } } void WebPageManager::requestCreated(QNetworkReply *reply) { + logger() << "Started request to" << reply->url().toString(); m_started += reply; } void WebPageManager::replyFinished(QNetworkReply *reply) { + int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + logger() << "Received" << status << "from" << reply->url().toString(); m_started.remove(reply); + logger() << m_started.size() << "requests remaining"; + if (m_started.empty() && !m_success) { + emitPageFinished(); + } } -void WebPageManager::emitPageFinished(bool success) { +void WebPageManager::setPageStatus(bool success) { + logger() << "Page finished with" << success; m_success = success && m_success; if (m_started.empty()) { - emit pageFinished(m_success); - m_success = true; + emitPageFinished(); } } +void WebPageManager::emitPageFinished() { + logger() << "Load finished"; + emit pageFinished(m_success); + m_success = true; +} + void WebPageManager::setIgnoreSslErrors(bool value) { m_ignoreSslErrors = value; } @@ -89,3 +104,14 @@ bool WebPageManager::isLoading() const { } return false; } + +QDebug WebPageManager::logger() const { + if (m_loggingEnabled) + return qDebug(); + else + return QDebug(m_ignoredOutput); +} + +void WebPageManager::enableLogging() { + m_loggingEnabled = true; +} diff --git a/src/WebPageManager.h b/src/WebPageManager.h index de19030..fcf0c8a 100644 --- a/src/WebPageManager.h +++ b/src/WebPageManager.h @@ -4,6 +4,8 @@ #include #include #include +#include +#include class WebPage; class NetworkCookieJar; @@ -16,17 +18,19 @@ class WebPageManager : public QObject { void append(WebPage *value); QList pages() const; void setCurrentPage(WebPage *); - WebPage *currentPage(); + WebPage *currentPage() const; WebPage *createPage(QObject *parent); void setIgnoreSslErrors(bool); bool ignoreSslErrors(); void reset(); NetworkCookieJar *cookieJar(); bool isLoading() const; + QDebug logger() const; + void enableLogging(); public slots: void emitLoadStarted(); - void emitPageFinished(bool); + void setPageStatus(bool); void requestCreated(QNetworkReply *reply); void replyFinished(QNetworkReply *reply); @@ -35,12 +39,17 @@ class WebPageManager : public QObject { void loadStarted(); private: + void emitPageFinished(); + static void handleDebugMessage(QtMsgType type, const char *message); + QList m_pages; WebPage *m_currentPage; bool m_ignoreSslErrors; NetworkCookieJar *m_cookieJar; QSet m_started; bool m_success; + bool m_loggingEnabled; + QString *m_ignoredOutput; }; #endif // _WEBPAGEMANAGER_H diff --git a/src/find_command.h b/src/find_command.h index 3806f23..a939c00 100644 --- a/src/find_command.h +++ b/src/find_command.h @@ -31,3 +31,4 @@ CHECK_COMMAND(WindowFocus) CHECK_COMMAND(GetWindowHandles) CHECK_COMMAND(GetWindowHandle) CHECK_COMMAND(Authenticate) +CHECK_COMMAND(EnableLogging) diff --git a/src/webkit_server.pro b/src/webkit_server.pro index 608c415..adfc4bb 100644 --- a/src/webkit_server.pro +++ b/src/webkit_server.pro @@ -2,6 +2,7 @@ TEMPLATE = app TARGET = webkit_server DESTDIR = . HEADERS = \ + EnableLogging.h \ Authenticate.h \ IgnoreSslErrors.h \ ResizeWindow.h \ @@ -46,6 +47,7 @@ HEADERS = \ GetWindowHandle.h \ SOURCES = \ + EnableLogging.cpp \ Authenticate.cpp \ IgnoreSslErrors.cpp \ ResizeWindow.cpp \ diff --git a/templates/Command.cpp b/templates/Command.cpp index 8dc6790..e2529c4 100644 --- a/templates/Command.cpp +++ b/templates/Command.cpp @@ -1,10 +1,8 @@ #include "NAME.h" #include "WebPage.h" -NAME::NAME(WebPage *page, QObject *parent) : Command(page, parent) { +NAME::NAME(WebPageManager *manager, QStringList &arguments, QObject *parent) : Command(manager, arguments, parent) { } -void NAME::start(QStringList &arguments) { - Q_UNUSED(arguments); +void NAME::start() { } - diff --git a/templates/Command.h b/templates/Command.h index 3b3f869..aca6d87 100644 --- a/templates/Command.h +++ b/templates/Command.h @@ -6,7 +6,7 @@ class NAME : public Command { Q_OBJECT public: - NAME(WebPage *page, QObject *parent = 0); - virtual void start(QStringList &arguments); + NAME(WebPageManager *, QStringList &arguments, QObject *parent = 0); + virtual void start(); };