From 18d424803d0d6ecb4c1642c4553c4489628c8632 Mon Sep 17 00:00:00 2001 From: Joe Ferris Date: Fri, 25 Feb 2011 22:57:55 -0500 Subject: [PATCH] Invoke Javascript functions by setting QObjects on the window object instead of string evals so that strings don't need to be escaped --- spec/driver_spec.rb | 4 ++++ src/Find.cpp | 10 +++------- src/JavascriptInvocation.cpp | 14 ++++++++++++++ src/JavascriptInvocation.h | 19 +++++++++++++++++++ src/WebPage.cpp | 10 ++++++++++ src/WebPage.h | 1 + src/capybara.js | 4 ++++ src/webkit_server.pro | 4 ++-- 8 files changed, 57 insertions(+), 9 deletions(-) create mode 100644 src/JavascriptInvocation.cpp create mode 100644 src/JavascriptInvocation.h diff --git a/spec/driver_spec.rb b/spec/driver_spec.rb index 136ad9c..c415761 100644 --- a/spec/driver_spec.rb +++ b/spec/driver_spec.rb @@ -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 diff --git a/src/Find.cpp b/src/Find.cpp index 1c1747a..74f80ad 100644 --- a/src/Find.cpp +++ b/src/Find.cpp @@ -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(); diff --git a/src/JavascriptInvocation.cpp b/src/JavascriptInvocation.cpp new file mode 100644 index 0000000..b69c4b7 --- /dev/null +++ b/src/JavascriptInvocation.cpp @@ -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; +} diff --git a/src/JavascriptInvocation.h b/src/JavascriptInvocation.h new file mode 100644 index 0000000..7a1d5b9 --- /dev/null +++ b/src/JavascriptInvocation.h @@ -0,0 +1,19 @@ +#include +#include +#include + +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; +}; + diff --git a/src/WebPage.cpp b/src/WebPage.cpp index 1bb6393..11b2f13 100644 --- a/src/WebPage.cpp +++ b/src/WebPage.cpp @@ -1,4 +1,5 @@ #include "WebPage.h" +#include "JavascriptInvocation.h" #include 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); +} + diff --git a/src/WebPage.h b/src/WebPage.h index 9c27736..d12e1fb 100644 --- a/src/WebPage.h +++ b/src/WebPage.h @@ -6,6 +6,7 @@ class WebPage : public QWebPage { public: WebPage(QObject *parent = 0); + QVariant invokeCapybaraFunction(const char *name, QStringList &arguments); public slots: bool shouldInterruptJavaScript(); diff --git a/src/capybara.js b/src/capybara.js index a00f3d6..35158d0 100644 --- a/src/capybara.js +++ b/src/capybara.js @@ -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; diff --git a/src/webkit_server.pro b/src/webkit_server.pro index cc52059..ac9d2e3 100644 --- a/src/webkit_server.pro +++ b/src/webkit_server.pro @@ -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