bbc-capybara-mechanize 0.3.3 → 0.3.4
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/lib/capybara/mechanize/browser.rb +215 -205
- data/lib/capybara/mechanize/driver.rb +2 -2
- data/lib/capybara/mechanize/version.rb +1 -1
- data/lib/capybara/spec/extended_test_app.rb +12 -9
- data/spec/driver/remote_mechanize_driver_spec.rb +1 -1
- data/spec/session/mechanize_spec.rb +10 -4
- data/spec/session/remote_mechanize_spec.rb +1 -0
- metadata +4 -4
@@ -4,232 +4,242 @@ require 'mechanize'
|
|
4
4
|
class Capybara::Mechanize::Browser < Capybara::RackTest::Browser
|
5
5
|
extend Forwardable
|
6
6
|
|
7
|
+
attr_reader :driver
|
8
|
+
|
7
9
|
def_delegator :agent, :scheme_handlers
|
8
10
|
def_delegator :agent, :scheme_handlers=
|
9
11
|
|
10
|
-
def initialize(
|
12
|
+
def initialize(driver)
|
11
13
|
@agent = ::Mechanize.new
|
12
14
|
@agent.redirect_ok = false
|
13
|
-
|
14
|
-
|
15
|
+
@agent.user_agent = default_user_agent
|
16
|
+
if !driver.options.empty?
|
17
|
+
if driver.options[:proxy] && !driver.options[:proxy].empty?
|
15
18
|
proxy = nil
|
16
19
|
begin
|
17
|
-
proxy = URI.parse(options[:proxy])
|
20
|
+
proxy = URI.parse(driver.options[:proxy])
|
18
21
|
rescue URI::InvalidURIError => e
|
19
|
-
raise "You have entered an invalid proxy address #{options[:proxy]}. Check proxy settings."
|
22
|
+
raise "You have entered an invalid proxy address #{driver.options[:proxy]}. Check proxy settings."
|
20
23
|
end
|
21
24
|
if proxy && proxy.instance_of?(URI::HTTP)
|
22
25
|
@agent.set_proxy(proxy.host, proxy.port)
|
23
26
|
else
|
24
|
-
raise "ProxyError: You have entered an invalid proxy address #{options[:proxy]}. e.g. (http|https)://proxy.com(:port)"
|
27
|
+
raise "ProxyError: You have entered an invalid proxy address #{driver.options[:proxy]}. e.g. (http|https)://proxy.com(:port)"
|
25
28
|
end
|
26
29
|
end
|
27
30
|
end
|
28
31
|
super
|
29
|
-
end
|
32
|
+
end
|
30
33
|
|
31
34
|
def reset_host!
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
def current_url
|
38
|
-
last_request_remote? ? remote_response.current_url : super
|
39
|
-
end
|
40
|
-
|
41
|
-
def last_response
|
42
|
-
last_request_remote? ? remote_response : super
|
43
|
-
end
|
44
|
-
|
45
|
-
def follow_redirects!
|
46
|
-
5.times do
|
47
|
-
follow_redirect! if last_response.redirect?
|
48
|
-
end
|
49
|
-
raise Capybara::InfiniteRedirectError, "redirected more than 5 times, check for infinite redirects." if last_response.redirect?
|
50
|
-
end
|
51
|
-
|
52
|
-
def follow_redirect!
|
53
|
-
unless last_response.redirect?
|
54
|
-
raise "Last response was not a redirect. Cannot follow_redirect!"
|
55
|
-
end
|
56
|
-
|
57
|
-
get(last_location_header)
|
58
|
-
end
|
59
|
-
|
60
|
-
def process(method, path, *options)
|
61
|
-
reset_cache!
|
62
|
-
send(method, path, *options)
|
63
|
-
follow_redirects!
|
64
|
-
end
|
65
|
-
|
66
|
-
def process_without_redirect(method, path, attributes, headers)
|
67
|
-
path = @last_path if path.nil? || path.empty?
|
68
|
-
|
69
|
-
if remote?(path)
|
70
|
-
process_remote_request(method, path, attributes, headers)
|
71
|
-
else
|
72
|
-
register_local_request
|
73
|
-
|
74
|
-
path = determine_path(path)
|
75
|
-
|
76
|
-
reset_cache!
|
77
|
-
send("racktest_#{method}", path, attributes, env.merge(headers))
|
78
|
-
end
|
79
|
-
|
80
|
-
@last_path = path
|
81
|
-
end
|
82
|
-
|
83
|
-
# TODO path Capybara to move this into its own method
|
84
|
-
def determine_path(path)
|
85
|
-
new_uri = URI.parse(path)
|
86
|
-
current_uri = URI.parse(current_url)
|
35
|
+
@last_remote_host = nil
|
36
|
+
@last_request_remote = nil
|
37
|
+
super
|
38
|
+
end
|
87
39
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
end
|
123
|
-
|
124
|
-
def post_data(params)
|
125
|
-
params.inject({}) do |memo, param|
|
126
|
-
case param
|
127
|
-
when Hash
|
128
|
-
param.each {|attribute, value| memo[attribute] = value }
|
129
|
-
memo
|
130
|
-
when Array
|
131
|
-
case param.last
|
132
|
-
when Hash
|
133
|
-
param.last.each {|attribute, value| memo["#{param.first}[#{attribute}]"] = value }
|
40
|
+
def current_url
|
41
|
+
last_request_remote? ? remote_response.current_url : super
|
42
|
+
end
|
43
|
+
|
44
|
+
def last_response
|
45
|
+
last_request_remote? ? remote_response : super
|
46
|
+
end
|
47
|
+
|
48
|
+
def follow_redirects!
|
49
|
+
5.times do
|
50
|
+
follow_redirect! if last_response.redirect?
|
51
|
+
end
|
52
|
+
raise Capybara::InfiniteRedirectError, "redirected more than 5 times, check for infinite redirects." if last_response.redirect?
|
53
|
+
end
|
54
|
+
|
55
|
+
def follow_redirect!
|
56
|
+
unless last_response.redirect?
|
57
|
+
raise "Last response was not a redirect. Cannot follow_redirect!"
|
58
|
+
end
|
59
|
+
|
60
|
+
get(last_location_header)
|
61
|
+
end
|
62
|
+
|
63
|
+
def process(method, path, *options)
|
64
|
+
reset_cache!
|
65
|
+
send(method, path, *options)
|
66
|
+
follow_redirects!
|
67
|
+
end
|
68
|
+
|
69
|
+
def process_without_redirect(method, path, attributes, headers)
|
70
|
+
path = @last_path if path.nil? || path.empty?
|
71
|
+
|
72
|
+
if remote?(path)
|
73
|
+
process_remote_request(method, path, attributes, headers)
|
134
74
|
else
|
135
|
-
|
75
|
+
register_local_request
|
76
|
+
|
77
|
+
path = determine_path(path)
|
78
|
+
|
79
|
+
reset_cache!
|
80
|
+
send("racktest_#{method}", path, attributes, env.merge(headers))
|
136
81
|
end
|
137
|
-
|
82
|
+
|
83
|
+
@last_path = path
|
138
84
|
end
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
85
|
+
|
86
|
+
# TODO path Capybara to move this into its own method
|
87
|
+
def determine_path(path)
|
88
|
+
new_uri = URI.parse(path)
|
89
|
+
current_uri = URI.parse(current_url)
|
90
|
+
|
91
|
+
if new_uri.host
|
92
|
+
@current_host = new_uri.scheme + '://' + new_uri.host
|
93
|
+
end
|
94
|
+
|
95
|
+
if new_uri.relative?
|
96
|
+
path = request_path + path if path.start_with?('?')
|
97
|
+
|
98
|
+
unless path.start_with?('/')
|
99
|
+
folders = request_path.split('/')
|
100
|
+
if folders.empty?
|
101
|
+
path = '/' + path
|
102
|
+
else
|
103
|
+
path = (folders[0, folders.size - 1] << path).join('/')
|
104
|
+
end
|
105
|
+
end
|
106
|
+
path = current_host + path
|
107
|
+
end
|
108
|
+
path
|
109
|
+
end
|
110
|
+
|
111
|
+
alias :racktest_get :get
|
112
|
+
def get(path, attributes = {}, headers = {})
|
113
|
+
process_without_redirect(:get, path, attributes, headers)
|
114
|
+
end
|
115
|
+
|
116
|
+
alias :racktest_post :post
|
117
|
+
def post(path, attributes = {}, headers = {})
|
118
|
+
process_without_redirect(:post, path, post_data(attributes), headers)
|
119
|
+
end
|
120
|
+
|
121
|
+
alias :racktest_put :put
|
122
|
+
def put(path, attributes = {}, headers = {})
|
123
|
+
process_without_redirect(:put, path, attributes, headers)
|
124
|
+
end
|
125
|
+
|
126
|
+
alias :racktest_delete :delete
|
127
|
+
def delete(path, attributes = {}, headers = {})
|
128
|
+
process_without_redirect(:delete, path, attributes, headers)
|
129
|
+
end
|
130
|
+
|
131
|
+
def post_data(params)
|
132
|
+
params.inject({}) do |memo, param|
|
133
|
+
case param
|
134
|
+
when Hash
|
135
|
+
param.each {|attribute, value| memo[attribute] = value }
|
136
|
+
memo
|
137
|
+
when Array
|
138
|
+
case param.last
|
139
|
+
when Hash
|
140
|
+
param.last.each {|attribute, value| memo["#{param.first}[#{attribute}]"] = value }
|
141
|
+
else
|
142
|
+
memo[param.first] = param.last
|
143
|
+
end
|
144
|
+
memo
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def remote?(url)
|
150
|
+
if Capybara.app_host
|
151
|
+
true
|
152
|
+
else
|
153
|
+
host = URI.parse(url).host
|
154
|
+
|
155
|
+
if host.nil?
|
156
|
+
last_request_remote?
|
157
|
+
else
|
158
|
+
!Capybara::Mechanize.local_hosts.include?(host)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
attr_reader :agent
|
164
|
+
|
165
|
+
private
|
166
|
+
|
167
|
+
def last_location_header
|
168
|
+
last_request_remote? ? remote_response.page.response['Location'] : last_response['Location']
|
169
|
+
end
|
170
|
+
|
171
|
+
def last_request_remote?
|
172
|
+
!!@last_request_remote
|
173
|
+
end
|
174
|
+
|
175
|
+
def register_local_request
|
176
|
+
@last_remote_host = nil
|
177
|
+
@last_request_remote = false
|
178
|
+
end
|
179
|
+
|
180
|
+
def process_remote_request(method, url, attributes, headers)
|
181
|
+
if remote?(url)
|
182
|
+
remote_uri = URI.parse(url)
|
183
|
+
|
184
|
+
if remote_uri.host.nil?
|
185
|
+
remote_host = @last_remote_host || Capybara.app_host || Capybara.default_host
|
186
|
+
url = File.join(remote_host, url)
|
187
|
+
url = "http://#{url}" unless url.include?("http")
|
188
|
+
else
|
189
|
+
@last_remote_host = "#{remote_uri.host}:#{remote_uri.port}"
|
190
|
+
end
|
191
|
+
|
192
|
+
reset_cache!
|
193
|
+
begin
|
194
|
+
args = []
|
195
|
+
args << attributes unless attributes.empty?
|
196
|
+
args << headers unless headers.empty?
|
197
|
+
@agent.send(method, url, *args)
|
198
|
+
rescue => e
|
199
|
+
raise "Received the following error for a #{method.to_s.upcase} request to #{url}: '#{e.message}'"
|
200
|
+
end
|
201
|
+
@last_request_remote = true
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
def remote_response
|
206
|
+
ResponseProxy.new(@agent.current_page) if @agent.current_page
|
207
|
+
end
|
208
|
+
|
209
|
+
def default_user_agent
|
210
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.853.0 Safari/535.2"
|
211
|
+
end
|
212
|
+
|
213
|
+
class ResponseProxy
|
214
|
+
extend Forwardable
|
215
|
+
|
216
|
+
def_delegator :page, :body
|
217
|
+
|
218
|
+
attr_reader :page
|
219
|
+
|
220
|
+
def initialize(page)
|
221
|
+
@page = page
|
222
|
+
end
|
223
|
+
|
224
|
+
def current_url
|
225
|
+
page.uri.to_s
|
226
|
+
end
|
227
|
+
|
228
|
+
def headers
|
229
|
+
# Hax the content-type contains utf8, so Capybara specs are failing, need to ask mailinglist
|
230
|
+
headers = page.response
|
231
|
+
headers["content-type"].gsub!(';charset=utf-8', '') if headers["content-type"]
|
232
|
+
headers
|
233
|
+
end
|
234
|
+
|
235
|
+
def status
|
236
|
+
page.code.to_i
|
237
|
+
end
|
238
|
+
|
239
|
+
def redirect?
|
240
|
+
[301, 302].include?(status)
|
241
|
+
end
|
242
|
+
|
152
243
|
end
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
attr_reader :agent
|
157
|
-
|
158
|
-
private
|
159
|
-
|
160
|
-
def last_location_header
|
161
|
-
last_request_remote? ? remote_response.page.response['Location'] : last_response['Location']
|
162
|
-
end
|
163
|
-
|
164
|
-
def last_request_remote?
|
165
|
-
!!@last_request_remote
|
166
|
-
end
|
167
|
-
|
168
|
-
def register_local_request
|
169
|
-
@last_remote_host = nil
|
170
|
-
@last_request_remote = false
|
171
|
-
end
|
172
|
-
|
173
|
-
def process_remote_request(method, url, attributes, headers)
|
174
|
-
if remote?(url)
|
175
|
-
remote_uri = URI.parse(url)
|
176
|
-
|
177
|
-
if remote_uri.host.nil?
|
178
|
-
remote_host = @last_remote_host || Capybara.app_host || Capybara.default_host
|
179
|
-
url = File.join(remote_host, url)
|
180
|
-
url = "http://#{url}" unless url =~ /^http:/ or url =~ /^https:/
|
181
|
-
else
|
182
|
-
@last_remote_host = "#{remote_uri.host}:#{remote_uri.port}"
|
183
|
-
end
|
184
|
-
|
185
|
-
reset_cache!
|
186
|
-
begin
|
187
|
-
args = []
|
188
|
-
args << attributes unless attributes.empty?
|
189
|
-
args << headers unless headers.empty?
|
190
|
-
@agent.send(method, url, *args)
|
191
|
-
rescue => e
|
192
|
-
raise "Received the following error for a #{method.to_s.upcase} request to #{url}: '#{e.message}'"
|
193
|
-
end
|
194
|
-
@last_request_remote = true
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
def remote_response
|
199
|
-
ResponseProxy.new(@agent.current_page) if @agent.current_page
|
200
|
-
end
|
201
|
-
|
202
|
-
class ResponseProxy
|
203
|
-
extend Forwardable
|
204
|
-
|
205
|
-
def_delegator :page, :body
|
206
|
-
|
207
|
-
attr_reader :page
|
208
|
-
|
209
|
-
def initialize(page)
|
210
|
-
@page = page
|
211
|
-
end
|
212
|
-
|
213
|
-
def current_url
|
214
|
-
page.uri.to_s
|
215
|
-
end
|
216
|
-
|
217
|
-
def headers
|
218
|
-
# Hax the content-type contains utf8, so Capybara specs are failing, need to ask mailinglist
|
219
|
-
headers = page.response
|
220
|
-
headers["content-type"].gsub!(';charset=utf-8', '') if headers["content-type"]
|
221
|
-
headers
|
222
|
-
end
|
223
|
-
|
224
|
-
def status
|
225
|
-
page.code.to_i
|
226
|
-
end
|
227
|
-
|
228
|
-
def redirect?
|
229
|
-
[301, 302].include?(status)
|
230
|
-
end
|
231
|
-
|
232
|
-
end
|
233
|
-
|
234
|
-
end
|
235
244
|
|
245
|
+
end
|
@@ -2,27 +2,31 @@ require 'capybara/spec/test_app'
|
|
2
2
|
|
3
3
|
class ExtendedTestApp < TestApp#< Sinatra::Base
|
4
4
|
set :environment, :production # so we don't get debug info that makes our test pass!
|
5
|
-
|
5
|
+
|
6
6
|
get %r{/redirect_to/(.*)} do
|
7
7
|
redirect params[:captures]
|
8
8
|
end
|
9
|
-
|
9
|
+
|
10
10
|
get '/form_with_relative_action_to_host' do
|
11
11
|
%{<form action="/request_info/host" method="post">
|
12
12
|
<input type="submit" value="submit" />
|
13
13
|
</form>}
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
16
|
get '/request_info/form_with_no_action' do
|
17
17
|
%{<form method="post">
|
18
18
|
<input type="submit" value="submit" />
|
19
19
|
</form>}
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
get '/relative_link_to_host' do
|
23
23
|
%{<a href="/request_info/host">host</a>}
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
|
+
get '/request_info/user_agent' do
|
27
|
+
request.user_agent
|
28
|
+
end
|
29
|
+
|
26
30
|
get '/request_info/*' do
|
27
31
|
current_request_info
|
28
32
|
end
|
@@ -31,11 +35,10 @@ class ExtendedTestApp < TestApp#< Sinatra::Base
|
|
31
35
|
current_request_info
|
32
36
|
end
|
33
37
|
|
34
|
-
|
38
|
+
|
35
39
|
private
|
36
|
-
|
40
|
+
|
37
41
|
def current_request_info
|
38
42
|
"Current host is #{request.url}, method #{request.request_method.downcase}"
|
39
43
|
end
|
40
|
-
end
|
41
|
-
|
44
|
+
end
|
@@ -4,6 +4,7 @@ describe Capybara::Session do
|
|
4
4
|
context 'with mechanize driver' do
|
5
5
|
before do
|
6
6
|
@session = Capybara::Session.new(:mechanize, TestApp)
|
7
|
+
@session.driver.options[:respect_data_method] = true
|
7
8
|
Capybara.default_host = 'http://www.local.com'
|
8
9
|
end
|
9
10
|
|
@@ -26,28 +27,33 @@ describe Capybara::Session do
|
|
26
27
|
@session.body.should include('The requested object was deleted')
|
27
28
|
end
|
28
29
|
end
|
29
|
-
|
30
|
+
|
30
31
|
it "should use the last remote url when following relative links" do
|
31
32
|
@session.visit("#{REMOTE_TEST_URL}/relative_link_to_host")
|
32
33
|
@session.click_link "host"
|
33
34
|
@session.body.should include("Current host is #{REMOTE_TEST_URL}/request_info/host, method get")
|
34
35
|
end
|
35
|
-
|
36
|
+
|
36
37
|
it "should use the last remote url when submitting a form with a relative action" do
|
37
38
|
@session.visit("#{REMOTE_TEST_URL}/form_with_relative_action_to_host")
|
38
39
|
@session.click_button "submit"
|
39
40
|
@session.body.should include("Current host is #{REMOTE_TEST_URL}/request_info/host, method post")
|
40
41
|
end
|
41
|
-
|
42
|
+
|
42
43
|
it "should use the last url when submitting a form with no action" do
|
43
44
|
@session.visit("#{REMOTE_TEST_URL}/request_info/form_with_no_action")
|
44
45
|
@session.click_button "submit"
|
45
46
|
@session.body.should include("Current host is #{REMOTE_TEST_URL}/request_info/form_with_no_action, method post")
|
46
47
|
end
|
47
48
|
|
49
|
+
it "should send correct user agent" do
|
50
|
+
@session.visit("#{REMOTE_TEST_URL}/request_info/user_agent")
|
51
|
+
@session.body.should include("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.2 (KHTML, like Gecko) Chrome/15.0.853.0 Safari/535.2")
|
52
|
+
end
|
53
|
+
|
48
54
|
it_should_behave_like "session"
|
49
55
|
it_should_behave_like "session without javascript support"
|
50
56
|
it_should_behave_like "session with headers support"
|
51
57
|
it_should_behave_like "session with status code support"
|
52
58
|
end
|
53
|
-
end
|
59
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bbc-capybara-mechanize
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 3
|
9
|
-
-
|
10
|
-
version: 0.3.
|
9
|
+
- 4
|
10
|
+
version: 0.3.4
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jeroen van Dijk
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2012-01-
|
19
|
+
date: 2012-01-18 00:00:00 Z
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
version_requirements: &id001 !ruby/object:Gem::Requirement
|