capybara-webkit 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/CONTRIBUTING.md +38 -0
- data/Gemfile +3 -2
- data/Gemfile.lock +28 -28
- data/README.md +39 -4
- data/capybara-webkit.gemspec +2 -2
- data/lib/capybara-webkit.rb +4 -0
- data/lib/capybara/driver/webkit.rb +23 -3
- data/lib/capybara/driver/webkit/browser.rb +44 -6
- data/lib/capybara/driver/webkit/node.rb +15 -4
- data/lib/capybara/driver/webkit/socket_debugger.rb +43 -0
- data/lib/capybara_webkit_builder.rb +9 -2
- data/spec/browser_spec.rb +26 -0
- data/spec/driver_rendering_spec.rb +80 -0
- data/spec/driver_spec.rb +186 -15
- data/spec/integration/driver_spec.rb +4 -0
- data/spec/integration/session_spec.rb +2 -2
- data/src/Body.h +12 -0
- data/src/Connection.cpp +5 -2
- data/src/Header.cpp +18 -0
- data/src/Header.h +11 -0
- data/src/NetworkAccessManager.cpp +22 -0
- data/src/NetworkAccessManager.h +18 -0
- data/src/Render.cpp +19 -0
- data/src/Render.h +12 -0
- data/src/Reset.cpp +3 -0
- data/src/Server.cpp +5 -2
- data/src/Server.h +1 -0
- data/src/Source.cpp +9 -2
- data/src/Source.h +7 -0
- data/src/WebPage.cpp +79 -5
- data/src/WebPage.h +9 -0
- data/src/body.cpp +11 -0
- data/src/capybara.js +19 -4
- data/src/find_command.h +3 -0
- data/src/main.cpp +2 -1
- data/src/webkit_server.pro +2 -2
- metadata +34 -9
- data/spec/support/socket_debugger.rb +0 -42
data/.gitignore
CHANGED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
We love pull requests. Here's a quick guide:
|
2
|
+
|
3
|
+
1. Fork the repo.
|
4
|
+
|
5
|
+
2. Run the tests. We only take pull requests with passing tests, and it's great
|
6
|
+
to know that you have a clean slate: `bundle && rake`
|
7
|
+
|
8
|
+
3. Add a test for your change. Only refactoring and documentation changes
|
9
|
+
require no new tests. If you are adding functionality or fixing a bug, we need
|
10
|
+
a test!
|
11
|
+
|
12
|
+
4. Make the test pass.
|
13
|
+
|
14
|
+
5. Push to your fork and submit a pull request.
|
15
|
+
|
16
|
+
|
17
|
+
At this point you're waiting on us. We like to at least comment on, if not
|
18
|
+
accept, pull requests within three business days (and, typically, one business
|
19
|
+
day). We may suggest some changes or improvements or alternatives.
|
20
|
+
|
21
|
+
Some things that will increase the chance that your pull request is accepted,
|
22
|
+
taken straight from the Ruby on Rails guide:
|
23
|
+
|
24
|
+
* Use Rails idioms and helpers
|
25
|
+
* Include tests that fail without your code, and pass with it
|
26
|
+
* Update the documentation, the surrounding one, examples elsewhere, guides,
|
27
|
+
whatever is affected by your contribution
|
28
|
+
|
29
|
+
Syntax:
|
30
|
+
|
31
|
+
* Two spaces, no tabs.
|
32
|
+
* No trailing whitespace. Blank lines should not have any space.
|
33
|
+
* Prefer &&/|| over and/or.
|
34
|
+
* MyClass.my_method(my_arg) not my_method( my_arg ) or my_method my_arg.
|
35
|
+
* a = b and not a=b.
|
36
|
+
* Follow the conventions you see used in the source already.
|
37
|
+
|
38
|
+
And in case we didn't emphasize it enough: we love tests!
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,48 +1,46 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
-
capybara (0.
|
5
|
-
celerity (>= 0.7.9)
|
6
|
-
culerity (>= 0.2.4)
|
4
|
+
capybara (1.0.0)
|
7
5
|
mime-types (>= 1.16)
|
8
6
|
nokogiri (>= 1.3.3)
|
9
7
|
rack (>= 1.0.0)
|
10
8
|
rack-test (>= 0.5.4)
|
11
|
-
selenium-webdriver (
|
12
|
-
xpath (~> 0.1.
|
13
|
-
|
14
|
-
|
15
|
-
ffi (~> 0.6.3)
|
16
|
-
culerity (0.2.15)
|
9
|
+
selenium-webdriver (~> 0.2.0)
|
10
|
+
xpath (~> 0.1.4)
|
11
|
+
childprocess (0.1.9)
|
12
|
+
ffi (~> 1.0.6)
|
17
13
|
diff-lcs (1.1.2)
|
18
|
-
ffi (0.
|
19
|
-
|
20
|
-
json_pure (1.5.1)
|
14
|
+
ffi (1.0.9)
|
15
|
+
json_pure (1.5.3)
|
21
16
|
mime-types (1.16)
|
22
|
-
|
23
|
-
|
24
|
-
|
17
|
+
mini_magick (3.2.1)
|
18
|
+
subexec (~> 0.0.4)
|
19
|
+
nokogiri (1.5.0)
|
20
|
+
rack (1.3.0)
|
21
|
+
rack-test (0.6.0)
|
25
22
|
rack (>= 1.0)
|
26
|
-
rake (0.
|
27
|
-
rspec (2.
|
28
|
-
rspec-core (~> 2.
|
29
|
-
rspec-expectations (~> 2.
|
30
|
-
rspec-mocks (~> 2.
|
31
|
-
rspec-core (2.
|
32
|
-
rspec-expectations (2.
|
23
|
+
rake (0.9.2)
|
24
|
+
rspec (2.6.0)
|
25
|
+
rspec-core (~> 2.6.0)
|
26
|
+
rspec-expectations (~> 2.6.0)
|
27
|
+
rspec-mocks (~> 2.6.0)
|
28
|
+
rspec-core (2.6.4)
|
29
|
+
rspec-expectations (2.6.0)
|
33
30
|
diff-lcs (~> 1.1.2)
|
34
|
-
rspec-mocks (2.
|
31
|
+
rspec-mocks (2.6.0)
|
35
32
|
rubyzip (0.9.4)
|
36
|
-
selenium-webdriver (0.
|
37
|
-
childprocess (
|
38
|
-
ffi (
|
33
|
+
selenium-webdriver (0.2.2)
|
34
|
+
childprocess (>= 0.1.9)
|
35
|
+
ffi (>= 1.0.7)
|
39
36
|
json_pure
|
40
37
|
rubyzip
|
41
38
|
sinatra (1.1.2)
|
42
39
|
rack (~> 1.1)
|
43
40
|
tilt (~> 1.2)
|
41
|
+
subexec (0.0.4)
|
44
42
|
tilt (1.2.2)
|
45
|
-
xpath (0.1.
|
43
|
+
xpath (0.1.4)
|
46
44
|
nokogiri (~> 1.3)
|
47
45
|
|
48
46
|
PLATFORMS
|
@@ -50,5 +48,7 @@ PLATFORMS
|
|
50
48
|
|
51
49
|
DEPENDENCIES
|
52
50
|
capybara
|
53
|
-
|
51
|
+
mini_magick
|
52
|
+
rake
|
53
|
+
rspec (~> 2.6.0)
|
54
54
|
sinatra
|
data/README.md
CHANGED
@@ -3,14 +3,36 @@ capybara-webkit
|
|
3
3
|
|
4
4
|
A [capybara](https://github.com/jnicklas/capybara) driver that uses [WebKit](http://webkit.org) via [QtWebKit](http://doc.qt.nokia.com/4.7/qtwebkit.html).
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
Dependent on Qt
|
7
|
+
---------------
|
8
8
|
|
9
9
|
capybara-webkit depends on a WebKit implementation from Qt, a cross-platform development toolkit. You'll need to download the Qt libraries to build and install the gem.
|
10
10
|
|
11
|
-
|
11
|
+
OS X Lion 10.7:
|
12
|
+
|
13
|
+
Install Qt via [homebrew](http://mxcl.github.com/homebrew/)(can take more than an hour) using:
|
14
|
+
|
15
|
+
brew install qt --build-from-source
|
16
|
+
|
17
|
+
OS X < 10.7:
|
18
|
+
|
19
|
+
[Download the non-debug Cocoa package](http://qt.nokia.com/downloads/qt-for-open-source-cpp-development-on-mac-os-x).
|
20
|
+
|
21
|
+
Ubuntu:
|
22
|
+
|
23
|
+
apt-get install libqt4-dev
|
24
|
+
|
25
|
+
Fedora:
|
26
|
+
|
27
|
+
yum install qt-webkit-devel
|
28
|
+
|
29
|
+
Gentoo Linux:
|
12
30
|
|
13
|
-
|
31
|
+
emerge x11-libs/qt-webkit
|
32
|
+
|
33
|
+
Other Linux distributions:
|
34
|
+
|
35
|
+
[Download this package](http://qt.nokia.com/downloads/linux-x11-cpp).
|
14
36
|
|
15
37
|
CI
|
16
38
|
--
|
@@ -32,15 +54,28 @@ Set your Capybara Javascript driver to webkit:
|
|
32
54
|
|
33
55
|
Tag scenarios with @javascript to run them using a headless WebKit browser.
|
34
56
|
|
57
|
+
Contributing
|
58
|
+
------------
|
59
|
+
|
60
|
+
See the CONTRIBUTING document.
|
61
|
+
|
35
62
|
About
|
36
63
|
-----
|
37
64
|
|
38
65
|
The capybara WebKit driver was written by Joe Ferris, Tristan Dunn, and Jason Morrison from [thoughtbot, inc](http://thoughtbot.com/community).
|
39
66
|
|
67
|
+
Code for rendering the current webpage to a PNG is borrowed from Phantom.js' implementation.
|
68
|
+
|
40
69
|
![thoughtbot](http://thoughtbot.com/images/tm/logo.png)
|
41
70
|
|
42
71
|
The names and logos for thoughtbot are trademarks of thoughtbot, inc.
|
43
72
|
|
73
|
+
Notes
|
74
|
+
-----
|
75
|
+
|
76
|
+
This capybara WebKit driver will listen on port 8200, this may conflict
|
77
|
+
with other services.
|
78
|
+
|
44
79
|
License
|
45
80
|
-------
|
46
81
|
|
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.
|
3
|
+
s.version = "0.6.0"
|
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",
|
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
|
|
13
13
|
s.require_path = "lib"
|
14
14
|
s.rubygems_version = "1.3.5"
|
15
15
|
s.summary = "Headless Webkit driver for Capybara"
|
16
|
-
s.add_runtime_dependency "capybara", "~> 0.
|
16
|
+
s.add_runtime_dependency "capybara", "~> 1.0.0"
|
17
17
|
s.extensions = "extconf.rb"
|
18
18
|
end
|
19
19
|
|
data/lib/capybara-webkit.rb
CHANGED
@@ -5,3 +5,7 @@ Capybara.register_driver :webkit do |app|
|
|
5
5
|
Capybara::Driver::Webkit.new(app)
|
6
6
|
end
|
7
7
|
|
8
|
+
Capybara.register_driver :webkit_debug do |app|
|
9
|
+
browser = Capybara::Driver::Webkit::Browser.new(:socket_class => Capybara::Driver::Webkit::SocketDebugger)
|
10
|
+
Capybara::Driver::Webkit.new(app, :browser => browser)
|
11
|
+
end
|
@@ -1,9 +1,13 @@
|
|
1
1
|
require "capybara"
|
2
2
|
require "capybara/driver/webkit/node"
|
3
3
|
require "capybara/driver/webkit/browser"
|
4
|
+
require "capybara/driver/webkit/socket_debugger"
|
4
5
|
|
5
6
|
class Capybara::Driver::Webkit
|
6
|
-
class
|
7
|
+
class WebkitInvalidResponseError < StandardError
|
8
|
+
end
|
9
|
+
|
10
|
+
class WebkitNoResponseError < StandardError
|
7
11
|
end
|
8
12
|
|
9
13
|
attr_reader :browser
|
@@ -33,11 +37,16 @@ class Capybara::Driver::Webkit
|
|
33
37
|
end
|
34
38
|
|
35
39
|
def body
|
36
|
-
|
40
|
+
browser.body
|
41
|
+
end
|
42
|
+
|
43
|
+
def header(key, value)
|
44
|
+
browser.header(key, value)
|
37
45
|
end
|
38
46
|
|
39
47
|
def execute_script(script)
|
40
|
-
browser.execute_script script
|
48
|
+
value = browser.execute_script script
|
49
|
+
value.empty? ? nil : value
|
41
50
|
end
|
42
51
|
|
43
52
|
def evaluate_script(script)
|
@@ -80,6 +89,17 @@ class Capybara::Driver::Webkit
|
|
80
89
|
false
|
81
90
|
end
|
82
91
|
|
92
|
+
def render(path, options={})
|
93
|
+
options[:width] ||= 1000
|
94
|
+
options[:height] ||= 10
|
95
|
+
|
96
|
+
browser.render path, options[:width], options[:height]
|
97
|
+
end
|
98
|
+
|
99
|
+
def server_port
|
100
|
+
@rack_server.port
|
101
|
+
end
|
102
|
+
|
83
103
|
private
|
84
104
|
|
85
105
|
def url(path)
|
@@ -4,6 +4,8 @@ require 'json'
|
|
4
4
|
|
5
5
|
class Capybara::Driver::Webkit
|
6
6
|
class Browser
|
7
|
+
attr :server_port
|
8
|
+
|
7
9
|
def initialize(options = {})
|
8
10
|
@socket_class = options[:socket_class] || TCPSocket
|
9
11
|
start_server
|
@@ -14,6 +16,10 @@ class Capybara::Driver::Webkit
|
|
14
16
|
command "Visit", url
|
15
17
|
end
|
16
18
|
|
19
|
+
def header(key, value)
|
20
|
+
command("Header", key, value)
|
21
|
+
end
|
22
|
+
|
17
23
|
def find(query)
|
18
24
|
command("Find", query).split(",")
|
19
25
|
end
|
@@ -22,6 +28,10 @@ class Capybara::Driver::Webkit
|
|
22
28
|
command("Reset")
|
23
29
|
end
|
24
30
|
|
31
|
+
def body
|
32
|
+
command("Body")
|
33
|
+
end
|
34
|
+
|
25
35
|
def source
|
26
36
|
command("Source")
|
27
37
|
end
|
@@ -45,7 +55,7 @@ class Capybara::Driver::Webkit
|
|
45
55
|
@socket.puts args.size
|
46
56
|
args.each do |arg|
|
47
57
|
@socket.puts arg.to_s.bytesize
|
48
|
-
@socket.print arg
|
58
|
+
@socket.print arg.to_s
|
49
59
|
end
|
50
60
|
check
|
51
61
|
read_response
|
@@ -60,12 +70,35 @@ class Capybara::Driver::Webkit
|
|
60
70
|
command('Execute', script)
|
61
71
|
end
|
62
72
|
|
73
|
+
def render(path, width, height)
|
74
|
+
command "Render", path, width, height
|
75
|
+
end
|
76
|
+
|
63
77
|
private
|
64
78
|
|
65
79
|
def start_server
|
80
|
+
read_pipe, write_pipe = fork_server
|
81
|
+
@server_port = discover_server_port(read_pipe)
|
82
|
+
end
|
83
|
+
|
84
|
+
def fork_server
|
66
85
|
server_path = File.expand_path("../../../../../bin/webkit_server", __FILE__)
|
67
|
-
|
86
|
+
|
87
|
+
read_pipe, write_pipe = IO.pipe
|
88
|
+
@pid = fork do
|
89
|
+
$stdout.reopen write_pipe
|
90
|
+
read_pipe.close
|
91
|
+
exec(server_path)
|
92
|
+
end
|
68
93
|
at_exit { Process.kill("INT", @pid) }
|
94
|
+
|
95
|
+
write_pipe.close
|
96
|
+
[read_pipe, write_pipe]
|
97
|
+
end
|
98
|
+
|
99
|
+
def discover_server_port(read_pipe)
|
100
|
+
return unless IO.select([read_pipe], nil, nil, 10)
|
101
|
+
((read_pipe.first || '').match(/listening on port: (\d+)/) || [])[1].to_i
|
69
102
|
end
|
70
103
|
|
71
104
|
def connect
|
@@ -76,16 +109,21 @@ class Capybara::Driver::Webkit
|
|
76
109
|
end
|
77
110
|
|
78
111
|
def attempt_connect
|
79
|
-
@socket = @socket_class.open("localhost",
|
112
|
+
@socket = @socket_class.open("localhost", @server_port)
|
80
113
|
rescue Errno::ECONNREFUSED
|
81
114
|
end
|
82
115
|
|
83
116
|
def check
|
84
|
-
result = @socket.gets
|
117
|
+
result = @socket.gets
|
118
|
+
result.strip! if result
|
85
119
|
|
86
|
-
|
87
|
-
raise
|
120
|
+
if result.nil?
|
121
|
+
raise WebkitNoResponseError, "No response received from the server."
|
122
|
+
elsif result != 'ok'
|
123
|
+
raise WebkitInvalidResponseError, read_response
|
88
124
|
end
|
125
|
+
|
126
|
+
result
|
89
127
|
end
|
90
128
|
|
91
129
|
def read_response
|
@@ -34,7 +34,12 @@ class Capybara::Driver::Webkit
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def unselect_option
|
37
|
-
|
37
|
+
select = find("ancestor::select").first
|
38
|
+
if select.multiple_select?
|
39
|
+
invoke "unselectOption"
|
40
|
+
else
|
41
|
+
raise Capybara::UnselectNotAllowed
|
42
|
+
end
|
38
43
|
end
|
39
44
|
|
40
45
|
def click
|
@@ -53,10 +58,18 @@ class Capybara::Driver::Webkit
|
|
53
58
|
invoke("visible") == "true"
|
54
59
|
end
|
55
60
|
|
61
|
+
def selected?
|
62
|
+
invoke("selected") == "true"
|
63
|
+
end
|
64
|
+
|
65
|
+
def checked?
|
66
|
+
self['checked']
|
67
|
+
end
|
68
|
+
|
56
69
|
def disabled?
|
57
70
|
self['disabled']
|
58
71
|
end
|
59
|
-
|
72
|
+
|
60
73
|
def path
|
61
74
|
raise Capybara::NotSupportedByDriverError
|
62
75
|
end
|
@@ -79,8 +92,6 @@ class Capybara::Driver::Webkit
|
|
79
92
|
driver.browser
|
80
93
|
end
|
81
94
|
|
82
|
-
private
|
83
|
-
|
84
95
|
def multiple_select?
|
85
96
|
self.tag_name == "select" && self["multiple"] == "multiple"
|
86
97
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# Wraps the TCP socket and prints data sent and received. Used for debugging
|
2
|
+
# the wire protocol. You can use this by passing a :socket_class to Browser.
|
3
|
+
class Capybara::Driver::Webkit
|
4
|
+
class SocketDebugger
|
5
|
+
def self.open(host, port)
|
6
|
+
real_socket = TCPSocket.open(host, port)
|
7
|
+
new(real_socket)
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(socket)
|
11
|
+
@socket = socket
|
12
|
+
end
|
13
|
+
|
14
|
+
def read(length)
|
15
|
+
received @socket.read(length)
|
16
|
+
end
|
17
|
+
|
18
|
+
def puts(line)
|
19
|
+
sent line
|
20
|
+
@socket.puts(line)
|
21
|
+
end
|
22
|
+
|
23
|
+
def print(content)
|
24
|
+
sent content
|
25
|
+
@socket.print(content)
|
26
|
+
end
|
27
|
+
|
28
|
+
def gets
|
29
|
+
received @socket.gets
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def sent(content)
|
35
|
+
Kernel.puts " >> " + content.to_s
|
36
|
+
end
|
37
|
+
|
38
|
+
def received(content)
|
39
|
+
Kernel.puts " << " + content.to_s
|
40
|
+
content
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|