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