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

Sign up to get free protection for your applications and to get access to all the features.
@@ -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