capybara-webkit 0.7.2 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CONTRIBUTING.md +1 -1
- data/Gemfile +1 -6
- data/Gemfile.lock +15 -13
- data/README.md +9 -8
- data/Rakefile +3 -21
- data/capybara-webkit.gemspec +21 -18
- data/gemfiles/1.0.gemfile.lock +18 -13
- data/gemfiles/1.1.gemfile.lock +18 -13
- data/lib/capybara/driver/webkit.rb +20 -1
- data/lib/capybara/driver/webkit/browser.rb +49 -5
- data/lib/capybara/driver/webkit/cookie_jar.rb +55 -0
- data/lib/capybara/driver/webkit/node.rb +5 -1
- data/lib/capybara/driver/webkit/version.rb +7 -0
- data/lib/capybara/webkit/matchers.rb +39 -0
- data/lib/capybara_webkit_builder.rb +2 -1
- data/spec/browser_spec.rb +150 -2
- data/spec/cookie_jar_spec.rb +48 -0
- data/spec/driver_spec.rb +248 -16
- data/spec/self_signed_ssl_cert.rb +42 -0
- data/src/CommandFactory.cpp +31 -0
- data/src/CommandFactory.h +16 -0
- data/src/CommandParser.cpp +68 -0
- data/src/CommandParser.h +29 -0
- data/src/Connection.cpp +14 -83
- data/src/Connection.h +5 -8
- data/src/ConsoleMessages.cpp +11 -0
- data/src/ConsoleMessages.h +12 -0
- data/src/RequestedUrl.cpp +15 -0
- data/src/RequestedUrl.h +12 -0
- data/src/Reset.cpp +1 -0
- data/src/Server.cpp +2 -1
- data/src/Server.h +1 -1
- data/src/SetProxy.cpp +24 -0
- data/src/SetProxy.h +11 -0
- data/src/UnsupportedContentHandler.cpp +1 -0
- data/src/Visit.cpp +1 -1
- data/src/WebPage.cpp +28 -2
- data/src/WebPage.h +7 -0
- data/src/capybara.js +54 -11
- data/src/find_command.h +4 -0
- data/src/main.cpp +4 -1
- data/src/webkit_server.pro +10 -0
- metadata +67 -47
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
|
3
|
+
pem = <<-PEM_ENCODED
|
4
|
+
-----BEGIN PRIVATE KEY-----
|
5
|
+
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKW+grT6YW3gv79y
|
6
|
+
P9JkQDtm3cDSUhAhd/TEyRBt/pSKz3pNSygsleBJl2d7g8k0fteec95a7YnYRKGH
|
7
|
+
XhIpUOvl/3uaV2NVipqxwB+Z+0M+7HegxL3e4unaRFy9kf9/UXJzmuA9BTMLrm/w
|
8
|
+
IoW17f+dz7BIFZhCvRurkrmvzraNAgMBAAECgYBv4uB3bYJx20N16Jk+3OAjeXh/
|
9
|
+
Hzu4me9Rc7pLdgVinyYaaK0wrJBsfSFRASdgnyh1RAjx9K3f3PfPlwMg/XUbA6Yd
|
10
|
+
YOYlMnBUwCJX09TH8RFFCzJzbBylpk/sTF1geICln2O2BloT2cM24PlEPvyz1xLa
|
11
|
+
XvxCOnJJfgNU1K6kvQJBANcEVyOMJ9RBfI8gj1o7S70J9yJRI4jvqxuvcOxJBCi6
|
12
|
+
CDatkh/getHswsE3sLj25VhrNsi6UQcN8Bjm8Yjt8BsCQQDFVe0uCwobseprMOuW
|
13
|
+
dPU4+saN1cFnIT5Gp0iwYRPinjUlkh6H/AuUtUulKFXVmxk1KElpp1E3bxpCDgCp
|
14
|
+
oe53AkArO1Mt8Ys8kSIzQO+xy8RRsQRAoSHM8atsuJyy1YeBjM4D+GguApuPQ9Rw
|
15
|
+
tvrQZcv9OCleuJ98FKBW0XB1AKpLAkEAmOR3bJofDdAuWTjA/4TEzo32MsRwIZBv
|
16
|
+
KNzJg+bjOkzrzp1EzIVrD5/b6S20O1j9EeOR5as+UN3jEVS6DLQrBwJAe5OTrDiQ
|
17
|
+
vKtUaAwquC4f4Ia05KwJw+vFrPVaOqgc4QLdxRwx4PfV/Uw3OOqMolpPAvpUi9JI
|
18
|
+
LAwIaTtCvo18OQ==
|
19
|
+
-----END PRIVATE KEY-----
|
20
|
+
-----BEGIN CERTIFICATE-----
|
21
|
+
MIICgDCCAemgAwIBAgIJANWcyeZB2ql1MA0GCSqGSIb3DQEBBQUAMFkxCzAJBgNV
|
22
|
+
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
|
23
|
+
aWRnaXRzIFB0eSBMdGQxEjAQBgNVBAMMCWxvY2FsaG9zdDAeFw0xMTA5MjgyMDIx
|
24
|
+
MTFaFw0xMjA5MjcyMDIxMTFaMFkxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21l
|
25
|
+
LVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxEjAQBgNV
|
26
|
+
BAMMCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEApb6CtPph
|
27
|
+
beC/v3I/0mRAO2bdwNJSECF39MTJEG3+lIrPek1LKCyV4EmXZ3uDyTR+155z3lrt
|
28
|
+
idhEoYdeEilQ6+X/e5pXY1WKmrHAH5n7Qz7sd6DEvd7i6dpEXL2R/39RcnOa4D0F
|
29
|
+
Mwuub/AihbXt/53PsEgVmEK9G6uSua/Oto0CAwEAAaNQME4wHQYDVR0OBBYEFBAm
|
30
|
+
x19zpY8M8FEcMXB4WQeUhqIiMB8GA1UdIwQYMBaAFBAmx19zpY8M8FEcMXB4WQeU
|
31
|
+
hqIiMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAcznCusWS5Ws77IUl
|
32
|
+
b87vdfCPVphICyfGHGWhHp3BZ3WLOphauAMdOYIiJGtPExyWr4DYpzbvx0+Ljg7G
|
33
|
+
2FNaI0QRXqbR5ccpvwm6KELmU0XDhykNaXiXSdnvIanr3z/hZ5e03mXAywo+nGQj
|
34
|
+
UYTVCb6g/uHVNzXq1NgHGuqogKY=
|
35
|
+
-----END CERTIFICATE-----
|
36
|
+
PEM_ENCODED
|
37
|
+
|
38
|
+
key = OpenSSL::PKey::RSA.new(pem)
|
39
|
+
cert = OpenSSL::X509::Certificate.new(pem)
|
40
|
+
$openssl_self_signed_ctx = OpenSSL::SSL::SSLContext.new
|
41
|
+
$openssl_self_signed_ctx.key = key
|
42
|
+
$openssl_self_signed_ctx.cert = cert
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#include "CommandFactory.h"
|
2
|
+
#include "Visit.h"
|
3
|
+
#include "Find.h"
|
4
|
+
#include "Command.h"
|
5
|
+
#include "Reset.h"
|
6
|
+
#include "Node.h"
|
7
|
+
#include "Url.h"
|
8
|
+
#include "Source.h"
|
9
|
+
#include "Evaluate.h"
|
10
|
+
#include "Execute.h"
|
11
|
+
#include "FrameFocus.h"
|
12
|
+
#include "Header.h"
|
13
|
+
#include "Render.h"
|
14
|
+
#include "Body.h"
|
15
|
+
#include "Status.h"
|
16
|
+
#include "Headers.h"
|
17
|
+
#include "SetCookie.h"
|
18
|
+
#include "ClearCookies.h"
|
19
|
+
#include "GetCookies.h"
|
20
|
+
#include "SetProxy.h"
|
21
|
+
#include "ConsoleMessages.h"
|
22
|
+
#include "RequestedUrl.h"
|
23
|
+
|
24
|
+
CommandFactory::CommandFactory(WebPage *page, QObject *parent) : QObject(parent) {
|
25
|
+
m_page = page;
|
26
|
+
}
|
27
|
+
|
28
|
+
Command *CommandFactory::createCommand(const char *name) {
|
29
|
+
#include "find_command.h"
|
30
|
+
return NULL;
|
31
|
+
}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#include <QObject>
|
2
|
+
|
3
|
+
class Command;
|
4
|
+
class WebPage;
|
5
|
+
|
6
|
+
class CommandFactory : public QObject {
|
7
|
+
Q_OBJECT
|
8
|
+
|
9
|
+
public:
|
10
|
+
CommandFactory(WebPage *page, QObject *parent = 0);
|
11
|
+
Command *createCommand(const char *name);
|
12
|
+
|
13
|
+
private:
|
14
|
+
WebPage *m_page;
|
15
|
+
};
|
16
|
+
|
@@ -0,0 +1,68 @@
|
|
1
|
+
#include "CommandParser.h"
|
2
|
+
|
3
|
+
#include <QIODevice>
|
4
|
+
|
5
|
+
CommandParser::CommandParser(QIODevice *device, QObject *parent) :
|
6
|
+
QObject(parent) {
|
7
|
+
m_device = device;
|
8
|
+
m_expectingDataSize = -1;
|
9
|
+
connect(m_device, SIGNAL(readyRead()), this, SLOT(checkNext()));
|
10
|
+
}
|
11
|
+
|
12
|
+
void CommandParser::checkNext() {
|
13
|
+
if (m_expectingDataSize == -1) {
|
14
|
+
if (m_device->canReadLine()) {
|
15
|
+
readLine();
|
16
|
+
checkNext();
|
17
|
+
}
|
18
|
+
} else {
|
19
|
+
if (m_device->bytesAvailable() >= m_expectingDataSize) {
|
20
|
+
readDataBlock();
|
21
|
+
checkNext();
|
22
|
+
}
|
23
|
+
}
|
24
|
+
}
|
25
|
+
|
26
|
+
void CommandParser::readLine() {
|
27
|
+
char buffer[128];
|
28
|
+
qint64 lineLength = m_device->readLine(buffer, 128);
|
29
|
+
if (lineLength != -1) {
|
30
|
+
buffer[lineLength - 1] = 0;
|
31
|
+
processNext(buffer);
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
void CommandParser::readDataBlock() {
|
36
|
+
char *buffer = new char[m_expectingDataSize + 1];
|
37
|
+
m_device->read(buffer, m_expectingDataSize);
|
38
|
+
buffer[m_expectingDataSize] = 0;
|
39
|
+
processNext(buffer);
|
40
|
+
m_expectingDataSize = -1;
|
41
|
+
delete[] buffer;
|
42
|
+
}
|
43
|
+
|
44
|
+
void CommandParser::processNext(const char *data) {
|
45
|
+
if (m_commandName.isNull()) {
|
46
|
+
m_commandName = data;
|
47
|
+
m_argumentsExpected = -1;
|
48
|
+
} else {
|
49
|
+
processArgument(data);
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
void CommandParser::processArgument(const char *data) {
|
54
|
+
if (m_argumentsExpected == -1) {
|
55
|
+
m_argumentsExpected = QString(data).toInt();
|
56
|
+
} else if (m_expectingDataSize == -1) {
|
57
|
+
m_expectingDataSize = QString(data).toInt();
|
58
|
+
} else {
|
59
|
+
m_arguments.append(QString::fromUtf8(data));
|
60
|
+
}
|
61
|
+
|
62
|
+
if (m_arguments.length() == m_argumentsExpected) {
|
63
|
+
emit commandReady(m_commandName, m_arguments);
|
64
|
+
m_commandName = QString();
|
65
|
+
m_arguments.clear();
|
66
|
+
m_argumentsExpected = -1;
|
67
|
+
}
|
68
|
+
}
|
data/src/CommandParser.h
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#include <QObject>
|
2
|
+
#include <QStringList>
|
3
|
+
|
4
|
+
class QIODevice;
|
5
|
+
|
6
|
+
class CommandParser : public QObject {
|
7
|
+
Q_OBJECT
|
8
|
+
|
9
|
+
public:
|
10
|
+
CommandParser(QIODevice *device, QObject *parent = 0);
|
11
|
+
|
12
|
+
public slots:
|
13
|
+
void checkNext();
|
14
|
+
|
15
|
+
signals:
|
16
|
+
void commandReady(QString commandName, QStringList arguments);
|
17
|
+
|
18
|
+
private:
|
19
|
+
void readLine();
|
20
|
+
void readDataBlock();
|
21
|
+
void processNext(const char *line);
|
22
|
+
void processArgument(const char *data);
|
23
|
+
QIODevice *m_device;
|
24
|
+
QString m_commandName;
|
25
|
+
QStringList m_arguments;
|
26
|
+
int m_argumentsExpected;
|
27
|
+
int m_expectingDataSize;
|
28
|
+
};
|
29
|
+
|
data/src/Connection.cpp
CHANGED
@@ -1,24 +1,9 @@
|
|
1
1
|
#include "Connection.h"
|
2
2
|
#include "WebPage.h"
|
3
3
|
#include "UnsupportedContentHandler.h"
|
4
|
-
#include "
|
5
|
-
#include "
|
4
|
+
#include "CommandParser.h"
|
5
|
+
#include "CommandFactory.h"
|
6
6
|
#include "Command.h"
|
7
|
-
#include "Reset.h"
|
8
|
-
#include "Node.h"
|
9
|
-
#include "Url.h"
|
10
|
-
#include "Source.h"
|
11
|
-
#include "Evaluate.h"
|
12
|
-
#include "Execute.h"
|
13
|
-
#include "FrameFocus.h"
|
14
|
-
#include "Header.h"
|
15
|
-
#include "Render.h"
|
16
|
-
#include "Body.h"
|
17
|
-
#include "Status.h"
|
18
|
-
#include "Headers.h"
|
19
|
-
#include "SetCookie.h"
|
20
|
-
#include "ClearCookies.h"
|
21
|
-
#include "GetCookies.h"
|
22
7
|
|
23
8
|
#include <QTcpSocket>
|
24
9
|
#include <iostream>
|
@@ -27,76 +12,31 @@ Connection::Connection(QTcpSocket *socket, WebPage *page, QObject *parent) :
|
|
27
12
|
QObject(parent) {
|
28
13
|
m_socket = socket;
|
29
14
|
m_page = page;
|
15
|
+
m_commandParser = new CommandParser(socket, this);
|
16
|
+
m_commandFactory = new CommandFactory(page, this);
|
30
17
|
m_command = NULL;
|
31
|
-
m_expectingDataSize = -1;
|
32
18
|
m_pageSuccess = true;
|
33
19
|
m_commandWaiting = false;
|
34
|
-
connect(m_socket, SIGNAL(readyRead()),
|
20
|
+
connect(m_socket, SIGNAL(readyRead()), m_commandParser, SLOT(checkNext()));
|
21
|
+
connect(m_commandParser, SIGNAL(commandReady(QString, QStringList)), this, SLOT(commandReady(QString, QStringList)));
|
35
22
|
connect(m_page, SIGNAL(pageFinished(bool)), this, SLOT(pendingLoadFinished(bool)));
|
36
23
|
}
|
37
24
|
|
38
|
-
void Connection::checkNext() {
|
39
|
-
if (m_expectingDataSize == -1) {
|
40
|
-
if (m_socket->canReadLine()) {
|
41
|
-
readLine();
|
42
|
-
checkNext();
|
43
|
-
}
|
44
|
-
} else {
|
45
|
-
if (m_socket->bytesAvailable() >= m_expectingDataSize) {
|
46
|
-
readDataBlock();
|
47
|
-
checkNext();
|
48
|
-
}
|
49
|
-
}
|
50
|
-
}
|
51
|
-
|
52
|
-
void Connection::readLine() {
|
53
|
-
char buffer[128];
|
54
|
-
qint64 lineLength = m_socket->readLine(buffer, 128);
|
55
|
-
if (lineLength != -1) {
|
56
|
-
buffer[lineLength - 1] = 0;
|
57
|
-
processNext(buffer);
|
58
|
-
}
|
59
|
-
}
|
60
|
-
|
61
|
-
void Connection::readDataBlock() {
|
62
|
-
char *buffer = new char[m_expectingDataSize + 1];
|
63
|
-
m_socket->read(buffer, m_expectingDataSize);
|
64
|
-
buffer[m_expectingDataSize] = 0;
|
65
|
-
processNext(buffer);
|
66
|
-
m_expectingDataSize = -1;
|
67
|
-
delete[] buffer;
|
68
|
-
}
|
69
|
-
|
70
|
-
void Connection::processNext(const char *data) {
|
71
|
-
if (m_commandName.isNull()) {
|
72
|
-
m_commandName = data;
|
73
|
-
m_argumentsExpected = -1;
|
74
|
-
} else {
|
75
|
-
processArgument(data);
|
76
|
-
}
|
77
|
-
}
|
78
25
|
|
79
|
-
void Connection::
|
80
|
-
|
81
|
-
|
82
|
-
} else if (m_expectingDataSize == -1) {
|
83
|
-
m_expectingDataSize = QString(data).toInt();
|
84
|
-
} else {
|
85
|
-
m_arguments.append(QString::fromUtf8(data));
|
86
|
-
}
|
26
|
+
void Connection::commandReady(QString commandName, QStringList arguments) {
|
27
|
+
m_commandName = commandName;
|
28
|
+
m_arguments = arguments;
|
87
29
|
|
88
|
-
if (
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
startCommand();
|
93
|
-
}
|
30
|
+
if (m_page->isLoading())
|
31
|
+
m_commandWaiting = true;
|
32
|
+
else
|
33
|
+
startCommand();
|
94
34
|
}
|
95
35
|
|
96
36
|
void Connection::startCommand() {
|
97
37
|
m_commandWaiting = false;
|
98
38
|
if (m_pageSuccess) {
|
99
|
-
m_command = createCommand(m_commandName.toAscii().constData());
|
39
|
+
m_command = m_commandFactory->createCommand(m_commandName.toAscii().constData());
|
100
40
|
if (m_command) {
|
101
41
|
connect(m_command,
|
102
42
|
SIGNAL(finished(Response *)),
|
@@ -115,11 +55,6 @@ void Connection::startCommand() {
|
|
115
55
|
}
|
116
56
|
}
|
117
57
|
|
118
|
-
Command *Connection::createCommand(const char *name) {
|
119
|
-
#include "find_command.h"
|
120
|
-
return NULL;
|
121
|
-
}
|
122
|
-
|
123
58
|
void Connection::pendingLoadFinished(bool success) {
|
124
59
|
m_pageSuccess = success;
|
125
60
|
if (m_commandWaiting)
|
@@ -143,9 +78,5 @@ void Connection::writeResponse(Response *response) {
|
|
143
78
|
m_socket->write(messageLength.toAscii());
|
144
79
|
m_socket->write(messageUtf8);
|
145
80
|
delete response;
|
146
|
-
|
147
|
-
m_arguments.clear();
|
148
|
-
m_commandName = QString();
|
149
|
-
m_argumentsExpected = -1;
|
150
81
|
}
|
151
82
|
|
data/src/Connection.h
CHANGED
@@ -5,6 +5,8 @@ class QTcpSocket;
|
|
5
5
|
class WebPage;
|
6
6
|
class Command;
|
7
7
|
class Response;
|
8
|
+
class CommandParser;
|
9
|
+
class CommandFactory;
|
8
10
|
|
9
11
|
class Connection : public QObject {
|
10
12
|
Q_OBJECT
|
@@ -13,16 +15,11 @@ class Connection : public QObject {
|
|
13
15
|
Connection(QTcpSocket *socket, WebPage *page, QObject *parent = 0);
|
14
16
|
|
15
17
|
public slots:
|
16
|
-
void
|
18
|
+
void commandReady(QString commandName, QStringList arguments);
|
17
19
|
void finishCommand(Response *response);
|
18
20
|
void pendingLoadFinished(bool success);
|
19
21
|
|
20
22
|
private:
|
21
|
-
void readLine();
|
22
|
-
void readDataBlock();
|
23
|
-
void processNext(const char *line);
|
24
|
-
Command *createCommand(const char *name);
|
25
|
-
void processArgument(const char *line);
|
26
23
|
void startCommand();
|
27
24
|
void writeResponse(Response *response);
|
28
25
|
|
@@ -30,9 +27,9 @@ class Connection : public QObject {
|
|
30
27
|
QString m_commandName;
|
31
28
|
Command *m_command;
|
32
29
|
QStringList m_arguments;
|
33
|
-
int m_argumentsExpected;
|
34
30
|
WebPage *m_page;
|
35
|
-
|
31
|
+
CommandParser *m_commandParser;
|
32
|
+
CommandFactory *m_commandFactory;
|
36
33
|
bool m_pageSuccess;
|
37
34
|
bool m_commandWaiting;
|
38
35
|
};
|
@@ -0,0 +1,11 @@
|
|
1
|
+
#include "ConsoleMessages.h"
|
2
|
+
#include "WebPage.h"
|
3
|
+
|
4
|
+
ConsoleMessages::ConsoleMessages(WebPage *page, QObject *parent) : Command(page, parent) {
|
5
|
+
}
|
6
|
+
|
7
|
+
void ConsoleMessages::start(QStringList &arguments) {
|
8
|
+
Q_UNUSED(arguments);
|
9
|
+
emit finished(new Response(true, page()->consoleMessages()));
|
10
|
+
}
|
11
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#include "RequestedUrl.h"
|
2
|
+
#include "WebPage.h"
|
3
|
+
|
4
|
+
RequestedUrl::RequestedUrl(WebPage *page, QObject *parent) : Command(page, parent) {
|
5
|
+
}
|
6
|
+
|
7
|
+
void RequestedUrl::start(QStringList &arguments) {
|
8
|
+
Q_UNUSED(arguments);
|
9
|
+
|
10
|
+
QUrl humanUrl = page()->currentFrame()->requestedUrl();
|
11
|
+
QByteArray encodedBytes = humanUrl.toEncoded();
|
12
|
+
QString urlString = QString(encodedBytes);
|
13
|
+
emit finished(new Response(true, urlString));
|
14
|
+
}
|
15
|
+
|
data/src/RequestedUrl.h
ADDED
data/src/Reset.cpp
CHANGED
data/src/Server.cpp
CHANGED
@@ -4,9 +4,10 @@
|
|
4
4
|
|
5
5
|
#include <QTcpServer>
|
6
6
|
|
7
|
-
Server::Server(QObject *parent) : QObject(parent) {
|
7
|
+
Server::Server(QObject *parent, bool ignoreSslErrors) : QObject(parent) {
|
8
8
|
m_tcp_server = new QTcpServer(this);
|
9
9
|
m_page = new WebPage(this);
|
10
|
+
m_page->setIgnoreSslErrors(ignoreSslErrors);
|
10
11
|
}
|
11
12
|
|
12
13
|
bool Server::start() {
|