capybara-webkit 0.12.1 → 0.13.0

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.
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
@@ -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,186 @@
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 alert_messages
72
+ browser.alert_messages
73
+ end
74
+
75
+ def confirm_messages
76
+ browser.confirm_messages
77
+ end
78
+
79
+ def prompt_messages
80
+ browser.prompt_messages
81
+ end
82
+
83
+ def response_headers
84
+ browser.response_headers
85
+ end
86
+
87
+ def status_code
88
+ browser.status_code
89
+ end
90
+
91
+ def resize_window(width, height)
92
+ browser.resize_window(width, height)
93
+ end
94
+
95
+ def within_frame(frame_id_or_index)
96
+ browser.frame_focus(frame_id_or_index)
97
+ begin
98
+ yield
99
+ ensure
100
+ browser.frame_focus
101
+ end
102
+ end
103
+
104
+ def within_window(selector)
105
+ current_window = window_handle
106
+ browser.window_focus(selector)
107
+ begin
108
+ yield
109
+ ensure
110
+ browser.window_focus(current_window)
111
+ end
112
+ end
113
+
114
+ def window_handles
115
+ browser.get_window_handles
116
+ end
117
+
118
+ def window_handle
119
+ browser.get_window_handle
120
+ end
121
+
122
+ def accept_js_confirms!
123
+ browser.accept_js_confirms
124
+ end
125
+
126
+ def dismiss_js_confirms!
127
+ browser.reject_js_confirms
128
+ end
129
+
130
+ def accept_js_prompts!
131
+ browser.accept_js_prompts
132
+ end
133
+
134
+ def dismiss_js_prompts!
135
+ browser.reject_js_prompts
136
+ end
137
+
138
+ def js_prompt_input=(value)
139
+ if value.nil?
140
+ browser.clear_prompt_text
141
+ else
142
+ browser.set_prompt_text_to(value)
143
+ end
144
+ end
145
+
146
+ def wait?
147
+ true
148
+ end
149
+
150
+ def wait_until(*args)
151
+ end
152
+
153
+ def reset!
154
+ browser.reset!
155
+ end
156
+
157
+ def has_shortcircuit_timeout?
158
+ false
159
+ end
160
+
161
+ def render(path, options={})
162
+ options[:width] ||= 1000
163
+ options[:height] ||= 10
164
+
165
+ browser.render path, options[:width], options[:height]
166
+ end
167
+
168
+ def server_port
169
+ @rack_server.port
170
+ end
171
+
172
+ def cookies
173
+ @cookie_jar ||= CookieJar.new(browser)
174
+ end
175
+
176
+ def invalid_element_errors
177
+ []
178
+ end
179
+
180
+ private
181
+
182
+ def url(path)
183
+ @rack_server.url(path)
184
+ end
185
+ end
186
+ 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)
@@ -9,7 +9,7 @@ class Capybara::Driver::Webkit
9
9
 
10
10
  def [](name)
11
11
  value = invoke("attribute", name)
12
- if name == 'checked' || name == 'disabled'
12
+ if name == 'checked' || name == 'disabled' || name == 'multiple'
13
13
  value == 'true'
14
14
  else
15
15
  value
@@ -24,6 +24,14 @@ class Capybara::Driver::Webkit
24
24
  end
25
25
  end
26
26
 
27
+ def inner_html
28
+ invoke 'getInnerHTML'
29
+ end
30
+
31
+ def inner_html=(value)
32
+ invoke 'setInnerHTML', value
33
+ end
34
+
27
35
  def set(value)
28
36
  invoke "set", value
29
37
  end
@@ -91,7 +99,7 @@ class Capybara::Driver::Webkit
91
99
  if allow_unattached_nodes? || attached?
92
100
  browser.command "Node", name, native, *args
93
101
  else
94
- raise Capybara::Driver::Webkit::NodeNotAttachedError
102
+ raise Capybara::Webkit::NodeNotAttachedError
95
103
  end
96
104
  end
97
105
 
@@ -112,7 +120,7 @@ class Capybara::Driver::Webkit
112
120
  end
113
121
 
114
122
  def multiple_select?
115
- self.tag_name == "select" && self["multiple"] == "multiple"
123
+ self.tag_name == "select" && self["multiple"]
116
124
  end
117
125
  end
118
126
  end
@@ -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)
@@ -29,6 +29,9 @@ class Capybara::Driver::Webkit
29
29
  received @socket.gets
30
30
  end
31
31
 
32
+ def setsockopt(level, name, value)
33
+ end
34
+
32
35
  private
33
36
 
34
37
  def sent(content)
@@ -1,7 +1,7 @@
1
1
  module Capybara
2
2
  module Driver
3
3
  class Webkit
4
- VERSION = '0.12.1'.freeze
4
+ VERSION = '0.13.0'.freeze
5
5
  end
6
6
  end
7
7
  end
@@ -4,6 +4,9 @@ require "rbconfig"
4
4
  module CapybaraWebkitBuilder
5
5
  extend self
6
6
 
7
+ SUCCESS_STATUS = 0
8
+ COMMAND_NOT_FOUND_STATUS = 127
9
+
7
10
  def make_bin
8
11
  ENV['MAKE'] || 'make'
9
12
  end
@@ -29,12 +32,23 @@ module CapybaraWebkitBuilder
29
32
  end
30
33
  end
31
34
 
35
+ def sh(command)
36
+ system(command)
37
+ success = $?.exitstatus == SUCCESS_STATUS
38
+ if $?.exitstatus == COMMAND_NOT_FOUND_STATUS
39
+ puts "Command '#{command}' not available"
40
+ elsif !success
41
+ puts "Command '#{command}' failed"
42
+ end
43
+ success
44
+ end
45
+
32
46
  def makefile
33
- system("#{qmake_bin} -spec #{spec}")
47
+ sh("#{qmake_bin} -spec #{spec}")
34
48
  end
35
49
 
36
50
  def qmake
37
- system("#{make_bin} qmake")
51
+ sh("#{make_bin} qmake")
38
52
  end
39
53
 
40
54
  def path_to_binary
@@ -47,7 +61,7 @@ module CapybaraWebkitBuilder
47
61
  end
48
62
 
49
63
  def build
50
- system(make_bin) or return false
64
+ sh(make_bin) or return false
51
65
 
52
66
  FileUtils.mkdir("bin") unless File.directory?("bin")
53
67
  FileUtils.cp(path_to_binary, "bin", :preserve => true)
@@ -1,19 +1,23 @@
1
1
  require 'spec_helper'
2
2
  require 'self_signed_ssl_cert'
3
3
  require 'stringio'
4
- require 'capybara/driver/webkit/browser'
5
- require 'capybara/driver/webkit/connection'
4
+ require 'capybara/webkit/driver'
6
5
  require 'socket'
7
6
  require 'base64'
8
7
 
9
- describe Capybara::Driver::Webkit::Browser do
8
+ describe Capybara::Webkit::Browser do
10
9
 
11
- let(:browser) { Capybara::Driver::Webkit::Browser.new(Capybara::Driver::Webkit::Connection.new) }
10
+ let(:browser) { Capybara::Webkit::Browser.new(Capybara::Webkit::Connection.new) }
12
11
  let(:browser_ignore_ssl_err) do
13
- Capybara::Driver::Webkit::Browser.new(Capybara::Driver::Webkit::Connection.new).tap do |browser|
12
+ Capybara::Webkit::Browser.new(Capybara::Webkit::Connection.new).tap do |browser|
14
13
  browser.ignore_ssl_errors
15
14
  end
16
15
  end
16
+ let(:browser_skip_images) do
17
+ Capybara::Webkit::Browser.new(Capybara::Webkit::Connection.new).tap do |browser|
18
+ browser.set_skip_image_loading(true)
19
+ end
20
+ end
17
21
 
18
22
  context 'handling of SSL validation errors' do
19
23
  before do
@@ -57,6 +61,90 @@ describe Capybara::Driver::Webkit::Browser do
57
61
  it 'accepts a self-signed certificate if configured to do so' do
58
62
  browser_ignore_ssl_err.visit "https://#{@host}:#{@port}/"
59
63
  end
64
+
65
+ it "doesn't accept a self-signed certificate in a new window by default" do
66
+ browser.execute_script("window.open('about:blank')")
67
+ browser.window_focus(browser.get_window_handles.last)
68
+ lambda { browser.visit "https://#{@host}:#{@port}/" }.should raise_error
69
+ end
70
+
71
+ it 'accepts a self-signed certificate in a new window if configured to do so' do
72
+ browser_ignore_ssl_err.execute_script("window.open('about:blank')")
73
+ browser_ignore_ssl_err.window_focus(browser_ignore_ssl_err.get_window_handles.last)
74
+ browser_ignore_ssl_err.visit "https://#{@host}:#{@port}/"
75
+ end
76
+ end
77
+
78
+ context "skip image loading" do
79
+ before(:each) do
80
+ # set up minimal HTTP server
81
+ @host = "127.0.0.1"
82
+ @server = TCPServer.new(@host, 0)
83
+ @port = @server.addr[1]
84
+ @received_requests = []
85
+
86
+ @server_thread = Thread.new do
87
+ while conn = @server.accept
88
+ Thread.new(conn) do |conn|
89
+ # read request
90
+ request = []
91
+ until (line = conn.readline.strip).empty?
92
+ request << line
93
+ end
94
+
95
+ @received_requests << request.join("\n")
96
+
97
+ # write response
98
+ html = <<-HTML
99
+ <html>
100
+ <head>
101
+ <style>
102
+ body {
103
+ background-image: url(/path/to/bgimage);
104
+ }
105
+ </style>
106
+ </head>
107
+ <body>
108
+ <img src="/path/to/image"/>
109
+ </body>
110
+ </html>
111
+ HTML
112
+ conn.write "HTTP/1.1 200 OK\r\n"
113
+ conn.write "Content-Type:text/html\r\n"
114
+ conn.write "Content-Length: %i\r\n" % html.size
115
+ conn.write "\r\n"
116
+ conn.write html
117
+ conn.write("\r\n\r\n")
118
+ conn.close
119
+ end
120
+ end
121
+ end
122
+ end
123
+
124
+ after(:each) do
125
+ @server_thread.kill
126
+ @server.close
127
+ end
128
+
129
+ it "should load images in image tags by default" do
130
+ browser.visit("http://#{@host}:#{@port}/")
131
+ @received_requests.find {|r| r =~ %r{/path/to/image} }.should_not be_nil
132
+ end
133
+
134
+ it "should load images in css by default" do
135
+ browser.visit("http://#{@host}:#{@port}/")
136
+ @received_requests.find {|r| r =~ %r{/path/to/image} }.should_not be_nil
137
+ end
138
+
139
+ it "should not load images in image tags when skip_image_loading is true" do
140
+ browser_skip_images.visit("http://#{@host}:#{@port}/")
141
+ @received_requests.find {|r| r =~ %r{/path/to/image} }.should be_nil
142
+ end
143
+
144
+ it "should not load images in css when skip_image_loading is true" do
145
+ browser_skip_images.visit("http://#{@host}:#{@port}/")
146
+ @received_requests.find {|r| r =~ %r{/path/to/bgimage} }.should be_nil
147
+ end
60
148
  end
61
149
 
62
150
  describe "forking", :skip_on_windows => true do
@@ -148,7 +236,7 @@ describe Capybara::Driver::Webkit::Browser do
148
236
 
149
237
  it 'uses URLs changed by javascript' do
150
238
  browser.execute_script "window.history.pushState('', '', '/blah')"
151
- browser.requested_url.should == 'http://example.org/blah'
239
+ browser.current_url.should == 'http://example.org/blah'
152
240
  end
153
241
 
154
242
  it 'is possible to disable proxy again' do
@@ -166,7 +254,7 @@ describe Capybara::Driver::Webkit::Browser do
166
254
  connection.stub(:gets).and_return("ok\n", "0\n")
167
255
  connection.stub(:read).and_raise(StandardError.new("tried to read empty response"))
168
256
 
169
- browser = Capybara::Driver::Webkit::Browser.new(connection)
257
+ browser = Capybara::Webkit::Browser.new(connection)
170
258
 
171
259
  expect { browser.visit("/") }.not_to raise_error(/empty response/)
172
260
  end