otherinbox-capybara-webkit 0.12.0 → 0.12.0.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/GOALS +9 -0
- data/README.md +1 -1
- data/capybara-webkit.gemspec +1 -1
- data/lib/capybara/webkit.rb +11 -4
- data/lib/capybara/{driver/webkit → webkit}/browser.rb +27 -3
- data/lib/capybara/{driver/webkit → webkit}/connection.rb +45 -47
- data/lib/capybara/{driver/webkit → webkit}/cookie_jar.rb +1 -1
- data/lib/capybara/webkit/driver.rb +150 -0
- data/lib/capybara/webkit/errors.rb +10 -0
- data/lib/capybara/{driver/webkit → webkit}/node.rb +2 -2
- data/lib/capybara/{driver/webkit → webkit}/socket_debugger.rb +1 -1
- data/lib/capybara/{driver/webkit → webkit}/version.rb +1 -1
- data/lib/capybara_webkit_builder.rb +17 -3
- data/spec/browser_spec.rb +38 -25
- data/spec/connection_spec.rb +5 -5
- data/spec/cookie_jar_spec.rb +3 -3
- data/spec/driver_rendering_spec.rb +19 -26
- data/spec/driver_resize_window_spec.rb +3 -3
- data/spec/driver_spec.rb +907 -829
- data/spec/integration/driver_spec.rb +4 -3
- data/spec/spec_helper.rb +14 -6
- data/spec/support/app_runner.rb +91 -0
- data/src/Authenticate.cpp +18 -0
- data/src/Authenticate.h +12 -0
- data/src/Body.h +3 -5
- data/src/ClearCookies.cpp +3 -5
- data/src/ClearCookies.h +3 -5
- data/src/Command.cpp +4 -15
- data/src/Command.h +3 -14
- data/src/CommandFactory.cpp +10 -6
- data/src/CommandFactory.h +3 -2
- data/src/CommandParser.cpp +1 -1
- data/src/Connection.cpp +22 -11
- data/src/Connection.h +4 -2
- data/src/ConsoleMessages.cpp +2 -1
- data/src/ConsoleMessages.h +3 -5
- data/src/CurrentUrl.cpp +2 -1
- data/src/CurrentUrl.h +3 -5
- data/src/EnableLogging.cpp +10 -0
- data/src/EnableLogging.h +12 -0
- data/src/Evaluate.cpp +2 -1
- data/src/Evaluate.h +3 -5
- data/src/Execute.cpp +2 -1
- data/src/Execute.h +3 -5
- data/src/Find.cpp +3 -2
- data/src/Find.h +3 -5
- data/src/FrameFocus.cpp +3 -2
- data/src/FrameFocus.h +3 -4
- data/src/GetCookies.cpp +3 -4
- data/src/GetCookies.h +3 -5
- data/src/GetWindowHandle.cpp +11 -0
- data/src/GetWindowHandle.h +10 -0
- data/src/GetWindowHandles.cpp +20 -0
- data/src/GetWindowHandles.h +10 -0
- data/src/Header.cpp +2 -1
- data/src/Header.h +3 -5
- data/src/Headers.cpp +2 -1
- data/src/Headers.h +3 -5
- data/src/IgnoreSslErrors.cpp +4 -3
- data/src/IgnoreSslErrors.h +3 -5
- data/src/JavascriptInvocation.cpp +1 -1
- data/src/JavascriptInvocation.h +1 -1
- data/src/NetworkAccessManager.cpp +19 -1
- data/src/NetworkAccessManager.h +10 -0
- data/src/Node.cpp +6 -1
- data/src/Node.h +4 -5
- data/src/NullCommand.cpp +5 -2
- data/src/NullCommand.h +4 -3
- data/src/PageLoadingCommand.cpp +12 -7
- data/src/PageLoadingCommand.h +6 -9
- data/src/Render.cpp +2 -1
- data/src/Render.h +3 -5
- data/src/RequestedUrl.cpp +2 -1
- data/src/RequestedUrl.h +3 -5
- data/src/Reset.cpp +3 -17
- data/src/Reset.h +3 -8
- data/src/ResizeWindow.cpp +2 -1
- data/src/ResizeWindow.h +3 -5
- data/src/Server.cpp +2 -3
- data/src/Server.h +0 -2
- data/src/SetCookie.cpp +3 -4
- data/src/SetCookie.h +3 -5
- data/src/SetProxy.cpp +2 -1
- data/src/SetProxy.h +3 -5
- data/src/SetSkipImageLoading.cpp +3 -2
- data/src/SetSkipImageLoading.h +3 -5
- data/src/SocketCommand.cpp +21 -0
- data/src/SocketCommand.h +29 -0
- data/src/Source.cpp +2 -1
- data/src/Source.h +3 -4
- data/src/Status.cpp +2 -1
- data/src/Status.h +3 -5
- data/src/UnsupportedContentHandler.cpp +1 -1
- data/src/Url.cpp +2 -1
- data/src/Url.h +3 -5
- data/src/Visit.cpp +3 -2
- data/src/Visit.h +3 -5
- data/src/WebPage.cpp +86 -39
- data/src/WebPage.h +22 -8
- data/src/WebPageManager.cpp +117 -0
- data/src/WebPageManager.h +56 -0
- data/src/WindowFocus.cpp +32 -0
- data/src/WindowFocus.h +15 -0
- data/src/body.cpp +2 -1
- data/src/find_command.h +6 -2
- data/src/webkit_server.pro +14 -0
- data/templates/Command.cpp +2 -4
- data/templates/Command.h +3 -3
- metadata +29 -10
- data/lib/capybara/driver/webkit.rb +0 -135
data/GOALS
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
capybara-webkit hits 1.0.0 when:
|
2
|
+
|
3
|
+
* All shared examples from capybara are implemented. See
|
4
|
+
capybara:lib/capybara/spec/**/*rb for the shared example groups.
|
5
|
+
* Test failures are a result of issues in the developer's code and not
|
6
|
+
capybara-webkit.
|
7
|
+
* Test failures lead to clear explanations for what failed and what can
|
8
|
+
be done to resolve them.
|
9
|
+
* It handles iframes, cookies, page loading, and other oddities.
|
data/README.md
CHANGED
@@ -51,7 +51,7 @@ Set your Capybara Javascript driver to webkit:
|
|
51
51
|
|
52
52
|
In cucumber, tag scenarios with @javascript to run them using a headless WebKit browser.
|
53
53
|
|
54
|
-
In RSpec, use the :js => true flag.
|
54
|
+
In RSpec, use the :js => true flag. See the [capybara documention](http://rubydoc.info/gems/capybara#Using_Capybara_with_RSpec) for more information about using capybara with RSpec.
|
55
55
|
|
56
56
|
Take note of the transactional fixtures section of the [capybara README](https://github.com/jnicklas/capybara/blob/master/README.md).
|
57
57
|
|
data/capybara-webkit.gemspec
CHANGED
data/lib/capybara/webkit.rb
CHANGED
@@ -1,11 +1,18 @@
|
|
1
1
|
require "capybara"
|
2
|
-
|
2
|
+
|
3
|
+
module Capybara
|
4
|
+
module Webkit
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
require "capybara/webkit/driver"
|
3
9
|
|
4
10
|
Capybara.register_driver :webkit do |app|
|
5
|
-
Capybara::Driver
|
11
|
+
Capybara::Webkit::Driver.new(app)
|
6
12
|
end
|
7
13
|
|
8
14
|
Capybara.register_driver :webkit_debug do |app|
|
9
|
-
|
10
|
-
|
15
|
+
driver = Capybara::Webkit::Driver.new(app)
|
16
|
+
driver.enable_logging
|
17
|
+
driver
|
11
18
|
end
|
@@ -1,11 +1,19 @@
|
|
1
1
|
require 'json'
|
2
2
|
|
3
|
-
|
3
|
+
module Capybara::Webkit
|
4
4
|
class Browser
|
5
5
|
def initialize(connection)
|
6
6
|
@connection = connection
|
7
7
|
end
|
8
8
|
|
9
|
+
def authenticate(username, password)
|
10
|
+
command("Authenticate", username, password)
|
11
|
+
end
|
12
|
+
|
13
|
+
def enable_logging
|
14
|
+
command "EnableLogging"
|
15
|
+
end
|
16
|
+
|
9
17
|
def visit(url)
|
10
18
|
command "Visit", url
|
11
19
|
end
|
@@ -81,6 +89,22 @@ class Capybara::Driver::Webkit
|
|
81
89
|
command("SetSkipImageLoading", skip_image_loading)
|
82
90
|
end
|
83
91
|
|
92
|
+
def window_focus(selector)
|
93
|
+
command("WindowFocus", selector)
|
94
|
+
end
|
95
|
+
|
96
|
+
def get_window_handles
|
97
|
+
JSON.parse(command('GetWindowHandles'))
|
98
|
+
end
|
99
|
+
|
100
|
+
alias_method :window_handles, :get_window_handles
|
101
|
+
|
102
|
+
def get_window_handle
|
103
|
+
command('GetWindowHandle')
|
104
|
+
end
|
105
|
+
|
106
|
+
alias_method :window_handle, :get_window_handle
|
107
|
+
|
84
108
|
def command(name, *args)
|
85
109
|
@connection.puts name
|
86
110
|
@connection.puts args.size
|
@@ -137,9 +161,9 @@ class Capybara::Driver::Webkit
|
|
137
161
|
result.strip! if result
|
138
162
|
|
139
163
|
if result.nil?
|
140
|
-
raise
|
164
|
+
raise NoResponseError, "No response received from the server."
|
141
165
|
elsif result != 'ok'
|
142
|
-
raise
|
166
|
+
raise InvalidResponseError, read_response
|
143
167
|
end
|
144
168
|
|
145
169
|
result
|
@@ -2,17 +2,17 @@ require 'socket'
|
|
2
2
|
require 'timeout'
|
3
3
|
require 'thread'
|
4
4
|
|
5
|
-
|
5
|
+
module Capybara::Webkit
|
6
6
|
class Connection
|
7
|
+
SERVER_PATH = File.expand_path("../../../../bin/webkit_server", __FILE__)
|
7
8
|
WEBKIT_SERVER_START_TIMEOUT = 15
|
8
9
|
|
9
10
|
attr_reader :port
|
10
11
|
|
11
12
|
def initialize(options = {})
|
12
13
|
@socket_class = options[:socket_class] || TCPSocket
|
13
|
-
@stdout
|
14
|
-
|
15
|
-
$stdout
|
14
|
+
@stdout = options.has_key?(:stdout) ? options[:stdout] : $stdout
|
15
|
+
@command = options[:command] || SERVER_PATH
|
16
16
|
start_server
|
17
17
|
connect
|
18
18
|
end
|
@@ -36,52 +36,50 @@ class Capybara::Driver::Webkit
|
|
36
36
|
private
|
37
37
|
|
38
38
|
def start_server
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
Thread.current.abort_on_exception = true
|
43
|
-
forward_stdout(pipe)
|
44
|
-
end
|
39
|
+
open_pipe
|
40
|
+
discover_port
|
41
|
+
forward_stdout_in_background_thread
|
45
42
|
end
|
46
43
|
|
47
|
-
def
|
48
|
-
|
49
|
-
|
44
|
+
def open_pipe
|
45
|
+
@pipe = IO.popen(@command)
|
46
|
+
@pid = @pipe.pid
|
50
47
|
register_shutdown_hook
|
51
|
-
pipe
|
52
|
-
end
|
53
|
-
|
54
|
-
def kill_process(pid)
|
55
|
-
if RUBY_PLATFORM =~ /mingw32/
|
56
|
-
Process.kill(9, pid)
|
57
|
-
else
|
58
|
-
Process.kill("INT", pid)
|
59
|
-
end
|
60
48
|
end
|
61
49
|
|
62
50
|
def register_shutdown_hook
|
63
51
|
@owner_pid = Process.pid
|
64
52
|
at_exit do
|
65
53
|
if Process.pid == @owner_pid
|
66
|
-
kill_process
|
54
|
+
kill_process
|
67
55
|
end
|
68
56
|
end
|
69
57
|
end
|
70
58
|
|
71
|
-
def
|
72
|
-
|
73
|
-
|
74
|
-
|
59
|
+
def kill_process
|
60
|
+
if RUBY_PLATFORM =~ /mingw32/
|
61
|
+
Process.kill(9, @pid)
|
62
|
+
else
|
63
|
+
Process.kill("INT", @pid)
|
64
|
+
end
|
75
65
|
end
|
76
66
|
|
77
|
-
def discover_port
|
78
|
-
|
79
|
-
|
67
|
+
def discover_port
|
68
|
+
if IO.select([@pipe], nil, nil, WEBKIT_SERVER_START_TIMEOUT)
|
69
|
+
@port = ((@pipe.first || '').match(/listening on port: (\d+)/) || [])[1].to_i
|
70
|
+
end
|
80
71
|
end
|
81
72
|
|
82
|
-
def
|
83
|
-
|
84
|
-
|
73
|
+
def forward_stdout_in_background_thread
|
74
|
+
@stdout_thread = Thread.new do
|
75
|
+
Thread.current.abort_on_exception = true
|
76
|
+
forward_stdout
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def forward_stdout
|
81
|
+
while pipe_readable?
|
82
|
+
line = @pipe.readline
|
85
83
|
if @stdout
|
86
84
|
@stdout.write(line)
|
87
85
|
@stdout.flush
|
@@ -90,6 +88,20 @@ class Capybara::Driver::Webkit
|
|
90
88
|
rescue EOFError
|
91
89
|
end
|
92
90
|
|
91
|
+
if !defined?(RUBY_ENGINE) || (RUBY_ENGINE == "ruby" && RUBY_VERSION <= "1.8")
|
92
|
+
# please note the use of IO::select() here, as it is used specifically to
|
93
|
+
# preserve correct signal handling behavior in ruby 1.8.
|
94
|
+
# https://github.com/thibaudgg/rb-fsevent/commit/d1a868bf8dc72dbca102bedbadff76c7e6c2dc21
|
95
|
+
# https://github.com/thibaudgg/rb-fsevent/blob/1ca42b987596f350ee7b19d8f8210b7b6ae8766b/ext/fsevent/fsevent_watch.c#L171
|
96
|
+
def pipe_readable?
|
97
|
+
IO.select([@pipe])
|
98
|
+
end
|
99
|
+
else
|
100
|
+
def pipe_readable?
|
101
|
+
!@pipe.eof?
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
93
105
|
def connect
|
94
106
|
Timeout.timeout(5) do
|
95
107
|
while @socket.nil?
|
@@ -102,19 +114,5 @@ class Capybara::Driver::Webkit
|
|
102
114
|
@socket = @socket_class.open("127.0.0.1", @port)
|
103
115
|
rescue Errno::ECONNREFUSED
|
104
116
|
end
|
105
|
-
|
106
|
-
if !defined?(RUBY_ENGINE) || (RUBY_ENGINE == "ruby" && RUBY_VERSION <= "1.8")
|
107
|
-
# please note the use of IO::select() here, as it is used specifically to
|
108
|
-
# preserve correct signal handling behavior in ruby 1.8.
|
109
|
-
# https://github.com/thibaudgg/rb-fsevent/commit/d1a868bf8dc72dbca102bedbadff76c7e6c2dc21
|
110
|
-
# https://github.com/thibaudgg/rb-fsevent/blob/1ca42b987596f350ee7b19d8f8210b7b6ae8766b/ext/fsevent/fsevent_watch.c#L171
|
111
|
-
def pipe_readable?(pipe)
|
112
|
-
IO.select([pipe])
|
113
|
-
end
|
114
|
-
else
|
115
|
-
def pipe_readable?(pipe)
|
116
|
-
!pipe.eof?
|
117
|
-
end
|
118
|
-
end
|
119
117
|
end
|
120
118
|
end
|
@@ -3,7 +3,7 @@ require 'webrick'
|
|
3
3
|
# A simple cookie jar implementation.
|
4
4
|
# Does not take special cookie attributes
|
5
5
|
# into account like expire, max-age, httponly, secure
|
6
|
-
class Capybara::
|
6
|
+
class Capybara::Webkit::CookieJar
|
7
7
|
attr_reader :browser
|
8
8
|
|
9
9
|
def initialize(browser)
|
@@ -0,0 +1,150 @@
|
|
1
|
+
require "capybara"
|
2
|
+
require "capybara/webkit/version"
|
3
|
+
require "capybara/webkit/node"
|
4
|
+
require "capybara/webkit/connection"
|
5
|
+
require "capybara/webkit/browser"
|
6
|
+
require "capybara/webkit/socket_debugger"
|
7
|
+
require "capybara/webkit/cookie_jar"
|
8
|
+
require "capybara/webkit/errors"
|
9
|
+
|
10
|
+
module Capybara::Webkit
|
11
|
+
class Driver
|
12
|
+
attr_reader :browser
|
13
|
+
|
14
|
+
def initialize(app, options={})
|
15
|
+
@app = app
|
16
|
+
@options = options
|
17
|
+
@rack_server = Capybara::Server.new(@app)
|
18
|
+
@rack_server.boot if Capybara.run_server
|
19
|
+
@browser = options[:browser] || Browser.new(Connection.new(options))
|
20
|
+
end
|
21
|
+
|
22
|
+
def enable_logging
|
23
|
+
browser.enable_logging
|
24
|
+
end
|
25
|
+
|
26
|
+
def current_url
|
27
|
+
browser.current_url
|
28
|
+
end
|
29
|
+
|
30
|
+
def requested_url
|
31
|
+
browser.requested_url
|
32
|
+
end
|
33
|
+
|
34
|
+
def visit(path)
|
35
|
+
browser.visit(url(path))
|
36
|
+
end
|
37
|
+
|
38
|
+
def find(query)
|
39
|
+
browser.find(query).map { |native| Node.new(self, native) }
|
40
|
+
end
|
41
|
+
|
42
|
+
def source
|
43
|
+
browser.source
|
44
|
+
end
|
45
|
+
|
46
|
+
def body
|
47
|
+
browser.body
|
48
|
+
end
|
49
|
+
|
50
|
+
def header(key, value)
|
51
|
+
browser.header(key, value)
|
52
|
+
end
|
53
|
+
|
54
|
+
def execute_script(script)
|
55
|
+
value = browser.execute_script script
|
56
|
+
value.empty? ? nil : value
|
57
|
+
end
|
58
|
+
|
59
|
+
def evaluate_script(script)
|
60
|
+
browser.evaluate_script script
|
61
|
+
end
|
62
|
+
|
63
|
+
def console_messages
|
64
|
+
browser.console_messages
|
65
|
+
end
|
66
|
+
|
67
|
+
def error_messages
|
68
|
+
browser.error_messages
|
69
|
+
end
|
70
|
+
|
71
|
+
def response_headers
|
72
|
+
browser.response_headers
|
73
|
+
end
|
74
|
+
|
75
|
+
def status_code
|
76
|
+
browser.status_code
|
77
|
+
end
|
78
|
+
|
79
|
+
def resize_window(width, height)
|
80
|
+
browser.resize_window(width, height)
|
81
|
+
end
|
82
|
+
|
83
|
+
def within_frame(frame_id_or_index)
|
84
|
+
browser.frame_focus(frame_id_or_index)
|
85
|
+
begin
|
86
|
+
yield
|
87
|
+
ensure
|
88
|
+
browser.frame_focus
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def within_window(selector)
|
93
|
+
current_window = window_handle
|
94
|
+
browser.window_focus(selector)
|
95
|
+
begin
|
96
|
+
yield
|
97
|
+
ensure
|
98
|
+
browser.window_focus(current_window)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def window_handles
|
103
|
+
browser.get_window_handles
|
104
|
+
end
|
105
|
+
|
106
|
+
def window_handle
|
107
|
+
browser.get_window_handle
|
108
|
+
end
|
109
|
+
|
110
|
+
def wait?
|
111
|
+
true
|
112
|
+
end
|
113
|
+
|
114
|
+
def wait_until(*args)
|
115
|
+
end
|
116
|
+
|
117
|
+
def reset!
|
118
|
+
browser.reset!
|
119
|
+
end
|
120
|
+
|
121
|
+
def has_shortcircuit_timeout?
|
122
|
+
false
|
123
|
+
end
|
124
|
+
|
125
|
+
def render(path, options={})
|
126
|
+
options[:width] ||= 1000
|
127
|
+
options[:height] ||= 10
|
128
|
+
|
129
|
+
browser.render path, options[:width], options[:height]
|
130
|
+
end
|
131
|
+
|
132
|
+
def server_port
|
133
|
+
@rack_server.port
|
134
|
+
end
|
135
|
+
|
136
|
+
def cookies
|
137
|
+
@cookie_jar ||= CookieJar.new(browser)
|
138
|
+
end
|
139
|
+
|
140
|
+
def invalid_element_errors
|
141
|
+
[]
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def url(path)
|
147
|
+
@rack_server.url(path)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
module Capybara::Webkit
|
2
2
|
class Node < Capybara::Driver::Node
|
3
3
|
NBSP = "\xC2\xA0"
|
4
4
|
NBSP.force_encoding("UTF-8") if NBSP.respond_to?(:force_encoding)
|
@@ -91,7 +91,7 @@ class Capybara::Driver::Webkit
|
|
91
91
|
if allow_unattached_nodes? || attached?
|
92
92
|
browser.command "Node", name, native, *args
|
93
93
|
else
|
94
|
-
raise Capybara::
|
94
|
+
raise Capybara::Webkit::NodeNotAttachedError
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# Wraps the TCP socket and prints data sent and received. Used for debugging
|
2
2
|
# the wire protocol. You can use this by passing a :socket_class to Browser.
|
3
|
-
|
3
|
+
module Capybara::Webkit
|
4
4
|
class SocketDebugger
|
5
5
|
def self.open(host, port)
|
6
6
|
real_socket = TCPSocket.open(host, port)
|