Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: thoughtbot/capybara-webkit
...
head fork: niklasb/capybara-webkit
Checking mergeability… Don't worry, you can still create the pull request.
  • 11 commits
  • 28 files changed
  • 0 commit comments
  • 1 contributor
View
2  Gemfile
@@ -3,4 +3,4 @@ gem "rspec", '~> 2.6.0', :require => false
gem "capybara"
gem "sinatra", :require => false
gem "mini_magick", :require => false
-gem 'rake'
+gem 'rake', '~> 0.8.7'
View
34 Gemfile.lock
@@ -1,26 +1,26 @@
GEM
remote: http://rubygems.org/
specs:
- capybara (1.0.0)
+ capybara (1.1.1)
mime-types (>= 1.16)
nokogiri (>= 1.3.3)
rack (>= 1.0.0)
rack-test (>= 0.5.4)
- selenium-webdriver (~> 0.2.0)
+ selenium-webdriver (~> 2.0)
xpath (~> 0.1.4)
- childprocess (0.1.9)
+ childprocess (0.2.2)
ffi (~> 1.0.6)
- diff-lcs (1.1.2)
+ diff-lcs (1.1.3)
ffi (1.0.9)
- json_pure (1.5.3)
+ json_pure (1.6.0)
mime-types (1.16)
- mini_magick (3.2.1)
- subexec (~> 0.0.4)
+ mini_magick (3.3)
+ subexec (~> 0.1.0)
nokogiri (1.5.0)
- rack (1.3.0)
- rack-test (0.6.0)
+ rack (1.3.2)
+ rack-test (0.6.1)
rack (>= 1.0)
- rake (0.9.2)
+ rake (0.8.7)
rspec (2.6.0)
rspec-core (~> 2.6.0)
rspec-expectations (~> 2.6.0)
@@ -30,16 +30,16 @@ GEM
diff-lcs (~> 1.1.2)
rspec-mocks (2.6.0)
rubyzip (0.9.4)
- selenium-webdriver (0.2.2)
- childprocess (>= 0.1.9)
+ selenium-webdriver (2.5.0)
+ childprocess (>= 0.2.1)
ffi (>= 1.0.7)
json_pure
rubyzip
- sinatra (1.1.2)
+ sinatra (1.2.6)
rack (~> 1.1)
- tilt (~> 1.2)
- subexec (0.0.4)
- tilt (1.2.2)
+ tilt (>= 1.2.2, < 2.0)
+ subexec (0.1.0)
+ tilt (1.3.3)
xpath (0.1.4)
nokogiri (~> 1.3)
@@ -49,6 +49,6 @@ PLATFORMS
DEPENDENCIES
capybara
mini_magick
- rake
+ rake (~> 0.8.7)
rspec (~> 2.6.0)
sinatra
View
2  capybara-webkit.gemspec
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
s.require_path = "lib"
s.rubygems_version = "1.3.5"
s.summary = "Headless Webkit driver for Capybara"
- s.add_runtime_dependency "capybara", "~> 1.0.0"
+ s.add_runtime_dependency "capybara", "~> 1.1.0"
s.extensions = "extconf.rb"
end
View
43 lib/capybara/driver/webkit/browser.rb
@@ -86,6 +86,49 @@ def render(path, width, height)
command "Render", path, width, height
end
+ def set_cookie(cookie)
+ command "SetCookie", cookie
+ end
+
+ def clear_cookies
+ command "ClearCookies"
+ end
+
+ def get_cookies
+ command("GetCookies").lines
+ .map { |line| line.strip }
+ .select { |line| !line.empty? }
+ end
+
+ def set_html(html, url=nil)
+ if url
+ command("SetHtml", html, url)
+ else
+ command("SetHtml", html)
+ end
+ end
+
+ def set_proxy(opts = {})
+ # remove proxy?
+ return command("SetProxy") if opts.empty?
+
+ # set a HTTP proxy
+ command("SetProxy",
+ opts[:host] || "localhost",
+ opts[:port] || "0",
+ opts[:user] || "",
+ opts[:pass] || "")
+ end
+
+ def set_attribute(attr, value = true)
+ value = value ? "true" : "false"
+ command("SetAttribute", attr, value)
+ end
+
+ def reset_attribute(attr)
+ command("SetAttribute", attr, "reset")
+ end
+
private
def start_server
View
6 lib/capybara/driver/webkit/node.rb
@@ -71,7 +71,11 @@ def disabled?
end
def path
- raise Capybara::NotSupportedByDriverError
+ invoke "path"
+ end
+
+ def submit(opts)
+ invoke "submit"
end
def trigger(event)
View
86 spec/browser_spec.rb
@@ -1,6 +1,8 @@
require 'spec_helper'
require 'stringio'
require 'capybara/driver/webkit/browser'
+require 'socket'
+require 'base64'
describe Capybara::Driver::Webkit::Browser do
@@ -32,4 +34,88 @@
io.string.should == "hello world\n"
end
+ describe '#set_proxy' do
+ before do
+ @host = '127.0.0.1'
+ @user = 'user'
+ @pass = 'secret'
+ @url = "http://example.org/"
+
+ serv = TCPServer.new(@host, 0)
+ @port = serv.addr[1]
+
+ @proxy_requests = []
+ @proxy = Thread.new(serv, @proxy_requests) do |serv, proxy_requests|
+ while conn = serv.accept do
+ # read request
+ request = []
+ until (line = conn.readline.strip).empty?
+ request << line
+ end
+
+ # send response
+ auth_header = request.find { |h| h =~ /Authorization:/i }
+ if auth_header || request[0].split(/\s+/)[1] =~ /^\//
+ html = "<html><body>D'oh!</body></html>"
+ conn.write "HTTP/1.1 200 OK\r\n"
+ conn.write "Content-Type:text/html\r\n"
+ conn.write "Content-Length: %i\r\n" % html.size
+ conn.write "\r\n"
+ conn.write html
+ conn.close
+ proxy_requests << request if auth_header
+ else
+ conn.write "HTTP/1.1 407 Proxy Auth Required\r\n"
+ conn.write "Proxy-Authenticate: Basic realm=\"Proxy\"\r\n"
+ conn.write "\r\n"
+ conn.close
+ proxy_requests << request
+ end
+ end
+ end
+
+ browser.set_proxy(:host => @host,
+ :port => @port,
+ :user => @user,
+ :pass => @pass)
+ browser.visit @url
+ @proxy_requests.size.should == 2
+ @request = @proxy_requests[-1]
+ end
+
+ after do
+ @proxy.kill
+ end
+
+ it 'uses the HTTP proxy correctly' do
+ @request[0].should match /^GET\s+http:\/\/example.org\/\s+HTTP/i
+ @request.find { |header|
+ header =~ /^Host:\s+example.org$/i }.should_not be nil
+ end
+
+ it 'sends correct proxy authentication' do
+ auth_header = @request.find { |header|
+ header =~ /^Proxy-Authorization:\s+/i }
+ auth_header.should_not be nil
+
+ user, pass = Base64.decode64(auth_header.split(/\s+/)[-1]).split(":")
+ user.should == @user
+ pass.should == @pass
+ end
+
+ it "uses the proxies' response" do
+ browser.body.should include "D'oh!"
+ end
+
+ it 'uses original URL' do
+ browser.url.should == @url
+ end
+
+ it 'is possible to disable proxy again' do
+ @proxy_requests.clear
+ browser.set_proxy
+ browser.visit "http://#{@host}:#{@port}/"
+ @proxy_requests.size.should == 0
+ end
+ end
end
View
190 spec/integration/session_spec.rb
@@ -125,6 +125,196 @@
subject.response_headers['X-Capybara'].should == nil
end
end
+
+ context "cookie-based app" do
+ before(:all) do
+ @cookie = 'cookie=abc; domain=127.0.0.1; path=/'
+ @app = lambda do |env|
+ request = ::Rack::Request.new(env)
+
+ body = <<-HTML
+ <html><body>
+ <p id="cookie">#{request.cookies["cookie"] || ""}</p>
+ </body></html>
+ HTML
+ [200,
+ { 'Content-Type' => 'text/html; charset=UTF-8',
+ 'Content-Length' => body.length.to_s,
+ 'Set-Cookie' => @cookie,
+ },
+ [body]]
+ end
+ end
+
+ def echoed_cookie
+ subject.all(:css, "#cookie").first.text
+ end
+
+ it "should remember the cookie on second visit" do
+ subject.visit "/"
+ echoed_cookie.should == ""
+ subject.visit "/"
+ echoed_cookie.should == "abc"
+ end
+
+ it "should use the custom cookie" do
+ $webkit_browser.set_cookie @cookie
+ subject.visit "/"
+ echoed_cookie.should == "abc"
+ end
+
+ it "should clear cookies" do
+ subject.visit "/"
+ $webkit_browser.clear_cookies
+ subject.visit "/"
+ echoed_cookie.should == ""
+ end
+
+ it "should get cookies" do
+ subject.visit "/"
+ cookies = $webkit_browser.get_cookies
+
+ cookies.size.should == 1
+
+ cookie = Hash[cookies[0].split(/\s*;\s*/)
+ .map { |x| x.split("=", 2) }]
+ cookie["cookie"].should == "abc"
+ cookie["domain"].should include "127.0.0.1"
+ cookie["path"].should == "/"
+ end
+ end
+
+ context "custom HTML" do
+ before(:all) do
+ @requested = []
+ @app = lambda do |env|
+ params = ::Rack::Utils.parse_query(env['QUERY_STRING'])
+
+ type = params["get"]
+ @requested << type
+ if type == "javascript"
+ js = <<-JS
+ onload_handler = function() {
+ document.getElementById("url").innerHTML = document.location;
+ }
+ JS
+ [200,
+ { 'Content-Type' => 'text/javascript; charset=UTF-8',
+ 'Content-Length' => js.size.to_s,
+ }, [js]]
+ else
+ [200,
+ { 'Content-Type' => 'text/%s; charset=UTF-8' % type,
+ 'Content-Length' => "0",
+ }, [""]]
+ end
+ end
+ end
+
+ before do
+ @requested.clear
+ @root_url = subject.driver.send(:url, "/")
+ end
+
+ def set_html(url = @root_url)
+ $webkit_browser.set_html <<-HTML, url
+ <html>
+ <head>
+ <title>Test</title>
+ <script type="text/javascript" src="?get=javascript"></script>
+ <link rel="stylesheet" type="text/css" href="?get=css" />
+ </head>
+ <body onload="onload_handler();">
+ <p id="welcome">Hello</p>
+ <p id="url">n/a</p>
+ </body>
+ </html>
+ HTML
+ subject.all(:css, "#welcome").first.text.should == "Hello"
+ end
+
+ it "should allow setting custom HTML without URL" do
+ set_html nil
+ end
+
+ it "should allow setting custom HTML with URL" do
+ set_html
+ $webkit_browser.url.should == @root_url
+ end
+
+ it "should load resources from right location" do
+ set_html
+ @requested.size.should == 2
+ @requested.should include "javascript"
+ @requested.should include "css"
+ end
+
+ it "should make fake URL accessible through document.location" do
+ set_html
+ subject.all(:css, "#url").first.text.should == @root_url
+ end
+ end
+
+ context 'special HTML loading attributes' do
+ before(:all) do
+ @requested = []
+ @app = lambda do |env|
+ params = ::Rack::Utils.parse_query(env['QUERY_STRING'])
+
+ type = params["get"]
+ @requested << type if type
+ if type == "image"
+ [200,
+ { 'Content-Type' => 'image/jpeg',
+ 'Content-Length' => "0",
+ }, [""]]
+ else
+ body = <<-HTML
+ <html>
+ <head>
+ <title>Test</title>
+ </head>
+ <body onload="onload_handler();">
+ <p id="welcome">Hello</p>
+ <img src="?get=image" />
+ </body>
+ </html>
+ HTML
+
+ [200,
+ { 'Content-Type' => 'text/html',
+ 'Content-Length' => body.size.to_s,
+ }, [body]]
+ end
+ end
+ end
+
+ before do
+ @requested.clear
+ end
+
+ it 'should respect AutoLoadImages = false' do
+ $webkit_browser.set_attribute("AutoLoadImages", false)
+ subject.visit "/"
+ @requested.size.should == 0
+ end
+
+ it 'should reset AutoLoadImages when requested explicitly' do
+ $webkit_browser.set_attribute("AutoLoadImages", false)
+ subject.visit "/"
+ $webkit_browser.reset_attribute("AutoLoadImages")
+ subject.visit "/"
+ @requested.should include "image"
+ end
+
+ it 'should reset AutoLoadImages automatically on driver reset' do
+ $webkit_browser.set_attribute("AutoLoadImages", false)
+ subject.visit "/"
+ subject.reset!
+ subject.visit "/"
+ @requested.should include "image"
+ end
+ end
end
describe Capybara::Session, "with TestApp" do
View
18 src/ClearCookies.cpp
@@ -0,0 +1,18 @@
+#include "ClearCookies.h"
+#include "WebPage.h"
+#include "NetworkCookieJar.h"
+#include <QNetworkCookie>
+
+ClearCookies::ClearCookies(WebPage *page, QObject *parent)
+ : Command(page, parent)
+{ }
+
+void ClearCookies::start(QStringList &arguments)
+{
+ Q_UNUSED(arguments);
+ NetworkCookieJar *jar = qobject_cast<NetworkCookieJar*>(page()
+ ->networkAccessManager()
+ ->cookieJar());
+ jar->clearCookies();
+ emit finished(new Response(true));
+}
View
11 src/ClearCookies.h
@@ -0,0 +1,11 @@
+#include "Command.h"
+
+class WebPage;
+
+class ClearCookies : public Command {
+ Q_OBJECT;
+
+ public:
+ ClearCookies(WebPage *page, QObject *parent = 0);
+ virtual void start(QStringList &arguments);
+};
View
6 src/Connection.cpp
@@ -15,6 +15,12 @@
#include "Body.h"
#include "Status.h"
#include "Headers.h"
+#include "SetCookie.h"
+#include "ClearCookies.h"
+#include "GetCookies.h"
+#include "SetHtml.h"
+#include "SetProxy.h"
+#include "SetAttribute.h"
#include <QTcpSocket>
#include <iostream>
View
22 src/GetCookies.cpp
@@ -0,0 +1,22 @@
+#include "GetCookies.h"
+#include "WebPage.h"
+#include "NetworkCookieJar.h"
+
+GetCookies::GetCookies(WebPage *page, QObject *parent)
+ : Command(page, parent)
+{
+ m_buffer = "";
+}
+
+void GetCookies::start(QStringList &arguments)
+{
+ Q_UNUSED(arguments);
+ NetworkCookieJar *jar = qobject_cast<NetworkCookieJar*>(page()
+ ->networkAccessManager()
+ ->cookieJar());
+ foreach (QNetworkCookie cookie, jar->getAllCookies()) {
+ m_buffer.append(cookie.toRawForm());
+ m_buffer.append("\n");
+ }
+ emit finished(new Response(true, m_buffer));
+}
View
14 src/GetCookies.h
@@ -0,0 +1,14 @@
+#include "Command.h"
+
+class WebPage;
+
+class GetCookies : public Command {
+ Q_OBJECT;
+
+ public:
+ GetCookies(WebPage *page, QObject *parent = 0);
+ virtual void start(QStringList &arguments);
+
+ private:
+ QString m_buffer;
+};
View
101 src/NetworkCookieJar.cpp
@@ -0,0 +1,101 @@
+#include "NetworkCookieJar.h"
+#include "QtCore/qdatetime.h"
+
+NetworkCookieJar::NetworkCookieJar(QObject *parent)
+ : QNetworkCookieJar(parent)
+{ }
+
+QList<QNetworkCookie> NetworkCookieJar::getAllCookies() const
+{
+ return allCookies();
+}
+
+void NetworkCookieJar::clearCookies()
+{
+ setAllCookies(QList<QNetworkCookie>());
+}
+
+static inline bool isParentDomain(QString domain, QString reference)
+{
+ if (!reference.startsWith(QLatin1Char('.')))
+ return domain == reference;
+
+ return domain.endsWith(reference) || domain == reference.mid(1);
+}
+
+void NetworkCookieJar::overwriteCookies(const QList<QNetworkCookie>& cookieList)
+{
+ /* this function is basically a copy-and-paste of the original
+ QNetworkCookieJar::setCookiesFromUrl with the domain and
+ path validations removed */
+
+ QString defaultPath(QLatin1Char('/'));
+ QDateTime now = QDateTime::currentDateTime();
+ QList<QNetworkCookie> newCookies = allCookies();
+
+ foreach (QNetworkCookie cookie, cookieList) {
+ bool isDeletion = (!cookie.isSessionCookie() &&
+ cookie.expirationDate() < now);
+
+ // validate the cookie & set the defaults if unset
+ if (cookie.path().isEmpty())
+ cookie.setPath(defaultPath);
+
+ // don't do path checking. See http://bugreports.qt.nokia.com/browse/QTBUG-5815
+ // else if (!isParentPath(pathAndFileName, cookie.path())) {
+ // continue; // not accepted
+ // }
+
+ if (cookie.domain().isEmpty()) {
+ continue;
+ } else {
+ // Ensure the domain starts with a dot if its field was not empty
+ // in the HTTP header. There are some servers that forget the
+ // leading dot and this is actually forbidden according to RFC 2109,
+ // but all browsers accept it anyway so we do that as well.
+ if (!cookie.domain().startsWith(QLatin1Char('.')))
+ cookie.setDomain(QLatin1Char('.') + cookie.domain());
+
+ QString domain = cookie.domain();
+
+ // the check for effective TLDs makes the "embedded dot" rule from RFC 2109 section 4.3.2
+ // redundant; the "leading dot" rule has been relaxed anyway, see above
+ // we remove the leading dot for this check
+ /*
+ if (QNetworkCookieJarPrivate::isEffectiveTLD(domain.remove(0, 1)))
+ continue; // not accepted
+ */
+ }
+
+ for (int i = 0; i < newCookies.size(); ++i) {
+ // does this cookie already exist?
+ const QNetworkCookie &current = newCookies.at(i);
+ if (cookie.name() == current.name() &&
+ cookie.domain() == current.domain() &&
+ cookie.path() == current.path()) {
+ // found a match
+ newCookies.removeAt(i);
+ break;
+ }
+ }
+
+ // did not find a match
+ if (!isDeletion) {
+ int countForDomain = 0;
+ for (int i = newCookies.size() - 1; i >= 0; --i) {
+ // Start from the end and delete the oldest cookies to keep a maximum count of 50.
+ const QNetworkCookie &current = newCookies.at(i);
+ if (isParentDomain(cookie.domain(), current.domain())
+ || isParentDomain(current.domain(), cookie.domain())) {
+ if (countForDomain >= 49)
+ newCookies.removeAt(i);
+ else
+ ++countForDomain;
+ }
+ }
+
+ newCookies += cookie;
+ }
+ }
+ setAllCookies(newCookies);
+}
View
15 src/NetworkCookieJar.h
@@ -0,0 +1,15 @@
+#include <QtNetwork/QNetworkCookieJar>
+#include <QtNetwork/QNetworkCookie>
+
+class NetworkCookieJar : public QNetworkCookieJar {
+
+ Q_OBJECT;
+
+ public:
+
+ NetworkCookieJar(QObject *parent = 0);
+
+ QList<QNetworkCookie> getAllCookies() const;
+ void clearCookies();
+ void overwriteCookies(const QList<QNetworkCookie>& cookieList);
+};
View
5 src/Reset.cpp
@@ -1,6 +1,7 @@
#include "Reset.h"
#include "WebPage.h"
#include "NetworkAccessManager.h"
+#include "NetworkCookieJar.h"
Reset::Reset(WebPage *page, QObject *parent) : Command(page, parent) {
}
@@ -10,10 +11,12 @@ void Reset::start(QStringList &arguments) {
page()->triggerAction(QWebPage::Stop);
page()->currentFrame()->setHtml("<html><body></body></html>");
- page()->networkAccessManager()->setCookieJar(new QNetworkCookieJar());
+ page()->networkAccessManager()->setCookieJar(new NetworkCookieJar());
page()->setCustomNetworkAccessManager();
page()->setUserAgent(NULL);
page()->resetResponseHeaders();
+ page()->resetSettings();
+
emit finished(new Response(true));
}
View
53 src/SetAttribute.cpp
@@ -0,0 +1,53 @@
+#include "SetAttribute.h"
+#include "WebPage.h"
+#include <QWebSettings>
+#include <iostream>
+
+static QMap<QString, QWebSettings::WebAttribute> getAttributesByName()
+{
+ QMap<QString, QWebSettings::WebAttribute> map;
+ map.insert("AutoLoadImages",
+ QWebSettings::AutoLoadImages);
+ // disable setting JavascriptEnabled to false,
+ // as our Javascript helpers won't work then
+ //map.insert("JavascriptEnabled",
+ // QWebSettings::JavascriptEnabled);
+ map.insert("JavascriptCanOpenWindows",
+ QWebSettings::JavascriptCanOpenWindows);
+ map.insert("JavascriptCanAccessClipboard",
+ QWebSettings::JavascriptCanAccessClipboard);
+ map.insert("PrivateBrowsingEnabled",
+ QWebSettings::PrivateBrowsingEnabled);
+ map.insert("DnsPrefetchEnabled",
+ QWebSettings::DnsPrefetchEnabled);
+ map.insert("LocalStorageEnabled",
+ QWebSettings::LocalStorageEnabled);
+ return map;
+}
+
+const QMap<QString, QWebSettings::WebAttribute> attributes_by_name =
+ getAttributesByName();
+
+SetAttribute::SetAttribute(WebPage *page, QObject *parent)
+ : Command(page, parent)
+{ }
+
+void SetAttribute::start(QStringList &arguments)
+{
+ if (!attributes_by_name.contains(arguments[0])) {
+ // not found
+ emit finished(new Response(false, QString("No such attribute: ") +
+ arguments[0]));
+ return;
+ }
+
+ QWebSettings::WebAttribute attr =
+ attributes_by_name[arguments[0]];
+
+ if (arguments[1] != "reset")
+ page()->settings()->setAttribute(attr, arguments[1] != "false");
+ else
+ page()->settings()->resetAttribute(attr);
+
+ emit finished(new Response(true));
+}
View
16 src/SetAttribute.h
@@ -0,0 +1,16 @@
+#include "Command.h"
+#include <QMap>
+#include <QString>
+#include <QWebSettings>
+
+extern const QMap<QString, QWebSettings::WebAttribute> attributes_by_name;
+
+class WebPage;
+
+class SetAttribute : public Command {
+ Q_OBJECT;
+
+ public:
+ SetAttribute(WebPage *page, QObject *parent = 0);
+ virtual void start(QStringList &arguments);
+};
View
18 src/SetCookie.cpp
@@ -0,0 +1,18 @@
+#include "SetCookie.h"
+#include "WebPage.h"
+#include "NetworkCookieJar.h"
+#include <QNetworkCookie>
+
+SetCookie::SetCookie(WebPage *page, QObject *parent)
+ : Command(page, parent)
+{ }
+
+void SetCookie::start(QStringList &arguments)
+{
+ QList<QNetworkCookie> cookies = QNetworkCookie::parseCookies(arguments[0].toAscii());
+ NetworkCookieJar *jar = qobject_cast<NetworkCookieJar*>(page()
+ ->networkAccessManager()
+ ->cookieJar());
+ jar->overwriteCookies(cookies);
+ emit finished(new Response(true));
+}
View
11 src/SetCookie.h
@@ -0,0 +1,11 @@
+#include "Command.h"
+
+class WebPage;
+
+class SetCookie : public Command {
+ Q_OBJECT;
+
+ public:
+ SetCookie(WebPage *page, QObject *parent = 0);
+ virtual void start(QStringList &arguments);
+};
View
23 src/SetHtml.cpp
@@ -0,0 +1,23 @@
+#include "SetHtml.h"
+#include "WebPage.h"
+#include <QUrl>
+
+SetHtml::SetHtml(WebPage *page, QObject *parent)
+ : Command(page, parent)
+{ }
+
+void SetHtml::start(QStringList &arguments) {
+ if (arguments.size() > 1)
+ page()->currentFrame()->setHtml(arguments[0], QUrl(arguments[1]));
+ else
+ page()->currentFrame()->setHtml(arguments[0]);
+ emit finished(new Response(true));
+}
+
+void SetHtml::loadFinished(bool success) {
+ QString message;
+ if (!success)
+ message = page()->failureString();
+
+ emit finished(new Response(success, message));
+}
View
14 src/SetHtml.h
@@ -0,0 +1,14 @@
+#include "Command.h"
+
+class WebPage;
+
+class SetHtml : public Command {
+ Q_OBJECT;
+
+ public:
+ SetHtml(WebPage *page, QObject *parent = 0);
+ virtual void start(QStringList &arguments);
+
+ private slots:
+ void loadFinished(bool success);
+};
View
24 src/SetProxy.cpp
@@ -0,0 +1,24 @@
+#include "SetProxy.h"
+#include "WebPage.h"
+#include <QNetworkAccessManager>
+#include <QNetworkProxy>
+
+SetProxy::SetProxy(WebPage *page, QObject *parent)
+ : Command(page, parent)
+{ }
+
+void SetProxy::start(QStringList &arguments)
+{
+ // default to empty proxy
+ QNetworkProxy proxy;
+
+ if (arguments.size() > 0)
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy,
+ arguments[0],
+ (quint16)(arguments[1].toInt()),
+ arguments[2],
+ arguments[3]);
+
+ page()->networkAccessManager()->setProxy(proxy);
+ emit finished(new Response(true));
+}
View
11 src/SetProxy.h
@@ -0,0 +1,11 @@
+#include "Command.h"
+
+class WebPage;
+
+class SetProxy : public Command {
+ Q_OBJECT;
+
+ public:
+ SetProxy(WebPage *page, QObject *parent = 0);
+ virtual void start(QStringList &arguments);
+};
View
9 src/WebPage.cpp
@@ -1,6 +1,8 @@
#include "WebPage.h"
#include "JavascriptInvocation.h"
#include "NetworkAccessManager.h"
+#include "NetworkCookieJar.h"
+#include "SetAttribute.h"
#include <QResource>
#include <iostream>
@@ -19,6 +21,7 @@ WebPage::WebPage(QObject *parent) : QWebPage(parent) {
void WebPage::setCustomNetworkAccessManager() {
NetworkAccessManager *manager = new NetworkAccessManager();
+ manager->setCookieJar(new NetworkCookieJar());
this->setNetworkAccessManager(manager);
connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(replyFinished(QNetworkReply *)));
}
@@ -185,6 +188,12 @@ void WebPage::replyFinished(QNetworkReply *reply) {
}
}
+void WebPage::resetSettings() {
+ foreach (QWebSettings::WebAttribute attr, attributes_by_name) {
+ settings()->resetAttribute(attr);
+ }
+}
+
int WebPage::getLastStatus() {
return m_lastStatus;
}
View
1  src/WebPage.h
@@ -25,6 +25,7 @@ class WebPage : public QWebPage {
QString pageHeaders();
void frameCreated(QWebFrame *);
void replyFinished(QNetworkReply *reply);
+ void resetSettings();
protected:
virtual void javaScriptConsoleMessage(const QString &message, int lineNumber, const QString &sourceID);
View
41 src/capybara.js
@@ -52,10 +52,51 @@ Capybara = {
}
},
+ path: function(index) {
+ return "/" + this.getXPathNode(this.nodes[index]).join("/");
+ },
+
+ getXPathNode: function(node, path) {
+ path = path || [];
+ if(node.parentNode) {
+ path = this.getXPathNode(node.parentNode, path);
+ }
+
+ if(node.previousSibling) {
+ var count = 1;
+ var sibling = node.previousSibling
+ do {
+ if(sibling.nodeType == 1 && sibling.nodeName == node.nodeName) {count++;}
+ sibling = sibling.previousSibling;
+ } while(sibling);
+ if(count == 1) {count = null;}
+ } else if(node.nextSibling) {
+ var sibling = node.nextSibling;
+ do {
+ if(sibling.nodeType == 1 && sibling.nodeName == node.nodeName) {
+ var count = 1;
+ sibling = null;
+ } else {
+ var count = null;
+ sibling = sibling.previousSibling;
+ }
+ } while(sibling);
+ }
+
+ if(node.nodeType == 1) {
+ path.push(node.nodeName.toLowerCase() + (node.id ? "[@id='"+node.id+"']" : count > 0 ? "["+count+"]" : ''));
+ }
+ return path;
+ },
+
tagName: function(index) {
return this.nodes[index].tagName.toLowerCase();
},
+ submit: function(index) {
+ return this.nodes[index].submit();
+ },
+
click: function (index) {
var clickEvent = document.createEvent('MouseEvents');
clickEvent.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
View
8 src/find_command.h
@@ -16,4 +16,10 @@ CHECK_COMMAND(Header)
CHECK_COMMAND(Render)
CHECK_COMMAND(Body)
CHECK_COMMAND(Status)
-CHECK_COMMAND(Headers)
+CHECK_COMMAND(Headers)
+CHECK_COMMAND(SetCookie)
+CHECK_COMMAND(ClearCookies)
+CHECK_COMMAND(GetCookies)
+CHECK_COMMAND(SetHtml)
+CHECK_COMMAND(SetProxy)
+CHECK_COMMAND(SetAttribute)
View
63 src/webkit_server.pro
@@ -1,8 +1,67 @@
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 FrameFocus.h Response.h NetworkAccessManager.h Header.h Render.h body.h Status.h Headers.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 Response.cpp NetworkAccessManager.cpp Header.cpp Render.cpp body.cpp Status.cpp Headers.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 \
+ Response.h \
+ NetworkAccessManager.h \
+ NetworkCookieJar.h \
+ Header.h \
+ Render.h \
+ body.h \
+ Status.h \
+ Headers.h \
+ SetCookie.h \
+ ClearCookies.h \
+ GetCookies.h \
+ SetHtml.h \
+ SetProxy.h \
+ SetAttribute.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 \
+ Response.cpp \
+ NetworkAccessManager.cpp \
+ NetworkCookieJar.cpp \
+ Header.cpp \
+ Render.cpp \
+ body.cpp \
+ Status.cpp \
+ Headers.cpp \
+ SetCookie.cpp \
+ ClearCookies.cpp \
+ GetCookies.cpp \
+ SetHtml.cpp \
+ SetProxy.cpp \
+ SetAttribute.cpp \
+
RESOURCES = webkit_server.qrc
QT += network webkit
CONFIG += console

No commit comments for this range

Something went wrong with that request. Please try again.