bbc-capybara-mechanize-with-proxy 0.3.0.rc0 → 0.3.1

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.
@@ -1,17 +1,12 @@
1
1
  Capybara-mechanize
2
2
  ==================
3
3
 
4
- This gems makes it possible to use Capybara for (partially) remote testing. It inherits most functionality from the RackTest driver and only uses [Mechanize](http://github.com/tenderlove/mechanize) for remote requests.
5
-
6
- It is currently in use to test the integration between a Rails application and Twitter authorization and sharing.
7
-
8
- This gem is a [Capybara](http://github.com/jnicklas/capybara) extension. I have been inspired by the Capybara driver and some earlier efforts for a Mechanize driver.
9
-
10
- Thanks to [Pinkelstar](http://www.pinkelstar.com) for giving me the time and the need to develop this gem.
4
+ Forked from mobzilla/capybara-mechanize and modified to suit the needs of using capybara mechanize from behind a proxy
5
+ or firewall.
11
6
 
12
7
  ### Installation
13
8
 
14
- gem install capybara-mechanize
9
+ gem install capybara-mechanize-with-proxy
15
10
 
16
11
  ### Usage without Cucumber
17
12
 
@@ -20,5 +20,5 @@ end
20
20
  require 'capybara/mechanize/driver'
21
21
 
22
22
  Capybara.register_driver :mechanize do |app|
23
- Capybara::Mechanize::Driver.new(app, options = {})
23
+ Capybara::Mechanize::Driver.new(app)
24
24
  end
@@ -4,232 +4,246 @@ 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(app, options)
12
+ def initialize(driver)
11
13
  @agent = ::Mechanize.new
12
14
  @agent.redirect_ok = false
13
- if !options.empty?
14
- if options[:proxy] && !options[:proxy].empty?
15
- proxy = nil
16
- begin
17
- proxy = URI.parse(options[:proxy])
18
- rescue URI::InvalidURIError => e
19
- raise "You have entered an invalid proxy address #{options[:proxy]}. Check proxy settings."
20
- end
21
- if proxy && proxy.instance_of?(URI::HTTP)
22
- @agent.set_proxy(proxy.host, proxy.port)
23
- else
24
- raise "ProxyError: You have entered an invalid proxy address #{options[:proxy]}. e.g. (http|https)://proxy.com(:port)"
25
- end
26
- end
27
- end
15
+ @agent.user_agent = default_user_agent
16
+ if !driver.options.empty?
17
+ if driver.options[:certificate] && driver.options[:certificate][:key] && driver.options[:certificate][:cer]
18
+ @agent.cert = driver.options[:certificate][:cer]
19
+ @agent.key = driver.options[:certificate][:key]
20
+ end
21
+ if driver.options[:proxy] && !driver.options[:proxy].empty?
22
+ proxy = nil
23
+ begin
24
+ proxy = URI.parse(driver.options[:proxy])
25
+ rescue URI::InvalidURIError => e
26
+ raise "You have entered an invalid proxy address #{driver.options[:proxy]}. Check proxy settings."
27
+ end
28
+ if proxy && proxy.instance_of?(URI::HTTP)
29
+ @agent.set_proxy(proxy.host, proxy.port)
30
+ else
31
+ raise "ProxyError: You have entered an invalid proxy address #{driver.options[:proxy]}. e.g. (http|https)://proxy.com(:port)"
32
+ end
33
+ end
34
+ end
28
35
  super
29
- end
36
+ end
30
37
 
31
38
  def reset_host!
32
- @last_remote_host = nil
33
- @last_request_remote = nil
34
- super
35
- end
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)
39
+ @last_remote_host = nil
40
+ @last_request_remote = nil
41
+ super
42
+ end
87
43
 
88
- if new_uri.host
89
- @current_host = new_uri.scheme + '://' + new_uri.host
90
- end
91
-
92
- if new_uri.relative?
93
- path = request_path + path if path.start_with?('?')
94
-
95
- unless path.start_with?('/')
96
- folders = request_path.split('/')
97
- path = (folders[0, folders.size - 1] << path).join('/')
98
- end
99
- path = current_host + path
100
- end
101
- path
102
- end
103
-
104
- alias :racktest_get :get
105
- def get(path, attributes = {}, headers = {})
106
- process_without_redirect(:get, path, attributes, headers)
107
- end
108
-
109
- alias :racktest_post :post
110
- def post(path, attributes = {}, headers = {})
111
- process_without_redirect(:post, path, post_data(attributes), headers)
112
- end
113
-
114
- alias :racktest_put :put
115
- def put(path, attributes = {}, headers = {})
116
- process_without_redirect(:put, path, attributes, headers)
117
- end
118
-
119
- alias :racktest_delete :delete
120
- def delete(path, attributes = {}, headers = {})
121
- process_without_redirect(:delete, path, attributes, headers)
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 }
44
+ def current_url
45
+ last_request_remote? ? remote_response.current_url : super
46
+ end
47
+
48
+ def last_response
49
+ last_request_remote? ? remote_response : super
50
+ end
51
+
52
+ def follow_redirects!
53
+ 5.times do
54
+ follow_redirect! if last_response.redirect?
55
+ end
56
+ raise Capybara::InfiniteRedirectError, "redirected more than 5 times, check for infinite redirects." if last_response.redirect?
57
+ end
58
+
59
+ def follow_redirect!
60
+ unless last_response.redirect?
61
+ raise "Last response was not a redirect. Cannot follow_redirect!"
62
+ end
63
+
64
+ get(last_location_header)
65
+ end
66
+
67
+ def process(method, path, *options)
68
+ reset_cache!
69
+ send(method, path, *options)
70
+ follow_redirects!
71
+ end
72
+
73
+ def process_without_redirect(method, path, attributes, headers)
74
+ path = @last_path if path.nil? || path.empty?
75
+
76
+ if remote?(path)
77
+ process_remote_request(method, path, attributes, headers)
134
78
  else
135
- memo[param.first] = param.last
79
+ register_local_request
80
+
81
+ path = determine_path(path)
82
+
83
+ reset_cache!
84
+ send("racktest_#{method}", path, attributes, env.merge(headers))
136
85
  end
137
- memo
86
+
87
+ @last_path = path
138
88
  end
139
- end
140
- end
141
-
142
- def remote?(url)
143
- if Capybara.app_host
144
- true
145
- else
146
- host = URI.parse(url).host
147
-
148
- if host.nil?
149
- last_request_remote?
150
- else
151
- !Capybara::Mechanize.local_hosts.include?(host)
89
+
90
+ # TODO path Capybara to move this into its own method
91
+ def determine_path(path)
92
+ new_uri = URI.parse(path)
93
+ current_uri = URI.parse(current_url)
94
+
95
+ if new_uri.host
96
+ @current_host = new_uri.scheme + '://' + new_uri.host
97
+ end
98
+
99
+ if new_uri.relative?
100
+ path = request_path + path if path.start_with?('?')
101
+
102
+ unless path.start_with?('/')
103
+ folders = request_path.split('/')
104
+ if folders.empty?
105
+ path = '/' + path
106
+ else
107
+ path = (folders[0, folders.size - 1] << path).join('/')
108
+ end
109
+ end
110
+ path = current_host + path
111
+ end
112
+ path
113
+ end
114
+
115
+ alias :racktest_get :get
116
+ def get(path, attributes = {}, headers = {})
117
+ process_without_redirect(:get, path, attributes, headers)
118
+ end
119
+
120
+ alias :racktest_post :post
121
+ def post(path, attributes = {}, headers = {})
122
+ process_without_redirect(:post, path, post_data(attributes), headers)
123
+ end
124
+
125
+ alias :racktest_put :put
126
+ def put(path, attributes = {}, headers = {})
127
+ process_without_redirect(:put, path, attributes, headers)
128
+ end
129
+
130
+ alias :racktest_delete :delete
131
+ def delete(path, attributes = {}, headers = {})
132
+ process_without_redirect(:delete, path, attributes, headers)
133
+ end
134
+
135
+ def post_data(params)
136
+ params.inject({}) do |memo, param|
137
+ case param
138
+ when Hash
139
+ param.each {|attribute, value| memo[attribute] = value }
140
+ memo
141
+ when Array
142
+ case param.last
143
+ when Hash
144
+ param.last.each {|attribute, value| memo["#{param.first}[#{attribute}]"] = value }
145
+ else
146
+ memo[param.first] = param.last
147
+ end
148
+ memo
149
+ end
150
+ end
151
+ end
152
+
153
+ def remote?(url)
154
+ if Capybara.app_host
155
+ true
156
+ else
157
+ host = URI.parse(url).host
158
+
159
+ if host.nil?
160
+ last_request_remote?
161
+ else
162
+ !Capybara::Mechanize.local_hosts.include?(host)
163
+ end
164
+ end
165
+ end
166
+
167
+ attr_reader :agent
168
+
169
+ private
170
+
171
+ def last_location_header
172
+ last_request_remote? ? remote_response.page.response['Location'] : last_response['Location']
173
+ end
174
+
175
+ def last_request_remote?
176
+ !!@last_request_remote
177
+ end
178
+
179
+ def register_local_request
180
+ @last_remote_host = nil
181
+ @last_request_remote = false
182
+ end
183
+
184
+ def process_remote_request(method, url, attributes, headers)
185
+ if remote?(url)
186
+ remote_uri = URI.parse(url)
187
+
188
+ if remote_uri.host.nil?
189
+ remote_host = @last_remote_host || Capybara.app_host || Capybara.default_host
190
+ url = File.join(remote_host, url)
191
+ url = "http://#{url}" unless url =~ /^http:/ or url =~ /^https:/
192
+ else
193
+ @last_remote_host = "#{remote_uri.host}:#{remote_uri.port}"
194
+ end
195
+
196
+ reset_cache!
197
+ begin
198
+ args = []
199
+ args << attributes unless attributes.empty?
200
+ args << headers unless headers.empty?
201
+ @agent.send(method, url, *args)
202
+ rescue => e
203
+ raise "Received the following error for a #{method.to_s.upcase} request to #{url}: '#{e.message}'"
204
+ end
205
+ @last_request_remote = true
206
+ end
207
+ end
208
+
209
+ def remote_response
210
+ ResponseProxy.new(@agent.current_page) if @agent.current_page
211
+ end
212
+
213
+ def default_user_agent
214
+ "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"
215
+ end
216
+
217
+ class ResponseProxy
218
+ extend Forwardable
219
+
220
+ def_delegator :page, :body
221
+
222
+ attr_reader :page
223
+
224
+ def initialize(page)
225
+ @page = page
226
+ end
227
+
228
+ def current_url
229
+ page.uri.to_s
230
+ end
231
+
232
+ def headers
233
+ # Hax the content-type contains utf8, so Capybara specs are failing, need to ask mailinglist
234
+ headers = page.response
235
+ headers["content-type"].gsub!(';charset=utf-8', '') if headers["content-type"]
236
+ headers
237
+ end
238
+
239
+ def status
240
+ page.code.to_i
241
+ end
242
+
243
+ def redirect?
244
+ [301, 302].include?(status)
245
+ end
246
+
152
247
  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:/
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
248
 
249
+ end
@@ -15,7 +15,7 @@ class Capybara::Mechanize::Driver < Capybara::RackTest::Driver
15
15
  end
16
16
 
17
17
  def browser
18
- @browser ||= Capybara::Mechanize::Browser.new(app, options)
18
+ @browser ||= Capybara::Mechanize::Browser.new(self)
19
19
  end
20
20
 
21
- end
21
+ end
@@ -1,5 +1,5 @@
1
1
  module Capybara
2
2
  module Mechanize
3
- VERSION = '0.3.0.rc0'
3
+ VERSION = '0.3.1'
4
4
  end
5
- end
5
+ 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
@@ -58,38 +58,38 @@ describe Capybara::Mechanize::Driver do
58
58
  end
59
59
 
60
60
  describe "Capybara::Mechanize::Driver, browser" do
61
+
61
62
  before(:each) do
62
63
  Capybara.app_host = REMOTE_TEST_URL
63
64
  end
64
-
65
+
65
66
  after(:each) do
66
67
  Capybara.app_host = nil
67
68
  end
68
- context "in remote mode" do
69
- it "should not throw an error when empty option is passed" do
70
- running do
71
- Capybara::Mechanize::Driver.new(ExtendedTestApp, {})
72
- end.should_not raise_error()
73
- end
74
-
75
- it "should throw an error when bad proxy option is passed" do
76
- running do
77
- Capybara::Mechanize::Driver.new(ExtendedTestApp, {:proxy => BAD_PROXY}).browser
78
- end.should raise_error("ProxyError: You have entered an invalid proxy address #{BAD_PROXY}. e.g. (http|https)://proxy.com(:port)")
79
- end
80
-
81
- it "should not throw an error when good proxy option is passed" do
82
- running do
83
- Capybara::Mechanize::Driver.new(ExtendedTestApp, {:proxy => GOOD_PROXY}).browser
84
- end.should_not raise_error()
85
- end
86
-
87
- it "should not throw an error when good proxy with port option is passed" do
88
- running do
89
- Capybara::Mechanize::Driver.new(ExtendedTestApp, {:proxy => PROXY_WITH_PORT}).browser
90
- end.should_not raise_error()
91
- end
92
-
93
-
94
- end
69
+
70
+ context "in remote mode" do
71
+ it "should not throw an error when empty option is passed" do
72
+ running do
73
+ Capybara::Mechanize::Driver.new(ExtendedTestApp, {})
74
+ end.should_not raise_error()
75
+ end
76
+
77
+ it "should throw an error when bad proxy option is passed" do
78
+ running do
79
+ Capybara::Mechanize::Driver.new(ExtendedTestApp, {:proxy => BAD_PROXY}).browser
80
+ end.should raise_error("ProxyError: You have entered an invalid proxy address #{BAD_PROXY}. e.g. (http|https)://proxy.com(:port)")
81
+ end
82
+
83
+ it "should not throw an error when good proxy option is passed" do
84
+ running do
85
+ Capybara::Mechanize::Driver.new(ExtendedTestApp, {:proxy => GOOD_PROXY}).browser
86
+ end.should_not raise_error()
87
+ end
88
+
89
+ it "should not throw an error when good proxy with port option is passed" do
90
+ running do
91
+ Capybara::Mechanize::Driver.new(ExtendedTestApp, {:proxy => PROXY_WITH_PORT}).browser
92
+ end.should_not raise_error()
93
+ end
94
+ end
95
95
  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
@@ -13,6 +13,7 @@ describe Capybara::Session do
13
13
 
14
14
  before do
15
15
  @session = Capybara::Session.new(:mechanize)
16
+ @session.driver.options[:respect_data_method] = true
16
17
  end
17
18
 
18
19
  describe '#driver' do
metadata CHANGED
@@ -1,15 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bbc-capybara-mechanize-with-proxy
3
3
  version: !ruby/object:Gem::Version
4
- hash: 15424037
5
- prerelease: 6
4
+ hash: 17
5
+ prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 3
9
- - 0
10
- - rc
11
- - 0
12
- version: 0.3.0.rc0
9
+ - 1
10
+ version: 0.3.1
13
11
  platform: ruby
14
12
  authors:
15
13
  - Jeroen van Dijk
@@ -19,7 +17,7 @@ autorequire:
19
17
  bindir: bin
20
18
  cert_chain: []
21
19
 
22
- date: 2011-10-28 00:00:00 Z
20
+ date: 2012-02-20 00:00:00 Z
23
21
  dependencies:
24
22
  - !ruby/object:Gem::Dependency
25
23
  name: mechanize
@@ -48,9 +46,9 @@ dependencies:
48
46
  hash: 23
49
47
  segments:
50
48
  - 1
51
- - 0
52
- - 0
53
- version: 1.0.0
49
+ - 1
50
+ - 2
51
+ version: 1.1.2
54
52
  type: :runtime
55
53
  version_requirements: *id002
56
54
  description: RackTest driver for Capybara, but with remote request support thanks to mechanize and added proxy configuration features