otherinbox-capybara-webkit 0.12.0 → 0.12.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/GOALS +9 -0
- data/README.md +1 -1
- data/capybara-webkit.gemspec +1 -1
- data/lib/capybara/webkit.rb +11 -4
- data/lib/capybara/{driver/webkit → webkit}/browser.rb +27 -3
- data/lib/capybara/{driver/webkit → webkit}/connection.rb +45 -47
- data/lib/capybara/{driver/webkit → webkit}/cookie_jar.rb +1 -1
- data/lib/capybara/webkit/driver.rb +150 -0
- data/lib/capybara/webkit/errors.rb +10 -0
- data/lib/capybara/{driver/webkit → webkit}/node.rb +2 -2
- data/lib/capybara/{driver/webkit → webkit}/socket_debugger.rb +1 -1
- data/lib/capybara/{driver/webkit → webkit}/version.rb +1 -1
- data/lib/capybara_webkit_builder.rb +17 -3
- data/spec/browser_spec.rb +38 -25
- data/spec/connection_spec.rb +5 -5
- data/spec/cookie_jar_spec.rb +3 -3
- data/spec/driver_rendering_spec.rb +19 -26
- data/spec/driver_resize_window_spec.rb +3 -3
- data/spec/driver_spec.rb +907 -829
- data/spec/integration/driver_spec.rb +4 -3
- data/spec/spec_helper.rb +14 -6
- data/spec/support/app_runner.rb +91 -0
- data/src/Authenticate.cpp +18 -0
- data/src/Authenticate.h +12 -0
- data/src/Body.h +3 -5
- data/src/ClearCookies.cpp +3 -5
- data/src/ClearCookies.h +3 -5
- data/src/Command.cpp +4 -15
- data/src/Command.h +3 -14
- data/src/CommandFactory.cpp +10 -6
- data/src/CommandFactory.h +3 -2
- data/src/CommandParser.cpp +1 -1
- data/src/Connection.cpp +22 -11
- data/src/Connection.h +4 -2
- data/src/ConsoleMessages.cpp +2 -1
- data/src/ConsoleMessages.h +3 -5
- data/src/CurrentUrl.cpp +2 -1
- data/src/CurrentUrl.h +3 -5
- data/src/EnableLogging.cpp +10 -0
- data/src/EnableLogging.h +12 -0
- data/src/Evaluate.cpp +2 -1
- data/src/Evaluate.h +3 -5
- data/src/Execute.cpp +2 -1
- data/src/Execute.h +3 -5
- data/src/Find.cpp +3 -2
- data/src/Find.h +3 -5
- data/src/FrameFocus.cpp +3 -2
- data/src/FrameFocus.h +3 -4
- data/src/GetCookies.cpp +3 -4
- data/src/GetCookies.h +3 -5
- data/src/GetWindowHandle.cpp +11 -0
- data/src/GetWindowHandle.h +10 -0
- data/src/GetWindowHandles.cpp +20 -0
- data/src/GetWindowHandles.h +10 -0
- data/src/Header.cpp +2 -1
- data/src/Header.h +3 -5
- data/src/Headers.cpp +2 -1
- data/src/Headers.h +3 -5
- data/src/IgnoreSslErrors.cpp +4 -3
- data/src/IgnoreSslErrors.h +3 -5
- data/src/JavascriptInvocation.cpp +1 -1
- data/src/JavascriptInvocation.h +1 -1
- data/src/NetworkAccessManager.cpp +19 -1
- data/src/NetworkAccessManager.h +10 -0
- data/src/Node.cpp +6 -1
- data/src/Node.h +4 -5
- data/src/NullCommand.cpp +5 -2
- data/src/NullCommand.h +4 -3
- data/src/PageLoadingCommand.cpp +12 -7
- data/src/PageLoadingCommand.h +6 -9
- data/src/Render.cpp +2 -1
- data/src/Render.h +3 -5
- data/src/RequestedUrl.cpp +2 -1
- data/src/RequestedUrl.h +3 -5
- data/src/Reset.cpp +3 -17
- data/src/Reset.h +3 -8
- data/src/ResizeWindow.cpp +2 -1
- data/src/ResizeWindow.h +3 -5
- data/src/Server.cpp +2 -3
- data/src/Server.h +0 -2
- data/src/SetCookie.cpp +3 -4
- data/src/SetCookie.h +3 -5
- data/src/SetProxy.cpp +2 -1
- data/src/SetProxy.h +3 -5
- data/src/SetSkipImageLoading.cpp +3 -2
- data/src/SetSkipImageLoading.h +3 -5
- data/src/SocketCommand.cpp +21 -0
- data/src/SocketCommand.h +29 -0
- data/src/Source.cpp +2 -1
- data/src/Source.h +3 -4
- data/src/Status.cpp +2 -1
- data/src/Status.h +3 -5
- data/src/UnsupportedContentHandler.cpp +1 -1
- data/src/Url.cpp +2 -1
- data/src/Url.h +3 -5
- data/src/Visit.cpp +3 -2
- data/src/Visit.h +3 -5
- data/src/WebPage.cpp +86 -39
- data/src/WebPage.h +22 -8
- data/src/WebPageManager.cpp +117 -0
- data/src/WebPageManager.h +56 -0
- data/src/WindowFocus.cpp +32 -0
- data/src/WindowFocus.h +15 -0
- data/src/body.cpp +2 -1
- data/src/find_command.h +6 -2
- data/src/webkit_server.pro +14 -0
- data/templates/Command.cpp +2 -4
- data/templates/Command.h +3 -3
- metadata +29 -10
- data/lib/capybara/driver/webkit.rb +0 -135
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require 'capybara/driver
|
2
|
+
require 'capybara/webkit/driver'
|
3
3
|
|
4
|
-
describe Capybara::Driver
|
4
|
+
describe Capybara::Webkit::Driver do
|
5
5
|
before do
|
6
|
-
@driver = Capybara::Driver
|
6
|
+
@driver = Capybara::Webkit::Driver.new(TestApp, :browser => $webkit_browser)
|
7
7
|
end
|
8
8
|
|
9
9
|
it_should_behave_like "driver"
|
@@ -12,6 +12,7 @@ describe Capybara::Driver::Webkit do
|
|
12
12
|
it_should_behave_like "driver with header support"
|
13
13
|
it_should_behave_like "driver with status code support"
|
14
14
|
it_should_behave_like "driver with frame support"
|
15
|
+
it_should_behave_like "driver with support for window switching"
|
15
16
|
|
16
17
|
it "returns the rack server port" do
|
17
18
|
@driver.server_port.should eq(@driver.instance_variable_get(:@rack_server).port)
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'rspec'
|
2
2
|
require 'rspec/autorun'
|
3
3
|
require 'rbconfig'
|
4
|
+
require 'capybara'
|
4
5
|
|
5
6
|
PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..')).freeze
|
6
7
|
|
@@ -20,15 +21,22 @@ RSpec.configure do |c|
|
|
20
21
|
c.filter_run_excluding :skip_on_windows => !(RbConfig::CONFIG['host_os'] =~ /mingw32/).nil?
|
21
22
|
end
|
22
23
|
|
23
|
-
require
|
24
|
+
require 'capybara/webkit'
|
25
|
+
connection = Capybara::Webkit::Connection.new(:socket_class => TCPSocket, :stdout => nil)
|
26
|
+
$webkit_browser = Capybara::Webkit::Browser.new(connection)
|
27
|
+
|
28
|
+
if ENV['DEBUG']
|
29
|
+
$webkit_browser.enable_logging
|
30
|
+
end
|
24
31
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
32
|
+
RSpec.configure do |config|
|
33
|
+
config.before { $webkit_browser.reset! }
|
34
|
+
end
|
35
|
+
|
36
|
+
require File.join(spec_dir, "spec_helper")
|
29
37
|
|
30
38
|
Capybara.register_driver :reusable_webkit do |app|
|
31
|
-
Capybara::Driver
|
39
|
+
Capybara::Webkit::Driver.new(app, :browser => $webkit_browser)
|
32
40
|
end
|
33
41
|
|
34
42
|
def with_env_vars(vars)
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# Boots a single Capybara::Server for a Rack application that delegates to another, singleton Rack
|
2
|
+
# application that can be configured for each spec. Also configures Capybara to use that server.
|
3
|
+
|
4
|
+
require 'sinatra/base'
|
5
|
+
|
6
|
+
module AppRunner
|
7
|
+
class << self
|
8
|
+
attr_accessor :app, :app_host
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.boot
|
12
|
+
app_container = lambda { |env| AppRunner.app.call(env) }
|
13
|
+
server = Capybara::Server.new(app_container)
|
14
|
+
server.boot
|
15
|
+
self.app_host = "http://127.0.0.1:#{server.port}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.reset
|
19
|
+
self.app = lambda do |env|
|
20
|
+
[200, { 'Content-Type' => 'html', 'Content-Length' => 0 }, []]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def run_application(app)
|
25
|
+
AppRunner.app = app
|
26
|
+
end
|
27
|
+
|
28
|
+
def driver_for_app(&body)
|
29
|
+
app = Class.new(ExampleApp, &body)
|
30
|
+
run_application app
|
31
|
+
build_driver
|
32
|
+
end
|
33
|
+
|
34
|
+
def driver_for_html(html)
|
35
|
+
app = lambda do |env|
|
36
|
+
[200, { 'Content-Type' => 'text/html', 'Content-Length' => html.size.to_s }, [html]]
|
37
|
+
end
|
38
|
+
run_application app
|
39
|
+
build_driver
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def build_driver
|
45
|
+
Capybara::Webkit::Driver.new(AppRunner.app, :browser => $webkit_browser)
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.included(example_group)
|
49
|
+
example_group.class_eval do
|
50
|
+
before { AppRunner.reset }
|
51
|
+
|
52
|
+
around do |example|
|
53
|
+
Capybara.run_server = false
|
54
|
+
Capybara.app_host = AppRunner.app_host
|
55
|
+
begin
|
56
|
+
example.run
|
57
|
+
ensure
|
58
|
+
Capybara.run_server = true
|
59
|
+
Capybara.app_host = nil
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
class ExampleApp < Sinatra::Base
|
67
|
+
# Sinatra fixes invalid responses that would break QWebPage, so this middleware breaks them again
|
68
|
+
# for testing purposes.
|
69
|
+
class ResponseInvalidator
|
70
|
+
def initialize(app)
|
71
|
+
@app = app
|
72
|
+
end
|
73
|
+
|
74
|
+
def call(env)
|
75
|
+
response = @app.call(env)
|
76
|
+
if response.to_a[1]['X-Response-Invalid']
|
77
|
+
[404, {}, []]
|
78
|
+
else
|
79
|
+
response
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
use ResponseInvalidator
|
85
|
+
|
86
|
+
def invalid_response
|
87
|
+
[200, { 'X-Response-Invalid' => 'TRUE' }, []]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
AppRunner.boot
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#include "Authenticate.h"
|
2
|
+
#include "WebPage.h"
|
3
|
+
#include "NetworkAccessManager.h"
|
4
|
+
|
5
|
+
Authenticate::Authenticate(WebPageManager *manager, QStringList &arguments, QObject *parent) : SocketCommand(manager, arguments, parent) {
|
6
|
+
}
|
7
|
+
|
8
|
+
void Authenticate::start() {
|
9
|
+
QString username = arguments()[0];
|
10
|
+
QString password = arguments()[1];
|
11
|
+
|
12
|
+
NetworkAccessManager* networkAccessManager = qobject_cast<NetworkAccessManager*>(page()->networkAccessManager());
|
13
|
+
networkAccessManager->setUserName(username);
|
14
|
+
networkAccessManager->setPassword(password);
|
15
|
+
|
16
|
+
emit finished(new Response(true));
|
17
|
+
}
|
18
|
+
|
data/src/Authenticate.h
ADDED
data/src/Body.h
CHANGED
@@ -1,12 +1,10 @@
|
|
1
|
-
#include "
|
1
|
+
#include "SocketCommand.h"
|
2
2
|
|
3
|
-
class
|
4
|
-
|
5
|
-
class Body : public Command {
|
3
|
+
class Body : public SocketCommand {
|
6
4
|
Q_OBJECT
|
7
5
|
|
8
6
|
public:
|
9
|
-
Body(
|
7
|
+
Body(WebPageManager *, QStringList &arguments, QObject *parent = 0);
|
10
8
|
virtual void start();
|
11
9
|
};
|
12
10
|
|
data/src/ClearCookies.cpp
CHANGED
@@ -1,15 +1,13 @@
|
|
1
1
|
#include "ClearCookies.h"
|
2
2
|
#include "WebPage.h"
|
3
|
+
#include "WebPageManager.h"
|
3
4
|
#include "NetworkCookieJar.h"
|
4
5
|
#include <QNetworkCookie>
|
5
6
|
|
6
|
-
ClearCookies::ClearCookies(
|
7
|
+
ClearCookies::ClearCookies(WebPageManager *manager, QStringList &arguments, QObject *parent) : SocketCommand(manager, arguments, parent) {}
|
7
8
|
|
8
9
|
void ClearCookies::start()
|
9
10
|
{
|
10
|
-
|
11
|
-
->networkAccessManager()
|
12
|
-
->cookieJar());
|
13
|
-
jar->clearCookies();
|
11
|
+
manager()->cookieJar()->clearCookies();
|
14
12
|
emit finished(new Response(true));
|
15
13
|
}
|
data/src/ClearCookies.h
CHANGED
@@ -1,11 +1,9 @@
|
|
1
|
-
#include "
|
1
|
+
#include "SocketCommand.h"
|
2
2
|
|
3
|
-
class
|
4
|
-
|
5
|
-
class ClearCookies : public Command {
|
3
|
+
class ClearCookies : public SocketCommand {
|
6
4
|
Q_OBJECT;
|
7
5
|
|
8
6
|
public:
|
9
|
-
ClearCookies(
|
7
|
+
ClearCookies(WebPageManager *, QStringList &arguments, QObject *parent = 0);
|
10
8
|
virtual void start();
|
11
9
|
};
|
data/src/Command.cpp
CHANGED
@@ -1,19 +1,8 @@
|
|
1
|
-
#include "
|
2
|
-
#include "WebPage.h"
|
1
|
+
#include "SocketCommand.h"
|
3
2
|
|
4
|
-
Command::Command(
|
5
|
-
m_page = page;
|
6
|
-
m_arguments = arguments;
|
3
|
+
Command::Command(QObject *parent) : QObject(parent) {
|
7
4
|
}
|
8
5
|
|
9
|
-
|
6
|
+
QString Command::toString() const {
|
7
|
+
return metaObject()->className();
|
10
8
|
}
|
11
|
-
|
12
|
-
WebPage *Command::page() {
|
13
|
-
return m_page;
|
14
|
-
}
|
15
|
-
|
16
|
-
QStringList &Command::arguments() {
|
17
|
-
return m_arguments;
|
18
|
-
}
|
19
|
-
|
data/src/Command.h
CHANGED
@@ -2,29 +2,18 @@
|
|
2
2
|
#define COMMAND_H
|
3
3
|
|
4
4
|
#include <QObject>
|
5
|
-
#include <QStringList>
|
6
5
|
#include "Response.h"
|
7
6
|
|
8
|
-
class WebPage;
|
9
|
-
|
10
7
|
class Command : public QObject {
|
11
8
|
Q_OBJECT
|
12
9
|
|
13
10
|
public:
|
14
|
-
Command(
|
15
|
-
virtual void start();
|
11
|
+
Command(QObject *parent = 0);
|
12
|
+
virtual void start() = 0;
|
13
|
+
virtual QString toString() const;
|
16
14
|
|
17
15
|
signals:
|
18
16
|
void finished(Response *response);
|
19
|
-
|
20
|
-
protected:
|
21
|
-
WebPage *page();
|
22
|
-
QStringList &arguments();
|
23
|
-
|
24
|
-
private:
|
25
|
-
WebPage *m_page;
|
26
|
-
QStringList m_arguments;
|
27
|
-
|
28
17
|
};
|
29
18
|
|
30
19
|
#endif
|
data/src/CommandFactory.cpp
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
#include "CommandFactory.h"
|
2
2
|
#include "NullCommand.h"
|
3
|
+
#include "SocketCommand.h"
|
3
4
|
#include "Visit.h"
|
4
5
|
#include "Find.h"
|
5
|
-
#include "Command.h"
|
6
6
|
#include "Reset.h"
|
7
7
|
#include "Node.h"
|
8
8
|
#include "Url.h"
|
@@ -25,14 +25,18 @@
|
|
25
25
|
#include "ResizeWindow.h"
|
26
26
|
#include "IgnoreSslErrors.h"
|
27
27
|
#include "SetSkipImageLoading.h"
|
28
|
+
#include "WindowFocus.h"
|
29
|
+
#include "GetWindowHandles.h"
|
30
|
+
#include "GetWindowHandle.h"
|
31
|
+
#include "WebPageManager.h"
|
32
|
+
#include "Authenticate.h"
|
33
|
+
#include "EnableLogging.h"
|
28
34
|
|
29
|
-
CommandFactory::CommandFactory(
|
30
|
-
|
35
|
+
CommandFactory::CommandFactory(WebPageManager *manager, QObject *parent) : QObject(parent) {
|
36
|
+
m_manager = manager;
|
31
37
|
}
|
32
38
|
|
33
39
|
Command *CommandFactory::createCommand(const char *name, QStringList &arguments) {
|
34
40
|
#include "find_command.h"
|
35
|
-
|
36
|
-
arguments.append(QString(name));
|
37
|
-
return new NullCommand(m_page, arguments);
|
41
|
+
return new NullCommand(QString(name));
|
38
42
|
}
|
data/src/CommandFactory.h
CHANGED
@@ -2,15 +2,16 @@
|
|
2
2
|
|
3
3
|
class Command;
|
4
4
|
class WebPage;
|
5
|
+
class WebPageManager;
|
5
6
|
|
6
7
|
class CommandFactory : public QObject {
|
7
8
|
Q_OBJECT
|
8
9
|
|
9
10
|
public:
|
10
|
-
CommandFactory(
|
11
|
+
CommandFactory(WebPageManager *, QObject *parent = 0);
|
11
12
|
Command *createCommand(const char *name, QStringList &arguments);
|
12
13
|
|
13
14
|
private:
|
14
|
-
|
15
|
+
WebPageManager *m_manager;
|
15
16
|
};
|
16
17
|
|
data/src/CommandParser.cpp
CHANGED
data/src/Connection.cpp
CHANGED
@@ -1,37 +1,41 @@
|
|
1
1
|
#include "Connection.h"
|
2
2
|
#include "WebPage.h"
|
3
|
+
#include "WebPageManager.h"
|
3
4
|
#include "CommandParser.h"
|
4
5
|
#include "CommandFactory.h"
|
5
6
|
#include "PageLoadingCommand.h"
|
6
|
-
#include "
|
7
|
+
#include "SocketCommand.h"
|
7
8
|
|
8
9
|
#include <QTcpSocket>
|
9
10
|
|
10
|
-
Connection::Connection(QTcpSocket *socket,
|
11
|
+
Connection::Connection(QTcpSocket *socket, WebPageManager *manager, QObject *parent) :
|
11
12
|
QObject(parent) {
|
12
13
|
m_socket = socket;
|
13
|
-
|
14
|
-
m_commandFactory = new CommandFactory(
|
14
|
+
m_manager = manager;
|
15
|
+
m_commandFactory = new CommandFactory(m_manager, this);
|
15
16
|
m_commandParser = new CommandParser(socket, m_commandFactory, this);
|
16
17
|
m_pageSuccess = true;
|
17
18
|
m_commandWaiting = false;
|
18
19
|
connect(m_socket, SIGNAL(readyRead()), m_commandParser, SLOT(checkNext()));
|
19
20
|
connect(m_commandParser, SIGNAL(commandReady(Command *)), this, SLOT(commandReady(Command *)));
|
20
|
-
connect(
|
21
|
+
connect(m_manager, SIGNAL(pageFinished(bool)), this, SLOT(pendingLoadFinished(bool)));
|
21
22
|
}
|
22
23
|
|
23
24
|
void Connection::commandReady(Command *command) {
|
24
25
|
m_queuedCommand = command;
|
25
|
-
|
26
|
+
m_manager->logger() << "Received" << command->toString();
|
27
|
+
if (m_manager->isLoading()) {
|
28
|
+
m_manager->logger() << command->toString() << "waiting for load to finish";
|
26
29
|
m_commandWaiting = true;
|
27
|
-
else
|
30
|
+
} else {
|
28
31
|
startCommand();
|
32
|
+
}
|
29
33
|
}
|
30
34
|
|
31
35
|
void Connection::startCommand() {
|
32
36
|
m_commandWaiting = false;
|
33
37
|
if (m_pageSuccess) {
|
34
|
-
m_runningCommand = new PageLoadingCommand(m_queuedCommand,
|
38
|
+
m_runningCommand = new PageLoadingCommand(m_queuedCommand, m_manager, this);
|
35
39
|
connect(m_runningCommand, SIGNAL(finished(Response *)), this, SLOT(finishCommand(Response *)));
|
36
40
|
m_runningCommand->start();
|
37
41
|
} else {
|
@@ -40,18 +44,20 @@ void Connection::startCommand() {
|
|
40
44
|
}
|
41
45
|
|
42
46
|
void Connection::pendingLoadFinished(bool success) {
|
43
|
-
m_pageSuccess = success;
|
44
|
-
if (m_commandWaiting)
|
47
|
+
m_pageSuccess = m_pageSuccess && success;
|
48
|
+
if (m_commandWaiting) {
|
45
49
|
startCommand();
|
50
|
+
}
|
46
51
|
}
|
47
52
|
|
48
53
|
void Connection::writePageLoadFailure() {
|
49
54
|
m_pageSuccess = true;
|
50
|
-
QString message =
|
55
|
+
QString message = currentPage()->failureString();
|
51
56
|
writeResponse(new Response(false, message));
|
52
57
|
}
|
53
58
|
|
54
59
|
void Connection::finishCommand(Response *response) {
|
60
|
+
m_pageSuccess = true;
|
55
61
|
m_runningCommand->deleteLater();
|
56
62
|
writeResponse(response);
|
57
63
|
}
|
@@ -62,6 +68,8 @@ void Connection::writeResponse(Response *response) {
|
|
62
68
|
else
|
63
69
|
m_socket->write("failure\n");
|
64
70
|
|
71
|
+
m_manager->logger() << "Wrote response" << response->isSuccess() << response->message();
|
72
|
+
|
65
73
|
QByteArray messageUtf8 = response->message();
|
66
74
|
QString messageLength = QString::number(messageUtf8.size()) + "\n";
|
67
75
|
m_socket->write(messageLength.toAscii());
|
@@ -69,3 +77,6 @@ void Connection::writeResponse(Response *response) {
|
|
69
77
|
delete response;
|
70
78
|
}
|
71
79
|
|
80
|
+
WebPage *Connection::currentPage() {
|
81
|
+
return m_manager->currentPage();
|
82
|
+
}
|