JavaScript error handling

This commit is contained in:
Matthew Horan 2013-01-20 18:57:04 -05:00
parent be6a055687
commit fe6eff79e6
11 changed files with 83 additions and 27 deletions

View File

@ -7,7 +7,7 @@ CurrentUrl::CurrentUrl(WebPageManager *manager, QStringList &arguments, QObject
void CurrentUrl::start() {
QStringList arguments;
QVariant result = page()->invokeCapybaraFunction("currentUrl", arguments);
QVariant result = page()->currentFrame()->evaluateJavaScript("window.location.toString()");
QString url = result.toString();
emitFinished(true, url);
}

View File

@ -2,19 +2,19 @@
#include "SocketCommand.h"
#include "WebPage.h"
#include "WebPageManager.h"
#include "InvocationResult.h"
Find::Find(WebPageManager *manager, QStringList &arguments, QObject *parent) : SocketCommand(manager, arguments, parent) {
}
void Find::start() {
QString message;
QVariant result = page()->invokeCapybaraFunction("find", arguments());
InvocationResult result = page()->invokeCapybaraFunction("find", arguments());
if (result.isValid()) {
message = result.toString();
emitFinished(true, message);
} else {
emitFinished(false, QString("Invalid XPath expression"));
}
if (result.hasError())
return emitFinished(false, QString("Invalid XPath expression"));
QString message;
message = result.result().toString();
emitFinished(true, message);
}

14
src/InvocationResult.cpp Normal file
View File

@ -0,0 +1,14 @@
#include "InvocationResult.h"
InvocationResult::InvocationResult(QVariant result, bool error) {
m_result = result;
m_error = error;
}
const QVariant &InvocationResult::result() const {
return m_result;
}
bool InvocationResult::hasError() {
return m_error;
}

13
src/InvocationResult.h Normal file
View File

@ -0,0 +1,13 @@
#include <QVariant>
class InvocationResult {
public:
InvocationResult(QVariant result, bool error = false);
const QVariant &result() const;
bool hasError();
private:
QVariant m_result;
bool m_error;
};

View File

@ -1,5 +1,6 @@
#include "JavascriptInvocation.h"
#include "WebPage.h"
#include "InvocationResult.h"
#include <QApplication>
JavascriptInvocation::JavascriptInvocation(const QString &functionName, const QStringList &arguments, WebPage *page, QObject *parent) : QObject(parent) {
@ -16,6 +17,23 @@ QStringList &JavascriptInvocation::arguments() {
return m_arguments;
}
QVariantMap JavascriptInvocation::getError() {
return m_error;
}
void JavascriptInvocation::setError(QVariantMap error) {
m_error = error;
}
InvocationResult JavascriptInvocation::invoke(QWebFrame *frame) {
frame->addToJavaScriptWindowObject("CapybaraInvocation", this);
QVariant result = frame->evaluateJavaScript("Capybara.invoke()");
if (getError().isEmpty())
return InvocationResult(result);
else
return InvocationResult(getError(), true);
}
bool JavascriptInvocation::click(QWebElement element, int left, int top, int width, int height) {
QRect elementBox(left, top, width, height);
QRect viewport(QPoint(0, 0), m_page->viewportSize());

View File

@ -4,23 +4,28 @@
#include <QWebElement>
class WebPage;
class InvocationResult;
class JavascriptInvocation : public QObject {
Q_OBJECT
Q_PROPERTY(QString functionName READ functionName)
Q_PROPERTY(QStringList arguments READ arguments)
Q_PROPERTY(QVariantMap error READ getError WRITE setError)
public:
JavascriptInvocation(const QString &functionName, const QStringList &arguments, WebPage *page, QObject *parent = 0);
QString &functionName();
QStringList &arguments();
Q_INVOKABLE bool click(QWebElement element, int left, int top, int width, int height);
QVariantMap getError();
void setError(QVariantMap error);
InvocationResult invoke(QWebFrame *);
private:
QString m_functionName;
QStringList m_arguments;
WebPage *m_page;
void execClick(QPoint mousePos);
QVariantMap m_error;
};

View File

@ -1,6 +1,7 @@
#include "Node.h"
#include "WebPage.h"
#include "WebPageManager.h"
#include "InvocationResult.h"
Node::Node(WebPageManager *manager, QStringList &arguments, QObject *parent) : SocketCommand(manager, arguments, parent) {
}
@ -8,8 +9,12 @@ Node::Node(WebPageManager *manager, QStringList &arguments, QObject *parent) : S
void Node::start() {
QStringList functionArguments(arguments());
QString functionName = functionArguments.takeFirst();
QVariant result = page()->invokeCapybaraFunction(functionName, functionArguments);
QString attributeValue = result.toString();
InvocationResult result = page()->invokeCapybaraFunction(functionName, functionArguments);
if (result.hasError())
return emitFinished(false);
QString attributeValue = result.result().toString();
emitFinished(true, attributeValue);
}

View File

@ -4,6 +4,7 @@
#include "NetworkAccessManager.h"
#include "NetworkCookieJar.h"
#include "UnsupportedContentHandler.h"
#include "InvocationResult.h"
#include <QResource>
#include <iostream>
#include <QWebSettings>
@ -117,16 +118,13 @@ bool WebPage::shouldInterruptJavaScript() {
return false;
}
QVariant WebPage::invokeCapybaraFunction(const char *name, const QStringList &arguments) {
InvocationResult WebPage::invokeCapybaraFunction(const char *name, const QStringList &arguments) {
QString qname(name);
QString objectName("CapybaraInvocation");
JavascriptInvocation invocation(qname, arguments, this);
currentFrame()->addToJavaScriptWindowObject(objectName, &invocation);
QString javascript = QString("Capybara.invoke()");
return currentFrame()->evaluateJavaScript(javascript);
return invocation.invoke(currentFrame());
}
QVariant WebPage::invokeCapybaraFunction(QString &name, const QStringList &arguments) {
InvocationResult WebPage::invokeCapybaraFunction(QString &name, const QStringList &arguments) {
return invokeCapybaraFunction(name.toAscii().data(), arguments);
}

View File

@ -4,14 +4,15 @@
class WebPageManager;
class NetworkAccessManager;
class InvocationResult;
class WebPage : public QWebPage {
Q_OBJECT
public:
WebPage(WebPageManager *, QObject *parent = 0);
QVariant invokeCapybaraFunction(const char *name, const QStringList &arguments);
QVariant invokeCapybaraFunction(QString &name, const QStringList &arguments);
InvocationResult invokeCapybaraFunction(const char *name, const QStringList &arguments);
InvocationResult invokeCapybaraFunction(QString &name, const QStringList &arguments);
QString failureString();
QString userAgentForUrl(const QUrl &url ) const;
void setUserAgent(QString userAgent);

View File

@ -4,17 +4,17 @@ Capybara = {
attachedFiles: [],
invoke: function () {
return this[CapybaraInvocation.functionName].apply(this, CapybaraInvocation.arguments);
try {
return this[CapybaraInvocation.functionName].apply(this, CapybaraInvocation.arguments);
} catch (e) {
CapybaraInvocation.error = e;
}
},
find: function (xpath) {
return this.findRelativeTo(document, xpath);
},
currentUrl: function () {
return window.location.toString();
},
findWithin: function (index, xpath) {
return this.findRelativeTo(this.nodes[index], xpath);
},

View File

@ -56,7 +56,8 @@ HEADERS = \
TimeoutCommand.h \
SetUrlBlacklist.h \
NoOpReply.h \
JsonSerializer.h
JsonSerializer.h \
InvocationResult.h
SOURCES = \
Version.cpp \
@ -114,7 +115,8 @@ SOURCES = \
TimeoutCommand.cpp \
SetUrlBlacklist.cpp \
NoOpReply.cpp \
JsonSerializer.cpp
JsonSerializer.cpp \
InvocationResult.cpp
RESOURCES = webkit_server.qrc
QT += network webkit