intentmedia-capybara-webkit 0.7.2.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.
Files changed (97) hide show
  1. data/.gitignore +17 -0
  2. data/.rspec +2 -0
  3. data/Appraisals +7 -0
  4. data/CONTRIBUTING.md +38 -0
  5. data/Gemfile +8 -0
  6. data/Gemfile.lock +65 -0
  7. data/LICENSE +19 -0
  8. data/README.md +67 -0
  9. data/Rakefile +78 -0
  10. data/bin/Info.plist +22 -0
  11. data/capybara-webkit.gemspec +24 -0
  12. data/extconf.rb +2 -0
  13. data/gemfiles/1.0.gemfile +7 -0
  14. data/gemfiles/1.0.gemfile.lock +65 -0
  15. data/gemfiles/1.1.gemfile +7 -0
  16. data/gemfiles/1.1.gemfile.lock +65 -0
  17. data/lib/capybara-webkit.rb +1 -0
  18. data/lib/capybara/driver/webkit.rb +113 -0
  19. data/lib/capybara/driver/webkit/browser.rb +216 -0
  20. data/lib/capybara/driver/webkit/node.rb +118 -0
  21. data/lib/capybara/driver/webkit/socket_debugger.rb +43 -0
  22. data/lib/capybara/webkit.rb +11 -0
  23. data/lib/capybara_webkit_builder.rb +40 -0
  24. data/spec/browser_spec.rb +178 -0
  25. data/spec/driver_rendering_spec.rb +80 -0
  26. data/spec/driver_spec.rb +1048 -0
  27. data/spec/integration/driver_spec.rb +20 -0
  28. data/spec/integration/session_spec.rb +137 -0
  29. data/spec/self_signed_ssl_cert.rb +42 -0
  30. data/spec/spec_helper.rb +25 -0
  31. data/src/Body.h +12 -0
  32. data/src/ClearCookies.cpp +18 -0
  33. data/src/ClearCookies.h +11 -0
  34. data/src/Command.cpp +15 -0
  35. data/src/Command.h +29 -0
  36. data/src/CommandFactory.cpp +29 -0
  37. data/src/CommandFactory.h +16 -0
  38. data/src/CommandParser.cpp +68 -0
  39. data/src/CommandParser.h +29 -0
  40. data/src/Connection.cpp +82 -0
  41. data/src/Connection.h +36 -0
  42. data/src/Evaluate.cpp +84 -0
  43. data/src/Evaluate.h +22 -0
  44. data/src/Execute.cpp +16 -0
  45. data/src/Execute.h +12 -0
  46. data/src/Find.cpp +19 -0
  47. data/src/Find.h +13 -0
  48. data/src/FrameFocus.cpp +66 -0
  49. data/src/FrameFocus.h +28 -0
  50. data/src/GetCookies.cpp +22 -0
  51. data/src/GetCookies.h +14 -0
  52. data/src/Header.cpp +18 -0
  53. data/src/Header.h +11 -0
  54. data/src/Headers.cpp +11 -0
  55. data/src/Headers.h +12 -0
  56. data/src/JavascriptInvocation.cpp +14 -0
  57. data/src/JavascriptInvocation.h +19 -0
  58. data/src/NetworkAccessManager.cpp +25 -0
  59. data/src/NetworkAccessManager.h +18 -0
  60. data/src/NetworkCookieJar.cpp +101 -0
  61. data/src/NetworkCookieJar.h +15 -0
  62. data/src/Node.cpp +14 -0
  63. data/src/Node.h +13 -0
  64. data/src/Render.cpp +19 -0
  65. data/src/Render.h +12 -0
  66. data/src/Reset.cpp +20 -0
  67. data/src/Reset.h +12 -0
  68. data/src/Response.cpp +19 -0
  69. data/src/Response.h +13 -0
  70. data/src/Server.cpp +25 -0
  71. data/src/Server.h +21 -0
  72. data/src/SetCookie.cpp +18 -0
  73. data/src/SetCookie.h +11 -0
  74. data/src/SetProxy.cpp +24 -0
  75. data/src/SetProxy.h +11 -0
  76. data/src/Source.cpp +20 -0
  77. data/src/Source.h +19 -0
  78. data/src/Status.cpp +13 -0
  79. data/src/Status.h +12 -0
  80. data/src/UnsupportedContentHandler.cpp +32 -0
  81. data/src/UnsupportedContentHandler.h +18 -0
  82. data/src/Url.cpp +15 -0
  83. data/src/Url.h +12 -0
  84. data/src/Visit.cpp +21 -0
  85. data/src/Visit.h +15 -0
  86. data/src/WebPage.cpp +226 -0
  87. data/src/WebPage.h +54 -0
  88. data/src/body.cpp +11 -0
  89. data/src/capybara.js +205 -0
  90. data/src/find_command.h +24 -0
  91. data/src/main.cpp +34 -0
  92. data/src/webkit_server.pro +71 -0
  93. data/src/webkit_server.qrc +5 -0
  94. data/templates/Command.cpp +10 -0
  95. data/templates/Command.h +12 -0
  96. data/webkit_server.pro +4 -0
  97. metadata +246 -0
data/src/SetCookie.h ADDED
@@ -0,0 +1,11 @@
1
+ #include "Command.h"
2
+
3
+ class WebPage;
4
+
5
+ class SetCookie : public Command {
6
+ Q_OBJECT;
7
+
8
+ public:
9
+ SetCookie(WebPage *page, QObject *parent = 0);
10
+ virtual void start(QStringList &arguments);
11
+ };
data/src/SetProxy.cpp ADDED
@@ -0,0 +1,24 @@
1
+ #include "SetProxy.h"
2
+ #include "WebPage.h"
3
+ #include <QNetworkAccessManager>
4
+ #include <QNetworkProxy>
5
+
6
+ SetProxy::SetProxy(WebPage *page, QObject *parent)
7
+ : Command(page, parent)
8
+ { }
9
+
10
+ void SetProxy::start(QStringList &arguments)
11
+ {
12
+ // default to empty proxy
13
+ QNetworkProxy proxy;
14
+
15
+ if (arguments.size() > 0)
16
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy,
17
+ arguments[0],
18
+ (quint16)(arguments[1].toInt()),
19
+ arguments[2],
20
+ arguments[3]);
21
+
22
+ page()->networkAccessManager()->setProxy(proxy);
23
+ emit finished(new Response(true));
24
+ }
data/src/SetProxy.h ADDED
@@ -0,0 +1,11 @@
1
+ #include "Command.h"
2
+
3
+ class WebPage;
4
+
5
+ class SetProxy : public Command {
6
+ Q_OBJECT;
7
+
8
+ public:
9
+ SetProxy(WebPage *page, QObject *parent = 0);
10
+ virtual void start(QStringList &arguments);
11
+ };
data/src/Source.cpp ADDED
@@ -0,0 +1,20 @@
1
+ #include "Source.h"
2
+ #include "WebPage.h"
3
+
4
+ Source::Source(WebPage *page, QObject *parent) : Command(page, parent) {
5
+ }
6
+
7
+ void Source::start(QStringList &arguments) {
8
+ Q_UNUSED(arguments)
9
+
10
+ QNetworkAccessManager* accessManager = page()->networkAccessManager();
11
+ QNetworkRequest request(page()->currentFrame()->url());
12
+ reply = accessManager->get(request);
13
+
14
+ connect(reply, SIGNAL(finished()), this, SLOT(sourceLoaded()));
15
+ }
16
+
17
+ void Source::sourceLoaded() {
18
+ emit finished(new Response(true, reply->readAll()));
19
+ }
20
+
data/src/Source.h ADDED
@@ -0,0 +1,19 @@
1
+ #include "Command.h"
2
+
3
+ class WebPage;
4
+ class QNetworkReply;
5
+
6
+ class Source : public Command {
7
+ Q_OBJECT
8
+
9
+ public:
10
+ Source(WebPage *page, QObject *parent = 0);
11
+ virtual void start(QStringList &arguments);
12
+
13
+ public slots:
14
+ void sourceLoaded();
15
+
16
+ private:
17
+ QNetworkReply *reply;
18
+ };
19
+
data/src/Status.cpp ADDED
@@ -0,0 +1,13 @@
1
+ #include "Status.h"
2
+ #include "WebPage.h"
3
+ #include <sstream>
4
+
5
+ Status::Status(WebPage *page, QObject *parent) : Command(page, parent) {
6
+ }
7
+
8
+ void Status::start(QStringList &arguments) {
9
+ Q_UNUSED(arguments);
10
+ int status = page()->getLastStatus();
11
+ emit finished(new Response(true, QString::number(status)));
12
+ }
13
+
data/src/Status.h ADDED
@@ -0,0 +1,12 @@
1
+ #include "Command.h"
2
+
3
+ class WebPage;
4
+
5
+ class Status : public Command {
6
+ Q_OBJECT
7
+
8
+ public:
9
+ Status(WebPage *page, QObject *parent = 0);
10
+ virtual void start(QStringList &arguments);
11
+ };
12
+
@@ -0,0 +1,32 @@
1
+ #include "UnsupportedContentHandler.h"
2
+ #include "WebPage.h"
3
+ #include <QNetworkReply>
4
+
5
+ UnsupportedContentHandler::UnsupportedContentHandler(WebPage *page, QNetworkReply *reply, QObject *parent) : QObject(parent) {
6
+ m_page = page;
7
+ m_reply = reply;
8
+ connect(m_reply, SIGNAL(finished()), this, SLOT(handleUnsupportedContent()));
9
+ disconnect(m_page, SIGNAL(loadFinished(bool)), m_page, SLOT(loadFinished(bool)));
10
+ }
11
+
12
+ void UnsupportedContentHandler::handleUnsupportedContent() {
13
+ QVariant contentMimeType = m_reply->header(QNetworkRequest::ContentTypeHeader);
14
+ if(contentMimeType.isNull()) {
15
+ this->finish(false);
16
+ } else {
17
+ this->loadUnsupportedContent();
18
+ this->finish(true);
19
+ }
20
+ this->deleteLater();
21
+ }
22
+
23
+ void UnsupportedContentHandler::loadUnsupportedContent() {
24
+ QByteArray text = m_reply->readAll();
25
+ m_page->mainFrame()->setContent(text, QString("text/plain"), m_reply->url());
26
+ }
27
+
28
+ void UnsupportedContentHandler::finish(bool success) {
29
+ connect(m_page, SIGNAL(loadFinished(bool)), m_page, SLOT(loadFinished(bool)));
30
+ m_page->replyFinished(m_reply);
31
+ m_page->loadFinished(success);
32
+ }
@@ -0,0 +1,18 @@
1
+ #include <QObject>
2
+ class WebPage;
3
+ class QNetworkReply;
4
+ class UnsupportedContentHandler : public QObject {
5
+ Q_OBJECT
6
+
7
+ public:
8
+ UnsupportedContentHandler(WebPage *page, QNetworkReply *reply, QObject *parent = 0);
9
+
10
+ public slots:
11
+ void handleUnsupportedContent();
12
+
13
+ private:
14
+ WebPage *m_page;
15
+ QNetworkReply *m_reply;
16
+ void loadUnsupportedContent();
17
+ void finish(bool success);
18
+ };
data/src/Url.cpp ADDED
@@ -0,0 +1,15 @@
1
+ #include "Url.h"
2
+ #include "WebPage.h"
3
+
4
+ Url::Url(WebPage *page, QObject *parent) : Command(page, parent) {
5
+ }
6
+
7
+ void Url::start(QStringList &argments) {
8
+ Q_UNUSED(argments);
9
+
10
+ QUrl humanUrl = page()->currentFrame()->url();
11
+ QByteArray encodedBytes = humanUrl.toEncoded();
12
+ QString urlString = QString(encodedBytes);
13
+ emit finished(new Response(true, urlString));
14
+ }
15
+
data/src/Url.h ADDED
@@ -0,0 +1,12 @@
1
+ #include "Command.h"
2
+
3
+ class WebPage;
4
+
5
+ class Url : public Command {
6
+ Q_OBJECT
7
+
8
+ public:
9
+ Url(WebPage *page, QObject *parent = 0);
10
+ virtual void start(QStringList &argments);
11
+ };
12
+
data/src/Visit.cpp ADDED
@@ -0,0 +1,21 @@
1
+ #include "Visit.h"
2
+ #include "Command.h"
3
+ #include "WebPage.h"
4
+
5
+ Visit::Visit(WebPage *page, QObject *parent) : Command(page, parent) {
6
+ connect(page, SIGNAL(pageFinished(bool)), this, SLOT(loadFinished(bool)));
7
+ }
8
+
9
+ void Visit::start(QStringList &arguments) {
10
+ QUrl requestedUrl = QUrl(arguments[0]);
11
+ page()->currentFrame()->load(QUrl(requestedUrl));
12
+ }
13
+
14
+ void Visit::loadFinished(bool success) {
15
+ QString message;
16
+ if (!success)
17
+ message = page()->failureString();
18
+
19
+ disconnect(page(), SIGNAL(pageFinished(bool)), this, SLOT(loadFinished(bool)));
20
+ emit finished(new Response(success, message));
21
+ }
data/src/Visit.h ADDED
@@ -0,0 +1,15 @@
1
+ #include "Command.h"
2
+
3
+ class WebPage;
4
+
5
+ class Visit : public Command {
6
+ Q_OBJECT
7
+
8
+ public:
9
+ Visit(WebPage *page, QObject *parent = 0);
10
+ virtual void start(QStringList &arguments);
11
+
12
+ private slots:
13
+ void loadFinished(bool success);
14
+ };
15
+
data/src/WebPage.cpp ADDED
@@ -0,0 +1,226 @@
1
+ #include "WebPage.h"
2
+ #include "JavascriptInvocation.h"
3
+ #include "NetworkAccessManager.h"
4
+ #include "NetworkCookieJar.h"
5
+ #include "UnsupportedContentHandler.h"
6
+ #include <QResource>
7
+ #include <iostream>
8
+
9
+ WebPage::WebPage(QObject *parent) : QWebPage(parent) {
10
+ setForwardUnsupportedContent(true);
11
+ loadJavascript();
12
+ setUserStylesheet();
13
+
14
+ m_loading = false;
15
+ this->setCustomNetworkAccessManager();
16
+
17
+ connect(this, SIGNAL(loadStarted()), this, SLOT(loadStarted()));
18
+ connect(this, SIGNAL(loadFinished(bool)), this, SLOT(loadFinished(bool)));
19
+ connect(this, SIGNAL(frameCreated(QWebFrame *)),
20
+ this, SLOT(frameCreated(QWebFrame *)));
21
+ connect(this, SIGNAL(unsupportedContent(QNetworkReply*)),
22
+ this, SLOT(handleUnsupportedContent(QNetworkReply*)));
23
+ }
24
+
25
+ void WebPage::setCustomNetworkAccessManager() {
26
+ NetworkAccessManager *manager = new NetworkAccessManager();
27
+ manager->setCookieJar(new NetworkCookieJar());
28
+ this->setNetworkAccessManager(manager);
29
+ connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(replyFinished(QNetworkReply *)));
30
+ connect(manager, SIGNAL(sslErrors(QNetworkReply *, QList<QSslError>)), this, SLOT(ignoreSslErrors(QNetworkReply *, QList<QSslError>)));
31
+ }
32
+
33
+ void WebPage::loadJavascript() {
34
+ QResource javascript(":/capybara.js");
35
+ if (javascript.isCompressed()) {
36
+ QByteArray uncompressedBytes(qUncompress(javascript.data(), javascript.size()));
37
+ m_capybaraJavascript = QString(uncompressedBytes);
38
+ } else {
39
+ char * javascriptString = new char[javascript.size() + 1];
40
+ strcpy(javascriptString, (const char *)javascript.data());
41
+ javascriptString[javascript.size()] = 0;
42
+ m_capybaraJavascript = javascriptString;
43
+ }
44
+ }
45
+
46
+ void WebPage::setUserStylesheet() {
47
+ QString data = QString("* { font-family: 'Arial' ! important; }").toUtf8().toBase64();
48
+ QUrl url = QUrl(QString("data:text/css;charset=utf-8;base64,") + data);
49
+ settings()->setUserStyleSheetUrl(url);
50
+ }
51
+
52
+ QString WebPage::userAgentForUrl(const QUrl &url ) const {
53
+ if (!m_userAgent.isEmpty()) {
54
+ return m_userAgent;
55
+ } else {
56
+ return QWebPage::userAgentForUrl(url);
57
+ }
58
+ }
59
+
60
+ void WebPage::setUserAgent(QString userAgent) {
61
+ m_userAgent = userAgent;
62
+ }
63
+
64
+ void WebPage::frameCreated(QWebFrame * frame) {
65
+ connect(frame, SIGNAL(javaScriptWindowObjectCleared()),
66
+ this, SLOT(injectJavascriptHelpers()));
67
+ }
68
+
69
+ void WebPage::injectJavascriptHelpers() {
70
+ QWebFrame* frame = qobject_cast<QWebFrame *>(QObject::sender());
71
+ frame->evaluateJavaScript(m_capybaraJavascript);
72
+ }
73
+
74
+ bool WebPage::shouldInterruptJavaScript() {
75
+ return false;
76
+ }
77
+
78
+ QVariant WebPage::invokeCapybaraFunction(const char *name, QStringList &arguments) {
79
+ QString qname(name);
80
+ QString objectName("CapybaraInvocation");
81
+ JavascriptInvocation invocation(qname, arguments);
82
+ currentFrame()->addToJavaScriptWindowObject(objectName, &invocation);
83
+ QString javascript = QString("Capybara.invoke()");
84
+ return currentFrame()->evaluateJavaScript(javascript);
85
+ }
86
+
87
+ QVariant WebPage::invokeCapybaraFunction(QString &name, QStringList &arguments) {
88
+ return invokeCapybaraFunction(name.toAscii().data(), arguments);
89
+ }
90
+
91
+ void WebPage::javaScriptConsoleMessage(const QString &message, int lineNumber, const QString &sourceID) {
92
+ if (!sourceID.isEmpty())
93
+ std::cout << qPrintable(sourceID) << ":" << lineNumber << " ";
94
+ std::cout << qPrintable(message) << std::endl;
95
+ }
96
+
97
+ void WebPage::javaScriptAlert(QWebFrame *frame, const QString &message) {
98
+ Q_UNUSED(frame);
99
+ std::cout << "ALERT: " << qPrintable(message) << std::endl;
100
+ }
101
+
102
+ bool WebPage::javaScriptConfirm(QWebFrame *frame, const QString &message) {
103
+ Q_UNUSED(frame);
104
+ Q_UNUSED(message);
105
+ return true;
106
+ }
107
+
108
+ bool WebPage::javaScriptPrompt(QWebFrame *frame, const QString &message, const QString &defaultValue, QString *result) {
109
+ Q_UNUSED(frame)
110
+ Q_UNUSED(message)
111
+ Q_UNUSED(defaultValue)
112
+ Q_UNUSED(result)
113
+ return false;
114
+ }
115
+
116
+ void WebPage::loadStarted() {
117
+ m_loading = true;
118
+ }
119
+
120
+ void WebPage::loadFinished(bool success) {
121
+ m_loading = false;
122
+ emit pageFinished(success);
123
+ }
124
+
125
+ bool WebPage::isLoading() const {
126
+ return m_loading;
127
+ }
128
+
129
+ QString WebPage::failureString() {
130
+ return QString("Unable to load URL: ") + currentFrame()->requestedUrl().toString();
131
+ }
132
+
133
+ bool WebPage::render(const QString &fileName) {
134
+ QFileInfo fileInfo(fileName);
135
+ QDir dir;
136
+ dir.mkpath(fileInfo.absolutePath());
137
+
138
+ QSize viewportSize = this->viewportSize();
139
+ QSize pageSize = this->mainFrame()->contentsSize();
140
+ if (pageSize.isEmpty()) {
141
+ return false;
142
+ }
143
+
144
+ QImage buffer(pageSize, QImage::Format_ARGB32);
145
+ buffer.fill(qRgba(255, 255, 255, 0));
146
+
147
+ QPainter p(&buffer);
148
+ p.setRenderHint( QPainter::Antialiasing, true);
149
+ p.setRenderHint( QPainter::TextAntialiasing, true);
150
+ p.setRenderHint( QPainter::SmoothPixmapTransform, true);
151
+
152
+ this->setViewportSize(pageSize);
153
+ this->mainFrame()->render(&p);
154
+ p.end();
155
+ this->setViewportSize(viewportSize);
156
+
157
+ return buffer.save(fileName);
158
+ }
159
+
160
+ QString WebPage::chooseFile(QWebFrame *parentFrame, const QString &suggestedFile) {
161
+ Q_UNUSED(parentFrame);
162
+ Q_UNUSED(suggestedFile);
163
+
164
+ return getLastAttachedFileName();
165
+ }
166
+
167
+ bool WebPage::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output) {
168
+ Q_UNUSED(option);
169
+ if (extension == ChooseMultipleFilesExtension) {
170
+ QStringList names = QStringList() << getLastAttachedFileName();
171
+ static_cast<ChooseMultipleFilesExtensionReturn*>(output)->fileNames = names;
172
+ return true;
173
+ }
174
+ return false;
175
+ }
176
+
177
+ QString WebPage::getLastAttachedFileName() {
178
+ return currentFrame()->evaluateJavaScript(QString("Capybara.lastAttachedFile")).toString();
179
+ }
180
+
181
+ void WebPage::replyFinished(QNetworkReply *reply) {
182
+ if (reply->url() == this->currentFrame()->url()) {
183
+ QStringList headers;
184
+ m_lastStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
185
+ QList<QByteArray> list = reply->rawHeaderList();
186
+
187
+ int length = list.size();
188
+ for(int i = 0; i < length; i++) {
189
+ headers << list.at(i)+": "+reply->rawHeader(list.at(i));
190
+ }
191
+
192
+ m_pageHeaders = headers.join("\n");
193
+ }
194
+ }
195
+
196
+ void WebPage::ignoreSslErrors(QNetworkReply *reply, const QList<QSslError> &errors) {
197
+ if (m_ignoreSslErrors)
198
+ reply->ignoreSslErrors(errors);
199
+ }
200
+
201
+ void WebPage::setIgnoreSslErrors(bool ignore) {
202
+ m_ignoreSslErrors = ignore;
203
+ }
204
+
205
+ bool WebPage::ignoreSslErrors() {
206
+ return m_ignoreSslErrors;
207
+ }
208
+
209
+
210
+ int WebPage::getLastStatus() {
211
+ return m_lastStatus;
212
+ }
213
+
214
+ void WebPage::resetResponseHeaders() {
215
+ m_lastStatus = 0;
216
+ m_pageHeaders = QString();
217
+ }
218
+
219
+ QString WebPage::pageHeaders() {
220
+ return m_pageHeaders;
221
+ }
222
+
223
+ void WebPage::handleUnsupportedContent(QNetworkReply *reply) {
224
+ UnsupportedContentHandler *handler = new UnsupportedContentHandler(this, reply);
225
+ Q_UNUSED(handler);
226
+ }