otherinbox-capybara-webkit 0.12.0 → 0.12.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. data/GOALS +9 -0
  2. data/README.md +1 -1
  3. data/capybara-webkit.gemspec +1 -1
  4. data/lib/capybara/webkit.rb +11 -4
  5. data/lib/capybara/{driver/webkit → webkit}/browser.rb +27 -3
  6. data/lib/capybara/{driver/webkit → webkit}/connection.rb +45 -47
  7. data/lib/capybara/{driver/webkit → webkit}/cookie_jar.rb +1 -1
  8. data/lib/capybara/webkit/driver.rb +150 -0
  9. data/lib/capybara/webkit/errors.rb +10 -0
  10. data/lib/capybara/{driver/webkit → webkit}/node.rb +2 -2
  11. data/lib/capybara/{driver/webkit → webkit}/socket_debugger.rb +1 -1
  12. data/lib/capybara/{driver/webkit → webkit}/version.rb +1 -1
  13. data/lib/capybara_webkit_builder.rb +17 -3
  14. data/spec/browser_spec.rb +38 -25
  15. data/spec/connection_spec.rb +5 -5
  16. data/spec/cookie_jar_spec.rb +3 -3
  17. data/spec/driver_rendering_spec.rb +19 -26
  18. data/spec/driver_resize_window_spec.rb +3 -3
  19. data/spec/driver_spec.rb +907 -829
  20. data/spec/integration/driver_spec.rb +4 -3
  21. data/spec/spec_helper.rb +14 -6
  22. data/spec/support/app_runner.rb +91 -0
  23. data/src/Authenticate.cpp +18 -0
  24. data/src/Authenticate.h +12 -0
  25. data/src/Body.h +3 -5
  26. data/src/ClearCookies.cpp +3 -5
  27. data/src/ClearCookies.h +3 -5
  28. data/src/Command.cpp +4 -15
  29. data/src/Command.h +3 -14
  30. data/src/CommandFactory.cpp +10 -6
  31. data/src/CommandFactory.h +3 -2
  32. data/src/CommandParser.cpp +1 -1
  33. data/src/Connection.cpp +22 -11
  34. data/src/Connection.h +4 -2
  35. data/src/ConsoleMessages.cpp +2 -1
  36. data/src/ConsoleMessages.h +3 -5
  37. data/src/CurrentUrl.cpp +2 -1
  38. data/src/CurrentUrl.h +3 -5
  39. data/src/EnableLogging.cpp +10 -0
  40. data/src/EnableLogging.h +12 -0
  41. data/src/Evaluate.cpp +2 -1
  42. data/src/Evaluate.h +3 -5
  43. data/src/Execute.cpp +2 -1
  44. data/src/Execute.h +3 -5
  45. data/src/Find.cpp +3 -2
  46. data/src/Find.h +3 -5
  47. data/src/FrameFocus.cpp +3 -2
  48. data/src/FrameFocus.h +3 -4
  49. data/src/GetCookies.cpp +3 -4
  50. data/src/GetCookies.h +3 -5
  51. data/src/GetWindowHandle.cpp +11 -0
  52. data/src/GetWindowHandle.h +10 -0
  53. data/src/GetWindowHandles.cpp +20 -0
  54. data/src/GetWindowHandles.h +10 -0
  55. data/src/Header.cpp +2 -1
  56. data/src/Header.h +3 -5
  57. data/src/Headers.cpp +2 -1
  58. data/src/Headers.h +3 -5
  59. data/src/IgnoreSslErrors.cpp +4 -3
  60. data/src/IgnoreSslErrors.h +3 -5
  61. data/src/JavascriptInvocation.cpp +1 -1
  62. data/src/JavascriptInvocation.h +1 -1
  63. data/src/NetworkAccessManager.cpp +19 -1
  64. data/src/NetworkAccessManager.h +10 -0
  65. data/src/Node.cpp +6 -1
  66. data/src/Node.h +4 -5
  67. data/src/NullCommand.cpp +5 -2
  68. data/src/NullCommand.h +4 -3
  69. data/src/PageLoadingCommand.cpp +12 -7
  70. data/src/PageLoadingCommand.h +6 -9
  71. data/src/Render.cpp +2 -1
  72. data/src/Render.h +3 -5
  73. data/src/RequestedUrl.cpp +2 -1
  74. data/src/RequestedUrl.h +3 -5
  75. data/src/Reset.cpp +3 -17
  76. data/src/Reset.h +3 -8
  77. data/src/ResizeWindow.cpp +2 -1
  78. data/src/ResizeWindow.h +3 -5
  79. data/src/Server.cpp +2 -3
  80. data/src/Server.h +0 -2
  81. data/src/SetCookie.cpp +3 -4
  82. data/src/SetCookie.h +3 -5
  83. data/src/SetProxy.cpp +2 -1
  84. data/src/SetProxy.h +3 -5
  85. data/src/SetSkipImageLoading.cpp +3 -2
  86. data/src/SetSkipImageLoading.h +3 -5
  87. data/src/SocketCommand.cpp +21 -0
  88. data/src/SocketCommand.h +29 -0
  89. data/src/Source.cpp +2 -1
  90. data/src/Source.h +3 -4
  91. data/src/Status.cpp +2 -1
  92. data/src/Status.h +3 -5
  93. data/src/UnsupportedContentHandler.cpp +1 -1
  94. data/src/Url.cpp +2 -1
  95. data/src/Url.h +3 -5
  96. data/src/Visit.cpp +3 -2
  97. data/src/Visit.h +3 -5
  98. data/src/WebPage.cpp +86 -39
  99. data/src/WebPage.h +22 -8
  100. data/src/WebPageManager.cpp +117 -0
  101. data/src/WebPageManager.h +56 -0
  102. data/src/WindowFocus.cpp +32 -0
  103. data/src/WindowFocus.h +15 -0
  104. data/src/body.cpp +2 -1
  105. data/src/find_command.h +6 -2
  106. data/src/webkit_server.pro +14 -0
  107. data/templates/Command.cpp +2 -4
  108. data/templates/Command.h +3 -3
  109. metadata +29 -10
  110. 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
 
@@ -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 = "otherinbox-capybara-webkit"
@@ -1,11 +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
- browser = Capybara::Driver::Webkit::Browser.new(:socket_class => Capybara::Driver::Webkit::SocketDebugger)
10
- Capybara::Driver::Webkit.new(app, :browser => browser)
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
- 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
@@ -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 WebkitNoResponseError, "No response received from the server."
164
+ raise NoResponseError, "No response received from the server."
141
165
  elsif result != 'ok'
142
- raise WebkitInvalidResponseError, read_response
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
- 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?
@@ -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::Driver::Webkit::CookieJar
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
@@ -0,0 +1,10 @@
1
+ module Capybara::Webkit
2
+ class InvalidResponseError < StandardError
3
+ end
4
+
5
+ class NoResponseError < StandardError
6
+ end
7
+
8
+ class NodeNotAttachedError < Capybara::ElementNotFound
9
+ end
10
+ end
@@ -1,4 +1,4 @@
1
- class Capybara::Driver::Webkit
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::Driver::Webkit::NodeNotAttachedError
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
- class Capybara::Driver::Webkit
3
+ module Capybara::Webkit
4
4
  class SocketDebugger
5
5
  def self.open(host, port)
6
6
  real_socket = TCPSocket.open(host, port)