intentmedia-capybara-webkit 0.7.2.1

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