Invoke Javascript functions by setting QObjects on the window object instead of string evals so that strings don't need to be escaped

This commit is contained in:
Joe Ferris 2011-02-25 22:57:55 -05:00
parent 879eeba471
commit 18d424803d
8 changed files with 57 additions and 9 deletions

View File

@ -38,5 +38,9 @@ describe Capybara::Driver::Webkit do
it "returns an attribute's value" do
subject.find("//p").first["id"].should == "greeting"
end
it "parses xpath with quotes" do
subject.find('//*[contains(., "hello")]').should_not be_empty
end
end

View File

@ -7,14 +7,10 @@ Find::Find(WebPage *page, QObject *parent) : Command(page, parent) {
}
void Find::receivedArgument(const char *xpath) {
std::cout << "<< Running query: " << xpath << std::endl;
QString javascript = QString("Capybara.find(\"") + xpath + "\")";
std::cout << "<< Javascript to execute:" << std::endl;
std::cout << javascript.toAscii().data() << std::endl;
QStringList arguments;
QString response;
QVariant result = page()->mainFrame()->evaluateJavaScript(javascript);
arguments.append(QString(xpath));
QVariant result = page()->invokeCapybaraFunction("find", arguments);
if (result.isValid()) {
response = result.toString();

View File

@ -0,0 +1,14 @@
#include "JavascriptInvocation.h"
JavascriptInvocation::JavascriptInvocation(QString &functionName, QStringList &arguments, QObject *parent) : QObject(parent) {
m_functionName = functionName;
m_arguments = arguments;
}
QString &JavascriptInvocation::functionName() {
return m_functionName;
}
QStringList &JavascriptInvocation::arguments() {
return m_arguments;
}

View File

@ -0,0 +1,19 @@
#include <QObject>
#include <QString>
#include <QStringList>
class JavascriptInvocation : public QObject {
Q_OBJECT
Q_PROPERTY(QString functionName READ functionName)
Q_PROPERTY(QStringList arguments READ arguments)
public:
JavascriptInvocation(QString &functionName, QStringList &arguments, QObject *parent = 0);
QString &functionName();
QStringList &arguments();
private:
QString m_functionName;
QStringList m_arguments;
};

View File

@ -1,4 +1,5 @@
#include "WebPage.h"
#include "JavascriptInvocation.h"
#include <QResource>
WebPage::WebPage(QObject *parent) : QWebPage(parent) {
@ -16,3 +17,12 @@ bool WebPage::shouldInterruptJavaScript() {
return false;
}
QVariant WebPage::invokeCapybaraFunction(const char *name, QStringList &arguments) {
QString qname(name);
QString objectName("CapybaraInvocation");
JavascriptInvocation invocation(qname, arguments);
mainFrame()->addToJavaScriptWindowObject(objectName, &invocation);
QString javascript = QString("Capybara.invoke()");
return mainFrame()->evaluateJavaScript(javascript);
}

View File

@ -6,6 +6,7 @@ class WebPage : public QWebPage {
public:
WebPage(QObject *parent = 0);
QVariant invokeCapybaraFunction(const char *name, QStringList &arguments);
public slots:
bool shouldInterruptJavaScript();

View File

@ -2,6 +2,10 @@ Capybara = {
nextIndex: 0,
nodes: {},
invoke: function () {
return this[CapybaraInvocation.functionName].apply(this, CapybaraInvocation.arguments);
},
find: function (xpath) {
var iterator = document.evaluate(xpath, document, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null);
var node;

View File

@ -1,8 +1,8 @@
TEMPLATE = app
TARGET = webkit_server
DESTDIR = .
HEADERS = WebPage.h Server.h Connection.h Command.h Visit.h Find.h Reset.h Attribute.h
SOURCES = main.cpp WebPage.cpp Server.cpp Connection.cpp Command.cpp Visit.cpp Find.cpp Reset.cpp Attribute.cpp
HEADERS = WebPage.h Server.h Connection.h Command.h Visit.h Find.h Reset.h Attribute.h JavascriptInvocation.h
SOURCES = main.cpp WebPage.cpp Server.cpp Connection.cpp Command.cpp Visit.cpp Find.cpp Reset.cpp Attribute.cpp JavascriptInvocation.cpp
RESOURCES = webkit_server.qrc
QT += network webkit
CONFIG += console