capybara-webkit 0.12.1 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -1
- data/GOALS +9 -0
- data/Gemfile.lock +15 -12
- data/LICENSE +1 -1
- data/NEWS.md +18 -0
- data/README.md +81 -2
- data/capybara-webkit.gemspec +1 -1
- data/lib/capybara/webkit.rb +11 -6
- data/lib/capybara/{driver/webkit → webkit}/browser.rb +90 -4
- data/lib/capybara/{driver/webkit → webkit}/connection.rb +48 -47
- data/lib/capybara/{driver/webkit → webkit}/cookie_jar.rb +1 -1
- data/lib/capybara/webkit/driver.rb +186 -0
- data/lib/capybara/webkit/errors.rb +10 -0
- data/lib/capybara/{driver/webkit → webkit}/node.rb +12 -4
- data/lib/capybara/{driver/webkit → webkit}/socket_debugger.rb +4 -1
- data/lib/capybara/{driver/webkit → webkit}/version.rb +1 -1
- data/lib/capybara_webkit_builder.rb +17 -3
- data/spec/browser_spec.rb +95 -7
- data/spec/connection_spec.rb +16 -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 +1200 -822
- data/spec/integration/driver_spec.rb +4 -3
- data/spec/selenium_compatibility_spec.rb +49 -0
- data/spec/spec_helper.rb +14 -6
- data/spec/support/app_runner.rb +94 -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/ClearPromptText.cpp +11 -0
- data/src/ClearPromptText.h +9 -0
- data/src/Command.cpp +4 -15
- data/src/Command.h +3 -14
- data/src/CommandFactory.cpp +20 -6
- data/src/CommandFactory.h +3 -2
- data/src/CommandParser.cpp +1 -1
- data/src/Connection.cpp +22 -21
- data/src/Connection.h +5 -6
- data/src/ConsoleMessages.cpp +2 -1
- data/src/ConsoleMessages.h +3 -5
- data/src/CurrentUrl.cpp +9 -48
- data/src/CurrentUrl.h +8 -8
- 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/GetTimeout.cpp +9 -0
- data/src/GetTimeout.h +11 -0
- 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 +8 -2
- data/src/Headers.h +3 -5
- data/src/IgnoreSslErrors.cpp +4 -3
- data/src/IgnoreSslErrors.h +3 -5
- data/src/JavascriptAlertMessages.cpp +10 -0
- data/src/JavascriptAlertMessages.h +9 -0
- data/src/JavascriptConfirmMessages.cpp +10 -0
- data/src/JavascriptConfirmMessages.h +9 -0
- data/src/JavascriptInvocation.cpp +1 -1
- data/src/JavascriptInvocation.h +1 -1
- data/src/JavascriptPromptMessages.cpp +10 -0
- data/src/JavascriptPromptMessages.h +9 -0
- data/src/NetworkAccessManager.cpp +38 -5
- data/src/NetworkAccessManager.h +20 -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/Response.cpp +4 -0
- data/src/Response.h +1 -0
- data/src/Server.cpp +2 -3
- data/src/Server.h +0 -2
- data/src/SetConfirmAction.cpp +11 -0
- data/src/SetConfirmAction.h +9 -0
- data/src/SetCookie.cpp +3 -4
- data/src/SetCookie.h +3 -5
- data/src/SetPromptAction.cpp +11 -0
- data/src/SetPromptAction.h +9 -0
- data/src/SetPromptText.cpp +11 -0
- data/src/SetPromptText.h +9 -0
- data/src/SetProxy.cpp +2 -1
- data/src/SetProxy.h +3 -5
- data/src/SetSkipImageLoading.cpp +12 -0
- data/src/SetSkipImageLoading.h +9 -0
- data/src/SetTimeout.cpp +19 -0
- data/src/SetTimeout.h +9 -0
- data/src/SocketCommand.cpp +21 -0
- data/src/SocketCommand.h +29 -0
- data/src/Source.cpp +3 -2
- data/src/Source.h +3 -4
- data/src/Status.cpp +2 -1
- data/src/Status.h +3 -5
- data/src/TimeoutCommand.cpp +69 -0
- data/src/TimeoutCommand.h +41 -0
- data/src/UnsupportedContentHandler.cpp +11 -17
- data/src/UnsupportedContentHandler.h +5 -3
- 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 +129 -44
- data/src/WebPage.h +37 -11
- data/src/WebPageManager.cpp +127 -0
- data/src/WebPageManager.h +59 -0
- data/src/WindowFocus.cpp +32 -0
- data/src/WindowFocus.h +15 -0
- data/src/body.cpp +2 -1
- data/src/capybara.js +38 -10
- data/src/find_command.h +17 -2
- data/src/main.cpp +0 -2
- data/src/webkit_server.pro +36 -0
- data/templates/Command.cpp +2 -4
- data/templates/Command.h +3 -3
- metadata +106 -27
- data/ChangeLog +0 -70
- data/lib/capybara/driver/webkit.rb +0 -136
data/.gitignore
CHANGED
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/Gemfile.lock
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
capybara-webkit (0.
|
4
|
+
capybara-webkit (0.13.0)
|
5
5
|
capybara (>= 1.0.0, < 1.2)
|
6
6
|
json
|
7
7
|
|
8
8
|
GEM
|
9
9
|
remote: http://rubygems.org/
|
10
10
|
specs:
|
11
|
+
addressable (2.3.2)
|
11
12
|
appraisal (0.4.0)
|
12
13
|
bundler
|
13
14
|
rake
|
@@ -18,18 +19,20 @@ GEM
|
|
18
19
|
rack-test (>= 0.5.4)
|
19
20
|
selenium-webdriver (~> 2.0)
|
20
21
|
xpath (~> 0.1.4)
|
21
|
-
childprocess (0.3.
|
22
|
-
ffi (~> 1.0.6)
|
22
|
+
childprocess (0.3.6)
|
23
|
+
ffi (~> 1.0, >= 1.0.6)
|
23
24
|
diff-lcs (1.1.2)
|
24
|
-
ffi (1.
|
25
|
-
json (1.7.
|
26
|
-
|
25
|
+
ffi (1.1.5)
|
26
|
+
json (1.7.5)
|
27
|
+
libwebsocket (0.1.5)
|
28
|
+
addressable
|
29
|
+
mime-types (1.19)
|
27
30
|
mini_magick (3.2.1)
|
28
31
|
subexec (~> 0.0.4)
|
29
|
-
multi_json (1.3.
|
30
|
-
nokogiri (1.5.
|
32
|
+
multi_json (1.3.6)
|
33
|
+
nokogiri (1.5.5)
|
31
34
|
rack (1.3.2)
|
32
|
-
rack-test (0.6.
|
35
|
+
rack-test (0.6.2)
|
33
36
|
rack (>= 1.0)
|
34
37
|
rake (0.9.2)
|
35
38
|
rspec (2.6.0)
|
@@ -40,10 +43,10 @@ GEM
|
|
40
43
|
rspec-expectations (2.6.0)
|
41
44
|
diff-lcs (~> 1.1.2)
|
42
45
|
rspec-mocks (2.6.0)
|
43
|
-
rubyzip (0.9.
|
44
|
-
selenium-webdriver (2.
|
46
|
+
rubyzip (0.9.9)
|
47
|
+
selenium-webdriver (2.25.0)
|
45
48
|
childprocess (>= 0.2.5)
|
46
|
-
|
49
|
+
libwebsocket (~> 0.1.3)
|
47
50
|
multi_json (~> 1.0)
|
48
51
|
rubyzip
|
49
52
|
sinatra (1.1.2)
|
data/LICENSE
CHANGED
data/NEWS.md
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
New for HEAD:
|
2
|
+
|
3
|
+
* Better detect page load success, and better handle load failures.
|
4
|
+
* HTTP Basic Auth support.
|
5
|
+
* within_window support.
|
6
|
+
* More useful and detailed debugging output.
|
7
|
+
* Catch up with recent capybara releases.
|
8
|
+
* Ignore errors from canceled requests.
|
9
|
+
* Follow how Selenium treats focus and blur form events.
|
10
|
+
* Control JavaScript prompts from Ruby.
|
11
|
+
* Each command has a configurable timeout.
|
12
|
+
* Performance improvements on Linux.
|
13
|
+
* Support empty `multiple` attributes.
|
14
|
+
|
15
|
+
New for 0.12.1:
|
16
|
+
|
17
|
+
* Fix integration with newer capybara for the debugging driver.
|
18
|
+
|
1
19
|
New for 0.12.0:
|
2
20
|
* Better windows support
|
3
21
|
* Support for localStorage
|
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
capybara-webkit
|
2
2
|
===============
|
3
3
|
|
4
|
+
[![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/thoughtbot/capybara-webkit)
|
5
|
+
|
4
6
|
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
7
|
|
6
8
|
Qt Dependency and Installation Issues
|
@@ -51,7 +53,7 @@ Set your Capybara Javascript driver to webkit:
|
|
51
53
|
|
52
54
|
In cucumber, tag scenarios with @javascript to run them using a headless WebKit browser.
|
53
55
|
|
54
|
-
In RSpec, use the :js => true flag.
|
56
|
+
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
57
|
|
56
58
|
Take note of the transactional fixtures section of the [capybara README](https://github.com/jnicklas/capybara/blob/master/README.md).
|
57
59
|
|
@@ -77,6 +79,20 @@ capybara-webkit supports a few methods that are not part of the standard capybar
|
|
77
79
|
page.driver.error_messages
|
78
80
|
=> {:source=>"http://example.com", :line_number=>1, :message=>"SyntaxError: Parse error"}
|
79
81
|
|
82
|
+
**alert_messages, confirm_messages, prompt_messages**: returns arrays of Javascript dialog messages for each dialog type
|
83
|
+
|
84
|
+
# In Javascript:
|
85
|
+
alert("HI");
|
86
|
+
confirm("Ok?");
|
87
|
+
prompt("Number?", "42");
|
88
|
+
# In Ruby:
|
89
|
+
page.driver.alert_messages
|
90
|
+
=> ["Hi"]
|
91
|
+
page.driver.confirm_messages
|
92
|
+
=> ["Ok?"]
|
93
|
+
page.driver.prompt_messages
|
94
|
+
=> ["Number?"]
|
95
|
+
|
80
96
|
**resize_window**: change the viewport size to the given width and height
|
81
97
|
|
82
98
|
page.driver.resize_window(500, 300)
|
@@ -92,6 +108,69 @@ capybara-webkit supports a few methods that are not part of the standard capybar
|
|
92
108
|
page.driver.cookies["alpha"]
|
93
109
|
=> "abc"
|
94
110
|
|
111
|
+
**accept_js_confirms!**: accept any Javascript confirm that is triggered by the page's Javascript
|
112
|
+
|
113
|
+
# In Javascript:
|
114
|
+
if (confirm("Ok?"))
|
115
|
+
console.log("Hi");
|
116
|
+
else
|
117
|
+
console.log("Bye");
|
118
|
+
# In Ruby:
|
119
|
+
page.driver.accept_js_confirms!
|
120
|
+
visit "/"
|
121
|
+
page.driver.console_messages.first[:message]
|
122
|
+
=> "Hi"
|
123
|
+
|
124
|
+
**dismiss_js_confirms!**: dismiss any Javascript confirm that is triggered by the page's Javascript
|
125
|
+
|
126
|
+
# In Javascript:
|
127
|
+
if (confirm("Ok?"))
|
128
|
+
console.log("Hi");
|
129
|
+
else
|
130
|
+
console.log("Bye");
|
131
|
+
# In Ruby:
|
132
|
+
page.driver.dismiss_js_confirms!
|
133
|
+
visit "/"
|
134
|
+
page.driver.console_messages.first[:message]
|
135
|
+
=> "Bye"
|
136
|
+
|
137
|
+
**accept_js_prompts!**: accept any Javascript prompt that is triggered by the page's Javascript
|
138
|
+
|
139
|
+
# In Javascript:
|
140
|
+
var a = prompt("Number?", "0")
|
141
|
+
console.log(a);
|
142
|
+
# In Ruby:
|
143
|
+
page.driver.accept_js_prompts!
|
144
|
+
visit "/"
|
145
|
+
page.driver.console_messages.first[:message]
|
146
|
+
=> "0"
|
147
|
+
|
148
|
+
**dismiss_js_prompts!**: dismiss any Javascript prompt that is triggered by the page's Javascript
|
149
|
+
|
150
|
+
# In Javascript:
|
151
|
+
var a = prompt("Number?", "0")
|
152
|
+
if (a != null)
|
153
|
+
console.log(a);
|
154
|
+
else
|
155
|
+
console.log("you said no"));
|
156
|
+
# In Ruby:
|
157
|
+
page.driver.dismiss_js_prompts!
|
158
|
+
visit "/"
|
159
|
+
page.driver.console_messages.first[:message]
|
160
|
+
=> "you said no"
|
161
|
+
|
162
|
+
**js_prompt_input=(value)**: set the text to use if a Javascript prompt is encountered and accepted
|
163
|
+
|
164
|
+
# In Javascript:
|
165
|
+
var a = prompt("Number?", "0")
|
166
|
+
console.log(a);
|
167
|
+
# In Ruby:
|
168
|
+
page.driver.js_prompt_input = "42"
|
169
|
+
page.driver.accept_js_prompts!
|
170
|
+
visit "/"
|
171
|
+
page.driver.console_messages.first[:message]
|
172
|
+
=> "42"
|
173
|
+
|
95
174
|
Contributing
|
96
175
|
------------
|
97
176
|
|
@@ -111,4 +190,4 @@ The names and logos for thoughtbot are trademarks of thoughtbot, inc.
|
|
111
190
|
License
|
112
191
|
-------
|
113
192
|
|
114
|
-
capybara-webkit is Copyright (c)
|
193
|
+
capybara-webkit is Copyright (c) 2010-2012 thoughtbot, inc. It is free software, and may be redistributed under the terms specified in the LICENSE file.
|
data/capybara-webkit.gemspec
CHANGED
data/lib/capybara/webkit.rb
CHANGED
@@ -1,13 +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
|
-
|
11
|
-
|
12
|
-
Capybara::Driver::Webkit.new(app, :browser => browser)
|
15
|
+
driver = Capybara::Webkit::Driver.new(app)
|
16
|
+
driver.enable_logging
|
17
|
+
driver
|
13
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
|
@@ -47,6 +55,18 @@ class Capybara::Driver::Webkit
|
|
47
55
|
end
|
48
56
|
end
|
49
57
|
|
58
|
+
def alert_messages
|
59
|
+
command("JavascriptAlertMessages").split("\n")
|
60
|
+
end
|
61
|
+
|
62
|
+
def confirm_messages
|
63
|
+
command("JavascriptConfirmMessages").split("\n")
|
64
|
+
end
|
65
|
+
|
66
|
+
def prompt_messages
|
67
|
+
command("JavascriptPromptMessages").split("\n")
|
68
|
+
end
|
69
|
+
|
50
70
|
def response_headers
|
51
71
|
Hash[command("Headers").split("\n").map { |header| header.split(": ") }]
|
52
72
|
end
|
@@ -77,6 +97,50 @@ class Capybara::Driver::Webkit
|
|
77
97
|
command("IgnoreSslErrors")
|
78
98
|
end
|
79
99
|
|
100
|
+
def set_skip_image_loading(skip_image_loading)
|
101
|
+
command("SetSkipImageLoading", skip_image_loading)
|
102
|
+
end
|
103
|
+
|
104
|
+
def window_focus(selector)
|
105
|
+
command("WindowFocus", selector)
|
106
|
+
end
|
107
|
+
|
108
|
+
def get_window_handles
|
109
|
+
JSON.parse(command('GetWindowHandles'))
|
110
|
+
end
|
111
|
+
|
112
|
+
alias_method :window_handles, :get_window_handles
|
113
|
+
|
114
|
+
def get_window_handle
|
115
|
+
command('GetWindowHandle')
|
116
|
+
end
|
117
|
+
|
118
|
+
alias_method :window_handle, :get_window_handle
|
119
|
+
|
120
|
+
def accept_js_confirms
|
121
|
+
command("SetConfirmAction", "Yes")
|
122
|
+
end
|
123
|
+
|
124
|
+
def reject_js_confirms
|
125
|
+
command("SetConfirmAction", "No")
|
126
|
+
end
|
127
|
+
|
128
|
+
def accept_js_prompts
|
129
|
+
command("SetPromptAction", "Yes")
|
130
|
+
end
|
131
|
+
|
132
|
+
def reject_js_prompts
|
133
|
+
command("SetPromptAction", "No")
|
134
|
+
end
|
135
|
+
|
136
|
+
def set_prompt_text_to(string)
|
137
|
+
command("SetPromptText", string)
|
138
|
+
end
|
139
|
+
|
140
|
+
def clear_prompt_text
|
141
|
+
command("ClearPromptText")
|
142
|
+
end
|
143
|
+
|
80
144
|
def command(name, *args)
|
81
145
|
@connection.puts name
|
82
146
|
@connection.puts args.size
|
@@ -101,6 +165,14 @@ class Capybara::Driver::Webkit
|
|
101
165
|
command "Render", path, width, height
|
102
166
|
end
|
103
167
|
|
168
|
+
def timeout=(timeout_in_seconds)
|
169
|
+
command "SetTimeout", timeout_in_seconds
|
170
|
+
end
|
171
|
+
|
172
|
+
def timeout
|
173
|
+
command("GetTimeout").to_i
|
174
|
+
end
|
175
|
+
|
104
176
|
def set_cookie(cookie)
|
105
177
|
command "SetCookie", cookie
|
106
178
|
end
|
@@ -133,14 +205,28 @@ class Capybara::Driver::Webkit
|
|
133
205
|
result.strip! if result
|
134
206
|
|
135
207
|
if result.nil?
|
136
|
-
raise
|
137
|
-
elsif result != 'ok'
|
138
|
-
|
208
|
+
raise NoResponseError, "No response received from the server."
|
209
|
+
elsif result != 'ok'
|
210
|
+
case response = read_response
|
211
|
+
when "timeout"
|
212
|
+
raise Capybara::TimeoutError, "Request timed out after #{timeout_seconds}"
|
213
|
+
else
|
214
|
+
raise InvalidResponseError, response
|
215
|
+
end
|
139
216
|
end
|
140
217
|
|
141
218
|
result
|
142
219
|
end
|
143
220
|
|
221
|
+
def timeout_seconds
|
222
|
+
seconds = timeout
|
223
|
+
if seconds > 1
|
224
|
+
"#{seconds} seconds"
|
225
|
+
else
|
226
|
+
"1 second"
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
144
230
|
def read_response
|
145
231
|
response_length = @connection.gets.to_i
|
146
232
|
if response_length > 0
|
@@ -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?
|
@@ -100,21 +112,10 @@ class Capybara::Driver::Webkit
|
|
100
112
|
|
101
113
|
def attempt_connect
|
102
114
|
@socket = @socket_class.open("127.0.0.1", @port)
|
103
|
-
|
104
|
-
|
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?
|
115
|
+
if defined?(Socket::TCP_NODELAY)
|
116
|
+
@socket.setsockopt(:IPPROTO_TCP, :TCP_NODELAY, 1)
|
117
117
|
end
|
118
|
+
rescue Errno::ECONNREFUSED
|
118
119
|
end
|
119
120
|
end
|
120
121
|
end
|