diff --git a/lib/capybara/driver/webkit.rb b/lib/capybara/driver/webkit.rb
index 55f9cee..67236b8 100644
--- a/lib/capybara/driver/webkit.rb
+++ b/lib/capybara/driver/webkit.rb
@@ -53,7 +53,9 @@ class Capybara::Driver::Webkit
end
def within_frame(frame_id)
- raise Capybara::NotSupportedByDriverError
+ browser.frame_focus_id(frame_id)
+ yield
+ browser.frame_focus_parent
end
def within_window(handle)
diff --git a/lib/capybara/driver/webkit/browser.rb b/lib/capybara/driver/webkit/browser.rb
index add4daa..cd40e69 100644
--- a/lib/capybara/driver/webkit/browser.rb
+++ b/lib/capybara/driver/webkit/browser.rb
@@ -30,6 +30,14 @@ class Capybara::Driver::Webkit
command("Url")
end
+ def frame_focus_id(frame_id)
+ command("FrameFocus", frame_id)
+ end
+
+ def frame_focus_parent
+ command("FrameFocus")
+ end
+
def command(name, *args)
@socket.puts name
@socket.puts args.size
diff --git a/spec/driver_spec.rb b/spec/driver_spec.rb
index 6ca3342..306d1c8 100644
--- a/spec/driver_spec.rb
+++ b/spec/driver_spec.rb
@@ -6,6 +6,89 @@ describe Capybara::Driver::Webkit do
before { subject.visit("/hello/world?success=true") }
after { subject.reset! }
+ context "iframe app" do
+ before(:all) do
+ @app = lambda do |env|
+ params = ::Rack::Utils.parse_query(env['QUERY_STRING'])
+ iframe = unless params["iframe"]
+ ""
+ end
+ if iframe
+ p_id = "farewell"
+ msg = "goodbye"
+ else
+ p_id = "greeting"
+ msg = "hello"
+ end
+ body = <<-HTML
+
+
+
+
+
+
+
+
+
+ HTML
+ [200,
+ { 'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s },
+ [body]]
+ end
+ end
+
+ it "finds content after loading a URL" do
+ subject.within_frame("f") do
+ subject.find("//*[contains(., 'goodbye')]").should_not be_empty
+ end
+ end
+
+ it "returns an attribute's value" do
+ subject.within_frame("f") do
+ subject.find("//p").first["id"].should == "farewell"
+ end
+ end
+
+ it "returns a node's text" do
+ subject.within_frame("f") do
+ subject.find("//p").first.text.should == "goodbye"
+ end
+ end
+
+ it "returns the current URL" do
+ subject.within_frame("f") do
+ port = subject.instance_variable_get("@rack_server").port
+ subject.current_url.should == "http://127.0.0.1:#{port}/hello/world?iframe=true"
+ end
+ end
+
+ it "returns the source code for the page" do
+ subject.within_frame("f") do
+ subject.source.should =~ %r{.*farewell.*}m
+ end
+ end
+
+ it "evaluates Javascript" do
+ subject.within_frame("f") do
+ result = subject.evaluate_script(%)
+ result.should == "hello"
+ end
+ end
+
+ it "executes Javascript" do
+ subject.within_frame("f") do
+ subject.execute_script(%)
+ subject.find("//p[contains(., 'yo')]").should_not be_empty
+ end
+ end
+ end
+
context "hello app" do
before(:all) do
@app = lambda do |env|
diff --git a/src/Connection.cpp b/src/Connection.cpp
index 66e0eac..3733be6 100644
--- a/src/Connection.cpp
+++ b/src/Connection.cpp
@@ -9,6 +9,7 @@
#include "Source.h"
#include "Evaluate.h"
#include "Execute.h"
+#include "FrameFocus.h"
#include
#include
diff --git a/src/Evaluate.cpp b/src/Evaluate.cpp
index 53699d5..695dabc 100644
--- a/src/Evaluate.cpp
+++ b/src/Evaluate.cpp
@@ -7,7 +7,7 @@ Evaluate::Evaluate(WebPage *page, QObject *parent) : Command(page, parent) {
}
void Evaluate::start(QStringList &arguments) {
- QVariant result = page()->mainFrame()->evaluateJavaScript(arguments[0]);
+ QVariant result = page()->currentFrame()->evaluateJavaScript(arguments[0]);
addVariant(result);
emit finished(true, m_buffer);
}
diff --git a/src/Execute.cpp b/src/Execute.cpp
index 06469e8..3a5410e 100644
--- a/src/Execute.cpp
+++ b/src/Execute.cpp
@@ -6,7 +6,7 @@ Execute::Execute(WebPage *page, QObject *parent) : Command(page, parent) {
void Execute::start(QStringList &arguments) {
QString script = arguments[0] + QString("; 'success'");
- QVariant result = page()->mainFrame()->evaluateJavaScript(script);
+ QVariant result = page()->currentFrame()->evaluateJavaScript(script);
QString response;
if (result.isValid()) {
emit finished(true, response);
diff --git a/src/FrameFocus.cpp b/src/FrameFocus.cpp
new file mode 100644
index 0000000..39b439d
--- /dev/null
+++ b/src/FrameFocus.cpp
@@ -0,0 +1,12 @@
+#include "FrameFocus.h"
+#include "Command.h"
+#include "WebPage.h"
+
+FrameFocus::FrameFocus(WebPage *page, QObject *parent) : Command(page, parent) {
+}
+
+void FrameFocus::start(QStringList &arguments) {
+ QString response;
+ emit finished(true, response);
+}
+
diff --git a/src/FrameFocus.h b/src/FrameFocus.h
new file mode 100644
index 0000000..a54f429
--- /dev/null
+++ b/src/FrameFocus.h
@@ -0,0 +1,12 @@
+#include "Command.h"
+
+class WebPage;
+
+class FrameFocus : public Command {
+ Q_OBJECT
+
+ public:
+ FrameFocus(WebPage *page, QObject *parent = 0);
+ virtual void start(QStringList &arguments);
+};
+
diff --git a/src/Reset.cpp b/src/Reset.cpp
index d20662b..5759074 100644
--- a/src/Reset.cpp
+++ b/src/Reset.cpp
@@ -8,7 +8,7 @@ void Reset::start(QStringList &arguments) {
Q_UNUSED(arguments);
page()->triggerAction(QWebPage::Stop);
- page()->mainFrame()->setHtml("");
+ page()->currentFrame()->setHtml("");
page()->networkAccessManager()->setCookieJar(new QNetworkCookieJar());
QString response = "";
emit finished(true, response);
diff --git a/src/Source.cpp b/src/Source.cpp
index 00b5240..c548923 100644
--- a/src/Source.cpp
+++ b/src/Source.cpp
@@ -7,7 +7,7 @@ Source::Source(WebPage *page, QObject *parent) : Command(page, parent) {
void Source::start(QStringList &arguments) {
Q_UNUSED(arguments)
- QString response = page()->mainFrame()->toHtml();
+ QString response = page()->currentFrame()->toHtml();
emit finished(true, response);
}
diff --git a/src/Url.cpp b/src/Url.cpp
index b7f2d33..0a5b451 100644
--- a/src/Url.cpp
+++ b/src/Url.cpp
@@ -7,7 +7,7 @@ Url::Url(WebPage *page, QObject *parent) : Command(page, parent) {
void Url::start(QStringList &argments) {
Q_UNUSED(argments);
- QUrl humanUrl = page()->mainFrame()->url();
+ QUrl humanUrl = page()->currentFrame()->url();
QByteArray encodedBytes = humanUrl.toEncoded();
QString response = QString(encodedBytes);
diff --git a/src/Visit.cpp b/src/Visit.cpp
index cd15e66..9214211 100644
--- a/src/Visit.cpp
+++ b/src/Visit.cpp
@@ -7,7 +7,7 @@ Visit::Visit(WebPage *page, QObject *parent) : Command(page, parent) {
}
void Visit::start(QStringList &arguments) {
- page()->mainFrame()->setUrl(QUrl(arguments[0]));
+ page()->currentFrame()->setUrl(QUrl(arguments[0]));
}
void Visit::loadFinished(bool success) {
diff --git a/src/WebPage.cpp b/src/WebPage.cpp
index d71f21c..2545f27 100644
--- a/src/WebPage.cpp
+++ b/src/WebPage.cpp
@@ -4,8 +4,6 @@
#include
WebPage::WebPage(QObject *parent) : QWebPage(parent) {
- connect(mainFrame(), SIGNAL(javaScriptWindowObjectCleared()),
- this, SLOT(injectJavascriptHelpers()));
QResource javascript(":/capybara.js");
char * javascriptString = new char[javascript.size() + 1];
strcpy(javascriptString, (const char *)javascript.data());
@@ -14,10 +12,18 @@ WebPage::WebPage(QObject *parent) : QWebPage(parent) {
m_loading = false;
connect(this, SIGNAL(loadStarted()), this, SLOT(loadStarted()));
connect(this, SIGNAL(loadFinished(bool)), this, SLOT(loadFinished(bool)));
+ connect(this, SIGNAL(frameCreated(QWebFrame *)),
+ this, SLOT(frameCreated(QWebFrame *)));
+}
+
+void WebPage::frameCreated(QWebFrame * frame) {
+ connect(frame, SIGNAL(javaScriptWindowObjectCleared()),
+ this, SLOT(injectJavascriptHelpers()));
}
void WebPage::injectJavascriptHelpers() {
- mainFrame()->evaluateJavaScript(m_capybaraJavascript);
+ QWebFrame* frame = qobject_cast(QObject::sender());
+ frame->evaluateJavaScript(m_capybaraJavascript);
}
bool WebPage::shouldInterruptJavaScript() {
@@ -28,9 +34,9 @@ QVariant WebPage::invokeCapybaraFunction(const char *name, QStringList &argument
QString qname(name);
QString objectName("CapybaraInvocation");
JavascriptInvocation invocation(qname, arguments);
- mainFrame()->addToJavaScriptWindowObject(objectName, &invocation);
+ currentFrame()->addToJavaScriptWindowObject(objectName, &invocation);
QString javascript = QString("Capybara.invoke()");
- return mainFrame()->evaluateJavaScript(javascript);
+ return currentFrame()->evaluateJavaScript(javascript);
}
QVariant WebPage::invokeCapybaraFunction(QString &name, QStringList &arguments) {
@@ -76,6 +82,6 @@ bool WebPage::isLoading() const {
}
QString WebPage::failureString() {
- return QString("Unable to load URL: ") + mainFrame()->url().toString();
+ return QString("Unable to load URL: ") + currentFrame()->url().toString();
}
diff --git a/src/WebPage.h b/src/WebPage.h
index 8bbba10..1ad634a 100644
--- a/src/WebPage.h
+++ b/src/WebPage.h
@@ -15,6 +15,7 @@ class WebPage : public QWebPage {
void loadStarted();
void loadFinished(bool);
bool isLoading() const;
+ void frameCreated(QWebFrame *);
protected:
virtual void javaScriptConsoleMessage(const QString &message, int lineNumber, const QString &sourceID);
diff --git a/src/find_command.h b/src/find_command.h
index b38ad33..9744c1a 100644
--- a/src/find_command.h
+++ b/src/find_command.h
@@ -11,3 +11,4 @@ CHECK_COMMAND(Url)
CHECK_COMMAND(Source)
CHECK_COMMAND(Evaluate)
CHECK_COMMAND(Execute)
+CHECK_COMMAND(FrameFocus)
diff --git a/src/webkit_server.pro b/src/webkit_server.pro
index 8079223..1a72cae 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 Node.h JavascriptInvocation.h Url.h Source.h Evaluate.h Execute.h
-SOURCES = main.cpp WebPage.cpp Server.cpp Connection.cpp Command.cpp Visit.cpp Find.cpp Reset.cpp Node.cpp JavascriptInvocation.cpp Url.cpp Source.cpp Evaluate.cpp Execute.cpp
+HEADERS = WebPage.h Server.h Connection.h Command.h Visit.h Find.h Reset.h Node.h JavascriptInvocation.h Url.h Source.h Evaluate.h Execute.h FrameFocus.h
+SOURCES = main.cpp WebPage.cpp Server.cpp Connection.cpp Command.cpp Visit.cpp Find.cpp Reset.cpp Node.cpp JavascriptInvocation.cpp Url.cpp Source.cpp Evaluate.cpp Execute.cpp FrameFocus.cpp
RESOURCES = webkit_server.qrc
QT += network webkit
CONFIG += console