capybara-webkit 0.13.2 → 0.14.0
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/.travis.yml +10 -0
- data/Gemfile.lock +20 -18
- data/NEWS.md +20 -1
- data/README.md +12 -10
- data/capybara-webkit.gemspec +3 -2
- data/lib/capybara/webkit/browser.rb +10 -19
- data/lib/capybara/webkit/connection.rb +13 -34
- data/lib/capybara/webkit/driver.rb +5 -22
- data/lib/capybara/webkit/node.rb +10 -2
- data/lib/capybara/webkit/version.rb +1 -1
- data/lib/capybara_webkit_builder.rb +10 -1
- data/spec/browser_spec.rb +1 -1
- data/spec/connection_spec.rb +4 -2
- data/spec/driver_rendering_spec.rb +2 -2
- data/spec/driver_resize_window_spec.rb +29 -40
- data/spec/driver_spec.rb +368 -125
- data/spec/integration/session_spec.rb +100 -6
- data/spec/spec_helper.rb +6 -9
- data/spec/support/app_runner.rb +2 -12
- data/src/Authenticate.cpp +2 -2
- data/src/ClearCookies.cpp +1 -1
- data/src/ClearPromptText.cpp +1 -1
- data/src/Command.cpp +13 -0
- data/src/Command.h +6 -0
- data/src/CommandFactory.cpp +1 -3
- data/src/Connection.cpp +4 -3
- data/src/ConsoleMessages.cpp +4 -1
- data/src/CurrentUrl.cpp +1 -16
- data/src/CurrentUrl.h +0 -6
- data/src/EnableLogging.cpp +1 -1
- data/src/Evaluate.cpp +3 -74
- data/src/Evaluate.h +0 -8
- data/src/Execute.cpp +2 -2
- data/src/Find.cpp +2 -2
- data/src/FrameFocus.cpp +3 -3
- data/src/GetCookies.cpp +1 -1
- data/src/GetTimeout.cpp +1 -1
- data/src/GetWindowHandle.cpp +1 -1
- data/src/GetWindowHandles.cpp +6 -5
- data/src/Header.cpp +2 -2
- data/src/Headers.cpp +1 -1
- data/src/IgnoreSslErrors.cpp +1 -1
- data/src/JavascriptAlertMessages.cpp +4 -1
- data/src/JavascriptConfirmMessages.cpp +4 -1
- data/src/JavascriptPromptMessages.cpp +4 -1
- data/src/JsonSerializer.cpp +116 -0
- data/src/JsonSerializer.h +20 -0
- data/src/NetworkAccessManager.cpp +58 -17
- data/src/NetworkAccessManager.h +6 -0
- data/src/NoOpReply.cpp +32 -0
- data/src/NoOpReply.h +18 -0
- data/src/Node.cpp +1 -1
- data/src/NullCommand.cpp +1 -1
- data/src/PageLoadingCommand.cpp +5 -4
- data/src/Render.cpp +1 -1
- data/src/Reset.cpp +1 -1
- data/src/ResizeWindow.cpp +1 -1
- data/src/Response.cpp +3 -3
- data/src/Response.h +13 -4
- data/src/SetConfirmAction.cpp +1 -1
- data/src/SetCookie.cpp +1 -1
- data/src/SetPromptAction.cpp +1 -1
- data/src/SetPromptText.cpp +1 -1
- data/src/SetProxy.cpp +2 -2
- data/src/SetSkipImageLoading.cpp +1 -1
- data/src/SetTimeout.cpp +2 -2
- data/src/SetUrlBlacklist.cpp +15 -0
- data/src/SetUrlBlacklist.h +11 -0
- data/src/Status.cpp +1 -1
- data/src/TimeoutCommand.cpp +6 -6
- data/src/TimeoutCommand.h +0 -3
- data/src/UnsupportedContentHandler.cpp +1 -4
- data/src/Visit.cpp +1 -1
- data/src/WebPage.cpp +41 -31
- data/src/WebPage.h +14 -12
- data/src/WebPageManager.cpp +13 -8
- data/src/WebPageManager.h +3 -2
- data/src/WindowFocus.cpp +2 -2
- data/src/body.cpp +7 -2
- data/src/capybara.js +10 -2
- data/src/find_command.h +1 -3
- data/src/webkit_server.pro +7 -7
- metadata +47 -82
- checksums.yaml +0 -7
- data/spec/integration/driver_spec.rb +0 -21
- data/src/RequestedUrl.cpp +0 -13
- data/src/RequestedUrl.h +0 -10
- data/src/Source.cpp +0 -19
- data/src/Source.h +0 -18
- data/src/Url.cpp +0 -13
- data/src/Url.h +0 -10
@@ -3,6 +3,12 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
require 'capybara/webkit'
|
5
5
|
|
6
|
+
module TestSessions
|
7
|
+
Webkit = Capybara::Session.new(:reusable_webkit, TestApp)
|
8
|
+
end
|
9
|
+
|
10
|
+
Capybara::SpecHelper.run_specs TestSessions::Webkit, "webkit"
|
11
|
+
|
6
12
|
describe Capybara::Session do
|
7
13
|
subject { Capybara::Session.new(:reusable_webkit, @app) }
|
8
14
|
after { subject.reset! }
|
@@ -125,13 +131,101 @@ describe Capybara::Session do
|
|
125
131
|
subject.response_headers['X-Capybara'].should == nil
|
126
132
|
end
|
127
133
|
end
|
128
|
-
end
|
129
134
|
|
130
|
-
|
131
|
-
|
132
|
-
|
135
|
+
context "slow iframe app" do
|
136
|
+
before do
|
137
|
+
@app = Class.new(ExampleApp) do
|
138
|
+
get '/' do
|
139
|
+
<<-HTML
|
140
|
+
<html>
|
141
|
+
<head>
|
142
|
+
<script>
|
143
|
+
function hang() {
|
144
|
+
xhr = new XMLHttpRequest();
|
145
|
+
xhr.onreadystatechange = function() {
|
146
|
+
if(xhr.readyState == 4){
|
147
|
+
document.getElementById('p').innerText = 'finished'
|
148
|
+
}
|
149
|
+
}
|
150
|
+
xhr.open('GET', '/slow', true);
|
151
|
+
xhr.send();
|
152
|
+
document.getElementById("f").src = '/iframe';
|
153
|
+
return false;
|
154
|
+
}
|
155
|
+
</script>
|
156
|
+
</head>
|
157
|
+
<body>
|
158
|
+
<a href="#" onclick="hang()">Click Me!</a>
|
159
|
+
<iframe src="about:blank" id="f"></iframe>
|
160
|
+
<p id="p"></p>
|
161
|
+
</body>
|
162
|
+
</html>
|
163
|
+
HTML
|
164
|
+
end
|
165
|
+
|
166
|
+
get '/slow' do
|
167
|
+
sleep 1
|
168
|
+
status 204
|
169
|
+
end
|
170
|
+
|
171
|
+
get '/iframe' do
|
172
|
+
status 204
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should not hang the server" do
|
178
|
+
subject.visit("/")
|
179
|
+
subject.click_link('Click Me!')
|
180
|
+
Capybara.using_wait_time(5) do
|
181
|
+
subject.should have_content("finished")
|
182
|
+
end
|
183
|
+
end
|
133
184
|
end
|
134
185
|
|
135
|
-
|
136
|
-
|
186
|
+
context "session app" do
|
187
|
+
before do
|
188
|
+
@app = Class.new(ExampleApp) do
|
189
|
+
enable :sessions
|
190
|
+
get '/' do
|
191
|
+
<<-HTML
|
192
|
+
<html>
|
193
|
+
<body>
|
194
|
+
<form method="post" action="/sign_in">
|
195
|
+
<input type="text" name="username">
|
196
|
+
<input type="password" name="password">
|
197
|
+
<input type="submit" value="Submit">
|
198
|
+
</form>
|
199
|
+
</body>
|
200
|
+
</html>
|
201
|
+
HTML
|
202
|
+
end
|
203
|
+
|
204
|
+
post '/sign_in' do
|
205
|
+
session[:username] = params[:username]
|
206
|
+
session[:password] = params[:password]
|
207
|
+
redirect '/'
|
208
|
+
end
|
209
|
+
|
210
|
+
get '/other' do
|
211
|
+
<<-HTML
|
212
|
+
<html>
|
213
|
+
<body>
|
214
|
+
<p>Welcome, #{session[:username]}.</p>
|
215
|
+
</body>
|
216
|
+
</html>
|
217
|
+
HTML
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
it "should not start queued commands more than once" do
|
223
|
+
subject.visit('/')
|
224
|
+
subject.fill_in('username', with: 'admin')
|
225
|
+
subject.fill_in('password', with: 'temp4now')
|
226
|
+
subject.click_button('Submit')
|
227
|
+
subject.visit('/other')
|
228
|
+
subject.should have_content('admin')
|
229
|
+
end
|
230
|
+
end
|
137
231
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -17,28 +17,25 @@ $:.detect do |dir|
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
RSpec.configure do |c|
|
21
|
-
c.filter_run_excluding :skip_on_windows => !(RbConfig::CONFIG['host_os'] =~ /mingw32/).nil?
|
22
|
-
end
|
23
|
-
|
24
20
|
require 'capybara/webkit'
|
25
|
-
connection = Capybara::Webkit::Connection.new(:socket_class => TCPSocket
|
21
|
+
connection = Capybara::Webkit::Connection.new(:socket_class => TCPSocket)
|
26
22
|
$webkit_browser = Capybara::Webkit::Browser.new(connection)
|
27
23
|
|
28
24
|
if ENV['DEBUG']
|
29
25
|
$webkit_browser.enable_logging
|
30
26
|
end
|
31
27
|
|
32
|
-
RSpec.configure do |config|
|
33
|
-
config.before { $webkit_browser.reset! }
|
34
|
-
end
|
35
|
-
|
36
28
|
require File.join(spec_dir, "spec_helper")
|
37
29
|
|
38
30
|
Capybara.register_driver :reusable_webkit do |app|
|
39
31
|
Capybara::Webkit::Driver.new(app, :browser => $webkit_browser)
|
40
32
|
end
|
41
33
|
|
34
|
+
RSpec.configure do |c|
|
35
|
+
c.filter_run_excluding :skip_on_windows => !(RbConfig::CONFIG['host_os'] =~ /mingw32/).nil?
|
36
|
+
Capybara::SpecHelper.configure(c)
|
37
|
+
end
|
38
|
+
|
42
39
|
def with_env_vars(vars)
|
43
40
|
old_env_variables = {}
|
44
41
|
vars.each do |key, value|
|
data/spec/support/app_runner.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
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.
|
2
|
+
# application that can be configured for each spec.
|
3
3
|
|
4
4
|
require 'sinatra/base'
|
5
5
|
|
@@ -51,17 +51,7 @@ module AppRunner
|
|
51
51
|
def self.included(example_group)
|
52
52
|
example_group.class_eval do
|
53
53
|
before { AppRunner.reset }
|
54
|
-
|
55
|
-
around do |example|
|
56
|
-
Capybara.run_server = false
|
57
|
-
Capybara.app_host = AppRunner.app_host
|
58
|
-
begin
|
59
|
-
example.run
|
60
|
-
ensure
|
61
|
-
Capybara.run_server = true
|
62
|
-
Capybara.app_host = nil
|
63
|
-
end
|
64
|
-
end
|
54
|
+
after { $webkit_browser.reset! }
|
65
55
|
end
|
66
56
|
end
|
67
57
|
end
|
data/src/Authenticate.cpp
CHANGED
@@ -9,10 +9,10 @@ void Authenticate::start() {
|
|
9
9
|
QString username = arguments()[0];
|
10
10
|
QString password = arguments()[1];
|
11
11
|
|
12
|
-
NetworkAccessManager* networkAccessManager =
|
12
|
+
NetworkAccessManager* networkAccessManager = page()->networkAccessManager();
|
13
13
|
networkAccessManager->setUserName(username);
|
14
14
|
networkAccessManager->setPassword(password);
|
15
15
|
|
16
|
-
|
16
|
+
emitFinished(true);
|
17
17
|
}
|
18
18
|
|
data/src/ClearCookies.cpp
CHANGED
data/src/ClearPromptText.cpp
CHANGED
data/src/Command.cpp
CHANGED
@@ -6,3 +6,16 @@ Command::Command(QObject *parent) : QObject(parent) {
|
|
6
6
|
QString Command::toString() const {
|
7
7
|
return metaObject()->className();
|
8
8
|
}
|
9
|
+
|
10
|
+
void Command::emitFinished(bool success) {
|
11
|
+
emit finished(new Response(success, this));
|
12
|
+
}
|
13
|
+
|
14
|
+
void Command::emitFinished(bool success, QString message) {
|
15
|
+
emit finished(new Response(success, message, this));
|
16
|
+
}
|
17
|
+
|
18
|
+
void Command::emitFinished(bool success, QByteArray message) {
|
19
|
+
emit finished(new Response(success, message, this));
|
20
|
+
}
|
21
|
+
|
data/src/Command.h
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
|
4
4
|
#include <QObject>
|
5
5
|
#include "Response.h"
|
6
|
+
#include <QString>
|
6
7
|
|
7
8
|
class Command : public QObject {
|
8
9
|
Q_OBJECT
|
@@ -12,6 +13,11 @@ class Command : public QObject {
|
|
12
13
|
virtual void start() = 0;
|
13
14
|
virtual QString toString() const;
|
14
15
|
|
16
|
+
protected:
|
17
|
+
void emitFinished(bool success);
|
18
|
+
void emitFinished(bool success, QString message);
|
19
|
+
void emitFinished(bool success, QByteArray message);
|
20
|
+
|
15
21
|
signals:
|
16
22
|
void finished(Response *response);
|
17
23
|
};
|
data/src/CommandFactory.cpp
CHANGED
@@ -5,8 +5,6 @@
|
|
5
5
|
#include "Find.h"
|
6
6
|
#include "Reset.h"
|
7
7
|
#include "Node.h"
|
8
|
-
#include "Url.h"
|
9
|
-
#include "Source.h"
|
10
8
|
#include "Evaluate.h"
|
11
9
|
#include "Execute.h"
|
12
10
|
#include "FrameFocus.h"
|
@@ -20,7 +18,6 @@
|
|
20
18
|
#include "GetCookies.h"
|
21
19
|
#include "SetProxy.h"
|
22
20
|
#include "ConsoleMessages.h"
|
23
|
-
#include "RequestedUrl.h"
|
24
21
|
#include "CurrentUrl.h"
|
25
22
|
#include "SetTimeout.h"
|
26
23
|
#include "GetTimeout.h"
|
@@ -40,6 +37,7 @@
|
|
40
37
|
#include "JavascriptAlertMessages.h"
|
41
38
|
#include "JavascriptConfirmMessages.h"
|
42
39
|
#include "JavascriptPromptMessages.h"
|
40
|
+
#include "SetUrlBlacklist.h"
|
43
41
|
|
44
42
|
CommandFactory::CommandFactory(WebPageManager *manager, QObject *parent) : QObject(parent) {
|
45
43
|
m_manager = manager;
|
data/src/Connection.cpp
CHANGED
@@ -43,13 +43,15 @@ void Connection::pendingLoadFinished(bool success) {
|
|
43
43
|
void Connection::writePageLoadFailure() {
|
44
44
|
m_pageSuccess = true;
|
45
45
|
QString message = currentPage()->failureString();
|
46
|
-
|
46
|
+
Response *response = new Response(false, message, this);
|
47
|
+
writeResponse(response);
|
48
|
+
delete response;
|
47
49
|
}
|
48
50
|
|
49
51
|
void Connection::finishCommand(Response *response) {
|
50
52
|
m_pageSuccess = true;
|
51
|
-
sender()->deleteLater();
|
52
53
|
writeResponse(response);
|
54
|
+
sender()->deleteLater();
|
53
55
|
}
|
54
56
|
|
55
57
|
void Connection::writeResponse(Response *response) {
|
@@ -64,7 +66,6 @@ void Connection::writeResponse(Response *response) {
|
|
64
66
|
QString messageLength = QString::number(messageUtf8.size()) + "\n";
|
65
67
|
m_socket->write(messageLength.toAscii());
|
66
68
|
m_socket->write(messageUtf8);
|
67
|
-
delete response;
|
68
69
|
}
|
69
70
|
|
70
71
|
WebPage *Connection::currentPage() {
|
data/src/ConsoleMessages.cpp
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
#include "ConsoleMessages.h"
|
2
2
|
#include "WebPage.h"
|
3
3
|
#include "WebPageManager.h"
|
4
|
+
#include "JsonSerializer.h"
|
4
5
|
|
5
6
|
ConsoleMessages::ConsoleMessages(WebPageManager *manager, QStringList &arguments, QObject *parent) : SocketCommand(manager, arguments, parent) {
|
6
7
|
}
|
7
8
|
|
8
9
|
void ConsoleMessages::start() {
|
9
|
-
|
10
|
+
JsonSerializer serializer;
|
11
|
+
QByteArray json = serializer.serialize(page()->consoleMessages());
|
12
|
+
emitFinished(true, json);
|
10
13
|
}
|
11
14
|
|
data/src/CurrentUrl.cpp
CHANGED
@@ -6,24 +6,9 @@ CurrentUrl::CurrentUrl(WebPageManager *manager, QStringList &arguments, QObject
|
|
6
6
|
}
|
7
7
|
|
8
8
|
void CurrentUrl::start() {
|
9
|
-
#if QT_VERSION >= QT_VERSION_CHECK(4, 8, 0)
|
10
9
|
QStringList arguments;
|
11
10
|
QVariant result = page()->invokeCapybaraFunction("currentUrl", arguments);
|
12
11
|
QString url = result.toString();
|
13
|
-
|
14
|
-
#else
|
15
|
-
QUrl humanUrl = wasRedirectedAndNotModifiedByJavascript() ?
|
16
|
-
page()->currentFrame()->url() : page()->currentFrame()->requestedUrl();
|
17
|
-
QByteArray encodedBytes = humanUrl.toEncoded();
|
18
|
-
emit finished(new Response(true, encodedBytes));
|
19
|
-
}
|
20
|
-
|
21
|
-
bool CurrentUrl::wasRegularLoad() {
|
22
|
-
return page()->currentFrame()->url() == page()->currentFrame()->requestedUrl();
|
23
|
-
}
|
24
|
-
|
25
|
-
bool CurrentUrl::wasRedirectedAndNotModifiedByJavascript() {
|
26
|
-
return !wasRegularLoad() && page()->currentFrame()->url() == page()->history()->currentItem().url();
|
27
|
-
#endif
|
12
|
+
emitFinished(true, url);
|
28
13
|
}
|
29
14
|
|
data/src/CurrentUrl.h
CHANGED
@@ -6,11 +6,5 @@ class CurrentUrl : public SocketCommand {
|
|
6
6
|
public:
|
7
7
|
CurrentUrl(WebPageManager *, QStringList &arguments, QObject *parent = 0);
|
8
8
|
virtual void start();
|
9
|
-
#if QT_VERSION < QT_VERSION_CHECK(4, 8, 0)
|
10
|
-
|
11
|
-
private:
|
12
|
-
bool wasRegularLoad();
|
13
|
-
bool wasRedirectedAndNotModifiedByJavascript();
|
14
|
-
#endif
|
15
9
|
};
|
16
10
|
|
data/src/EnableLogging.cpp
CHANGED
data/src/Evaluate.cpp
CHANGED
@@ -1,85 +1,14 @@
|
|
1
1
|
#include "Evaluate.h"
|
2
2
|
#include "WebPage.h"
|
3
3
|
#include "WebPageManager.h"
|
4
|
+
#include "JsonSerializer.h"
|
4
5
|
#include <iostream>
|
5
6
|
|
6
7
|
Evaluate::Evaluate(WebPageManager *manager, QStringList &arguments, QObject *parent) : SocketCommand(manager, arguments, parent) {
|
7
|
-
m_buffer = "";
|
8
8
|
}
|
9
9
|
|
10
10
|
void Evaluate::start() {
|
11
11
|
QVariant result = page()->currentFrame()->evaluateJavaScript(arguments()[0]);
|
12
|
-
|
13
|
-
|
14
|
-
}
|
15
|
-
|
16
|
-
void Evaluate::addVariant(QVariant &object) {
|
17
|
-
if (object.isValid()) {
|
18
|
-
switch(object.type()) {
|
19
|
-
case QMetaType::QString:
|
20
|
-
{
|
21
|
-
QString string = object.toString();
|
22
|
-
addString(string);
|
23
|
-
}
|
24
|
-
break;
|
25
|
-
case QMetaType::QVariantList:
|
26
|
-
{
|
27
|
-
QVariantList list = object.toList();
|
28
|
-
addArray(list);
|
29
|
-
}
|
30
|
-
break;
|
31
|
-
case QMetaType::Double:
|
32
|
-
m_buffer.append(object.toString());
|
33
|
-
break;
|
34
|
-
case QMetaType::QVariantMap:
|
35
|
-
{
|
36
|
-
QVariantMap map = object.toMap();
|
37
|
-
addMap(map);
|
38
|
-
break;
|
39
|
-
}
|
40
|
-
case QMetaType::Bool:
|
41
|
-
{
|
42
|
-
m_buffer.append(object.toString());
|
43
|
-
break;
|
44
|
-
}
|
45
|
-
default:
|
46
|
-
m_buffer.append("null");
|
47
|
-
}
|
48
|
-
} else {
|
49
|
-
m_buffer.append("null");
|
50
|
-
}
|
51
|
-
}
|
52
|
-
|
53
|
-
void Evaluate::addString(QString &string) {
|
54
|
-
QString escapedString(string);
|
55
|
-
escapedString.replace("\"", "\\\"");
|
56
|
-
m_buffer.append("\"");
|
57
|
-
m_buffer.append(escapedString);
|
58
|
-
m_buffer.append("\"");
|
59
|
-
}
|
60
|
-
|
61
|
-
void Evaluate::addArray(QVariantList &list) {
|
62
|
-
m_buffer.append("[");
|
63
|
-
for (int i = 0; i < list.length(); i++) {
|
64
|
-
if (i > 0)
|
65
|
-
m_buffer.append(",");
|
66
|
-
addVariant(list[i]);
|
67
|
-
}
|
68
|
-
m_buffer.append("]");
|
69
|
-
}
|
70
|
-
|
71
|
-
void Evaluate::addMap(QVariantMap &map) {
|
72
|
-
m_buffer.append("{");
|
73
|
-
QMapIterator<QString, QVariant> iterator(map);
|
74
|
-
while (iterator.hasNext()) {
|
75
|
-
iterator.next();
|
76
|
-
QString key = iterator.key();
|
77
|
-
QVariant value = iterator.value();
|
78
|
-
addString(key);
|
79
|
-
m_buffer.append(":");
|
80
|
-
addVariant(value);
|
81
|
-
if (iterator.hasNext())
|
82
|
-
m_buffer.append(",");
|
83
|
-
}
|
84
|
-
m_buffer.append("}");
|
12
|
+
JsonSerializer serializer;
|
13
|
+
emitFinished(true, serializer.serialize(result));
|
85
14
|
}
|