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.
Files changed (141) hide show
  1. data/.gitignore +2 -1
  2. data/GOALS +9 -0
  3. data/Gemfile.lock +15 -12
  4. data/LICENSE +1 -1
  5. data/NEWS.md +18 -0
  6. data/README.md +81 -2
  7. data/capybara-webkit.gemspec +1 -1
  8. data/lib/capybara/webkit.rb +11 -6
  9. data/lib/capybara/{driver/webkit → webkit}/browser.rb +90 -4
  10. data/lib/capybara/{driver/webkit → webkit}/connection.rb +48 -47
  11. data/lib/capybara/{driver/webkit → webkit}/cookie_jar.rb +1 -1
  12. data/lib/capybara/webkit/driver.rb +186 -0
  13. data/lib/capybara/webkit/errors.rb +10 -0
  14. data/lib/capybara/{driver/webkit → webkit}/node.rb +12 -4
  15. data/lib/capybara/{driver/webkit → webkit}/socket_debugger.rb +4 -1
  16. data/lib/capybara/{driver/webkit → webkit}/version.rb +1 -1
  17. data/lib/capybara_webkit_builder.rb +17 -3
  18. data/spec/browser_spec.rb +95 -7
  19. data/spec/connection_spec.rb +16 -5
  20. data/spec/cookie_jar_spec.rb +3 -3
  21. data/spec/driver_rendering_spec.rb +19 -26
  22. data/spec/driver_resize_window_spec.rb +3 -3
  23. data/spec/driver_spec.rb +1200 -822
  24. data/spec/integration/driver_spec.rb +4 -3
  25. data/spec/selenium_compatibility_spec.rb +49 -0
  26. data/spec/spec_helper.rb +14 -6
  27. data/spec/support/app_runner.rb +94 -0
  28. data/src/Authenticate.cpp +18 -0
  29. data/src/Authenticate.h +12 -0
  30. data/src/Body.h +3 -5
  31. data/src/ClearCookies.cpp +3 -5
  32. data/src/ClearCookies.h +3 -5
  33. data/src/ClearPromptText.cpp +11 -0
  34. data/src/ClearPromptText.h +9 -0
  35. data/src/Command.cpp +4 -15
  36. data/src/Command.h +3 -14
  37. data/src/CommandFactory.cpp +20 -6
  38. data/src/CommandFactory.h +3 -2
  39. data/src/CommandParser.cpp +1 -1
  40. data/src/Connection.cpp +22 -21
  41. data/src/Connection.h +5 -6
  42. data/src/ConsoleMessages.cpp +2 -1
  43. data/src/ConsoleMessages.h +3 -5
  44. data/src/CurrentUrl.cpp +9 -48
  45. data/src/CurrentUrl.h +8 -8
  46. data/src/EnableLogging.cpp +10 -0
  47. data/src/EnableLogging.h +12 -0
  48. data/src/Evaluate.cpp +2 -1
  49. data/src/Evaluate.h +3 -5
  50. data/src/Execute.cpp +2 -1
  51. data/src/Execute.h +3 -5
  52. data/src/Find.cpp +3 -2
  53. data/src/Find.h +3 -5
  54. data/src/FrameFocus.cpp +3 -2
  55. data/src/FrameFocus.h +3 -4
  56. data/src/GetCookies.cpp +3 -4
  57. data/src/GetCookies.h +3 -5
  58. data/src/GetTimeout.cpp +9 -0
  59. data/src/GetTimeout.h +11 -0
  60. data/src/GetWindowHandle.cpp +11 -0
  61. data/src/GetWindowHandle.h +10 -0
  62. data/src/GetWindowHandles.cpp +20 -0
  63. data/src/GetWindowHandles.h +10 -0
  64. data/src/Header.cpp +2 -1
  65. data/src/Header.h +3 -5
  66. data/src/Headers.cpp +8 -2
  67. data/src/Headers.h +3 -5
  68. data/src/IgnoreSslErrors.cpp +4 -3
  69. data/src/IgnoreSslErrors.h +3 -5
  70. data/src/JavascriptAlertMessages.cpp +10 -0
  71. data/src/JavascriptAlertMessages.h +9 -0
  72. data/src/JavascriptConfirmMessages.cpp +10 -0
  73. data/src/JavascriptConfirmMessages.h +9 -0
  74. data/src/JavascriptInvocation.cpp +1 -1
  75. data/src/JavascriptInvocation.h +1 -1
  76. data/src/JavascriptPromptMessages.cpp +10 -0
  77. data/src/JavascriptPromptMessages.h +9 -0
  78. data/src/NetworkAccessManager.cpp +38 -5
  79. data/src/NetworkAccessManager.h +20 -0
  80. data/src/Node.cpp +6 -1
  81. data/src/Node.h +4 -5
  82. data/src/NullCommand.cpp +5 -2
  83. data/src/NullCommand.h +4 -3
  84. data/src/PageLoadingCommand.cpp +12 -7
  85. data/src/PageLoadingCommand.h +6 -9
  86. data/src/Render.cpp +2 -1
  87. data/src/Render.h +3 -5
  88. data/src/RequestedUrl.cpp +2 -1
  89. data/src/RequestedUrl.h +3 -5
  90. data/src/Reset.cpp +3 -17
  91. data/src/Reset.h +3 -8
  92. data/src/ResizeWindow.cpp +2 -1
  93. data/src/ResizeWindow.h +3 -5
  94. data/src/Response.cpp +4 -0
  95. data/src/Response.h +1 -0
  96. data/src/Server.cpp +2 -3
  97. data/src/Server.h +0 -2
  98. data/src/SetConfirmAction.cpp +11 -0
  99. data/src/SetConfirmAction.h +9 -0
  100. data/src/SetCookie.cpp +3 -4
  101. data/src/SetCookie.h +3 -5
  102. data/src/SetPromptAction.cpp +11 -0
  103. data/src/SetPromptAction.h +9 -0
  104. data/src/SetPromptText.cpp +11 -0
  105. data/src/SetPromptText.h +9 -0
  106. data/src/SetProxy.cpp +2 -1
  107. data/src/SetProxy.h +3 -5
  108. data/src/SetSkipImageLoading.cpp +12 -0
  109. data/src/SetSkipImageLoading.h +9 -0
  110. data/src/SetTimeout.cpp +19 -0
  111. data/src/SetTimeout.h +9 -0
  112. data/src/SocketCommand.cpp +21 -0
  113. data/src/SocketCommand.h +29 -0
  114. data/src/Source.cpp +3 -2
  115. data/src/Source.h +3 -4
  116. data/src/Status.cpp +2 -1
  117. data/src/Status.h +3 -5
  118. data/src/TimeoutCommand.cpp +69 -0
  119. data/src/TimeoutCommand.h +41 -0
  120. data/src/UnsupportedContentHandler.cpp +11 -17
  121. data/src/UnsupportedContentHandler.h +5 -3
  122. data/src/Url.cpp +2 -1
  123. data/src/Url.h +3 -5
  124. data/src/Visit.cpp +3 -2
  125. data/src/Visit.h +3 -5
  126. data/src/WebPage.cpp +129 -44
  127. data/src/WebPage.h +37 -11
  128. data/src/WebPageManager.cpp +127 -0
  129. data/src/WebPageManager.h +59 -0
  130. data/src/WindowFocus.cpp +32 -0
  131. data/src/WindowFocus.h +15 -0
  132. data/src/body.cpp +2 -1
  133. data/src/capybara.js +38 -10
  134. data/src/find_command.h +17 -2
  135. data/src/main.cpp +0 -2
  136. data/src/webkit_server.pro +36 -0
  137. data/templates/Command.cpp +2 -4
  138. data/templates/Command.h +3 -3
  139. metadata +106 -27
  140. data/ChangeLog +0 -70
  141. data/lib/capybara/driver/webkit.rb +0 -136
data/.gitignore CHANGED
@@ -16,4 +16,5 @@ src/webkit_server.exe
16
16
  .DS_Store
17
17
  tmp
18
18
  .rvmrc
19
- src/debug
19
+ src/debug
20
+ webkit_server.pro.user
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.
@@ -1,13 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- capybara-webkit (0.12.1)
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.1)
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.0.11)
25
- json (1.7.1)
26
- mime-types (1.18)
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.2)
30
- nokogiri (1.5.2)
32
+ multi_json (1.3.6)
33
+ nokogiri (1.5.5)
31
34
  rack (1.3.2)
32
- rack-test (0.6.1)
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.7)
44
- selenium-webdriver (2.20.0)
46
+ rubyzip (0.9.9)
47
+ selenium-webdriver (2.25.0)
45
48
  childprocess (>= 0.2.5)
46
- ffi (~> 1.0)
49
+ libwebsocket (~> 0.1.3)
47
50
  multi_json (~> 1.0)
48
51
  rubyzip
49
52
  sinatra (1.1.2)
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2011 thoughtbot, inc.
1
+ Copyright (c) 2010-2012 thoughtbot, inc.
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
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) 2011 thoughtbot, inc. It is free software, and may be redistributed under the terms specified in the LICENSE file.
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.
@@ -1,5 +1,5 @@
1
1
  $:.push File.expand_path("../lib", __FILE__)
2
- require "capybara/driver/webkit/version"
2
+ require "capybara/webkit/version"
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "capybara-webkit"
@@ -1,13 +1,18 @@
1
1
  require "capybara"
2
- require "capybara/driver/webkit"
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::Webkit.new(app)
11
+ Capybara::Webkit::Driver.new(app)
6
12
  end
7
13
 
8
14
  Capybara.register_driver :webkit_debug do |app|
9
- connection = Capybara::Driver::Webkit::Connection.new(
10
- :socket_class => Capybara::Driver::Webkit::SocketDebugger)
11
- browser = Capybara::Driver::Webkit::Browser.new(connection)
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
- class Capybara::Driver::Webkit
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 WebkitNoResponseError, "No response received from the server."
137
- elsif result != 'ok'
138
- raise WebkitInvalidResponseError, read_response
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
- class Capybara::Driver::Webkit
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 = options.has_key?(:stdout) ?
14
- options[:stdout] :
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
- pipe = fork_server
40
- @port = discover_port(pipe)
41
- @stdout_thread = Thread.new do
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 fork_server
48
- server_path = File.expand_path("../../../../../bin/webkit_server", __FILE__)
49
- pipe, @pid = server_pipe_and_pid(server_path)
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(@pid)
54
+ kill_process
67
55
  end
68
56
  end
69
57
  end
70
58
 
71
- def server_pipe_and_pid(server_path)
72
- cmdline = [server_path]
73
- pipe = IO.popen(cmdline.join(" "))
74
- [pipe, pipe.pid]
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(read_pipe)
78
- return unless IO.select([read_pipe], nil, nil, WEBKIT_SERVER_START_TIMEOUT)
79
- ((read_pipe.first || '').match(/listening on port: (\d+)/) || [])[1].to_i
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 forward_stdout(pipe)
83
- while pipe_readable?(pipe)
84
- line = pipe.readline
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
- rescue Errno::ECONNREFUSED
104
- 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?
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