otherinbox-capybara-webkit 0.12.0 → 0.12.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
}
|