capybara-webkit 0.6.0 → 0.6.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.
- data/capybara-webkit.gemspec +1 -1
- data/lib/capybara/driver/webkit.rb +2 -2
- data/lib/capybara/driver/webkit/browser.rb +51 -10
- data/spec/browser_spec.rb +9 -0
- data/spec/driver_spec.rb +19 -0
- data/spec/integration/driver_spec.rb +5 -8
- data/spec/spec_helper.rb +1 -1
- data/src/Connection.cpp +2 -0
- data/src/Headers.cpp +11 -0
- data/src/Headers.h +12 -0
- data/src/Status.cpp +13 -0
- data/src/Status.h +12 -0
- data/src/WebPage.cpp +24 -1
- data/src/WebPage.h +5 -0
- data/src/capybara.js +8 -1
- data/src/find_command.h +2 -0
- data/src/main.cpp +10 -0
- data/src/webkit_server.pro +2 -2
- metadata +10 -22
data/capybara-webkit.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "capybara-webkit"
|
3
|
-
s.version = "0.6.
|
3
|
+
s.version = "0.6.1"
|
4
4
|
s.authors = ["thoughtbot", "Joe Ferris", "Jason Morrison", "Tristan Dunn",
|
5
5
|
"Joshua Clayton", "Yuichi Tateno", "Aaron Gibralter",
|
6
6
|
"Vasily Reys", "petrushka", "John Bintz", "Chad Pytel",
|
@@ -54,11 +54,11 @@ class Capybara::Driver::Webkit
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def response_headers
|
57
|
-
|
57
|
+
browser.response_headers
|
58
58
|
end
|
59
59
|
|
60
60
|
def status_code
|
61
|
-
|
61
|
+
browser.status_code
|
62
62
|
end
|
63
63
|
|
64
64
|
def within_frame(frame_id_or_index)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'socket'
|
2
|
+
require 'thread'
|
2
3
|
require 'capybara/util/timeout'
|
3
4
|
require 'json'
|
4
5
|
|
@@ -8,6 +9,9 @@ class Capybara::Driver::Webkit
|
|
8
9
|
|
9
10
|
def initialize(options = {})
|
10
11
|
@socket_class = options[:socket_class] || TCPSocket
|
12
|
+
@stdout = options.has_key?(:stdout) ?
|
13
|
+
options[:stdout] :
|
14
|
+
$stdout
|
11
15
|
start_server
|
12
16
|
connect
|
13
17
|
end
|
@@ -36,6 +40,14 @@ class Capybara::Driver::Webkit
|
|
36
40
|
command("Source")
|
37
41
|
end
|
38
42
|
|
43
|
+
def status_code
|
44
|
+
command("Status").to_i
|
45
|
+
end
|
46
|
+
|
47
|
+
def response_headers
|
48
|
+
Hash[command("Headers").split("\n").map { |header| header.split(": ") }]
|
49
|
+
end
|
50
|
+
|
39
51
|
def url
|
40
52
|
command("Url")
|
41
53
|
end
|
@@ -77,23 +89,27 @@ class Capybara::Driver::Webkit
|
|
77
89
|
private
|
78
90
|
|
79
91
|
def start_server
|
80
|
-
|
81
|
-
@server_port = discover_server_port(
|
92
|
+
pipe = fork_server
|
93
|
+
@server_port = discover_server_port(pipe)
|
94
|
+
@stdout_thread = Thread.new do
|
95
|
+
Thread.current.abort_on_exception = true
|
96
|
+
forward_stdout(pipe)
|
97
|
+
end
|
82
98
|
end
|
83
99
|
|
84
100
|
def fork_server
|
85
101
|
server_path = File.expand_path("../../../../../bin/webkit_server", __FILE__)
|
86
102
|
|
87
|
-
|
88
|
-
|
89
|
-
$stdout.reopen write_pipe
|
90
|
-
read_pipe.close
|
91
|
-
exec(server_path)
|
92
|
-
end
|
103
|
+
pipe, @pid = server_pipe_and_pid(server_path)
|
104
|
+
|
93
105
|
at_exit { Process.kill("INT", @pid) }
|
94
106
|
|
95
|
-
|
96
|
-
|
107
|
+
pipe
|
108
|
+
end
|
109
|
+
|
110
|
+
def server_pipe_and_pid(server_path)
|
111
|
+
pipe = IO.popen(server_path)
|
112
|
+
[pipe, pipe.pid]
|
97
113
|
end
|
98
114
|
|
99
115
|
def discover_server_port(read_pipe)
|
@@ -101,6 +117,31 @@ class Capybara::Driver::Webkit
|
|
101
117
|
((read_pipe.first || '').match(/listening on port: (\d+)/) || [])[1].to_i
|
102
118
|
end
|
103
119
|
|
120
|
+
def forward_stdout(pipe)
|
121
|
+
while pipe_readable?(pipe)
|
122
|
+
line = pipe.readline
|
123
|
+
if @stdout
|
124
|
+
@stdout.write(line)
|
125
|
+
@stdout.flush
|
126
|
+
end
|
127
|
+
end
|
128
|
+
rescue EOFError
|
129
|
+
end
|
130
|
+
|
131
|
+
if !defined?(RUBY_ENGINE) || (RUBY_ENGINE == "ruby" && RUBY_VERSION <= "1.8")
|
132
|
+
# please note the use of IO::select() here, as it is used specifically to
|
133
|
+
# preserve correct signal handling behavior in ruby 1.8.
|
134
|
+
# https://github.com/thibaudgg/rb-fsevent/commit/d1a868bf8dc72dbca102bedbadff76c7e6c2dc21
|
135
|
+
# https://github.com/thibaudgg/rb-fsevent/blob/1ca42b987596f350ee7b19d8f8210b7b6ae8766b/ext/fsevent/fsevent_watch.c#L171
|
136
|
+
def pipe_readable?(pipe)
|
137
|
+
IO.select([pipe])
|
138
|
+
end
|
139
|
+
else
|
140
|
+
def pipe_readable?(pipe)
|
141
|
+
!pipe.eof?
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
104
145
|
def connect
|
105
146
|
Capybara.timeout(5) do
|
106
147
|
attempt_connect
|
data/spec/browser_spec.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'stringio'
|
2
3
|
require 'capybara/driver/webkit/browser'
|
3
4
|
|
4
5
|
describe Capybara::Driver::Webkit::Browser do
|
@@ -22,5 +23,13 @@ describe Capybara::Driver::Webkit::Browser do
|
|
22
23
|
new_browser.server_port.should_not == browser.server_port
|
23
24
|
end
|
24
25
|
end
|
26
|
+
|
27
|
+
it 'forwards stdout to the given IO object' do
|
28
|
+
io = StringIO.new
|
29
|
+
new_browser = Capybara::Driver::Webkit::Browser.new(:stdout => io)
|
30
|
+
new_browser.execute_script('console.log("hello world")')
|
31
|
+
sleep(0.5)
|
32
|
+
io.string.should == "hello world\n"
|
33
|
+
end
|
25
34
|
|
26
35
|
end
|
data/spec/driver_spec.rb
CHANGED
@@ -267,6 +267,7 @@ describe Capybara::Driver::Webkit do
|
|
267
267
|
<html><body>
|
268
268
|
<form action="/" method="GET">
|
269
269
|
<input type="text" name="foo" value="bar"/>
|
270
|
+
<input type="text" name="maxlength_foo" value="bar" maxlength="10"/>
|
270
271
|
<input type="text" id="disabled_input" disabled="disabled"/>
|
271
272
|
<input type="checkbox" name="checkedbox" value="1" checked="checked"/>
|
272
273
|
<input type="checkbox" name="uncheckedbox" value="2"/>
|
@@ -312,6 +313,24 @@ describe Capybara::Driver::Webkit do
|
|
312
313
|
input.value.should == "newvalue"
|
313
314
|
end
|
314
315
|
|
316
|
+
it "sets an input's value greater than the max length" do
|
317
|
+
input = subject.find("//input[@name='maxlength_foo']").first
|
318
|
+
input.set("allegories (poems)")
|
319
|
+
input.value.should == "allegories"
|
320
|
+
end
|
321
|
+
|
322
|
+
it "sets an input's value equal to the max length" do
|
323
|
+
input = subject.find("//input[@name='maxlength_foo']").first
|
324
|
+
input.set("allegories")
|
325
|
+
input.value.should == "allegories"
|
326
|
+
end
|
327
|
+
|
328
|
+
it "sets an input's value less than the max length" do
|
329
|
+
input = subject.find("//input[@name='maxlength_foo']").first
|
330
|
+
input.set("poems")
|
331
|
+
input.value.should == "poems"
|
332
|
+
end
|
333
|
+
|
315
334
|
it "sets an input's nil value" do
|
316
335
|
input = subject.find("//input").first
|
317
336
|
input.set(nil)
|
@@ -6,18 +6,15 @@ describe Capybara::Driver::Webkit do
|
|
6
6
|
@driver = Capybara::Driver::Webkit.new(TestApp, :browser => $webkit_browser)
|
7
7
|
end
|
8
8
|
|
9
|
-
|
10
|
-
# it_should_behave_like "driver"
|
11
|
-
|
9
|
+
it_should_behave_like "driver"
|
12
10
|
it_should_behave_like "driver with javascript support"
|
13
11
|
it_should_behave_like "driver with cookies support"
|
14
|
-
|
12
|
+
it_should_behave_like "driver with header support"
|
13
|
+
it_should_behave_like "driver with status code support"
|
14
|
+
it_should_behave_like "driver with frame support"
|
15
|
+
|
15
16
|
it "returns the rack server port" do
|
16
17
|
@driver.server_port.should eq(@driver.instance_variable_get(:@rack_server).port)
|
17
18
|
end
|
18
19
|
|
19
|
-
# Can't support:
|
20
|
-
# it_should_behave_like "driver with header support"
|
21
|
-
# it_should_behave_like "driver with status code support"
|
22
|
-
# it_should_behave_like "driver with frame support"
|
23
20
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -18,7 +18,7 @@ end
|
|
18
18
|
require File.join(spec_dir,"spec_helper")
|
19
19
|
|
20
20
|
require 'capybara/driver/webkit/browser'
|
21
|
-
$webkit_browser = Capybara::Driver::Webkit::Browser.new(:socket_class => TCPSocket)
|
21
|
+
$webkit_browser = Capybara::Driver::Webkit::Browser.new(:socket_class => TCPSocket, :stdout => nil)
|
22
22
|
|
23
23
|
Capybara.register_driver :reusable_webkit do |app|
|
24
24
|
Capybara::Driver::Webkit.new(app, :browser => $webkit_browser)
|
data/src/Connection.cpp
CHANGED
data/src/Headers.cpp
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
#include "Headers.h"
|
2
|
+
#include "WebPage.h"
|
3
|
+
|
4
|
+
Headers::Headers(WebPage *page, QObject *parent) : Command(page, parent) {
|
5
|
+
}
|
6
|
+
|
7
|
+
void Headers::start(QStringList &arguments) {
|
8
|
+
Q_UNUSED(arguments);
|
9
|
+
emit finished(new Response(true, page()->pageHeaders()));
|
10
|
+
}
|
11
|
+
|
data/src/Headers.h
ADDED
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
data/src/WebPage.cpp
CHANGED
@@ -10,7 +10,9 @@ WebPage::WebPage(QObject *parent) : QWebPage(parent) {
|
|
10
10
|
|
11
11
|
m_loading = false;
|
12
12
|
|
13
|
-
|
13
|
+
NetworkAccessManager *manager = new NetworkAccessManager();
|
14
|
+
this->setNetworkAccessManager(manager);
|
15
|
+
connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(replyFinished(QNetworkReply *)));
|
14
16
|
|
15
17
|
connect(this, SIGNAL(loadStarted()), this, SLOT(loadStarted()));
|
16
18
|
connect(this, SIGNAL(loadFinished(bool)), this, SLOT(loadFinished(bool)));
|
@@ -164,3 +166,24 @@ bool WebPage::extension(Extension extension, const ExtensionOption *option, Exte
|
|
164
166
|
QString WebPage::getLastAttachedFileName() {
|
165
167
|
return currentFrame()->evaluateJavaScript(QString("Capybara.lastAttachedFile")).toString();
|
166
168
|
}
|
169
|
+
|
170
|
+
void WebPage::replyFinished(QNetworkReply *reply) {
|
171
|
+
QStringList headers;
|
172
|
+
lastStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
173
|
+
QList<QByteArray> list = reply->rawHeaderList();
|
174
|
+
|
175
|
+
int length = list.size();
|
176
|
+
for(int i = 0; i < length; i++) {
|
177
|
+
headers << list.at(i)+": "+reply->rawHeader(list.at(i));
|
178
|
+
}
|
179
|
+
|
180
|
+
m_pageHeaders = headers.join("\n");
|
181
|
+
}
|
182
|
+
|
183
|
+
int WebPage::getLastStatus() {
|
184
|
+
return lastStatus;
|
185
|
+
}
|
186
|
+
|
187
|
+
QString WebPage::pageHeaders() {
|
188
|
+
return m_pageHeaders;
|
189
|
+
}
|
data/src/WebPage.h
CHANGED
@@ -10,6 +10,7 @@ class WebPage : public QWebPage {
|
|
10
10
|
QString failureString();
|
11
11
|
QString userAgentForUrl(const QUrl &url ) const;
|
12
12
|
void setUserAgent(QString userAgent);
|
13
|
+
int getLastStatus();
|
13
14
|
bool render(const QString &fileName);
|
14
15
|
virtual bool extension (Extension extension, const ExtensionOption *option=0, ExtensionReturn *output=0);
|
15
16
|
|
@@ -19,7 +20,9 @@ class WebPage : public QWebPage {
|
|
19
20
|
void loadStarted();
|
20
21
|
void loadFinished(bool);
|
21
22
|
bool isLoading() const;
|
23
|
+
QString pageHeaders();
|
22
24
|
void frameCreated(QWebFrame *);
|
25
|
+
void replyFinished(QNetworkReply *reply);
|
23
26
|
|
24
27
|
protected:
|
25
28
|
virtual void javaScriptConsoleMessage(const QString &message, int lineNumber, const QString &sourceID);
|
@@ -35,5 +38,7 @@ class WebPage : public QWebPage {
|
|
35
38
|
QString getLastAttachedFileName();
|
36
39
|
void loadJavascript();
|
37
40
|
void setUserStylesheet();
|
41
|
+
int lastStatus;
|
42
|
+
QString m_pageHeaders;
|
38
43
|
};
|
39
44
|
|
data/src/capybara.js
CHANGED
@@ -105,7 +105,14 @@ Capybara = {
|
|
105
105
|
if (type == "text" || type == "textarea" || type == "password") {
|
106
106
|
this.trigger(index, "focus");
|
107
107
|
node.value = "";
|
108
|
-
var
|
108
|
+
var maxLength = this.attribute(index, "maxlength"),
|
109
|
+
length;
|
110
|
+
if (maxLength && value.length > maxLength) {
|
111
|
+
length = maxLength;
|
112
|
+
} else {
|
113
|
+
length = value.length;
|
114
|
+
}
|
115
|
+
|
109
116
|
for(var strindex = 0; strindex < length; strindex++) {
|
110
117
|
node.value += value[strindex];
|
111
118
|
this.trigger(index, "keydown");
|
data/src/find_command.h
CHANGED
data/src/main.cpp
CHANGED
@@ -1,8 +1,18 @@
|
|
1
1
|
#include "Server.h"
|
2
2
|
#include <QtGui>
|
3
3
|
#include <iostream>
|
4
|
+
#ifdef Q_OS_UNIX
|
5
|
+
#include <unistd.h>
|
6
|
+
#endif
|
4
7
|
|
5
8
|
int main(int argc, char **argv) {
|
9
|
+
#ifdef Q_OS_UNIX
|
10
|
+
if (setpgid(0, 0) < 0) {
|
11
|
+
std::cerr << "Unable to set new process group." << std::endl;
|
12
|
+
return 1;
|
13
|
+
}
|
14
|
+
#endif
|
15
|
+
|
6
16
|
QApplication app(argc, argv);
|
7
17
|
app.setApplicationName("capybara-webkit");
|
8
18
|
app.setOrganizationName("thoughtbot, inc");
|
data/src/webkit_server.pro
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
TEMPLATE = app
|
2
2
|
TARGET = webkit_server
|
3
3
|
DESTDIR = .
|
4
|
-
HEADERS = WebPage.h Server.h Connection.h Command.h Visit.h Find.h Reset.h Node.h JavascriptInvocation.h Url.h Source.h Evaluate.h Execute.h FrameFocus.h Response.h NetworkAccessManager.h Header.h Render.h body.h
|
5
|
-
SOURCES = main.cpp WebPage.cpp Server.cpp Connection.cpp Command.cpp Visit.cpp Find.cpp Reset.cpp Node.cpp JavascriptInvocation.cpp Url.cpp Source.cpp Evaluate.cpp Execute.cpp FrameFocus.cpp Response.cpp NetworkAccessManager.cpp Header.cpp Render.cpp body.cpp
|
4
|
+
HEADERS = WebPage.h Server.h Connection.h Command.h Visit.h Find.h Reset.h Node.h JavascriptInvocation.h Url.h Source.h Evaluate.h Execute.h FrameFocus.h Response.h NetworkAccessManager.h Header.h Render.h body.h Status.h Headers.h
|
5
|
+
SOURCES = main.cpp WebPage.cpp Server.cpp Connection.cpp Command.cpp Visit.cpp Find.cpp Reset.cpp Node.cpp JavascriptInvocation.cpp Url.cpp Source.cpp Evaluate.cpp Execute.cpp FrameFocus.cpp Response.cpp NetworkAccessManager.cpp Header.cpp Render.cpp body.cpp Status.cpp Headers.cpp
|
6
6
|
RESOURCES = webkit_server.qrc
|
7
7
|
QT += network webkit
|
8
8
|
CONFIG += console
|
metadata
CHANGED
@@ -1,13 +1,8 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capybara-webkit
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 7
|
5
4
|
prerelease:
|
6
|
-
|
7
|
-
- 0
|
8
|
-
- 6
|
9
|
-
- 0
|
10
|
-
version: 0.6.0
|
5
|
+
version: 0.6.1
|
11
6
|
platform: ruby
|
12
7
|
authors:
|
13
8
|
- thoughtbot
|
@@ -30,25 +25,20 @@ autorequire:
|
|
30
25
|
bindir: bin
|
31
26
|
cert_chain: []
|
32
27
|
|
33
|
-
date: 2011-08-
|
28
|
+
date: 2011-08-25 00:00:00 -04:00
|
34
29
|
default_executable:
|
35
30
|
dependencies:
|
36
31
|
- !ruby/object:Gem::Dependency
|
37
|
-
|
32
|
+
name: capybara
|
33
|
+
prerelease: false
|
38
34
|
requirement: &id001 !ruby/object:Gem::Requirement
|
39
35
|
none: false
|
40
36
|
requirements:
|
41
37
|
- - ~>
|
42
38
|
- !ruby/object:Gem::Version
|
43
|
-
hash: 23
|
44
|
-
segments:
|
45
|
-
- 1
|
46
|
-
- 0
|
47
|
-
- 0
|
48
39
|
version: 1.0.0
|
40
|
+
type: :runtime
|
49
41
|
version_requirements: *id001
|
50
|
-
name: capybara
|
51
|
-
prerelease: false
|
52
42
|
description:
|
53
43
|
email: support@thoughtbot.com
|
54
44
|
executables: []
|
@@ -96,6 +86,8 @@ files:
|
|
96
86
|
- src/FrameFocus.h
|
97
87
|
- src/Header.cpp
|
98
88
|
- src/Header.h
|
89
|
+
- src/Headers.cpp
|
90
|
+
- src/Headers.h
|
99
91
|
- src/JavascriptInvocation.cpp
|
100
92
|
- src/JavascriptInvocation.h
|
101
93
|
- src/NetworkAccessManager.cpp
|
@@ -112,6 +104,8 @@ files:
|
|
112
104
|
- src/Server.h
|
113
105
|
- src/Source.cpp
|
114
106
|
- src/Source.h
|
107
|
+
- src/Status.cpp
|
108
|
+
- src/Status.h
|
115
109
|
- src/Url.cpp
|
116
110
|
- src/Url.h
|
117
111
|
- src/Visit.cpp
|
@@ -141,23 +135,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
141
135
|
requirements:
|
142
136
|
- - ">="
|
143
137
|
- !ruby/object:Gem::Version
|
144
|
-
hash: 3
|
145
|
-
segments:
|
146
|
-
- 0
|
147
138
|
version: "0"
|
148
139
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
149
140
|
none: false
|
150
141
|
requirements:
|
151
142
|
- - ">="
|
152
143
|
- !ruby/object:Gem::Version
|
153
|
-
hash: 3
|
154
|
-
segments:
|
155
|
-
- 0
|
156
144
|
version: "0"
|
157
145
|
requirements: []
|
158
146
|
|
159
147
|
rubyforge_project:
|
160
|
-
rubygems_version: 1.6.
|
148
|
+
rubygems_version: 1.6.2
|
161
149
|
signing_key:
|
162
150
|
specification_version: 3
|
163
151
|
summary: Headless Webkit driver for Capybara
|